source: git/Singular/sparsmat.cc @ 416465

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