source: git/Singular/sparsmat.cc @ d5a51a

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