source: git/Singular/sparsmat.cc @ e406de

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