source: git/Singular/sparsmat.cc @ 9a596d

spielwiese
Last change on this file since 9a596d was 9a596d, checked in by Wilfred Pohl <pohl@…>, 24 years ago
det for sparse, bug fix git-svn-id: file:///usr/local/Singular/svn/trunk@3090 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 37.6 KB
Line 
1/****************************************
2*  Computer Algebra System SINGULAR     *
3****************************************/
4/* $Id: sparsmat.cc,v 1.7 1999-06-04 13:06:28 pohl Exp $ */
5
6/*
7* ABSTRACT: operations with sparse matrices (bareiss, ...)
8*/
9
10#include "mod2.h"
11#include "tok.h"
12#include "febase.h"
13#include "structs.h"
14#include "intvec.h"
15#include "lists.h"
16#include "ring.h"
17#include "polys.h"
18#include "ipid.h"
19#include "ideals.h"
20#include "numbers.h"
21#include "sparsmat.h"
22
23/* ----------------- macros ------------------ */
24/* #define OLD_DIV */
25#ifdef OLD_DIV
26#define SM_MULT(A,B,C) smMult(A,B)
27#define SM_DIV smPolyDiv
28#else
29#define SM_MULT smMultDiv
30#define SM_DIV smSpecialPolyDiv
31#endif
32/* ----------------- general definitions ------------------ */
33
34/* elements of a 'sparse' matrix in SINGULAR */
35typedef struct smprec sm_prec;
36typedef sm_prec * smpoly;
37struct smprec{
38  smpoly n;            // the next element
39  int pos;             // position
40  int e;               // level
41  poly m;              // the element
42  float f;             // complexity of the element
43};
44
45/* declare internal 'C' stuff */
46static void smDebug() { int k=0; }
47static void smExactPolyDiv(poly, poly);
48static BOOLEAN smIsScalar(const poly);
49static BOOLEAN smIsNegQuot(poly, const poly, const poly);
50static poly smEMult(poly, const poly);
51static BOOLEAN smCheckLead(const poly, const poly);
52static poly smDMult(poly, const poly);
53static void smPolyDivN(poly a, const number);
54static BOOLEAN smSmaller(poly, poly);
55static void smCombineChain(poly *, poly);
56static void smFindRef(poly *, poly *, poly);
57
58static void smElemDelete(smpoly *);
59static smpoly smElemCopy(smpoly);
60static float smPolyWeight(smpoly);
61static smpoly smPoly2Smpoly(poly p);
62static poly smSmpoly2Poly(smpoly a);
63
64/* class for sparse matrix:
65*      3 parts of matrix during the algorithm
66*      m_act[cols][pos(rows)] => m_row[rows][pos(cols)] => m_res[cols][pos(rows)]
67*      input                     pivotcols as rows         result
68*      pivot                     like a stack              from pivot and pivotcols
69*      elimination                                         rows reordered according
70*                                                          to pivot choise
71*                                                          stored in perm
72*      a step is as follows
73*      - search of pivot (smPivot)
74*      - swap pivot column and last column (smSwapC)
75*        select pivotrow to piv and red (smSelectPR)
76*        consider sign
77*      - elimination (smInitElim, sm0Elim, sm1Elim)
78*        clear zero column as result of elimination (smZeroElim)
79*      - tranfer from
80*        piv and m_row to m_res (smRowToCol)
81*        m_act to m_row (smColToRow)
82*/
83class sparse_mat{
84private:
85  int nrows, ncols;    // dimension of the problem
86  int sign;            // for determinant (start: 1)
87  int act;             // number of unreduced columns (start: ncols)
88  int crd;             // number of reduced columns (start: 0)
89  int tored;           // border for rows to reduce
90  int rpiv, cpiv;      // position of the pivot
91  unsigned short *perm;// permutation of rows
92  float wpoints;       // weight of all points
93  float *wrw, *wcl;    // weights of rows and columns
94  smpoly * m_act;      // unreduced columns
95  smpoly * m_res;      // reduced columns (result)
96  smpoly * m_row;      // reduced part of rows
97  smpoly red;          // row to reduce
98  smpoly piv, oldpiv;  // pivot and previous pivot
99  smpoly dumm;         // allocated dummy
100  void smColToRow();
101  void smRowToCol();
102  void smFinalMult();
103  void smSparseHomog();
104  void smWeights();
105  void smPivot();
106  void smNewWeights();
107  void smNewPivot();
108  void smZeroElim();
109  void smToredElim();
110  void smCopToRes();
111  void smSelectPR();
112  void smElim();
113  void sm1Elim();
114  void smHElim();
115  void smMultCol();
116  poly smMultPoly(smpoly);
117  void smActDel();
118  void smColDel();
119  void smPivDel();
120  void smSign();
121  void smInitPerm();
122public:
123  sparse_mat(ideal);
124  ~sparse_mat();
125  int smGetSign() { return sign; }
126  smpoly * smGetAct() { return m_act; }
127  int smGetRed() { return tored; }
128  ideal smRes2Mod();
129  poly smDet();
130  void smBareiss(int, int);
131  void smNewBareiss(int, int);
132  void smToIntvec(intvec *);
133};
134
135/* ----------------- ops with rings ------------------ */
136ideal smRingCopy(ideal I, ring *ri, sip_sring &tmpR)
137{
138  ring origR =NULL;
139  ideal II;
140  if (currRing->order[0]!=ringorder_c)
141  {
142    origR =currRing;
143    tmpR=*origR;
144    int *ord=(int*)Alloc0(3*sizeof(int));
145    int *block0=(int*)Alloc(3*sizeof(int));
146    int *block1=(int*)Alloc(3*sizeof(int));
147    ord[0]=ringorder_c;
148    ord[1]=ringorder_dp;
149    tmpR.order=ord;
150    block0[1]=1;
151    tmpR.block0=block0;
152    block1[1]=tmpR.N;
153    tmpR.block1=block1;
154    rComplete(&tmpR,1);
155    rChangeCurrRing(&tmpR,TRUE);
156    // fetch data from the old ring
157    II=idInit(IDELEMS(I),I->rank);
158    int k;
159    for (k=0;k<IDELEMS(I);k++) II->m[k] = pFetchCopy(origR, I->m[k]);
160  }
161  else
162  {
163    II=idCopy(I);
164  }
165  *ri = origR;
166  return II;
167}
168
169void smRingClean(ring origR, ip_sring &tmpR)
170{
171  rChangeCurrRing(origR,TRUE);
172  rUnComplete(&tmpR);
173  Free((ADDRESS)tmpR.order,3*sizeof(int));
174  Free((ADDRESS)tmpR.block0,3*sizeof(int));
175  Free((ADDRESS)tmpR.block1,3*sizeof(int));
176}
177
178/* ----------------- basics (used from 'C') ------------------ */
179/*2
180*returns the determinant of the module I;
181*uses Bareiss algorithm
182*/
183poly smCallDet(ideal I)
184{
185  int r=idRankFreeModule(I);
186  if (I->ncols != r)
187  {
188    Werror("det of %d x %d module (matrix)",r,I->ncols);
189    return NULL;
190  }
191  poly res,save;
192  ring origR;
193  sip_sring tmpR;
194  ideal II=smRingCopy(I,&origR,tmpR);
195  sparse_mat *det = new sparse_mat(II);
196
197  idDelete(&II);
198  if (det->smGetAct() == NULL)
199  {
200    delete det;
201    if (origR!=NULL) smRingClean(origR,tmpR);
202    return NULL;
203  }
204  res=det->smDet();
205  if(det->smGetSign()<0) res=pNeg(res);
206  delete det;
207  if (origR!=NULL)
208  {
209    rChangeCurrRing(origR,TRUE);
210    save = res;
211    res = pFetchCopy(&tmpR, save);
212    rChangeCurrRing(&tmpR,FALSE);
213    pDelete(&save);
214    smRingClean(origR,tmpR);
215  }
216  return res;
217}
218
219lists smCallBareiss(ideal I, int x, int y)
220{
221  lists res=(lists)Alloc(sizeof(slists));
222  ideal II = idCopy(I);
223  sparse_mat *bareiss = new sparse_mat(II);
224  intvec *v;
225  ideal m;
226
227  idDelete(&II);
228  if (bareiss->smGetAct() == NULL)
229  {
230    Free((ADDRESS)res, sizeof(slists));
231    return NULL;
232  }
233  bareiss->smBareiss(x, y);
234  m = bareiss->smRes2Mod();
235  v = new intvec(bareiss->smGetRed());
236  bareiss->smToIntvec(v);
237  delete bareiss;
238  res->Init(2);
239  res->m[0].rtyp=MODUL_CMD;
240  res->m[0].data=(void *)m;
241  res->m[1].rtyp=INTVEC_CMD;
242  res->m[1].data=(void *)v;
243  return res;
244}
245
246lists smCallNewBareiss(ideal I, int x, int y)
247{
248  ring origR;
249  sip_sring tmpR;
250  lists res=(lists)Alloc(sizeof(slists));
251  ideal II=smRingCopy(I,&origR,tmpR);
252  sparse_mat *bareiss = new sparse_mat(II);
253  ideal mm=II;
254  intvec *v;
255  ideal m;
256
257  if (bareiss->smGetAct() == NULL)
258  {
259    delete bareiss;
260    if (origR!=NULL) smRingClean(origR,tmpR);
261    v=new intvec(1,pVariables);
262  }
263  else
264  {
265    idDelete(&II);
266    bareiss->smNewBareiss(x, y);
267    m = bareiss->smRes2Mod();
268    v = new intvec(bareiss->smGetRed());
269    bareiss->smToIntvec(v);
270    delete bareiss;
271    if (origR!=NULL)
272    {
273      rChangeCurrRing(origR,TRUE);
274      mm=idInit(IDELEMS(m),m->rank);
275      int k;
276      for (k=0;k<IDELEMS(m);k++) mm->m[k] = pFetchCopy(&tmpR, m->m[k]);
277      rChangeCurrRing(&tmpR,FALSE);
278      idDelete(&m);
279      smRingClean(origR,tmpR);
280    }
281    else
282    {
283      mm=m;
284    }
285  }
286  res->Init(2);
287  res->m[0].rtyp=MODUL_CMD;
288  res->m[0].data=(void *)mm;
289  res->m[1].rtyp=INTVEC_CMD;
290  res->m[1].data=(void *)v;
291  return res;
292}
293
294/*
295* constructor
296*/
297sparse_mat::sparse_mat(ideal smat)
298{
299  int i;
300  polyset pmat;
301
302  ncols = smat->ncols;
303  nrows = idRankFreeModule(smat);
304  if (nrows <= 0)
305  {
306    m_act = NULL;
307    return;
308  }
309  sign = 1;
310  act = ncols;
311  crd = 0;
312  tored = nrows; // without border
313  i = tored+1;
314  perm = (unsigned short *)Alloc(sizeof(unsigned short)*(i+1));
315  perm[i] = 0;
316  m_row = (smpoly *)Alloc0(sizeof(smpoly)*i);
317  wrw = (float *)Alloc(sizeof(float)*i);
318  i = ncols+1;
319  wcl = (float *)Alloc(sizeof(float)*i);
320  m_act = (smpoly *)Alloc(sizeof(smpoly)*i);
321  m_res = (smpoly *)Alloc0(sizeof(smpoly)*i);
322  dumm = (smpoly)Alloc(sizeof(smprec));
323  m_res[0] = (smpoly)Alloc(sizeof(smprec));
324  m_res[0]->m = NULL;
325  pmat = smat->m;
326  for(i=ncols; i; i--)
327  {
328    m_act[i] = smPoly2Smpoly(pmat[i-1]);
329    pmat[i-1] = NULL;
330  }
331  this->smZeroElim();
332  oldpiv = NULL;
333}
334
335/*
336* destructor
337*/
338sparse_mat::~sparse_mat()
339{
340  int i;
341  if (m_act == NULL) return;
342  Free((ADDRESS)m_res[0], sizeof(smprec));
343  Free((ADDRESS)dumm, sizeof(smprec));
344  i = ncols+1;
345  Free((ADDRESS)m_res, sizeof(smpoly)*i);
346  Free((ADDRESS)m_act, sizeof(smpoly)*i);
347  Free((ADDRESS)wcl, sizeof(float)*i);
348  i = nrows+1;
349  Free((ADDRESS)wrw, sizeof(float)*i);
350  Free((ADDRESS)m_row, sizeof(smpoly)*i);
351  Free((ADDRESS)perm, sizeof(unsigned short)*(i+1));
352}
353
354/*
355* transform the result to a module
356*/
357ideal sparse_mat::smRes2Mod()
358{
359  ideal res = idInit(crd, crd);
360  int i;
361
362  for (i=crd; i; i--) res->m[i-1] = smSmpoly2Poly(m_res[i]);
363  res->rank = idRankFreeModule(res);
364  return res;
365}
366
367/*
368* permutation of rows
369*/
370void sparse_mat::smToIntvec(intvec *v)
371{
372  int i;
373
374  for (i=v->rows()-1; i>=0; i--)
375    (*v)[i] = perm[i+1];
376}
377
378/* ---------------- the algorithm's ------------------ */
379/*
380* the determinant (up to sign), uses new Bareiss elimination
381*/
382poly sparse_mat::smDet()
383{
384  int y;
385  poly res = NULL;
386
387  if (sign == 0)
388  {
389    this->smActDel();
390    return NULL;
391  }
392  if (act < 2)
393  {
394    if (act != 0) res = m_act[1]->m;
395    Free((void *)m_act[1], sizeof(smprec));
396    return res;
397  }
398  this->smInitPerm();
399  this->smPivot();
400  this->smSign();
401  this->smSelectPR();
402  this->sm1Elim();
403  crd++;
404  m_res[crd] = piv;
405  this->smColDel();
406  act--;
407  this->smZeroElim();
408  if (sign == 0)
409  {
410    this->smActDel();
411    return NULL;
412  }
413  if (act < 2)
414  {
415    this->smFinalMult();
416    this->smPivDel();
417    if (act != 0) res = m_act[1]->m;
418    Free((void *)m_act[1], sizeof(smprec));
419    return res;
420  }
421  loop
422  {
423    this->smNewPivot();
424    this->smSign();
425    this->smSelectPR();
426    this->smMultCol();
427    this->smHElim();
428    crd++;
429    m_res[crd] = piv;
430    this->smColDel();
431    act--;
432    this->smZeroElim();
433    if (sign == 0)
434    {
435      this->smPivDel();
436      this->smActDel();
437      return NULL;
438    }
439    if (act < 2)
440    {
441      this->smFinalMult();
442      this->smPivDel();
443      if (act != 0) res = m_act[1]->m;
444      Free((void *)m_act[1], sizeof(smprec));   
445      return res;
446    }
447  }
448}
449
450/*
451* the Bareiss elimination:
452*   - with x unreduced last rows, pivots from here are not allowed
453*   - the method will finish for number of unreduced columns < y
454*/
455void sparse_mat::smBareiss(int x, int y)
456{
457  if ((x > 0) && (x < nrows))
458  {
459    tored -= x;
460    this->smToredElim();
461  }
462  if (y < 2) y = 2;
463  if (act < y)
464  {
465    if (act != 0)
466    {
467      this->smCopToRes();
468    }
469    return;
470  }
471  this->smPivot();
472  this->smSelectPR();
473  this->smElim();
474  crd++;
475  this->smColToRow();
476  act--;
477  this->smRowToCol();
478  this->smZeroElim();
479  if (tored != nrows)
480    this->smToredElim();
481  if (act < y)
482  {
483    this->smCopToRes();
484    return;
485  }
486  loop
487  {
488    this->smPivot();
489    oldpiv = piv;
490    this->smSelectPR();
491    this->smElim();
492    crd++;
493    this->smColToRow();
494    act--;
495    this->smRowToCol();
496    this->smZeroElim();
497    if (tored != nrows)
498      this->smToredElim();
499    if (act < y)
500    {
501      if (act != 0)
502      {
503        this->smCopToRes();
504      }
505      else
506        tored = crd;
507      return;
508    }
509  }
510}
511
512/*
513* the new Bareiss elimination:
514*   - with x unreduced last rows, pivots from here are not allowed
515*   - the method will finish for number of unreduced columns < y
516*/
517void sparse_mat::smNewBareiss(int x, int y)
518{
519  if ((x > 0) && (x < nrows))
520  {
521    tored -= x;
522    this->smToredElim();
523  }
524  if (y < 2) y = 2;
525  if (act < y)
526  {
527    if (act != 0)
528    {
529      this->smCopToRes();
530    }
531    return;
532  }
533  this->smPivot();
534  this->smSelectPR();
535  this->sm1Elim();
536  crd++;
537  this->smColToRow();
538  act--;
539  this->smRowToCol();
540  this->smZeroElim();
541  if (tored != nrows)
542    this->smToredElim();
543  if (act < y)
544  {
545    this->smFinalMult();
546    this->smCopToRes();
547    return;
548  }
549  loop
550  {
551    this->smNewPivot();
552    this->smSelectPR();
553    this->smMultCol();
554    this->smHElim();
555    crd++;
556    this->smColToRow();
557    act--;
558    this->smRowToCol();
559    this->smZeroElim();
560    if (tored != nrows)
561      this->smToredElim();
562    if (act < y)
563    {
564      if (act != 0)
565      {
566        this->smFinalMult();
567        this->smCopToRes();
568      }
569      else
570        tored = crd;
571      return;
572    }
573  }
574}
575
576/* ----------------- pivot method ------------------ */
577
578/*
579* prepare smPivot, compute weights for rows and columns
580* and the weight for all points
581*/
582void sparse_mat::smWeights()
583{
584  float wc, wp, w;
585  smpoly a;
586  int i;
587
588  wp = 0.0;
589  for (i=tored; i; i--) wrw[i] = 0.0; // ???
590  for (i=act; i; i--)
591  {
592    wc = 0.0;
593    a = m_act[i];
594    loop
595    {
596      if (a->pos > tored)
597        break;
598      w = a->f = smPolyWeight(a);
599      wc += w;
600      wrw[a->pos] += w;
601      a = a->n;
602      if (a == NULL)
603        break;
604    }
605    wp += wc;
606    wcl[i] = wc;
607  }
608  wpoints = wp;
609}
610
611/*
612* compute pivot
613*/
614void sparse_mat::smPivot()
615{
616  float wopt = 1.0e30;
617  float wc, wr, wp, w;
618  smpoly a;
619  int i, copt, ropt;
620
621  this->smWeights();
622  for (i=act; i; i--)
623  {
624    a = m_act[i];
625    loop
626    {
627      if (a->pos > tored)
628        break;
629      w = a->f;
630      wc = wcl[i]-w;
631      wr = wrw[a->pos]-w;
632      if ((wr<0.25) || (wc<0.25)) // row or column with only one point
633      {
634        if (w<wopt)
635        {
636          wopt = w;
637          copt = i;
638          ropt = a->pos;
639        }
640      }
641      else // elimination
642      {
643        wp = w*(wpoints-wcl[i]-wr);
644        wp += wr*wc;
645        if (wp < wopt)
646        {
647          wopt = wp;
648          copt = i;
649          ropt = a->pos;
650        } 
651      }
652      a = a->n;
653      if (a == NULL)
654        break;
655    }
656  }
657  rpiv = ropt;
658  cpiv = copt;
659  if (cpiv != act)
660  {
661    a = m_act[act];
662    m_act[act] = m_act[cpiv];
663    m_act[cpiv] = a;
664  }
665}
666
667/*
668* prepare smPivot, compute weights for rows and columns
669* and the weight for all points
670*/
671void sparse_mat::smNewWeights()
672{
673  float wc, wp, w, hp = piv->f;
674  smpoly a;
675  int i, f, e = crd;
676
677  wp = 0.0;
678  for (i=tored; i; i--) wrw[i] = 0.0; // ???
679  for (i=act; i; i--)
680  {
681    wc = 0.0;
682    a = m_act[i];
683    loop
684    {
685      if (a->pos > tored)
686        break;
687      w = a->f;
688      f = a->e;
689      if (f < e)
690      {
691        w *= hp;
692        if (f) w /= m_res[f]->f;
693      }
694      wc += w;
695      wrw[a->pos] += w;
696      a = a->n;
697      if (a == NULL)
698        break;
699    }
700    wp += wc;
701    wcl[i] = wc;
702  }
703  wpoints = wp;
704}
705
706/*
707* compute pivot
708*/
709void sparse_mat::smNewPivot()
710{
711  float wopt = 1.0e30, hp = piv->f;
712  float wc, wr, wp, w;
713  smpoly a;
714  int i, copt, ropt, f, e = crd;
715
716  this->smNewWeights();
717  for (i=act; i; i--)
718  {
719    a = m_act[i];
720    loop
721    {
722      if (a->pos > tored)
723        break;
724      w = a->f;
725      f = a->e;
726      if (f < e)
727      {
728        w *= hp;
729        if (f) w /= m_res[f]->f;
730      }
731      wc = wcl[i]-w;
732      wr = wrw[a->pos]-w;
733      if ((wr<0.25) || (wc<0.25)) // row or column with only one point
734      {
735        if (w<wopt)
736        {
737          wopt = w;
738          copt = i;
739          ropt = a->pos;
740        }
741      }
742      else // elimination
743      {
744        wp = w*(wpoints-wcl[i]-wr);
745        wp += wr*wc;
746        if (wp < wopt)
747        {
748          wopt = wp;
749          copt = i;
750          ropt = a->pos;
751        } 
752      }
753      a = a->n;
754      if (a == NULL)
755        break;
756    }
757  }
758  rpiv = ropt;
759  cpiv = copt;
760  if (cpiv != act)
761  {
762    a = m_act[act];
763    m_act[act] = m_act[cpiv];
764    m_act[cpiv] = a;
765  }
766}
767
768/* ----------------- elimination ------------------ */
769
770/* steps of elimination */
771void sparse_mat::smElim()
772{
773  poly p = piv->m;        // pivotelement
774  smpoly c = m_act[act];  // pivotcolumn
775  smpoly r = red;         // row to reduce
776  poly q;
777  smpoly res, a, b;
778  poly w, ha, hb;
779  int i;
780
781  if (oldpiv != NULL) q = oldpiv->m; // previous pivot
782  else q = NULL; 
783  if ((c == NULL) || (r == NULL))
784  {
785    while (r) smElemDelete(&r);
786    for (i=1; i<act; i++)
787    {
788      a = m_act[i];
789      do
790      {
791        ha = SM_MULT(a->m, p, q);
792        pDelete(&a->m);
793        if (q) SM_DIV(ha, q);
794        a->m = ha;
795        a = a->n;
796      } while (a != NULL);
797    }
798    return;
799  }
800  for (i=1; i<act; i++)
801  {
802    a = m_act[i];
803    if ((r == NULL) || (i != r->pos))  // cols without elimination
804    {
805      do
806      {
807        ha = SM_MULT(a->m, p, q);
808        pDelete(&a->m);
809        if (q) SM_DIV(ha, q);
810        a->m = ha;
811        a = a->n;
812      } while (a != NULL);
813    }
814    else                    // cols with elimination
815    {
816      res = dumm;
817      res->n = NULL;
818      b = c;
819      w = r->m;
820      loop                  // combine the chains a and b: p*a + w*b
821      {
822        if (a->pos < b->pos)
823        {
824          ha = SM_MULT(a->m, p, q);
825          pDelete(&a->m);
826          if (q) SM_DIV(ha, q);
827          a->m = ha;
828          res = res->n = a;
829          a = a->n;
830        }
831        else if (a->pos > b->pos)
832        {
833          res = res->n = smElemCopy(b);
834          hb = SM_MULT(b->m, w, q);
835          b = b->n;
836          if (q) SM_DIV(hb, q);
837          res->m = hb;
838        }     
839        else
840        {
841          ha = SM_MULT(a->m, p, q);
842          pDelete(&a->m);
843          hb = SM_MULT(b->m, w, q);
844          ha = pAdd(ha, hb);
845          if (ha != NULL)
846          {
847            if (q) SM_DIV(ha, q);
848            a->m = ha;
849            res = res->n = a;
850            a = a->n;
851          }
852          else
853          {
854            smElemDelete(&a);
855          }
856          b = b->n;
857        }
858        if (a == NULL)
859        {
860          if (b != NULL)
861          {
862            do
863            {
864              res = res->n = smElemCopy(b);
865              hb = SM_MULT(b->m, w, q);
866              if (q) SM_DIV(hb, q);
867              res->m = hb;
868              b = b->n;
869            } while (b != NULL);
870          }
871          else
872            res->n = NULL;
873          break;
874        }
875        if (b == NULL)
876        {
877          do
878          {
879            ha = SM_MULT(a->m, p, q);
880            pDelete(&a->m);
881            if (q) SM_DIV(ha, q);
882            a->m = ha;
883            res = res->n = a;
884            a = a->n;
885          } while (a != NULL);
886          break;
887        }
888      }
889      m_act[i] = dumm->n;
890      if (r) smElemDelete(&r);
891    }
892  }
893}
894
895/* first step of elimination */
896void sparse_mat::sm1Elim()
897{
898  poly p = piv->m;        // pivotelement
899  smpoly c = m_act[act];  // pivotcolumn
900  smpoly r = red;         // row to reduce
901  smpoly res, a, b;
902  poly w, ha, hb;
903
904  if ((c == NULL) || (r == NULL))
905    return; 
906  do
907  {
908    a = m_act[r->pos];
909    res = dumm;
910    res->n = NULL;
911    b = c;
912    w = r->m;
913    loop                  // combine the chains a and b: p*a + w*b
914    {
915      if (a->pos < b->pos)
916      {
917        res = res->n = a;
918        a = a->n;
919      }
920      else if (a->pos > b->pos)
921      {
922        res = res->n = smElemCopy(b);
923        res->m = smMult(b->m, w);
924        res->e = 1;
925        res->f = smPolyWeight(res);
926        b = b->n;
927      }     
928      else
929      {
930        ha = smMult(a->m, p);
931        pDelete(&a->m);
932        hb = smMult(b->m, w);
933        ha = pAdd(ha, hb);
934        if (ha != NULL)
935        {
936          a->m = ha;
937          a->e = 1;
938          a->f = smPolyWeight(a);
939          res = res->n = a;
940          a = a->n;
941        }
942        else
943        {
944          smElemDelete(&a);
945        }
946        b = b->n;
947      }
948      if (b == NULL)
949      {
950        res->n = a;
951        break;
952      }
953      if (a == NULL)
954      {
955        do
956        {
957          res = res->n = smElemCopy(b);
958          res->m = smMult(b->m, w);
959          res->e = 1;
960          res->f = smPolyWeight(res);
961          b = b->n;
962        } while (b != NULL);
963        break;
964      }
965    }
966    m_act[r->pos] = dumm->n;
967    smElemDelete(&r);
968  } while (r != NULL);
969}
970
971/* higher steps of elimination */
972void sparse_mat::smHElim()
973{
974  poly hp = this->smMultPoly(piv);
975  poly gp = piv->m;       // pivotelement
976  smpoly c = m_act[act];  // pivotcolumn
977  smpoly r = red;         // row to reduce
978  smpoly res, a, b;
979  poly ha, hr, gc, x, y;
980  int e, ip, ir, ia, lev;
981
982  if ((c == NULL) || (r == NULL))
983  {
984    pDelete(&hp);
985    return;
986  }
987  e = crd+1;
988  ip = piv->e;
989  do
990  {
991    a = m_act[r->pos];
992    res = dumm;
993    res->n = NULL;
994    b = c;
995    hr = r->m;
996    ir = r->e;
997    loop                  // combine the chains a and b: (hp,gp)*a(l) + hr*b(h)
998    {
999      if (a->pos < b->pos)
1000      {
1001        res = res->n = a;
1002        a = a->n;
1003      }
1004      else if (a->pos > b->pos)
1005      {
1006        res = res->n = smElemCopy(b);
1007        x = SM_MULT(b->m, hr, m_res[ir]->m);
1008        b = b->n;
1009        if(ir) SM_DIV(x, m_res[ir]->m);
1010        res->m = x;
1011        res->e = e;
1012        res->f = smPolyWeight(res);
1013      }     
1014      else
1015      {
1016        y = NULL;
1017        x = hr;
1018        ha = a->m;
1019        ia = a->e;
1020        if (ir > ia)
1021        {
1022          gc = SM_MULT(ha, m_res[ir]->m, m_res[ia]->m);
1023          pDelete(&ha);
1024          ha = gc;
1025          if (ia) SM_DIV(ha, m_res[ia]->m);
1026          ia = ir;
1027        }
1028        else if (ir < ia)
1029        {
1030          if (ip < ia)
1031          {
1032            gc = SM_MULT(ha, m_res[crd]->m, m_res[ia]->m);
1033            pDelete(&ha);
1034            ha = gc;
1035            if (ia) SM_DIV(ha, m_res[ia]->m);
1036            y = hp;
1037            ia = ip;
1038            if (ir > ia)
1039            {
1040              y = SM_MULT(y, m_res[ir]->m, m_res[ia]->m);
1041              if (ia) SM_DIV(y, m_res[ia]->m);
1042              ia = ir;
1043            }
1044            else if (ir < ia)
1045            {
1046              x = SM_MULT(x, m_res[ia]->m, m_res[ir]->m);
1047              if (ir) SM_DIV(x, m_res[ir]->m);
1048            }
1049          }
1050          else
1051          {
1052            x = SM_MULT(x, m_res[ia]->m, m_res[ir]->m);
1053            if (ir) SM_DIV(x, m_res[ir]->m);
1054          }
1055        }
1056        if (y == NULL) y = gp;
1057        gc = SM_MULT(ha, y, m_res[ia]->m);
1058        pDelete(&ha);
1059        x = SM_MULT(x, b->m, m_res[ia]->m);
1060        x = pAdd(x, gc);
1061        if (x != NULL)
1062        {
1063          if (ia) SM_DIV(x, m_res[ia]->m);
1064          a->m = x;
1065          a->e = e;
1066          a->f = smPolyWeight(a);
1067          res = res->n = a;
1068          a = a->n;
1069        }
1070        else
1071        {
1072          a->m = NULL;
1073          smElemDelete(&a);
1074        }
1075        b = b->n;
1076      }
1077      if (b == NULL)
1078      {
1079        res->n = a;
1080        break;
1081      }
1082      if (a == NULL)
1083      {
1084        do
1085        {
1086          res = res->n = smElemCopy(b);
1087          x = SM_MULT(b->m, hr, m_res[ir]->m);
1088          b = b->n;
1089          if(ir) SM_DIV(x, m_res[ir]->m);
1090          res->m = x;
1091          res->e = e;
1092          res->f = smPolyWeight(res);
1093        } while (b != NULL);
1094        break;
1095      }
1096    }
1097    m_act[r->pos] = dumm->n;
1098    smElemDelete(&r);
1099  } while (r != NULL);
1100  pDelete(&hp);
1101}
1102
1103/* ----------------- transfer ------------------ */
1104
1105/*
1106* select the pivotrow and store it to red and piv
1107*/
1108void sparse_mat::smSelectPR()
1109{
1110  smpoly b = dumm;
1111  smpoly a, ap;
1112  int i;
1113
1114  a = m_act[act];
1115  if (a->pos < rpiv)
1116  {
1117    do
1118    {
1119      ap = a;
1120      a = a->n;
1121    } while (a->pos < rpiv);
1122    ap->n = a->n;
1123  }
1124  else
1125    m_act[act] = a->n;
1126  piv = a;
1127  a->n = NULL;
1128  for (i=1; i<act; i++)
1129  {
1130    a = m_act[i];
1131    if (a->pos < rpiv)
1132    {
1133      loop
1134      {
1135        ap = a;
1136        a = a->n;
1137        if ((a == NULL) || (a->pos > rpiv))
1138          break;
1139        if (a->pos == rpiv)
1140        {
1141          ap->n = a->n;
1142          a->m = pNeg(a->m);
1143          b = b->n = a;
1144          b->pos = i;
1145          break;
1146        }
1147      }
1148    }
1149    else if (a->pos == rpiv)
1150    {
1151      m_act[i] = a->n;
1152      a->m = pNeg(a->m);
1153      b = b->n = a;
1154      b->pos = i;
1155    }
1156  }
1157  b->n = NULL;
1158  red = dumm->n;
1159}
1160
1161/*
1162* store the pivotcol in m_row
1163*   m_act[cols][pos(rows)] => m_row[rows][pos(cols)]
1164*/
1165void sparse_mat::smColToRow()
1166{
1167  smpoly c = m_act[act];
1168  smpoly h;
1169
1170  while (c != NULL)
1171  {
1172    h = c;
1173    c = c->n;
1174    h->n = m_row[h->pos];
1175    m_row[h->pos] = h;
1176    h->pos = crd;
1177  }
1178}
1179
1180/*
1181* store the pivot and the assosiated row in m_row
1182* to m_res (result):
1183*   piv + m_row[rows][pos(cols)] => m_res[cols][pos(rows)]
1184*/
1185void sparse_mat::smRowToCol()
1186{
1187  smpoly r = m_row[rpiv];
1188  smpoly a, ap, h;
1189
1190  m_row[rpiv] = NULL;
1191  perm[crd] = rpiv;
1192  piv->pos = crd;
1193  m_res[crd] = piv;
1194  while (r != NULL)
1195  {
1196    ap = m_res[r->pos];
1197    loop
1198    {
1199      a = ap->n;
1200      if (a == NULL)
1201      {
1202        ap->n = h = r;
1203        r = r->n;
1204        h->n = a;
1205        h->pos = crd;
1206        break;
1207      }
1208      ap = a;
1209    }
1210  }
1211}
1212
1213/* ----------------- C++ stuff ------------------ */
1214
1215/*
1216*  clean m_act from zeros (after elim)
1217*/
1218void sparse_mat::smZeroElim()
1219{
1220  int i = 0;
1221  int j;
1222
1223  loop
1224  {
1225    i++;
1226    if (i > act) return;
1227    if (m_act[i] == NULL) break;
1228  }
1229  j = i;
1230  loop
1231  {
1232    j++;
1233    if (j > act) break;
1234    if (m_act[j] != NULL)
1235    {
1236      m_act[i] = m_act[j];
1237      i++;
1238    }
1239  }
1240  act -= (j-i);
1241  sign = 0;
1242}
1243
1244/*
1245*  clean m_act from cols not to reduced (after elim)
1246*  put them to m_res
1247*/
1248void sparse_mat::smToredElim()
1249{
1250  int i = 0;
1251  int j;
1252
1253  loop
1254  {
1255    i++;
1256    if (i > act) return;
1257    if (m_act[i]->pos > tored)
1258    {
1259      m_res[crd] = m_act[i];
1260      crd++;
1261      break;
1262    }
1263  }
1264  j = i;
1265  loop
1266  {
1267    j++;
1268    if (j > act) break;
1269    if (m_act[i]->pos > tored)
1270    {
1271      m_res[crd] = m_act[i];
1272      crd++;
1273    }
1274    else
1275    {
1276      m_act[i] = m_act[j];
1277      i++;
1278    }
1279  }
1280  act -= (j-i);
1281  sign = 0;
1282}
1283
1284/*
1285*  copy m_act to m_res
1286*/
1287void sparse_mat::smCopToRes()
1288{
1289  smpoly p, r, ap, a, h;
1290  int c, i;
1291
1292  if (act == 0) return;
1293  if (act > 1)
1294  {
1295    Werror("Not implemented");
1296  }
1297  crd++;
1298  c = crd;
1299  p = m_res[c] = m_act[act];
1300  do
1301  {
1302    r = m_row[p->pos];
1303    m_row[p->pos] = NULL;
1304    perm[c] = p->pos;
1305    p->pos = c;
1306    while (r != NULL)
1307    {
1308      ap = m_res[r->pos];
1309      loop
1310      {
1311        a = ap->n;
1312        if (a == NULL)
1313        {
1314          ap->n = h = r;
1315          r = r->n;
1316          h->n = a;
1317          h->pos = c;
1318          break;
1319        }
1320        ap = a;
1321      }
1322    }
1323    c++;
1324    p = p->n;
1325  } while (p != NULL);
1326  for (i=1;i<=nrows;i++)
1327  {
1328    if(m_row[i] != NULL)
1329    {
1330      r = m_row[i];
1331      m_row[i] = NULL;
1332      do
1333      {
1334        ap = m_res[r->pos];
1335        loop
1336        {
1337          a = ap->n;
1338          if (a == NULL)
1339          {
1340            ap->n = h = r;
1341            r = r->n;
1342            h->n = a;
1343            h->pos = c;
1344            break;
1345          }
1346          ap = a;
1347        }
1348      } while (r!=NULL);
1349      c++;
1350    }
1351  }
1352  tored = c-1;
1353}
1354
1355/*
1356* multiply and divide the column, that goes to result
1357*/
1358void sparse_mat::smMultCol()
1359{
1360  smpoly a = m_act[act];
1361  int e = crd;
1362  poly ha;
1363  int f;
1364
1365  while (a != NULL)
1366  {
1367    f = a->e;
1368    if (f < e)
1369    {
1370      ha = SM_MULT(a->m, m_res[e]->m, m_res[f]->m);
1371      pDelete(&a->m);
1372      if (f) SM_DIV(ha, m_res[f]->m);
1373      a->m = ha;
1374    }
1375    a = a->n;
1376  }
1377}
1378
1379/*
1380* multiply and divide the m_act finaly
1381*/
1382void sparse_mat::smFinalMult()
1383{
1384  smpoly a;
1385  poly ha;
1386  int i, f;
1387  int e = crd;
1388
1389  for (i=act; i; i--)
1390  {
1391    a = m_act[i];
1392    do
1393    {
1394      f = a->e;
1395      if (f < e)
1396      {
1397        ha = SM_MULT(a->m, m_res[e]->m, m_res[f]->m);
1398        pDelete(&a->m);
1399        if (f) SM_DIV(ha, m_res[f]->m);
1400        a->m = ha;
1401      }
1402      a = a->n;
1403    } while (a != NULL);
1404  }
1405}
1406
1407/*
1408* multiply and divide the element, save poly
1409*/
1410poly sparse_mat::smMultPoly(smpoly a)
1411{
1412  int f = a->e;
1413  poly r, h;
1414
1415  if (f < crd)
1416  {
1417    h = r = a->m;
1418    h = SM_MULT(h, m_res[crd]->m, m_res[f]->m);
1419    if (f) SM_DIV(h, m_res[f]->m);
1420    a->m = h;
1421    a->f = smPolyWeight(a);
1422    return r;
1423  }
1424  else
1425    return NULL;
1426}
1427
1428/*
1429* delete the m_act finaly
1430*/
1431void sparse_mat::smActDel()
1432{
1433  smpoly a;
1434  int i;
1435
1436  for (i=act; i; i--)
1437  {
1438    a = m_act[i];
1439    do
1440    {
1441      smElemDelete(&a);
1442    } while (a != NULL);
1443  }
1444}
1445
1446/*
1447* delete the pivotcol
1448*/
1449void sparse_mat::smColDel()
1450{
1451  smpoly a = m_act[act];
1452
1453  while (a != NULL)
1454  {
1455    smElemDelete(&a);
1456  }
1457}
1458
1459/*
1460* delete pivot elements
1461*/
1462void sparse_mat::smPivDel()
1463{
1464  int i=crd;
1465
1466  while (i != 0)
1467  {
1468    smElemDelete(&m_res[i]);
1469    i--;
1470  }
1471}
1472
1473/*
1474* the sign of the determinant
1475*/
1476void sparse_mat::smSign()
1477{
1478  int j,i;
1479  if (act > 2)
1480  {
1481    if (cpiv!=act) sign=-sign;
1482    if ((act%2)==0) sign=-sign;
1483    i=1;
1484    j=perm[1];
1485    while(j<rpiv)
1486    {
1487      sign=-sign;
1488      i++;
1489      j=perm[i];
1490    }
1491    while(perm[i]!=0)
1492    {
1493      perm[i]=perm[i+1];
1494      i++;
1495    }
1496  }
1497  else
1498  {
1499    if (cpiv!=1) sign=-sign;
1500    if (rpiv!=perm[1]) sign=-sign;
1501  }
1502}
1503
1504void sparse_mat::smInitPerm()
1505{
1506  int i;
1507  for (i=act;i;i--) perm[i]=i;
1508}
1509
1510/* ----------------- arithmetic ------------------ */
1511
1512/*
1513*  returns a*b
1514*  a,b NOT destroyed
1515*/
1516poly smMult(poly a, poly b)
1517{
1518  poly pa, res, r;
1519
1520  if (smSmaller(a, b))
1521  {
1522    r = a;
1523    a = b;
1524    b = r;
1525  }
1526  if (pNext(b) == NULL)
1527  {
1528    if (smIsScalar(b))
1529      return pMultCopyN(a, pGetCoeff(b));
1530    else
1531      return smEMult(a, b);
1532  }
1533  pa = res = smEMult(a, b);
1534  pIter(b);
1535  do
1536  {
1537    r = smEMult(a, b);
1538    smCombineChain(&pa, r);
1539    pIter(b);
1540  } while (b != NULL);
1541  return res;
1542}
1543
1544/*2
1545* exact division a/b
1546* a destroyed, b NOT destroyed
1547*/
1548void smPolyDiv(poly a, poly b)
1549{
1550  const number x = pGetCoeff(b);
1551  number y, yn;
1552  poly t, h, dummy;
1553  int i;
1554
1555  if (pNext(b) == NULL)
1556  {
1557    do
1558    {
1559      if (!smIsScalar(b))
1560      {
1561        for (i=pVariables; i; i--)
1562          pSubExp(a,i,pGetExp(b,i));
1563        pSetm(a);
1564      }
1565      y = nDiv(pGetCoeff(a),x);
1566      nNormalize(y);
1567      pSetCoeff(a,y);
1568      pIter(a);
1569    } while (a != NULL);
1570    return;
1571  }
1572  dummy = pInit();
1573  do
1574  {
1575    for (i=pVariables; i; i--)
1576      pSubExp(a,i,pGetExp(b,i));
1577    pSetm(a);
1578    y = nDiv(pGetCoeff(a),x);
1579    nNormalize(y);
1580    pSetCoeff(a,y);
1581    yn = nNeg(nCopy(y));
1582    t = pNext(b);
1583    h = dummy;
1584    do
1585    {
1586      h = pNext(h) = pInit();
1587      //pSetComp(h,0);
1588      for (i=pVariables; i; i--)
1589        pSetExp(h,i,pGetExp(a,i)+pGetExp(t,i));
1590      pSetm(h);
1591      pSetCoeff0(h,nMult(yn, pGetCoeff(t)));
1592      pIter(t);
1593    } while (t != NULL);
1594    nDelete(&yn);
1595    pNext(h) = NULL;
1596    a = pNext(a) = pAdd(pNext(a), pNext(dummy));
1597  } while (a!=NULL);
1598  pFree1(dummy);
1599}
1600
1601/*
1602*  returns the part of (a*b)/exp(lead(c)) with nonegative exponents
1603*/
1604poly smMultDiv(poly a, poly b, const poly c)
1605{
1606  poly pa, e, res, r;
1607  BOOLEAN lead;
1608
1609  if (smSmaller(a, b))
1610  {
1611    r = a;
1612    a = b;
1613    b = r;
1614  }
1615  if ((c == NULL) || smIsScalar(c))
1616  {
1617    if (pNext(b) == NULL)
1618    {
1619      if (smIsScalar(b))
1620        return pMultCopyN(a, pGetCoeff(b));
1621      else
1622        return smEMult(a, b);
1623    }
1624    pa = res = smEMult(a, b);
1625    pIter(b);
1626    do
1627    {
1628      r = smEMult(a, b);
1629      smCombineChain(&pa, r);
1630      pIter(b);
1631    } while (b != NULL);
1632    return res;
1633  }
1634  res = NULL;
1635  e = pInit();
1636  lead = FALSE;
1637  while (!lead)
1638  {
1639    pSetCoeff0(e,pGetCoeff(b));
1640    if (smIsNegQuot(e, b, c))
1641    {
1642      lead = smCheckLead(a, e);
1643      r = smDMult(a, e);
1644    }
1645    else
1646    {
1647      lead = TRUE;
1648      r = smEMult(a, e);
1649    }
1650    if (lead)
1651    {
1652      if (res != NULL)
1653      {
1654        smFindRef(&pa, &res, r);
1655        if (pa == NULL)
1656          lead = FALSE;
1657      }
1658      else
1659      {
1660        pa = res = r;
1661      }
1662    }
1663    else
1664      res = pAdd(res, r);
1665    pIter(b);
1666    if (b == NULL)
1667    {
1668      pFree1(e);
1669      return res;
1670    }
1671  }
1672  do
1673  {
1674    pSetCoeff0(e,pGetCoeff(b));
1675    if (smIsNegQuot(e, b, c))
1676    {
1677      r = smDMult(a, e);
1678      if (smCheckLead(a, e))
1679        smCombineChain(&pa, r);
1680      else
1681        pa = pAdd(pa,r); 
1682    }
1683    else
1684    {
1685      r = smEMult(a, e);
1686      smCombineChain(&pa, r);
1687    }
1688    pIter(b);
1689  } while (b != NULL);
1690  pFree1(e);
1691  return res;
1692}
1693
1694/*n
1695* exact division a/b
1696* a is a result of smMultDiv
1697* a destroyed, b NOT destroyed
1698*/
1699void smSpecialPolyDiv(poly a, poly b)
1700{
1701  if (pNext(b) == NULL)
1702  {
1703    smPolyDivN(a, pGetCoeff(b));
1704    return;
1705  }
1706  smExactPolyDiv(a, b);
1707}
1708
1709/* ------------ internals arithmetic ------------- */
1710static void smExactPolyDiv(poly a, poly b)
1711{
1712  const number x = pGetCoeff(b);
1713  poly tail = pNext(b), e = pInit();
1714  poly h;
1715  number y, yn;
1716
1717  do
1718  {
1719    y = nDiv(pGetCoeff(a), x);
1720    nNormalize(y);
1721    pSetCoeff(a,y);
1722    yn = nNeg(nCopy(y));
1723    pSetCoeff0(e,yn);
1724    if (smIsNegQuot(e, a, b)) 
1725      h = smDMult(tail, e);
1726    else
1727      h = smEMult(tail, e);
1728    nDelete(&yn);
1729    a = pNext(a) = pAdd(pNext(a), h);
1730  } while (a!=NULL);
1731  pFree1(e);
1732}
1733
1734static BOOLEAN smIsScalar(const poly Term)
1735{
1736  int i;
1737
1738  for (i=pVariables; i; i--)
1739  {
1740    if (pGetExp(Term,i)) return FALSE;
1741  }
1742  return TRUE;
1743}
1744
1745static BOOLEAN smIsNegQuot(poly a, const poly b, const poly c)
1746{
1747  int i;
1748
1749  for (i=pVariables; i; i--)
1750  {
1751    pSetExp(a,i,pGetExp(b,i)-pGetExp(c,i));
1752    if (pGetExp(a,i) < 0)
1753    {
1754      while(--i) pSetExp(a,i,pGetExp(b,i)-pGetExp(c,i));
1755      return TRUE;
1756    }
1757  }
1758  return FALSE;
1759}
1760
1761static poly smEMult(poly t, const poly e)
1762{
1763  const number y = pGetCoeff(e);
1764  poly res, h;
1765  int i;
1766
1767  h = res = pInit();
1768  loop
1769  {
1770    //pSetComp(h,0);
1771    for (i=pVariables; i; i--)
1772      pSetExp(h,i,pGetExp(e,i)+pGetExp(t,i));
1773    pSetm(h);
1774    pSetCoeff0(h,nMult(y,pGetCoeff(t)));
1775    pIter(t);
1776    if (t == NULL)
1777    {
1778      pNext(h) = NULL;
1779      return res;
1780    }
1781    h = pNext(h) = pInit();
1782  }
1783}
1784
1785static BOOLEAN smCheckLead(const poly t, const poly e)
1786{
1787  int i;
1788  for (i=pVariables; i; i--)
1789  {
1790    if ((pGetExp(e,i)+pGetExp(t,i)) < 0)
1791      return FALSE;
1792  }
1793  return TRUE;
1794}
1795
1796static poly smDMult(poly t, const poly e)
1797{
1798  const number y = pGetCoeff(e);
1799  number x;
1800  poly res, h, r;
1801  int i;
1802  EXPONENT_TYPE w;
1803
1804  r = h = res = pInit();
1805  loop
1806  {
1807    x = pGetCoeff(t);
1808    for (i=pVariables; i; i--)
1809    {
1810      w = pGetExp(e,i)+pGetExp(t,i);
1811      if (w < 0) break;
1812      pSetExp(h,i,w);
1813    }
1814    pIter(t);
1815    if (i == 0)
1816    {
1817      //pSetComp(h,0);
1818      pSetm(h);
1819      pSetCoeff0(h,nMult(y,x));
1820      if (t == NULL)
1821      {
1822        pNext(h) = NULL;
1823        return res;
1824      }
1825      r = h;
1826      h = pNext(h) = pInit();
1827    }
1828    else if (t == NULL)
1829    {
1830      if (r != h)
1831        pNext(r) = NULL;
1832      else
1833        res = NULL;
1834      pFree1(h);
1835      return res;
1836    }
1837  }
1838}
1839
1840static void smPolyDivN(poly a, const number x)
1841{
1842  number y;
1843
1844  do
1845  {
1846    y = nDiv(pGetCoeff(a),x);
1847    nNormalize(y);
1848    pSetCoeff(a,y);
1849    pIter(a);
1850  } while (a != NULL);
1851}
1852
1853static BOOLEAN smSmaller(poly a, poly b)
1854{
1855  loop
1856  {
1857    pIter(b);
1858    if (b == NULL) return TRUE;
1859    pIter(a);
1860    if (a == NULL) return FALSE;
1861  }
1862}
1863
1864static void smCombineChain(poly *px, poly r)
1865{
1866  poly pa = *px, pb;
1867  number x;
1868  int i;
1869
1870  loop
1871  {
1872    pb = pNext(pa);
1873    if (pb == NULL)
1874    {
1875      pa = pNext(pa) = r;
1876      break;
1877    }
1878    i = pComp0(pb, r);
1879    if (i > 0)
1880      pa = pb;
1881    else
1882    {
1883      if (i == 0)
1884      {
1885        x = nAdd(pGetCoeff(pb), pGetCoeff(r));
1886        pDelete1(&r);
1887        if (nIsZero(x))
1888        {
1889          pDelete1(&pb);
1890          pNext(pa) = pAdd(pb,r);
1891        }
1892        else
1893        {
1894          pa = pb;
1895          pSetCoeff(pa,x);
1896          pNext(pa) = pAdd(pNext(pa), r);
1897        }
1898      }
1899      else
1900      {
1901        pa = pNext(pa) = r;
1902        pNext(pa) = pAdd(pb, pNext(pa));
1903      }
1904      break;
1905    }
1906  }
1907  *px = pa;
1908}
1909
1910static void smFindRef(poly *ref, poly *px, poly r)
1911{
1912  number x;
1913  int i;
1914  poly pa = *px, pp = NULL;
1915
1916  loop
1917  {
1918    i = pComp0(pa, r);
1919    if (i > 0)
1920    {
1921      pp = pa;
1922      pIter(pa);
1923      if (pa==NULL)
1924      {
1925        pNext(pp) = r;
1926        break;
1927      }
1928    }
1929    else
1930    {
1931      if (i == 0)
1932      {
1933        x = nAdd(pGetCoeff(pa), pGetCoeff(r));
1934        pDelete1(&r);
1935        if (nIsZero(x))
1936        {
1937          pDelete1(&pa);
1938          if (pp!=NULL)
1939            pNext(pp) = pAdd(pa,r);
1940          else
1941            *px = pAdd(pa,r);
1942        }
1943        else
1944        {
1945          pp = pa;
1946          pSetCoeff(pp,x);
1947          pNext(pp) = pAdd(pNext(pp), r);
1948        }
1949      }
1950      else
1951      {
1952        if (pp!=NULL)
1953          pp = pNext(pp) = r;
1954        else
1955          *px = pp = r;
1956        pNext(pp) = pAdd(pa, pNext(r));
1957      }
1958      break;
1959    }
1960  }
1961  *ref = pp;
1962}
1963
1964/* ----------------- internal 'C' stuff ------------------ */
1965
1966static void smElemDelete(smpoly *r)
1967{
1968  smpoly a = *r, b = a->n;
1969
1970  pDelete(&a->m);
1971  Free((void *)a, sizeof(smprec));
1972  *r = b;
1973}
1974
1975static smpoly smElemCopy(smpoly a)
1976{
1977  smpoly r = (smpoly)Alloc(sizeof(smprec));
1978
1979  memcpy(r, a, sizeof(smprec));
1980/*  r->m = pCopy(r->m); */
1981  return r;
1982}
1983
1984/*
1985* from poly to smpoly
1986* do not destroy p
1987*/
1988static smpoly smPoly2Smpoly(poly q)
1989{
1990  poly pp;
1991  smpoly res, a;
1992  EXPONENT_TYPE x;
1993
1994  if (q == NULL)
1995    return NULL;
1996  a = res = (smpoly)Alloc(sizeof(smprec));
1997  a->pos = x = pGetComp(q);
1998  a->m = q;
1999  a->e = 0;
2000  loop
2001  {
2002    pSetComp(q,0);
2003    pp = q;
2004    pIter(q);
2005    if (q == NULL)
2006    {
2007      a->n = NULL;
2008      return res;
2009    }
2010    if (pGetComp(q) != x)
2011    {
2012      a = a->n = (smpoly)Alloc(sizeof(smprec));
2013      pNext(pp) = NULL;
2014      a->pos = x = pGetComp(q);
2015      a->m = q;
2016      a->e = 0;
2017    }
2018  }
2019}
2020
2021/*
2022* from smpoly to poly
2023* destroy a
2024*/
2025static poly smSmpoly2Poly(smpoly a)
2026{
2027  smpoly b;
2028  poly res, pp, q;
2029  EXPONENT_TYPE x;
2030
2031  if (a == NULL)
2032    return NULL;
2033  x = a->pos;
2034  q = res = a->m;
2035  loop
2036  {
2037    pSetComp(q,x);
2038    pp = q;
2039    pIter(q);
2040    if (q == NULL)
2041      break;
2042  }
2043  loop
2044  {
2045    b = a;
2046    a = a->n;
2047    Free((void *)b, sizeof(smprec));
2048    if (a == NULL)
2049      return res;
2050    x = a->pos;
2051    q = pNext(pp) = a->m;
2052    loop
2053    {
2054      pSetComp(q,x);
2055      pp = q;
2056      pIter(q);
2057      if (q == NULL)
2058        break;
2059    }
2060  }
2061}
2062
2063/*
2064* weigth of a polynomial, for pivot strategy
2065*/
2066static float smPolyWeight(smpoly a)
2067{
2068  poly p = a->m;
2069  int i;
2070  float res = (float)nSize(pGetCoeff(p));
2071
2072  if (pNext(p) == NULL)
2073  {
2074    for(i=pVariables; i>0; i--)
2075    {
2076      if (pGetExp(p,i) != 0) return res+1.0;
2077    }
2078    return res;
2079  }
2080  else
2081  {
2082    i = 0;
2083    res = 0.0;
2084    do
2085    {
2086      i++;
2087      res += (float)nSize(pGetCoeff(p));
2088      pIter(p);
2089    }
2090    while (p);
2091    return res+(float)i;
2092  }
2093}
2094
Note: See TracBrowser for help on using the repository browser.