source: git/Singular/sparsmat.cc @ 60763e

spielwiese
Last change on this file since 60763e was 60763e, checked in by Wilfred Pohl <pohl@…>, 25 years ago
bug fixes git-svn-id: file:///usr/local/Singular/svn/trunk@3119 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 38.6 KB
Line 
1/****************************************
2*  Computer Algebra System SINGULAR     *
3****************************************/
4/* $Id: sparsmat.cc,v 1.8 1999-06-10 09:01:17 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 smExactPolyDiv(poly, poly);
47static BOOLEAN smIsScalar(const poly);
48static BOOLEAN smIsNegQuot(poly, const poly, const poly);
49static poly smEMult(poly, const poly);
50static BOOLEAN smCheckLead(const poly, const poly);
51static poly smDMult(poly, const poly);
52static void smPolyDivN(poly a, const number);
53static BOOLEAN smSmaller(poly, poly);
54static void smCombineChain(poly *, poly);
55static void smFindRef(poly *, poly *, poly);
56
57static void smElemDelete(smpoly *);
58static smpoly smElemCopy(smpoly);
59static float smPolyWeight(smpoly);
60static smpoly smPoly2Smpoly(poly p);
61static poly smSmpoly2Poly(smpoly a);
62
63/* class for sparse matrix:
64*      3 parts of matrix during the algorithm
65*      m_act[cols][pos(rows)] => m_row[rows][pos(cols)] => m_res[cols][pos(rows)]
66*      input                     pivotcols as rows         result
67*      pivot                     like a stack              from pivot and pivotcols
68*      elimination                                         rows reordered according
69*                                                          to pivot choise
70*                                                          stored in perm
71*      a step is as follows
72*      - search of pivot (smPivot)
73*      - swap pivot column and last column (smSwapC)
74*        select pivotrow to piv and red (smSelectPR)
75*        consider sign
76*      - elimination (smInitElim, sm0Elim, sm1Elim)
77*        clear zero column as result of elimination (smZeroElim)
78*      - tranfer from
79*        piv and m_row to m_res (smRowToCol)
80*        m_act to m_row (smColToRow)
81*/
82class sparse_mat{
83private:
84  int nrows, ncols;    // dimension of the problem
85  int sign;            // for determinant (start: 1)
86  int act;             // number of unreduced columns (start: ncols)
87  int crd;             // number of reduced columns (start: 0)
88  int tored;           // border for rows to reduce
89  int inred;           // unreducable part
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  inred = 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    this->smCopToRes();
466    return;
467  }
468  this->smPivot();
469  this->smSelectPR();
470  this->smElim();
471  crd++;
472  this->smColToRow();
473  act--;
474  this->smRowToCol();
475  this->smZeroElim();
476  if (tored != nrows)
477    this->smToredElim();
478  if (act < y)
479  {
480    this->smCopToRes();
481    return;
482  }
483  loop
484  {
485    this->smPivot();
486    oldpiv = piv;
487    this->smSelectPR();
488    this->smElim();
489    crd++;
490    this->smColToRow();
491    act--;
492    this->smRowToCol();
493    this->smZeroElim();
494    if (tored != nrows)
495      this->smToredElim();
496    if (act < y)
497    {
498      this->smCopToRes();
499      return;
500    }
501  }
502}
503
504/*
505* the new Bareiss elimination:
506*   - with x unreduced last rows, pivots from here are not allowed
507*   - the method will finish for number of unreduced columns < y
508*/
509void sparse_mat::smNewBareiss(int x, int y)
510{
511  if ((x > 0) && (x < nrows))
512  {
513    tored -= x;
514    this->smToredElim();
515  }
516  if (y < 2) y = 2;
517  if (act < y)
518  {
519    this->smCopToRes();
520    return;
521  }
522  this->smPivot();
523  this->smSelectPR();
524  this->sm1Elim();
525  crd++;
526  this->smColToRow();
527  act--;
528  this->smRowToCol();
529  this->smZeroElim();
530  if (tored != nrows)
531    this->smToredElim();
532  if (act < y)
533  {
534    this->smFinalMult();
535    this->smCopToRes();
536    return;
537  }
538  loop
539  {
540    this->smNewPivot();
541    this->smSelectPR();
542    this->smMultCol();
543    this->smHElim();
544    crd++;
545    this->smColToRow();
546    act--;
547    this->smRowToCol();
548    this->smZeroElim();
549    if (tored != nrows)
550      this->smToredElim();
551    if (act < y)
552    {
553      this->smFinalMult();
554      this->smCopToRes();
555      return;
556    }
557  }
558}
559
560/* ----------------- pivot method ------------------ */
561
562/*
563* prepare smPivot, compute weights for rows and columns
564* and the weight for all points
565*/
566void sparse_mat::smWeights()
567{
568  float wc, wp, w;
569  smpoly a;
570  int i;
571
572  wp = 0.0;
573  for (i=tored; i; i--) wrw[i] = 0.0; // ???
574  for (i=act; i; i--)
575  {
576    wc = 0.0;
577    a = m_act[i];
578    loop
579    {
580      if (a->pos > tored)
581        break;
582      w = a->f = smPolyWeight(a);
583      wc += w;
584      wrw[a->pos] += w;
585      a = a->n;
586      if (a == NULL)
587        break;
588    }
589    wp += wc;
590    wcl[i] = wc;
591  }
592  wpoints = wp;
593}
594
595/*
596* compute pivot
597*/
598void sparse_mat::smPivot()
599{
600  float wopt = 1.0e30;
601  float wc, wr, wp, w;
602  smpoly a;
603  int i, copt, ropt;
604
605  this->smWeights();
606  for (i=act; i; i--)
607  {
608    a = m_act[i];
609    loop
610    {
611      if (a->pos > tored)
612        break;
613      w = a->f;
614      wc = wcl[i]-w;
615      wr = wrw[a->pos]-w;
616      if ((wr<0.25) || (wc<0.25)) // row or column with only one point
617      {
618        if (w<wopt)
619        {
620          wopt = w;
621          copt = i;
622          ropt = a->pos;
623        }
624      }
625      else // elimination
626      {
627        wp = w*(wpoints-wcl[i]-wr);
628        wp += wr*wc;
629        if (wp < wopt)
630        {
631          wopt = wp;
632          copt = i;
633          ropt = a->pos;
634        } 
635      }
636      a = a->n;
637      if (a == NULL)
638        break;
639    }
640  }
641  rpiv = ropt;
642  cpiv = copt;
643  if (cpiv != act)
644  {
645    a = m_act[act];
646    m_act[act] = m_act[cpiv];
647    m_act[cpiv] = a;
648  }
649}
650
651/*
652* prepare smPivot, compute weights for rows and columns
653* and the weight for all points
654*/
655void sparse_mat::smNewWeights()
656{
657  float wc, wp, w, hp = piv->f;
658  smpoly a;
659  int i, f, e = crd;
660
661  wp = 0.0;
662  for (i=tored; i; i--) wrw[i] = 0.0; // ???
663  for (i=act; i; i--)
664  {
665    wc = 0.0;
666    a = m_act[i];
667    loop
668    {
669      if (a->pos > tored)
670        break;
671      w = a->f;
672      f = a->e;
673      if (f < e)
674      {
675        w *= hp;
676        if (f) w /= m_res[f]->f;
677      }
678      wc += w;
679      wrw[a->pos] += w;
680      a = a->n;
681      if (a == NULL)
682        break;
683    }
684    wp += wc;
685    wcl[i] = wc;
686  }
687  wpoints = wp;
688}
689
690/*
691* compute pivot
692*/
693void sparse_mat::smNewPivot()
694{
695  float wopt = 1.0e30, hp = piv->f;
696  float wc, wr, wp, w;
697  smpoly a;
698  int i, copt, ropt, f, e = crd;
699
700  this->smNewWeights();
701  for (i=act; i; i--)
702  {
703    a = m_act[i];
704    loop
705    {
706      if (a->pos > tored)
707        break;
708      w = a->f;
709      f = a->e;
710      if (f < e)
711      {
712        w *= hp;
713        if (f) w /= m_res[f]->f;
714      }
715      wc = wcl[i]-w;
716      wr = wrw[a->pos]-w;
717      if ((wr<0.25) || (wc<0.25)) // row or column with only one point
718      {
719        if (w<wopt)
720        {
721          wopt = w;
722          copt = i;
723          ropt = a->pos;
724        }
725      }
726      else // elimination
727      {
728        wp = w*(wpoints-wcl[i]-wr);
729        wp += wr*wc;
730        if (wp < wopt)
731        {
732          wopt = wp;
733          copt = i;
734          ropt = a->pos;
735        } 
736      }
737      a = a->n;
738      if (a == NULL)
739        break;
740    }
741  }
742  rpiv = ropt;
743  cpiv = copt;
744  if (cpiv != act)
745  {
746    a = m_act[act];
747    m_act[act] = m_act[cpiv];
748    m_act[cpiv] = a;
749  }
750}
751
752/* ----------------- elimination ------------------ */
753
754/* steps of elimination */
755void sparse_mat::smElim()
756{
757  poly p = piv->m;        // pivotelement
758  smpoly c = m_act[act];  // pivotcolumn
759  smpoly r = red;         // row to reduce
760  poly q;
761  smpoly res, a, b;
762  poly w, ha, hb;
763  int i;
764
765  if (oldpiv != NULL) q = oldpiv->m; // previous pivot
766  else q = NULL; 
767  if ((c == NULL) || (r == NULL))
768  {
769    while (r) smElemDelete(&r);
770    for (i=1; i<act; i++)
771    {
772      a = m_act[i];
773      do
774      {
775        ha = SM_MULT(a->m, p, q);
776        pDelete(&a->m);
777        if (q) SM_DIV(ha, q);
778        a->m = ha;
779        a = a->n;
780      } while (a != NULL);
781    }
782    return;
783  }
784  for (i=1; i<act; i++)
785  {
786    a = m_act[i];
787    if ((r == NULL) || (i != r->pos))  // cols without elimination
788    {
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    else                    // cols with elimination
799    {
800      res = dumm;
801      res->n = NULL;
802      b = c;
803      w = r->m;
804      loop                  // combine the chains a and b: p*a + w*b
805      {
806        if (a->pos < b->pos)
807        {
808          ha = SM_MULT(a->m, p, q);
809          pDelete(&a->m);
810          if (q) SM_DIV(ha, q);
811          a->m = ha;
812          res = res->n = a;
813          a = a->n;
814        }
815        else if (a->pos > b->pos)
816        {
817          res = res->n = smElemCopy(b);
818          hb = SM_MULT(b->m, w, q);
819          b = b->n;
820          if (q) SM_DIV(hb, q);
821          res->m = hb;
822        }     
823        else
824        {
825          ha = SM_MULT(a->m, p, q);
826          pDelete(&a->m);
827          hb = SM_MULT(b->m, w, q);
828          ha = pAdd(ha, hb);
829          if (ha != NULL)
830          {
831            if (q) SM_DIV(ha, q);
832            a->m = ha;
833            res = res->n = a;
834            a = a->n;
835          }
836          else
837          {
838            smElemDelete(&a);
839          }
840          b = b->n;
841        }
842        if (a == NULL)
843        {
844          if (b != NULL)
845          {
846            do
847            {
848              res = res->n = smElemCopy(b);
849              hb = SM_MULT(b->m, w, q);
850              if (q) SM_DIV(hb, q);
851              res->m = hb;
852              b = b->n;
853            } while (b != NULL);
854          }
855          else
856            res->n = NULL;
857          break;
858        }
859        if (b == NULL)
860        {
861          do
862          {
863            ha = SM_MULT(a->m, p, q);
864            pDelete(&a->m);
865            if (q) SM_DIV(ha, q);
866            a->m = ha;
867            res = res->n = a;
868            a = a->n;
869          } while (a != NULL);
870          break;
871        }
872      }
873      m_act[i] = dumm->n;
874      if (r) smElemDelete(&r);
875    }
876  }
877}
878
879/* first step of elimination */
880void sparse_mat::sm1Elim()
881{
882  poly p = piv->m;        // pivotelement
883  smpoly c = m_act[act];  // pivotcolumn
884  smpoly r = red;         // row to reduce
885  smpoly res, a, b;
886  poly w, ha, hb;
887
888  if ((c == NULL) || (r == NULL))
889    return; 
890  do
891  {
892    a = m_act[r->pos];
893    res = dumm;
894    res->n = NULL;
895    b = c;
896    w = r->m;
897    loop                  // combine the chains a and b: p*a + w*b
898    {
899      if (a->pos < b->pos)
900      {
901        res = res->n = a;
902        a = a->n;
903      }
904      else if (a->pos > b->pos)
905      {
906        res = res->n = smElemCopy(b);
907        res->m = smMult(b->m, w);
908        res->e = 1;
909        res->f = smPolyWeight(res);
910        b = b->n;
911      }     
912      else
913      {
914        ha = smMult(a->m, p);
915        pDelete(&a->m);
916        hb = smMult(b->m, w);
917        ha = pAdd(ha, hb);
918        if (ha != NULL)
919        {
920          a->m = ha;
921          a->e = 1;
922          a->f = smPolyWeight(a);
923          res = res->n = a;
924          a = a->n;
925        }
926        else
927        {
928          smElemDelete(&a);
929        }
930        b = b->n;
931      }
932      if (b == NULL)
933      {
934        res->n = a;
935        break;
936      }
937      if (a == NULL)
938      {
939        do
940        {
941          res = res->n = smElemCopy(b);
942          res->m = smMult(b->m, w);
943          res->e = 1;
944          res->f = smPolyWeight(res);
945          b = b->n;
946        } while (b != NULL);
947        break;
948      }
949    }
950    m_act[r->pos] = dumm->n;
951    smElemDelete(&r);
952  } while (r != NULL);
953}
954
955/* higher steps of elimination */
956void sparse_mat::smHElim()
957{
958  poly hp = this->smMultPoly(piv);
959  poly gp = piv->m;       // pivotelement
960  smpoly c = m_act[act];  // pivotcolumn
961  smpoly r = red;         // row to reduce
962  smpoly res, a, b;
963  poly ha, hr, gc, x, y;
964  int e, ip, ir, ia, lev;
965
966  if ((c == NULL) || (r == NULL))
967  {
968    pDelete(&hp);
969    return;
970  }
971  e = crd+1;
972  ip = piv->e;
973  do
974  {
975    a = m_act[r->pos];
976    res = dumm;
977    res->n = NULL;
978    b = c;
979    hr = r->m;
980    ir = r->e;
981    loop                  // combine the chains a and b: (hp,gp)*a(l) + hr*b(h)
982    {
983      if (a->pos < b->pos)
984      {
985        res = res->n = a;
986        a = a->n;
987      }
988      else if (a->pos > b->pos)
989      {
990        res = res->n = smElemCopy(b);
991        x = SM_MULT(b->m, hr, m_res[ir]->m);
992        b = b->n;
993        if(ir) SM_DIV(x, m_res[ir]->m);
994        res->m = x;
995        res->e = e;
996        res->f = smPolyWeight(res);
997      }     
998      else
999      {
1000        y = NULL;
1001        x = hr;
1002        ha = a->m;
1003        ia = a->e;
1004        if (ir > ia)
1005        {
1006          gc = SM_MULT(ha, m_res[ir]->m, m_res[ia]->m);
1007          pDelete(&ha);
1008          ha = gc;
1009          if (ia) SM_DIV(ha, m_res[ia]->m);
1010          ia = ir;
1011        }
1012        else if (ir < ia)
1013        {
1014          if (ip < ia)
1015          {
1016            gc = SM_MULT(ha, m_res[crd]->m, m_res[ia]->m);
1017            pDelete(&ha);
1018            ha = gc;
1019            if (ia) SM_DIV(ha, m_res[ia]->m);
1020            y = hp;
1021            ia = ip;
1022            if (ir > ia)
1023            {
1024              y = SM_MULT(y, m_res[ir]->m, m_res[ia]->m);
1025              if (ia) SM_DIV(y, m_res[ia]->m);
1026              ia = ir;
1027            }
1028            else if (ir < ia)
1029            {
1030              x = SM_MULT(x, m_res[ia]->m, m_res[ir]->m);
1031              if (ir) SM_DIV(x, m_res[ir]->m);
1032            }
1033          }
1034          else
1035          {
1036            x = SM_MULT(x, m_res[ia]->m, m_res[ir]->m);
1037            if (ir) SM_DIV(x, m_res[ir]->m);
1038          }
1039        }
1040        if (y == NULL) y = gp;
1041        gc = SM_MULT(ha, y, m_res[ia]->m);
1042        pDelete(&ha);
1043        x = SM_MULT(x, b->m, m_res[ia]->m);
1044        x = pAdd(x, gc);
1045        if (x != NULL)
1046        {
1047          if (ia) SM_DIV(x, m_res[ia]->m);
1048          a->m = x;
1049          a->e = e;
1050          a->f = smPolyWeight(a);
1051          res = res->n = a;
1052          a = a->n;
1053        }
1054        else
1055        {
1056          a->m = NULL;
1057          smElemDelete(&a);
1058        }
1059        b = b->n;
1060      }
1061      if (b == NULL)
1062      {
1063        res->n = a;
1064        break;
1065      }
1066      if (a == NULL)
1067      {
1068        do
1069        {
1070          res = res->n = smElemCopy(b);
1071          x = SM_MULT(b->m, hr, m_res[ir]->m);
1072          b = b->n;
1073          if(ir) SM_DIV(x, m_res[ir]->m);
1074          res->m = x;
1075          res->e = e;
1076          res->f = smPolyWeight(res);
1077        } while (b != NULL);
1078        break;
1079      }
1080    }
1081    m_act[r->pos] = dumm->n;
1082    smElemDelete(&r);
1083  } while (r != NULL);
1084  pDelete(&hp);
1085}
1086
1087/* ----------------- transfer ------------------ */
1088
1089/*
1090* select the pivotrow and store it to red and piv
1091*/
1092void sparse_mat::smSelectPR()
1093{
1094  smpoly b = dumm;
1095  smpoly a, ap;
1096  int i;
1097
1098  a = m_act[act];
1099  if (a->pos < rpiv)
1100  {
1101    do
1102    {
1103      ap = a;
1104      a = a->n;
1105    } while (a->pos < rpiv);
1106    ap->n = a->n;
1107  }
1108  else
1109    m_act[act] = a->n;
1110  piv = a;
1111  a->n = NULL;
1112  for (i=1; i<act; i++)
1113  {
1114    a = m_act[i];
1115    if (a->pos < rpiv)
1116    {
1117      loop
1118      {
1119        ap = a;
1120        a = a->n;
1121        if ((a == NULL) || (a->pos > rpiv))
1122          break;
1123        if (a->pos == rpiv)
1124        {
1125          ap->n = a->n;
1126          a->m = pNeg(a->m);
1127          b = b->n = a;
1128          b->pos = i;
1129          break;
1130        }
1131      }
1132    }
1133    else if (a->pos == rpiv)
1134    {
1135      m_act[i] = a->n;
1136      a->m = pNeg(a->m);
1137      b = b->n = a;
1138      b->pos = i;
1139    }
1140  }
1141  b->n = NULL;
1142  red = dumm->n;
1143}
1144
1145/*
1146* store the pivotcol in m_row
1147*   m_act[cols][pos(rows)] => m_row[rows][pos(cols)]
1148*/
1149void sparse_mat::smColToRow()
1150{
1151  smpoly c = m_act[act];
1152  smpoly h;
1153
1154  while (c != NULL)
1155  {
1156    h = c;
1157    c = c->n;
1158    h->n = m_row[h->pos];
1159    m_row[h->pos] = h;
1160    h->pos = crd;
1161  }
1162}
1163
1164/*
1165* store the pivot and the assosiated row in m_row
1166* to m_res (result):
1167*   piv + m_row[rows][pos(cols)] => m_res[cols][pos(rows)]
1168*/
1169void sparse_mat::smRowToCol()
1170{
1171  smpoly r = m_row[rpiv];
1172  smpoly a, ap, h;
1173
1174  m_row[rpiv] = NULL;
1175  perm[crd] = rpiv;
1176  piv->pos = crd;
1177  m_res[crd] = piv;
1178  while (r != NULL)
1179  {
1180    ap = m_res[r->pos];
1181    loop
1182    {
1183      a = ap->n;
1184      if (a == NULL)
1185      {
1186        ap->n = h = r;
1187        r = r->n;
1188        h->n = a;
1189        h->pos = crd;
1190        break;
1191      }
1192      ap = a;
1193    }
1194  }
1195}
1196
1197/* ----------------- C++ stuff ------------------ */
1198
1199/*
1200*  clean m_act from zeros (after elim)
1201*/
1202void sparse_mat::smZeroElim()
1203{
1204  int i = 0;
1205  int j;
1206
1207  loop
1208  {
1209    i++;
1210    if (i > act) return;
1211    if (m_act[i] == NULL) break;
1212  }
1213  j = i;
1214  loop
1215  {
1216    j++;
1217    if (j > act) break;
1218    if (m_act[j] != NULL)
1219    {
1220      m_act[i] = m_act[j];
1221      i++;
1222    }
1223  }
1224  act -= (j-i);
1225  sign = 0;
1226}
1227
1228/*
1229*  clean m_act from cols not to reduced (after elim)
1230*  put them to m_res
1231*/
1232void sparse_mat::smToredElim()
1233{
1234  int i = 0;
1235  int j;
1236
1237  loop
1238  {
1239    i++;
1240    if (i > act) return;
1241    if (m_act[i]->pos > tored)
1242    {
1243      m_res[inred] = m_act[i];
1244      inred--;
1245      break;
1246    }
1247  }
1248  j = i;
1249  loop
1250  {
1251    j++;
1252    if (j > act) break;
1253    if (m_act[i]->pos > tored)
1254    {
1255      m_res[inred] = m_act[i];
1256      inred--;
1257    }
1258    else
1259    {
1260      m_act[i] = m_act[j];
1261      i++;
1262    }
1263  }
1264  act -= (j-i);
1265  sign = 0;
1266}
1267
1268/*
1269*  copy m_act to m_res
1270*/
1271void sparse_mat::smCopToRes()
1272{
1273  smpoly a,ap,r,h;
1274  int i,j,k,l;
1275
1276  i = 0;
1277  if (act)
1278  {
1279    a = m_act[act]; // init perm
1280    do
1281    {
1282      i++;
1283      perm[crd+i] = a->pos;
1284      a = a->n;
1285    } while (a != NULL);
1286    for (j=act-1;j;j--) // load all positions of perm
1287    {
1288      a = m_act[j];
1289      k = 1;
1290      loop
1291      {
1292        if (perm[crd+k] >= a->pos)
1293        {
1294          if (perm[crd+k] > a->pos)
1295          {
1296            for (l=i;l>=k;l--) perm[crd+l+1] = perm[crd+l];
1297            perm[crd+k] = a->pos;
1298            i++;
1299          }
1300          a = a->n;
1301          if (a == NULL) break;
1302        }
1303        k++;
1304        if (k > i)
1305        {
1306          do
1307          {
1308            i++;
1309            perm[crd+i] = a->pos;
1310            a = a->n;
1311          } while (a != NULL);
1312          break;
1313        }
1314      }
1315    }
1316  }
1317  tored = crd+i; // the number or permuted rows
1318  for (j=act;j;j--) // renumber m_act
1319  {
1320    k = 1;
1321    a = m_act[j];
1322    do
1323    {
1324      if (perm[crd+k] == a->pos)
1325      {
1326        a->pos = crd+k;
1327        a = a->n;
1328      }
1329      k++;
1330    } while (a != NULL);
1331  }
1332  for(k=1;k<=i;k++) // clean this from m_row
1333  {
1334    j = perm[crd+k];
1335    if (m_row[j] != NULL)
1336    {
1337      r = m_row[j];
1338      m_row[j] = NULL;
1339      do
1340      {
1341        ap = m_res[r->pos];
1342        loop
1343        {
1344          a = ap->n;
1345          if (a == NULL)
1346          {
1347            h = ap->n = r;
1348            r = r->n;
1349            h->n = NULL;
1350            h->pos = crd+k;
1351            break;
1352          }
1353          ap = a;
1354        }
1355      } while (r!=NULL);
1356    }
1357  }
1358  while(act) // clean m_act
1359  {
1360    crd++;
1361    m_res[crd] = m_act[act];
1362    act--;
1363  }
1364  for (i=1;i<=nrows;i++) // take the rest of m_row
1365  {
1366    if(m_row[i] != NULL)
1367    {
1368      tored++;
1369      r = m_row[i];
1370      m_row[i] = NULL;
1371      perm[tored] = i;
1372      do
1373      {
1374        ap = m_res[r->pos];
1375        loop
1376        {
1377          a = ap->n;
1378          if (a == NULL)
1379          {
1380            h = ap->n = r;
1381            r = r->n;
1382            h->n = NULL;
1383            h->pos = tored;
1384            break;
1385          }
1386          ap = a;
1387        }
1388      } while (r!=NULL);
1389    }
1390  }
1391  while (inred < ncols) // take unreducable
1392  {
1393    crd++;
1394    inred++;
1395    m_res[crd] = m_res[inred];
1396  }
1397}
1398
1399/*
1400* multiply and divide the column, that goes to result
1401*/
1402void sparse_mat::smMultCol()
1403{
1404  smpoly a = m_act[act];
1405  int e = crd;
1406  poly ha;
1407  int f;
1408
1409  while (a != NULL)
1410  {
1411    f = a->e;
1412    if (f < e)
1413    {
1414      ha = SM_MULT(a->m, m_res[e]->m, m_res[f]->m);
1415      pDelete(&a->m);
1416      if (f) SM_DIV(ha, m_res[f]->m);
1417      a->m = ha;
1418    }
1419    a = a->n;
1420  }
1421}
1422
1423/*
1424* multiply and divide the m_act finaly
1425*/
1426void sparse_mat::smFinalMult()
1427{
1428  smpoly a;
1429  poly ha;
1430  int i, f;
1431  int e = crd;
1432
1433  for (i=act; i; i--)
1434  {
1435    a = m_act[i];
1436    do
1437    {
1438      f = a->e;
1439      if (f < e)
1440      {
1441        ha = SM_MULT(a->m, m_res[e]->m, m_res[f]->m);
1442        pDelete(&a->m);
1443        if (f) SM_DIV(ha, m_res[f]->m);
1444        a->m = ha;
1445      }
1446      a = a->n;
1447    } while (a != NULL);
1448  }
1449}
1450
1451/*
1452* multiply and divide the element, save poly
1453*/
1454poly sparse_mat::smMultPoly(smpoly a)
1455{
1456  int f = a->e;
1457  poly r, h;
1458
1459  if (f < crd)
1460  {
1461    h = r = a->m;
1462    h = SM_MULT(h, m_res[crd]->m, m_res[f]->m);
1463    if (f) SM_DIV(h, m_res[f]->m);
1464    a->m = h;
1465    a->f = smPolyWeight(a);
1466    return r;
1467  }
1468  else
1469    return NULL;
1470}
1471
1472/*
1473* delete the m_act finaly
1474*/
1475void sparse_mat::smActDel()
1476{
1477  smpoly a;
1478  int i;
1479
1480  for (i=act; i; i--)
1481  {
1482    a = m_act[i];
1483    do
1484    {
1485      smElemDelete(&a);
1486    } while (a != NULL);
1487  }
1488}
1489
1490/*
1491* delete the pivotcol
1492*/
1493void sparse_mat::smColDel()
1494{
1495  smpoly a = m_act[act];
1496
1497  while (a != NULL)
1498  {
1499    smElemDelete(&a);
1500  }
1501}
1502
1503/*
1504* delete pivot elements
1505*/
1506void sparse_mat::smPivDel()
1507{
1508  int i=crd;
1509
1510  while (i != 0)
1511  {
1512    smElemDelete(&m_res[i]);
1513    i--;
1514  }
1515}
1516
1517/*
1518* the sign of the determinant
1519*/
1520void sparse_mat::smSign()
1521{
1522  int j,i;
1523  if (act > 2)
1524  {
1525    if (cpiv!=act) sign=-sign;
1526    if ((act%2)==0) sign=-sign;
1527    i=1;
1528    j=perm[1];
1529    while(j<rpiv)
1530    {
1531      sign=-sign;
1532      i++;
1533      j=perm[i];
1534    }
1535    while(perm[i]!=0)
1536    {
1537      perm[i]=perm[i+1];
1538      i++;
1539    }
1540  }
1541  else
1542  {
1543    if (cpiv!=1) sign=-sign;
1544    if (rpiv!=perm[1]) sign=-sign;
1545  }
1546}
1547
1548void sparse_mat::smInitPerm()
1549{
1550  int i;
1551  for (i=act;i;i--) perm[i]=i;
1552}
1553
1554/* ----------------- arithmetic ------------------ */
1555
1556/*
1557*  returns a*b
1558*  a,b NOT destroyed
1559*/
1560poly smMult(poly a, poly b)
1561{
1562  poly pa, res, r;
1563
1564  if (smSmaller(a, b))
1565  {
1566    r = a;
1567    a = b;
1568    b = r;
1569  }
1570  if (pNext(b) == NULL)
1571  {
1572    if (smIsScalar(b))
1573      return pMultCopyN(a, pGetCoeff(b));
1574    else
1575      return smEMult(a, b);
1576  }
1577  pa = res = smEMult(a, b);
1578  pIter(b);
1579  do
1580  {
1581    r = smEMult(a, b);
1582    smCombineChain(&pa, r);
1583    pIter(b);
1584  } while (b != NULL);
1585  return res;
1586}
1587
1588/*2
1589* exact division a/b
1590* a destroyed, b NOT destroyed
1591*/
1592void smPolyDiv(poly a, poly b)
1593{
1594  const number x = pGetCoeff(b);
1595  number y, yn;
1596  poly t, h, dummy;
1597  int i;
1598
1599  if (pNext(b) == NULL)
1600  {
1601    do
1602    {
1603      if (!smIsScalar(b))
1604      {
1605        for (i=pVariables; i; i--)
1606          pSubExp(a,i,pGetExp(b,i));
1607        pSetm(a);
1608      }
1609      y = nDiv(pGetCoeff(a),x);
1610      nNormalize(y);
1611      pSetCoeff(a,y);
1612      pIter(a);
1613    } while (a != NULL);
1614    return;
1615  }
1616  dummy = pInit();
1617  do
1618  {
1619    for (i=pVariables; i; i--)
1620      pSubExp(a,i,pGetExp(b,i));
1621    pSetm(a);
1622    y = nDiv(pGetCoeff(a),x);
1623    nNormalize(y);
1624    pSetCoeff(a,y);
1625    yn = nNeg(nCopy(y));
1626    t = pNext(b);
1627    h = dummy;
1628    do
1629    {
1630      h = pNext(h) = pInit();
1631      //pSetComp(h,0);
1632      for (i=pVariables; i; i--)
1633        pSetExp(h,i,pGetExp(a,i)+pGetExp(t,i));
1634      pSetm(h);
1635      pSetCoeff0(h,nMult(yn, pGetCoeff(t)));
1636      pIter(t);
1637    } while (t != NULL);
1638    nDelete(&yn);
1639    pNext(h) = NULL;
1640    a = pNext(a) = pAdd(pNext(a), pNext(dummy));
1641  } while (a!=NULL);
1642  pFree1(dummy);
1643}
1644
1645/*
1646*  returns the part of (a*b)/exp(lead(c)) with nonegative exponents
1647*/
1648poly smMultDiv(poly a, poly b, const poly c)
1649{
1650  poly pa, e, res, r;
1651  BOOLEAN lead;
1652
1653  if (smSmaller(a, b))
1654  {
1655    r = a;
1656    a = b;
1657    b = r;
1658  }
1659  if ((c == NULL) || smIsScalar(c))
1660  {
1661    if (pNext(b) == NULL)
1662    {
1663      if (smIsScalar(b))
1664        return pMultCopyN(a, pGetCoeff(b));
1665      else
1666        return smEMult(a, b);
1667    }
1668    pa = res = smEMult(a, b);
1669    pIter(b);
1670    do
1671    {
1672      r = smEMult(a, b);
1673      smCombineChain(&pa, r);
1674      pIter(b);
1675    } while (b != NULL);
1676    return res;
1677  }
1678  res = NULL;
1679  e = pInit();
1680  lead = FALSE;
1681  while (!lead)
1682  {
1683    pSetCoeff0(e,pGetCoeff(b));
1684    if (smIsNegQuot(e, b, c))
1685    {
1686      lead = smCheckLead(a, e);
1687      r = smDMult(a, e);
1688    }
1689    else
1690    {
1691      lead = TRUE;
1692      r = smEMult(a, e);
1693    }
1694    if (lead)
1695    {
1696      if (res != NULL)
1697      {
1698        smFindRef(&pa, &res, r);
1699        if (pa == NULL)
1700          lead = FALSE;
1701      }
1702      else
1703      {
1704        pa = res = r;
1705      }
1706    }
1707    else
1708      res = pAdd(res, r);
1709    pIter(b);
1710    if (b == NULL)
1711    {
1712      pFree1(e);
1713      return res;
1714    }
1715  }
1716  do
1717  {
1718    pSetCoeff0(e,pGetCoeff(b));
1719    if (smIsNegQuot(e, b, c))
1720    {
1721      r = smDMult(a, e);
1722      if (smCheckLead(a, e))
1723        smCombineChain(&pa, r);
1724      else
1725        pa = pAdd(pa,r); 
1726    }
1727    else
1728    {
1729      r = smEMult(a, e);
1730      smCombineChain(&pa, r);
1731    }
1732    pIter(b);
1733  } while (b != NULL);
1734  pFree1(e);
1735  return res;
1736}
1737
1738/*n
1739* exact division a/b
1740* a is a result of smMultDiv
1741* a destroyed, b NOT destroyed
1742*/
1743void smSpecialPolyDiv(poly a, poly b)
1744{
1745  if (pNext(b) == NULL)
1746  {
1747    smPolyDivN(a, pGetCoeff(b));
1748    return;
1749  }
1750  smExactPolyDiv(a, b);
1751}
1752
1753/* ------------ internals arithmetic ------------- */
1754static void smExactPolyDiv(poly a, poly b)
1755{
1756  const number x = pGetCoeff(b);
1757  poly tail = pNext(b), e = pInit();
1758  poly h;
1759  number y, yn;
1760
1761  do
1762  {
1763    y = nDiv(pGetCoeff(a), x);
1764    nNormalize(y);
1765    pSetCoeff(a,y);
1766    yn = nNeg(nCopy(y));
1767    pSetCoeff0(e,yn);
1768    if (smIsNegQuot(e, a, b)) 
1769      h = smDMult(tail, e);
1770    else
1771      h = smEMult(tail, e);
1772    nDelete(&yn);
1773    a = pNext(a) = pAdd(pNext(a), h);
1774  } while (a!=NULL);
1775  pFree1(e);
1776}
1777
1778static BOOLEAN smIsScalar(const poly Term)
1779{
1780  int i;
1781
1782  for (i=pVariables; i; i--)
1783  {
1784    if (pGetExp(Term,i)) return FALSE;
1785  }
1786  return TRUE;
1787}
1788
1789static BOOLEAN smIsNegQuot(poly a, const poly b, const poly c)
1790{
1791  int i;
1792
1793  for (i=pVariables; i; i--)
1794  {
1795    pSetExp(a,i,pGetExp(b,i)-pGetExp(c,i));
1796    if (pGetExp(a,i) < 0)
1797    {
1798      while(--i) pSetExp(a,i,pGetExp(b,i)-pGetExp(c,i));
1799      return TRUE;
1800    }
1801  }
1802  return FALSE;
1803}
1804
1805static poly smEMult(poly t, const poly e)
1806{
1807  const number y = pGetCoeff(e);
1808  poly res, h;
1809  int i;
1810
1811  h = res = pInit();
1812  loop
1813  {
1814    //pSetComp(h,0);
1815    for (i=pVariables; i; i--)
1816      pSetExp(h,i,pGetExp(e,i)+pGetExp(t,i));
1817    pSetm(h);
1818    pSetCoeff0(h,nMult(y,pGetCoeff(t)));
1819    pIter(t);
1820    if (t == NULL)
1821    {
1822      pNext(h) = NULL;
1823      return res;
1824    }
1825    h = pNext(h) = pInit();
1826  }
1827}
1828
1829static BOOLEAN smCheckLead(const poly t, const poly e)
1830{
1831  int i;
1832  for (i=pVariables; i; i--)
1833  {
1834    if ((pGetExp(e,i)+pGetExp(t,i)) < 0)
1835      return FALSE;
1836  }
1837  return TRUE;
1838}
1839
1840static poly smDMult(poly t, const poly e)
1841{
1842  const number y = pGetCoeff(e);
1843  number x;
1844  poly res, h, r;
1845  int i;
1846  EXPONENT_TYPE w;
1847
1848  r = h = res = pInit();
1849  loop
1850  {
1851    x = pGetCoeff(t);
1852    for (i=pVariables; i; i--)
1853    {
1854      w = pGetExp(e,i)+pGetExp(t,i);
1855      if (w < 0) break;
1856      pSetExp(h,i,w);
1857    }
1858    pIter(t);
1859    if (i == 0)
1860    {
1861      //pSetComp(h,0);
1862      pSetm(h);
1863      pSetCoeff0(h,nMult(y,x));
1864      if (t == NULL)
1865      {
1866        pNext(h) = NULL;
1867        return res;
1868      }
1869      r = h;
1870      h = pNext(h) = pInit();
1871    }
1872    else if (t == NULL)
1873    {
1874      if (r != h)
1875        pNext(r) = NULL;
1876      else
1877        res = NULL;
1878      pFree1(h);
1879      return res;
1880    }
1881  }
1882}
1883
1884static void smPolyDivN(poly a, const number x)
1885{
1886  number y;
1887
1888  do
1889  {
1890    y = nDiv(pGetCoeff(a),x);
1891    nNormalize(y);
1892    pSetCoeff(a,y);
1893    pIter(a);
1894  } while (a != NULL);
1895}
1896
1897static BOOLEAN smSmaller(poly a, poly b)
1898{
1899  loop
1900  {
1901    pIter(b);
1902    if (b == NULL) return TRUE;
1903    pIter(a);
1904    if (a == NULL) return FALSE;
1905  }
1906}
1907
1908static void smCombineChain(poly *px, poly r)
1909{
1910  poly pa = *px, pb;
1911  number x;
1912  int i;
1913
1914  loop
1915  {
1916    pb = pNext(pa);
1917    if (pb == NULL)
1918    {
1919      pa = pNext(pa) = r;
1920      break;
1921    }
1922    i = pComp0(pb, r);
1923    if (i > 0)
1924      pa = pb;
1925    else
1926    {
1927      if (i == 0)
1928      {
1929        x = nAdd(pGetCoeff(pb), pGetCoeff(r));
1930        pDelete1(&r);
1931        if (nIsZero(x))
1932        {
1933          pDelete1(&pb);
1934          pNext(pa) = pAdd(pb,r);
1935        }
1936        else
1937        {
1938          pa = pb;
1939          pSetCoeff(pa,x);
1940          pNext(pa) = pAdd(pNext(pa), r);
1941        }
1942      }
1943      else
1944      {
1945        pa = pNext(pa) = r;
1946        pNext(pa) = pAdd(pb, pNext(pa));
1947      }
1948      break;
1949    }
1950  }
1951  *px = pa;
1952}
1953
1954static void smFindRef(poly *ref, poly *px, poly r)
1955{
1956  number x;
1957  int i;
1958  poly pa = *px, pp = NULL;
1959
1960  loop
1961  {
1962    i = pComp0(pa, r);
1963    if (i > 0)
1964    {
1965      pp = pa;
1966      pIter(pa);
1967      if (pa==NULL)
1968      {
1969        pNext(pp) = r;
1970        break;
1971      }
1972    }
1973    else
1974    {
1975      if (i == 0)
1976      {
1977        x = nAdd(pGetCoeff(pa), pGetCoeff(r));
1978        pDelete1(&r);
1979        if (nIsZero(x))
1980        {
1981          pDelete1(&pa);
1982          if (pp!=NULL)
1983            pNext(pp) = pAdd(pa,r);
1984          else
1985            *px = pAdd(pa,r);
1986        }
1987        else
1988        {
1989          pp = pa;
1990          pSetCoeff(pp,x);
1991          pNext(pp) = pAdd(pNext(pp), r);
1992        }
1993      }
1994      else
1995      {
1996        if (pp!=NULL)
1997          pp = pNext(pp) = r;
1998        else
1999          *px = pp = r;
2000        pNext(pp) = pAdd(pa, pNext(r));
2001      }
2002      break;
2003    }
2004  }
2005  *ref = pp;
2006}
2007
2008/* ----------------- internal 'C' stuff ------------------ */
2009
2010static void smElemDelete(smpoly *r)
2011{
2012  smpoly a = *r, b = a->n;
2013
2014  pDelete(&a->m);
2015  Free((void *)a, sizeof(smprec));
2016  *r = b;
2017}
2018
2019static smpoly smElemCopy(smpoly a)
2020{
2021  smpoly r = (smpoly)Alloc(sizeof(smprec));
2022
2023  memcpy(r, a, sizeof(smprec));
2024/*  r->m = pCopy(r->m); */
2025  return r;
2026}
2027
2028/*
2029* from poly to smpoly
2030* do not destroy p
2031*/
2032static smpoly smPoly2Smpoly(poly q)
2033{
2034  poly pp;
2035  smpoly res, a;
2036  EXPONENT_TYPE x;
2037
2038  if (q == NULL)
2039    return NULL;
2040  a = res = (smpoly)Alloc(sizeof(smprec));
2041  a->pos = x = pGetComp(q);
2042  a->m = q;
2043  a->e = 0;
2044  loop
2045  {
2046    pSetComp(q,0);
2047    pp = q;
2048    pIter(q);
2049    if (q == NULL)
2050    {
2051      a->n = NULL;
2052      return res;
2053    }
2054    if (pGetComp(q) != x)
2055    {
2056      a = a->n = (smpoly)Alloc(sizeof(smprec));
2057      pNext(pp) = NULL;
2058      a->pos = x = pGetComp(q);
2059      a->m = q;
2060      a->e = 0;
2061    }
2062  }
2063}
2064
2065/*
2066* from smpoly to poly
2067* destroy a
2068*/
2069static poly smSmpoly2Poly(smpoly a)
2070{
2071  smpoly b;
2072  poly res, pp, q;
2073  EXPONENT_TYPE x;
2074
2075  if (a == NULL)
2076    return NULL;
2077  x = a->pos;
2078  q = res = a->m;
2079  loop
2080  {
2081    pSetComp(q,x);
2082    pp = q;
2083    pIter(q);
2084    if (q == NULL)
2085      break;
2086  }
2087  loop
2088  {
2089    b = a;
2090    a = a->n;
2091    Free((void *)b, sizeof(smprec));
2092    if (a == NULL)
2093      return res;
2094    x = a->pos;
2095    q = pNext(pp) = a->m;
2096    loop
2097    {
2098      pSetComp(q,x);
2099      pp = q;
2100      pIter(q);
2101      if (q == NULL)
2102        break;
2103    }
2104  }
2105}
2106
2107/*
2108* weigth of a polynomial, for pivot strategy
2109*/
2110static float smPolyWeight(smpoly a)
2111{
2112  poly p = a->m;
2113  int i;
2114  float res = (float)nSize(pGetCoeff(p));
2115
2116  if (pNext(p) == NULL)
2117  {
2118    for(i=pVariables; i>0; i--)
2119    {
2120      if (pGetExp(p,i) != 0) return res+1.0;
2121    }
2122    return res;
2123  }
2124  else
2125  {
2126    i = 0;
2127    res = 0.0;
2128    do
2129    {
2130      i++;
2131      res += (float)nSize(pGetCoeff(p));
2132      pIter(p);
2133    }
2134    while (p);
2135    return res+(float)i;
2136  }
2137}
2138
Note: See TracBrowser for help on using the repository browser.