source: git/kernel/sparsmat.cc @ a24e0a

spielwiese
Last change on this file since a24e0a was a24e0a, checked in by Hans Schoenemann <hannes@…>, 13 years ago
remove static forward decl. git-svn-id: file:///usr/local/Singular/svn/trunk@14416 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 53.1 KB
Line 
1/****************************************
2*  Computer Algebra System SINGULAR     *
3****************************************/
4/* $Id$ */
5
6/*
7* ABSTRACT: operations with sparse matrices (bareiss, ...)
8*/
9
10#include <kernel/mod2.h>
11#include <kernel/options.h>
12#include <kernel/febase.h>
13#include <kernel/intvec.h>
14#include <kernel/ring.h>
15#include <kernel/polys.h>
16#include <kernel/ideals.h>
17#include <kernel/numbers.h>
18#include <kernel/sparsmat.h>
19#include <kernel/prCopy.h>
20#include <kernel/p_Procs.h>
21#include <kernel/kbuckets.h>
22#include <kernel/p_Mult_q.h>
23
24// define SM_NO_BUCKETS, if sparsemat stuff should not use buckets
25// #define SM_NO_BUCKETS
26
27// this is also influenced by TEST_OPT_NOTBUCKETS
28#ifndef SM_NO_BUCKETS
29// buckets do carry a small additional overhead: only use them if
30// min-length of polys is >= SM_MIN_LENGTH_BUCKET
31#define SM_MIN_LENGTH_BUCKET MIN_LENGTH_BUCKET - 5
32#else
33#define SM_MIN_LENGTH_BUCKET    INT_MAX
34#endif
35
36typedef struct smprec sm_prec;
37typedef sm_prec * smpoly;
38struct smprec
39{
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
48omBin smprec_bin = omGetSpecBin(sizeof(smprec));
49
50static void smExpMultDiv(poly t, const poly b, const poly c)
51{
52  int i;
53  pTest(t);
54  pLmTest(b);
55  pLmTest(c);
56  poly bc = p_New(currRing);
57
58  p_ExpVectorDiff(bc, b, c, currRing);
59
60  while(t!=NULL)
61  {
62    pExpVectorAdd(t, bc);
63    pIter(t);
64  }
65  p_LmFree(bc, currRing);
66}
67
68static poly pp_Mult_Coeff_mm_DivSelect_MultDiv(poly p, int &lp, poly m,
69                                               poly a, poly b)
70{
71  if (rOrd_is_Comp_dp(currRing) && currRing->ExpL_Size > 2)
72  {
73    // pp_Mult_Coeff_mm_DivSelectMult only works for (c/C,dp) and
74    // ExpL_Size > 2
75    // should be generalized, at least to dp with ExpL_Size == 2
76    // (is the case for 1 variable)
77    int shorter;
78    p = currRing->p_Procs->pp_Mult_Coeff_mm_DivSelectMult(p, m, a, b,
79                                                          shorter, currRing);
80    lp -= shorter;
81  }
82  else
83  {
84    p = pp_Mult_Coeff_mm_DivSelect(p, lp, m, currRing);
85    smExpMultDiv(p, a, b);
86  }
87  return p;
88}
89
90static poly smSelectCopy_ExpMultDiv(poly p, poly m, poly a, poly b)
91{
92  int lp = 0;
93  return pp_Mult_Coeff_mm_DivSelect_MultDiv(p, lp, m, a, b);
94}
95
96
97/* class for sparse matrix:
98*      3 parts of matrix during the algorithm
99*      m_act[cols][pos(rows)] => m_row[rows][pos(cols)] => m_res[cols][pos(rows)]
100*      input                     pivotcols as rows         result
101*      pivot                     like a stack              from pivot and pivotcols
102*      elimination                                         rows reordered according
103*                                                          to pivot choise
104*                                                          stored in perm
105*      a step is as follows
106*      - search of pivot (smPivot)
107*      - swap pivot column and last column (smSwapC)
108*        select pivotrow to piv and red (smSelectPR)
109*        consider sign
110*      - elimination (smInitElim, sm0Elim, sm1Elim)
111*        clear zero column as result of elimination (smZeroElim)
112*      - tranfer from
113*        piv and m_row to m_res (smRowToCol)
114*        m_act to m_row (smColToRow)
115*/
116class sparse_mat{
117private:
118  int nrows, ncols;    // dimension of the problem
119  int sign;            // for determinant (start: 1)
120  int act;             // number of unreduced columns (start: ncols)
121  int crd;             // number of reduced columns (start: 0)
122  int tored;           // border for rows to reduce
123  int inred;           // unreducable part
124  int rpiv, cpiv;      // position of the pivot
125  int normalize;       // Normalization flag
126  int *perm;           // permutation of rows
127  float wpoints;       // weight of all points
128  float *wrw, *wcl;    // weights of rows and columns
129  smpoly * m_act;      // unreduced columns
130  smpoly * m_res;      // reduced columns (result)
131  smpoly * m_row;      // reduced part of rows
132  smpoly red;          // row to reduce
133  smpoly piv, oldpiv;  // pivot and previous pivot
134  smpoly dumm;         // allocated dummy
135  void smColToRow();
136  void smRowToCol();
137  void smFinalMult();
138  void smSparseHomog();
139  void smWeights();
140  void smPivot();
141  void smNewWeights();
142  void smNewPivot();
143  void smZeroElim();
144  void smToredElim();
145  void smCopToRes();
146  void smSelectPR();
147  void sm1Elim();
148  void smHElim();
149  void smMultCol();
150  poly smMultPoly(smpoly);
151  void smActDel();
152  void smColDel();
153  void smPivDel();
154  void smSign();
155  void smInitPerm();
156  int smCheckNormalize();
157  void smNormalize();
158public:
159  sparse_mat(ideal);
160  ~sparse_mat();
161  int smGetSign() { return sign; }
162  smpoly * smGetAct() { return m_act; }
163  int smGetRed() { return tored; }
164  ideal smRes2Mod();
165  poly smDet();
166  void smNewBareiss(int, int);
167  void smToIntvec(intvec *);
168};
169
170/*
171* estimate maximal exponent for det or minors,
172* the module m has di vectors and maximal rank ra,
173* estimate yields for the tXt minors,
174* we have di,ra >= t
175*/
176static void smMinSelect(long *, int, int);
177long smExpBound( ideal m, int di, int ra, int t)
178{
179  poly p;
180  long kr, kc;
181  long *r, *c;
182  int al, bl, i, j, k;
183
184  if (ra==0) ra=1;
185  al = di*sizeof(long);
186  c = (long *)omAlloc(al);
187  bl = ra*sizeof(long);
188  r = (long *)omAlloc0(bl);
189  for (i=di-1;i>=0;i--)
190  {
191    kc = 0;
192    p = m->m[i];
193    while(p!=NULL)
194    {
195      k = pGetComp(p)-1;
196      kr = r[k];
197      for (j=pVariables;j>0;j--)
198      {
199        if(pGetExp(p,j)>kc)
200          kc=pGetExp(p,j);
201        if(pGetExp(p,j)>kr)
202          kr=pGetExp(p,j);
203      }
204      r[k] = kr;
205      pIter(p);
206    }
207    c[i] = kc;
208  }
209  if (t<di) smMinSelect(c, t, di);
210  if (t<ra) smMinSelect(r, t, ra);
211  kr = kc = 0;
212  for (j=t-1;j>=0;j--)
213  {
214    kr += r[j];
215    kc += c[j];
216  }
217  omFreeSize((ADDRESS)c, al);
218  omFreeSize((ADDRESS)r, bl);
219  if (kr<kc) kc = kr;
220  if (kr<1) kr = 1;
221  return kr;
222}
223
224static void smMinSelect(long *c, int t, int d)
225{
226  long m;
227  int pos, i;
228  do
229  {
230    d--;
231    pos = d;
232    m = c[pos];
233    for (i=d-1;i>=0;i--)
234    {
235      if(c[i]<m)
236      {
237        pos = i;
238        m = c[i];
239      }
240    }
241    for (i=pos;i<d;i++) c[i] = c[i+1];
242  } while (d>t);
243}
244
245/* ----------------- ops with rings ------------------ */
246ring smRingChange(ring *origR, long bound)
247{
248  *origR =currRing;
249  ring tmpR=rCopy0(currRing,FALSE,FALSE);
250  int *ord=(int*)omAlloc0(3*sizeof(int));
251  int *block0=(int*)omAlloc(3*sizeof(int));
252  int *block1=(int*)omAlloc(3*sizeof(int));
253  ord[0]=ringorder_c;
254  ord[1]=ringorder_dp;
255  tmpR->order=ord;
256  tmpR->OrdSgn=1;
257  block0[1]=1;
258  tmpR->block0=block0;
259  block1[1]=tmpR->N;
260  tmpR->block1=block1;
261  tmpR->bitmask = 2*bound;
262  tmpR->wvhdl = (int **)omAlloc0((3) * sizeof(int_ptr));
263
264// ???
265//  if (tmpR->bitmask > currRing->bitmask) tmpR->bitmask = currRing->bitmask;
266
267  rComplete(tmpR,1);
268  if ((*origR)->qideal!=NULL)
269  {
270    tmpR->qideal= idrCopyR_NoSort((*origR)->qideal, (*origR), tmpR);
271  }
272  rChangeCurrRing(tmpR);
273  if (TEST_OPT_PROT)
274    Print("[%ld:%d]", (long) tmpR->bitmask, tmpR->ExpL_Size);
275  return tmpR;
276}
277
278void smKillModifiedRing(ring r)
279{
280  if (r->qideal!=NULL) id_Delete(&(r->qideal),r);
281  rKillModifiedRing(r);
282}
283
284/*2
285* Bareiss or Chinese remainder ?
286* I is dXd
287* sw = TRUE  -> I Matrix
288*      FALSE -> I Module
289* return True  -> change Type
290*        FALSE -> same Type
291*/
292BOOLEAN smCheckDet(ideal I, int d, BOOLEAN sw)
293{
294  int s,t,i;
295  poly p;
296
297  if ((d>100) || (currRing->parameter!=NULL))
298    return sw;
299  if (rField_is_Q(currRing)==FALSE)
300    return sw;
301  s = t = 0;
302  if (sw)
303  {
304    for(i=IDELEMS(I)-1;i>=0;i--)
305    {
306      p=I->m[i];
307      if (p!=NULL)
308      {
309        if(!pIsConstant(p))
310          return sw;
311        s++;
312        t+=nSize(pGetCoeff(p));
313      }
314    }
315  }
316  else
317  {
318    for(i=IDELEMS(I)-1;i>=0;i--)
319    {
320      p=I->m[i];
321      if (!pIsConstantPoly(p))
322        return sw;
323      while (p!=NULL)
324      {
325        s++;
326        t+=nSize(pGetCoeff(p));
327        pIter(p);
328      }
329    }
330  }
331  s*=15;
332  if (t>s)
333    return !sw;
334  else
335    return sw;
336}
337
338/* ----------------- basics (used from 'C') ------------------ */
339static BOOLEAN smHaveDenom(poly a)
340{
341  BOOLEAN sw;
342  number x;
343
344  while (a != NULL)
345  {
346    x = nGetDenom(pGetCoeff(a));
347    sw = nIsOne(x);
348    nDelete(&x);
349    if (!sw)
350    {
351      return TRUE;
352    }
353    pIter(a);
354  }
355  return FALSE;
356}
357
358static number smCleardenom(ideal id)
359{
360  poly a;
361  number x,y,res=nInit(1);
362  BOOLEAN sw=FALSE;
363
364  for (int i=0; i<IDELEMS(id); i++)
365  {
366    a = id->m[i];
367    sw = smHaveDenom(a);
368    if (sw) break;
369  }
370  if (!sw) return res;
371  for (int i=0; i<IDELEMS(id); i++)
372  {
373    a = id->m[i];
374    if (a!=NULL)
375    {
376      x = nCopy(pGetCoeff(a));
377      p_Cleardenom(a, currRing);
378      y = nDiv(x,pGetCoeff(a));
379      nDelete(&x);
380      x = nMult(res,y);
381      nNormalize(x);
382      nDelete(&res);
383      res = x;
384    }
385  }
386  return res;
387}
388
389/*2
390*returns the determinant of the module I;
391*uses Bareiss algorithm
392*/
393poly smCallDet(ideal I)
394{
395  if (I->ncols != I->rank)
396  {
397    Werror("det of %ld x %d module (matrix)",I->rank,I->ncols);
398    return NULL;
399  }
400  int r=idRankFreeModule(I);
401  if (I->ncols != r) // some 0-lines at the end
402  {
403    return NULL;
404  }
405  long bound=smExpBound(I,r,r,r);
406  number diag,h=nInit(1);
407  poly res;
408  ring origR;
409  ring tmpR;
410  sparse_mat *det;
411  ideal II;
412
413  tmpR=smRingChange(&origR,bound);
414  II = idrCopyR(I, origR);
415  diag = smCleardenom(II);
416  det = new sparse_mat(II);
417  idDelete(&II);
418  if (det->smGetAct() == NULL)
419  {
420    delete det;
421    rChangeCurrRing(origR);
422    smKillModifiedRing(tmpR);
423    return NULL;
424  }
425  res=det->smDet();
426  if(det->smGetSign()<0) res=pNeg(res);
427  delete det;
428  rChangeCurrRing(origR);
429  res = prMoveR(res, tmpR);
430  smKillModifiedRing(tmpR);
431  if (nEqual(diag,h) == FALSE)
432  {
433    pMult_nn(res,diag);
434    pNormalize(res);
435  }
436  nDelete(&diag);
437  nDelete(&h);
438  return res;
439}
440
441void smCallBareiss(ideal I, int x, int y, ideal & M, intvec **iv)
442{
443  int r=idRankFreeModule(I),t=r;
444  int c=IDELEMS(I),s=c;
445  long bound;
446  ring origR;
447  ring tmpR;
448  sparse_mat *bareiss;
449
450  if ((x>0) && (x<t))
451    t-=x;
452  if ((y>1) && (y<s))
453    s-=y;
454  if (t>s) t=s;
455  bound=smExpBound(I,c,r,t);
456  tmpR=smRingChange(&origR,bound);
457  ideal II = idrCopyR(I, origR);
458  bareiss = new sparse_mat(II);
459  if (bareiss->smGetAct() == NULL)
460  {
461    delete bareiss;
462    *iv=new intvec(1,pVariables);
463    rChangeCurrRing(origR);
464  }
465  else
466  {
467    idDelete(&II);
468    bareiss->smNewBareiss(x, y);
469    II = bareiss->smRes2Mod();
470    *iv = new intvec(bareiss->smGetRed());
471    bareiss->smToIntvec(*iv);
472    delete bareiss;
473    rChangeCurrRing(origR);
474    II = idrMoveR(II,tmpR);
475  }
476  smKillModifiedRing(tmpR);
477  M=II;
478}
479
480/*
481* from poly to smpoly
482* do not destroy p
483*/
484static smpoly smPoly2Smpoly(poly q)
485{
486  poly pp;
487  smpoly res, a;
488  long x;
489
490  if (q == NULL)
491    return NULL;
492  a = res = (smpoly)omAllocBin(smprec_bin);
493  a->pos = x = pGetComp(q);
494  a->m = q;
495  a->e = 0;
496  loop
497  {
498    pSetComp(q,0);
499    pp = q;
500    pIter(q);
501    if (q == NULL)
502    {
503      a->n = NULL;
504      return res;
505    }
506    if (pGetComp(q) != x)
507    {
508      a = a->n = (smpoly)omAllocBin(smprec_bin);
509      pNext(pp) = NULL;
510      a->pos = x = pGetComp(q);
511      a->m = q;
512      a->e = 0;
513    }
514  }
515}
516
517/*
518* constructor
519*/
520sparse_mat::sparse_mat(ideal smat)
521{
522  int i;
523  polyset pmat;
524
525  ncols = smat->ncols;
526  nrows = idRankFreeModule(smat);
527  if (nrows <= 0)
528  {
529    m_act = NULL;
530    return;
531  }
532  sign = 1;
533  inred = act = ncols;
534  crd = 0;
535  tored = nrows; // without border
536  i = tored+1;
537  perm = (int *)omAlloc(sizeof(int)*(i+1));
538  perm[i] = 0;
539  m_row = (smpoly *)omAlloc0(sizeof(smpoly)*i);
540  wrw = (float *)omAlloc(sizeof(float)*i);
541  i = ncols+1;
542  wcl = (float *)omAlloc(sizeof(float)*i);
543  m_act = (smpoly *)omAlloc(sizeof(smpoly)*i);
544  m_res = (smpoly *)omAlloc0(sizeof(smpoly)*i);
545  dumm = (smpoly)omAllocBin(smprec_bin);
546  m_res[0] = (smpoly)omAllocBin(smprec_bin);
547  m_res[0]->m = NULL;
548  pmat = smat->m;
549  for(i=ncols; i; i--)
550  {
551    m_act[i] = smPoly2Smpoly(pmat[i-1]);
552    pmat[i-1] = NULL;
553  }
554  this->smZeroElim();
555  oldpiv = NULL;
556}
557
558/*
559* destructor
560*/
561sparse_mat::~sparse_mat()
562{
563  int i;
564  if (m_act == NULL) return;
565  omFreeBin((ADDRESS)m_res[0],  smprec_bin);
566  omFreeBin((ADDRESS)dumm,  smprec_bin);
567  i = ncols+1;
568  omFreeSize((ADDRESS)m_res, sizeof(smpoly)*i);
569  omFreeSize((ADDRESS)m_act, sizeof(smpoly)*i);
570  omFreeSize((ADDRESS)wcl, sizeof(float)*i);
571  i = nrows+1;
572  omFreeSize((ADDRESS)wrw, sizeof(float)*i);
573  omFreeSize((ADDRESS)m_row, sizeof(smpoly)*i);
574  omFreeSize((ADDRESS)perm, sizeof(int)*(i+1));
575}
576
577/*
578* from smpoly to poly
579* destroy a
580*/
581static poly smSmpoly2Poly(smpoly a)
582{
583  smpoly b;
584  poly res, pp, q;
585  long x;
586
587  if (a == NULL)
588    return NULL;
589  x = a->pos;
590  q = res = a->m;
591  loop
592  {
593    pSetComp(q,x);
594    pp = q;
595    pIter(q);
596    if (q == NULL)
597      break;
598  }
599  loop
600  {
601    b = a;
602    a = a->n;
603    omFreeBin((void *)b,  smprec_bin);
604    if (a == NULL)
605      return res;
606    x = a->pos;
607    q = pNext(pp) = a->m;
608    loop
609    {
610      pSetComp(q,x);
611      pp = q;
612      pIter(q);
613      if (q == NULL)
614        break;
615    }
616  }
617}
618
619/*
620* transform the result to a module
621*/
622ideal sparse_mat::smRes2Mod()
623{
624  ideal res = idInit(crd, crd);
625  int i;
626
627  for (i=crd; i; i--) res->m[i-1] = smSmpoly2Poly(m_res[i]);
628  res->rank = idRankFreeModule(res);
629  return res;
630}
631
632/*
633* permutation of rows
634*/
635void sparse_mat::smToIntvec(intvec *v)
636{
637  int i;
638
639  for (i=v->rows()-1; i>=0; i--)
640    (*v)[i] = perm[i+1];
641}
642/* ---------------- the algorithm's ------------------ */
643/*
644* the determinant (up to sign), uses new Bareiss elimination
645*/
646poly sparse_mat::smDet()
647{
648  int y;
649  poly res = NULL;
650
651  if (sign == 0)
652  {
653    this->smActDel();
654    return NULL;
655  }
656  if (act < 2)
657  {
658    if (act != 0) res = m_act[1]->m;
659    omFreeBin((void *)m_act[1],  smprec_bin);
660    return res;
661  }
662  normalize = 0;
663  this->smInitPerm();
664  this->smPivot();
665  this->smSign();
666  this->smSelectPR();
667  this->sm1Elim();
668  crd++;
669  m_res[crd] = piv;
670  this->smColDel();
671  act--;
672  this->smZeroElim();
673  if (sign == 0)
674  {
675    this->smActDel();
676    return NULL;
677  }
678  if (act < 2)
679  {
680    this->smFinalMult();
681    this->smPivDel();
682    if (act != 0) res = m_act[1]->m;
683    omFreeBin((void *)m_act[1],  smprec_bin);
684    return res;
685  }
686  loop
687  {
688    this->smNewPivot();
689    this->smSign();
690    this->smSelectPR();
691    this->smMultCol();
692    this->smHElim();
693    crd++;
694    m_res[crd] = piv;
695    this->smColDel();
696    act--;
697    this->smZeroElim();
698    if (sign == 0)
699    {
700      this->smPivDel();
701      this->smActDel();
702      return NULL;
703    }
704    if (act < 2)
705    {
706      if (TEST_OPT_PROT) PrintS(".\n");
707      this->smFinalMult();
708      this->smPivDel();
709      if (act != 0) res = m_act[1]->m;
710      omFreeBin((void *)m_act[1],  smprec_bin);
711      return res;
712    }
713  }
714}
715
716/*
717* the new Bareiss elimination:
718*   - with x unreduced last rows, pivots from here are not allowed
719*   - the method will finish for number of unreduced columns < y
720*/
721void sparse_mat::smNewBareiss(int x, int y)
722{
723  if ((x > 0) && (x < nrows))
724  {
725    tored -= x;
726    this->smToredElim();
727  }
728  if (y < 1) y = 1;
729  if (act <= y)
730  {
731    this->smCopToRes();
732    return;
733  }
734  normalize = this->smCheckNormalize();
735  if (normalize) this->smNormalize();
736  this->smPivot();
737  this->smSelectPR();
738  this->sm1Elim();
739  crd++;
740  this->smColToRow();
741  act--;
742  this->smRowToCol();
743  this->smZeroElim();
744  if (tored != nrows)
745    this->smToredElim();
746  if (act <= y)
747  {
748    this->smFinalMult();
749    this->smCopToRes();
750    return;
751  }
752  loop
753  {
754    if (normalize) this->smNormalize();
755    this->smNewPivot();
756    this->smSelectPR();
757    this->smMultCol();
758    this->smHElim();
759    crd++;
760    this->smColToRow();
761    act--;
762    this->smRowToCol();
763    this->smZeroElim();
764    if (tored != nrows)
765      this->smToredElim();
766    if (act <= y)
767    {
768      if (TEST_OPT_PROT) PrintS(".\n");
769      this->smFinalMult();
770      this->smCopToRes();
771      return;
772    }
773  }
774}
775
776/* ----------------- pivot method ------------------ */
777
778/*
779* weigth of a polynomial, for pivot strategy
780*/
781static float smPolyWeight(smpoly a)
782{
783  poly p = a->m;
784  int i;
785  float res = (float)nSize(pGetCoeff(p));
786
787  if (pNext(p) == NULL)
788  {
789    for(i=pVariables; i>0; i--)
790    {
791      if (pGetExp(p,i) != 0) return res+1.0;
792    }
793    return res;
794  }
795  else
796  {
797    i = 0;
798    res = 0.0;
799    do
800    {
801      i++;
802      res += (float)nSize(pGetCoeff(p));
803      pIter(p);
804    }
805    while (p);
806    return res+(float)i;
807  }
808}
809
810/*
811* prepare smPivot, compute weights for rows and columns
812* and the weight for all points
813*/
814void sparse_mat::smWeights()
815{
816  float wc, wp, w;
817  smpoly a;
818  int i;
819
820  wp = 0.0;
821  for (i=tored; i; i--) wrw[i] = 0.0; // ???
822  for (i=act; i; i--)
823  {
824    wc = 0.0;
825    a = m_act[i];
826    loop
827    {
828      if (a->pos > tored)
829        break;
830      w = a->f = smPolyWeight(a);
831      wc += w;
832      wrw[a->pos] += w;
833      a = a->n;
834      if (a == NULL)
835        break;
836    }
837    wp += wc;
838    wcl[i] = wc;
839  }
840  wpoints = wp;
841}
842
843/*
844* compute pivot
845*/
846void sparse_mat::smPivot()
847{
848  float wopt = 1.0e30;
849  float wc, wr, wp, w;
850  smpoly a;
851  int i, copt, ropt;
852
853  this->smWeights();
854  for (i=act; i; i--)
855  {
856    a = m_act[i];
857    loop
858    {
859      if (a->pos > tored)
860        break;
861      w = a->f;
862      wc = wcl[i]-w;
863      wr = wrw[a->pos]-w;
864      if ((wr<0.25) || (wc<0.25)) // row or column with only one point
865      {
866        if (w<wopt)
867        {
868          wopt = w;
869          copt = i;
870          ropt = a->pos;
871        }
872      }
873      else // elimination
874      {
875        wp = w*(wpoints-wcl[i]-wr);
876        wp += wr*wc;
877        if (wp < wopt)
878        {
879          wopt = wp;
880          copt = i;
881          ropt = a->pos;
882        }
883      }
884      a = a->n;
885      if (a == NULL)
886        break;
887    }
888  }
889  rpiv = ropt;
890  cpiv = copt;
891  if (cpiv != act)
892  {
893    a = m_act[act];
894    m_act[act] = m_act[cpiv];
895    m_act[cpiv] = a;
896  }
897}
898
899/*
900* prepare smPivot, compute weights for rows and columns
901* and the weight for all points
902*/
903void sparse_mat::smNewWeights()
904{
905  float wc, wp, w, hp = piv->f;
906  smpoly a;
907  int i, f, e = crd;
908
909  wp = 0.0;
910  for (i=tored; i; i--) wrw[i] = 0.0; // ???
911  for (i=act; i; i--)
912  {
913    wc = 0.0;
914    a = m_act[i];
915    loop
916    {
917      if (a->pos > tored)
918        break;
919      w = a->f;
920      f = a->e;
921      if (f < e)
922      {
923        w *= hp;
924        if (f) w /= m_res[f]->f;
925      }
926      wc += w;
927      wrw[a->pos] += w;
928      a = a->n;
929      if (a == NULL)
930        break;
931    }
932    wp += wc;
933    wcl[i] = wc;
934  }
935  wpoints = wp;
936}
937
938/*
939* compute pivot
940*/
941void sparse_mat::smNewPivot()
942{
943  float wopt = 1.0e30, hp = piv->f;
944  float wc, wr, wp, w;
945  smpoly a;
946  int i, copt, ropt, f, e = crd;
947
948  this->smNewWeights();
949  for (i=act; i; i--)
950  {
951    a = m_act[i];
952    loop
953    {
954      if (a->pos > tored)
955        break;
956      w = a->f;
957      f = a->e;
958      if (f < e)
959      {
960        w *= hp;
961        if (f) w /= m_res[f]->f;
962      }
963      wc = wcl[i]-w;
964      wr = wrw[a->pos]-w;
965      if ((wr<0.25) || (wc<0.25)) // row or column with only one point
966      {
967        if (w<wopt)
968        {
969          wopt = w;
970          copt = i;
971          ropt = a->pos;
972        }
973      }
974      else // elimination
975      {
976        wp = w*(wpoints-wcl[i]-wr);
977        wp += wr*wc;
978        if (wp < wopt)
979        {
980          wopt = wp;
981          copt = i;
982          ropt = a->pos;
983        }
984      }
985      a = a->n;
986      if (a == NULL)
987        break;
988    }
989  }
990  rpiv = ropt;
991  cpiv = copt;
992  if (cpiv != act)
993  {
994    a = m_act[act];
995    m_act[act] = m_act[cpiv];
996    m_act[cpiv] = a;
997  }
998}
999
1000/* ----------------- elimination ------------------ */
1001static void smElemDelete(smpoly *r)
1002{
1003  smpoly a = *r, b = a->n;
1004
1005  pDelete(&a->m);
1006  omFreeBin((void *)a,  smprec_bin);
1007  *r = b;
1008}
1009
1010static smpoly smElemCopy(smpoly a)
1011{
1012  smpoly r = (smpoly)omAllocBin(smprec_bin);
1013  memcpy(r, a, sizeof(smprec));
1014/*  r->m = pCopy(r->m); */
1015  return r;
1016}
1017
1018/* first step of elimination */
1019void sparse_mat::sm1Elim()
1020{
1021  poly p = piv->m;        // pivotelement
1022  smpoly c = m_act[act];  // pivotcolumn
1023  smpoly r = red;         // row to reduce
1024  smpoly res, a, b;
1025  poly w, ha, hb;
1026
1027  if ((c == NULL) || (r == NULL))
1028  {
1029    while (r!=NULL) smElemDelete(&r);
1030    return;
1031  }
1032  do
1033  {
1034    a = m_act[r->pos];
1035    res = dumm;
1036    res->n = NULL;
1037    b = c;
1038    w = r->m;
1039    loop                  // combine the chains a and b: p*a + w*b
1040    {
1041      if (a == NULL)
1042      {
1043        do
1044        {
1045          res = res->n = smElemCopy(b);
1046          res->m = ppMult_qq(b->m, w);
1047          res->e = 1;
1048          res->f = smPolyWeight(res);
1049          b = b->n;
1050        } while (b != NULL);
1051        break;
1052      }
1053      if (a->pos < b->pos)
1054      {
1055        res = res->n = a;
1056        a = a->n;
1057      }
1058      else if (a->pos > b->pos)
1059      {
1060        res = res->n = smElemCopy(b);
1061        res->m = ppMult_qq(b->m, w);
1062        res->e = 1;
1063        res->f = smPolyWeight(res);
1064        b = b->n;
1065      }
1066      else
1067      {
1068        ha = ppMult_qq(a->m, p);
1069        pDelete(&a->m);
1070        hb = ppMult_qq(b->m, w);
1071        ha = pAdd(ha, hb);
1072        if (ha != NULL)
1073        {
1074          a->m = ha;
1075          a->e = 1;
1076          a->f = smPolyWeight(a);
1077          res = res->n = a;
1078          a = a->n;
1079        }
1080        else
1081        {
1082          smElemDelete(&a);
1083        }
1084        b = b->n;
1085      }
1086      if (b == NULL)
1087      {
1088        res->n = a;
1089        break;
1090      }
1091    }
1092    m_act[r->pos] = dumm->n;
1093    smElemDelete(&r);
1094  } while (r != NULL);
1095}
1096
1097/* higher steps of elimination */
1098void sparse_mat::smHElim()
1099{
1100  poly hp = this->smMultPoly(piv);
1101  poly gp = piv->m;       // pivotelement
1102  smpoly c = m_act[act];  // pivotcolumn
1103  smpoly r = red;         // row to reduce
1104  smpoly res, a, b;
1105  poly ha, hr, x, y;
1106  int e, ip, ir, ia, lev;
1107
1108  if ((c == NULL) || (r == NULL))
1109  {
1110    while(r!=NULL) smElemDelete(&r);
1111    pDelete(&hp);
1112    return;
1113  }
1114  e = crd+1;
1115  ip = piv->e;
1116  do
1117  {
1118    a = m_act[r->pos];
1119    res = dumm;
1120    res->n = NULL;
1121    b = c;
1122    hr = r->m;
1123    ir = r->e;
1124    loop                  // combine the chains a and b: (hp,gp)*a(l) + hr*b(h)
1125    {
1126      if (a == NULL)
1127      {
1128        do
1129        {
1130          res = res->n = smElemCopy(b);
1131          x = SM_MULT(b->m, hr, m_res[ir]->m);
1132          b = b->n;
1133          if(ir) SM_DIV(x, m_res[ir]->m);
1134          res->m = x;
1135          res->e = e;
1136          res->f = smPolyWeight(res);
1137        } while (b != NULL);
1138        break;
1139      }
1140      if (a->pos < b->pos)
1141      {
1142        res = res->n = a;
1143        a = a->n;
1144      }
1145      else if (a->pos > b->pos)
1146      {
1147        res = res->n = smElemCopy(b);
1148        x = SM_MULT(b->m, hr, m_res[ir]->m);
1149        b = b->n;
1150        if(ir) SM_DIV(x, m_res[ir]->m);
1151        res->m = x;
1152        res->e = e;
1153        res->f = smPolyWeight(res);
1154      }
1155      else
1156      {
1157        ha = a->m;
1158        ia = a->e;
1159        if (ir >= ia)
1160        {
1161          if (ir > ia)
1162          {
1163            x = SM_MULT(ha, m_res[ir]->m, m_res[ia]->m);
1164            pDelete(&ha);
1165            ha = x;
1166            if (ia) SM_DIV(ha, m_res[ia]->m);
1167            ia = ir;
1168          }
1169          x = SM_MULT(ha, gp, m_res[ia]->m);
1170          pDelete(&ha);
1171          y = SM_MULT(b->m, hr, m_res[ia]->m);
1172        }
1173        else if (ir >= ip)
1174        {
1175          if (ia < crd)
1176          {
1177            x = SM_MULT(ha, m_res[crd]->m, m_res[ia]->m);
1178            pDelete(&ha);
1179            ha = x;
1180            SM_DIV(ha, m_res[ia]->m);
1181          }
1182          y = hp;
1183          if(ir > ip)
1184          {
1185            y = SM_MULT(y, m_res[ir]->m, m_res[ip]->m);
1186            if (ip) SM_DIV(y, m_res[ip]->m);
1187          }
1188          ia = ir;
1189          x = SM_MULT(ha, y, m_res[ia]->m);
1190          if (y != hp) pDelete(&y);
1191          pDelete(&ha);
1192          y = SM_MULT(b->m, hr, m_res[ia]->m);
1193        }
1194        else
1195        {
1196          x = SM_MULT(hr, m_res[ia]->m, m_res[ir]->m);
1197          if (ir) SM_DIV(x, m_res[ir]->m);
1198          y = SM_MULT(b->m, x, m_res[ia]->m);
1199          pDelete(&x);
1200          x = SM_MULT(ha, gp, m_res[ia]->m);
1201          pDelete(&ha);
1202        }
1203        ha = pAdd(x, y);
1204        if (ha != NULL)
1205        {
1206          if (ia) SM_DIV(ha, m_res[ia]->m);
1207          a->m = ha;
1208          a->e = e;
1209          a->f = smPolyWeight(a);
1210          res = res->n = a;
1211          a = a->n;
1212        }
1213        else
1214        {
1215          a->m = NULL;
1216          smElemDelete(&a);
1217        }
1218        b = b->n;
1219      }
1220      if (b == NULL)
1221      {
1222        res->n = a;
1223        break;
1224      }
1225    }
1226    m_act[r->pos] = dumm->n;
1227    smElemDelete(&r);
1228  } while (r != NULL);
1229  pDelete(&hp);
1230}
1231
1232/* ----------------- transfer ------------------ */
1233
1234/*
1235* select the pivotrow and store it to red and piv
1236*/
1237void sparse_mat::smSelectPR()
1238{
1239  smpoly b = dumm;
1240  smpoly a, ap;
1241  int i;
1242
1243  if (TEST_OPT_PROT)
1244  {
1245    if ((crd+1)%10)
1246      PrintS(".");
1247    else
1248      PrintS(".\n");
1249  }
1250  a = m_act[act];
1251  if (a->pos < rpiv)
1252  {
1253    do
1254    {
1255      ap = a;
1256      a = a->n;
1257    } while (a->pos < rpiv);
1258    ap->n = a->n;
1259  }
1260  else
1261    m_act[act] = a->n;
1262  piv = a;
1263  a->n = NULL;
1264  for (i=1; i<act; i++)
1265  {
1266    a = m_act[i];
1267    if (a->pos < rpiv)
1268    {
1269      loop
1270      {
1271        ap = a;
1272        a = a->n;
1273        if ((a == NULL) || (a->pos > rpiv))
1274          break;
1275        if (a->pos == rpiv)
1276        {
1277          ap->n = a->n;
1278          a->m = pNeg(a->m);
1279          b = b->n = a;
1280          b->pos = i;
1281          break;
1282        }
1283      }
1284    }
1285    else if (a->pos == rpiv)
1286    {
1287      m_act[i] = a->n;
1288      a->m = pNeg(a->m);
1289      b = b->n = a;
1290      b->pos = i;
1291    }
1292  }
1293  b->n = NULL;
1294  red = dumm->n;
1295}
1296
1297/*
1298* store the pivotcol in m_row
1299*   m_act[cols][pos(rows)] => m_row[rows][pos(cols)]
1300*/
1301void sparse_mat::smColToRow()
1302{
1303  smpoly c = m_act[act];
1304  smpoly h;
1305
1306  while (c != NULL)
1307  {
1308    h = c;
1309    c = c->n;
1310    h->n = m_row[h->pos];
1311    m_row[h->pos] = h;
1312    h->pos = crd;
1313  }
1314}
1315
1316/*
1317* store the pivot and the assosiated row in m_row
1318* to m_res (result):
1319*   piv + m_row[rows][pos(cols)] => m_res[cols][pos(rows)]
1320*/
1321void sparse_mat::smRowToCol()
1322{
1323  smpoly r = m_row[rpiv];
1324  smpoly a, ap, h;
1325
1326  m_row[rpiv] = NULL;
1327  perm[crd] = rpiv;
1328  piv->pos = crd;
1329  m_res[crd] = piv;
1330  while (r != NULL)
1331  {
1332    ap = m_res[r->pos];
1333    loop
1334    {
1335      a = ap->n;
1336      if (a == NULL)
1337      {
1338        ap->n = h = r;
1339        r = r->n;
1340        h->n = a;
1341        h->pos = crd;
1342        break;
1343      }
1344      ap = a;
1345    }
1346  }
1347}
1348
1349/* ----------------- C++ stuff ------------------ */
1350
1351/*
1352*  clean m_act from zeros (after elim)
1353*/
1354void sparse_mat::smZeroElim()
1355{
1356  int i = 0;
1357  int j;
1358
1359  loop
1360  {
1361    i++;
1362    if (i > act) return;
1363    if (m_act[i] == NULL) break;
1364  }
1365  j = i;
1366  loop
1367  {
1368    j++;
1369    if (j > act) break;
1370    if (m_act[j] != NULL)
1371    {
1372      m_act[i] = m_act[j];
1373      i++;
1374    }
1375  }
1376  act -= (j-i);
1377  sign = 0;
1378}
1379
1380/*
1381*  clean m_act from cols not to reduced (after elim)
1382*  put them to m_res
1383*/
1384void sparse_mat::smToredElim()
1385{
1386  int i = 0;
1387  int j;
1388
1389  loop
1390  {
1391    i++;
1392    if (i > act) return;
1393    if (m_act[i]->pos > tored)
1394    {
1395      m_res[inred] = m_act[i];
1396      inred--;
1397      break;
1398    }
1399  }
1400  j = i;
1401  loop
1402  {
1403    j++;
1404    if (j > act) break;
1405    if (m_act[j]->pos > tored)
1406    {
1407      m_res[inred] = m_act[j];
1408      inred--;
1409    }
1410    else
1411    {
1412      m_act[i] = m_act[j];
1413      i++;
1414    }
1415  }
1416  act -= (j-i);
1417  sign = 0;
1418}
1419
1420/*
1421*  copy m_act to m_res
1422*/
1423void sparse_mat::smCopToRes()
1424{
1425  smpoly a,ap,r,h;
1426  int i,j,k,l;
1427
1428  i = 0;
1429  if (act)
1430  {
1431    a = m_act[act]; // init perm
1432    do
1433    {
1434      i++;
1435      perm[crd+i] = a->pos;
1436      a = a->n;
1437    } while ((a != NULL) && (a->pos <= tored));
1438    for (j=act-1;j;j--) // load all positions of perm
1439    {
1440      a = m_act[j];
1441      k = 1;
1442      loop
1443      {
1444        if (perm[crd+k] >= a->pos)
1445        {
1446          if (perm[crd+k] > a->pos)
1447          {
1448            for (l=i;l>=k;l--) perm[crd+l+1] = perm[crd+l];
1449            perm[crd+k] = a->pos;
1450            i++;
1451          }
1452          a = a->n;
1453          if ((a == NULL) || (a->pos > tored)) break;
1454        }
1455        k++;
1456        if ((k > i) && (a->pos <= tored))
1457        {
1458          do
1459          {
1460            i++;
1461            perm[crd+i] = a->pos;
1462            a = a->n;
1463          } while ((a != NULL) && (a->pos <= tored));
1464          break;
1465        }
1466      }
1467    }
1468  }
1469  for (j=act;j;j--) // renumber m_act
1470  {
1471    k = 1;
1472    a = m_act[j];
1473    while ((a != NULL) && (a->pos <= tored))
1474    {
1475      if (perm[crd+k] == a->pos)
1476      {
1477        a->pos = crd+k;
1478        a = a->n;
1479      }
1480      k++;
1481    }
1482  }
1483  tored = crd+i;
1484  for(k=1;k<=i;k++) // clean this from m_row
1485  {
1486    j = perm[crd+k];
1487    if (m_row[j] != NULL)
1488    {
1489      r = m_row[j];
1490      m_row[j] = NULL;
1491      do
1492      {
1493        ap = m_res[r->pos];
1494        loop
1495        {
1496          a = ap->n;
1497          if (a == NULL)
1498          {
1499            h = ap->n = r;
1500            r = r->n;
1501            h->n = NULL;
1502            h->pos = crd+k;
1503            break;
1504          }
1505          ap = a;
1506        }
1507      } while (r!=NULL);
1508    }
1509  }
1510  while(act) // clean m_act
1511  {
1512    crd++;
1513    m_res[crd] = m_act[act];
1514    act--;
1515  }
1516  for (i=1;i<=tored;i++) // take the rest of m_row
1517  {
1518    if(m_row[i] != NULL)
1519    {
1520      tored++;
1521      r = m_row[i];
1522      m_row[i] = NULL;
1523      perm[tored] = i;
1524      do
1525      {
1526        ap = m_res[r->pos];
1527        loop
1528        {
1529          a = ap->n;
1530          if (a == NULL)
1531          {
1532            h = ap->n = r;
1533            r = r->n;
1534            h->n = NULL;
1535            h->pos = tored;
1536            break;
1537          }
1538          ap = a;
1539        }
1540      } while (r!=NULL);
1541    }
1542  }
1543  for (i=tored+1;i<=nrows;i++) // take the rest of m_row
1544  {
1545    if(m_row[i] != NULL)
1546    {
1547      r = m_row[i];
1548      m_row[i] = NULL;
1549      do
1550      {
1551        ap = m_res[r->pos];
1552        loop
1553        {
1554          a = ap->n;
1555          if (a == NULL)
1556          {
1557            h = ap->n = r;
1558            r = r->n;
1559            h->n = NULL;
1560            h->pos = i;
1561            break;
1562          }
1563          ap = a;
1564        }
1565      } while (r!=NULL);
1566    }
1567  }
1568  while (inred < ncols) // take unreducable
1569  {
1570    crd++;
1571    inred++;
1572    m_res[crd] = m_res[inred];
1573  }
1574}
1575
1576/*
1577* multiply and divide the column, that goes to result
1578*/
1579void sparse_mat::smMultCol()
1580{
1581  smpoly a = m_act[act];
1582  int e = crd;
1583  poly ha;
1584  int f;
1585
1586  while (a != NULL)
1587  {
1588    f = a->e;
1589    if (f < e)
1590    {
1591      ha = SM_MULT(a->m, m_res[e]->m, m_res[f]->m);
1592      pDelete(&a->m);
1593      if (f) SM_DIV(ha, m_res[f]->m);
1594      a->m = ha;
1595      if (normalize) pNormalize(a->m);
1596    }
1597    a = a->n;
1598  }
1599}
1600
1601/*
1602* multiply and divide the m_act finaly
1603*/
1604void sparse_mat::smFinalMult()
1605{
1606  smpoly a;
1607  poly ha;
1608  int i, f;
1609  int e = crd;
1610
1611  for (i=act; i; i--)
1612  {
1613    a = m_act[i];
1614    do
1615    {
1616      f = a->e;
1617      if (f < e)
1618      {
1619        ha = SM_MULT(a->m, m_res[e]->m, m_res[f]->m);
1620        pDelete(&a->m);
1621        if (f) SM_DIV(ha, m_res[f]->m);
1622        a->m = ha;
1623      }
1624      if (normalize) pNormalize(a->m);
1625      a = a->n;
1626    } while (a != NULL);
1627  }
1628}
1629
1630/*
1631* check for denominators
1632*/
1633int sparse_mat::smCheckNormalize()
1634{
1635  int i;
1636  smpoly a;
1637
1638  for (i=act; i; i--)
1639  {
1640    a = m_act[i];
1641    do
1642    {
1643      if(smHaveDenom(a->m)) return 1;
1644      a = a->n;
1645    } while (a != NULL);
1646  }
1647  return 0;
1648}
1649
1650/*
1651* normalize
1652*/
1653void sparse_mat::smNormalize()
1654{
1655  smpoly a;
1656  int i;
1657  int e = crd;
1658
1659  for (i=act; i; i--)
1660  {
1661    a = m_act[i];
1662    do
1663    {
1664      if (e == a->e) pNormalize(a->m);
1665      a = a->n;
1666    } while (a != NULL);
1667  }
1668}
1669
1670/*
1671* multiply and divide the element, save poly
1672*/
1673poly sparse_mat::smMultPoly(smpoly a)
1674{
1675  int f = a->e;
1676  poly r, h;
1677
1678  if (f < crd)
1679  {
1680    h = r = a->m;
1681    h = SM_MULT(h, m_res[crd]->m, m_res[f]->m);
1682    if (f) SM_DIV(h, m_res[f]->m);
1683    a->m = h;
1684    if (normalize) pNormalize(a->m);
1685    a->f = smPolyWeight(a);
1686    return r;
1687  }
1688  else
1689    return NULL;
1690}
1691
1692/*
1693* delete the m_act finaly
1694*/
1695void sparse_mat::smActDel()
1696{
1697  smpoly a;
1698  int i;
1699
1700  for (i=act; i; i--)
1701  {
1702    a = m_act[i];
1703    do
1704    {
1705      smElemDelete(&a);
1706    } while (a != NULL);
1707  }
1708}
1709
1710/*
1711* delete the pivotcol
1712*/
1713void sparse_mat::smColDel()
1714{
1715  smpoly a = m_act[act];
1716
1717  while (a != NULL)
1718  {
1719    smElemDelete(&a);
1720  }
1721}
1722
1723/*
1724* delete pivot elements
1725*/
1726void sparse_mat::smPivDel()
1727{
1728  int i=crd;
1729
1730  while (i != 0)
1731  {
1732    smElemDelete(&m_res[i]);
1733    i--;
1734  }
1735}
1736
1737/*
1738* the sign of the determinant
1739*/
1740void sparse_mat::smSign()
1741{
1742  int j,i;
1743  if (act > 2)
1744  {
1745    if (cpiv!=act) sign=-sign;
1746    if ((act%2)==0) sign=-sign;
1747    i=1;
1748    j=perm[1];
1749    while(j<rpiv)
1750    {
1751      sign=-sign;
1752      i++;
1753      j=perm[i];
1754    }
1755    while(perm[i]!=0)
1756    {
1757      perm[i]=perm[i+1];
1758      i++;
1759    }
1760  }
1761  else
1762  {
1763    if (cpiv!=1) sign=-sign;
1764    if (rpiv!=perm[1]) sign=-sign;
1765  }
1766}
1767
1768void sparse_mat::smInitPerm()
1769{
1770  int i;
1771  for (i=act;i;i--) perm[i]=i;
1772}
1773
1774/* ----------------- arithmetic ------------------ */
1775/*2
1776* exact division a/b
1777* a destroyed, b NOT destroyed
1778*/
1779void smPolyDiv(poly a, poly b)
1780{
1781  const number x = pGetCoeff(b);
1782  number y, yn;
1783  poly t, h, dummy;
1784  int i;
1785
1786  if (pNext(b) == NULL)
1787  {
1788    do
1789    {
1790      if (!pLmIsConstantComp(b))
1791      {
1792        for (i=pVariables; i; i--)
1793          pSubExp(a,i,pGetExp(b,i));
1794        pSetm(a);
1795      }
1796      y = nDiv(pGetCoeff(a),x);
1797      nNormalize(y);
1798      pSetCoeff(a,y);
1799      pIter(a);
1800    } while (a != NULL);
1801    return;
1802  }
1803  dummy = pInit();
1804  do
1805  {
1806    for (i=pVariables; i; i--)
1807      pSubExp(a,i,pGetExp(b,i));
1808    pSetm(a);
1809    y = nDiv(pGetCoeff(a),x);
1810    nNormalize(y);
1811    pSetCoeff(a,y);
1812    yn = nNeg(nCopy(y));
1813    t = pNext(b);
1814    h = dummy;
1815    do
1816    {
1817      h = pNext(h) = pInit();
1818      //pSetComp(h,0);
1819      for (i=pVariables; i; i--)
1820        pSetExp(h,i,pGetExp(a,i)+pGetExp(t,i));
1821      pSetm(h);
1822      pSetCoeff0(h,nMult(yn, pGetCoeff(t)));
1823      pIter(t);
1824    } while (t != NULL);
1825    nDelete(&yn);
1826    pNext(h) = NULL;
1827    a = pNext(a) = pAdd(pNext(a), pNext(dummy));
1828  } while (a!=NULL);
1829  pLmFree(dummy);
1830}
1831
1832
1833static BOOLEAN smIsNegQuot(poly a, const poly b, const poly c)
1834{
1835  if (pLmDivisibleByNoComp(c, b))
1836  {
1837    pExpVectorDiff(a, b, c);
1838    // Hmm: here used to be a pSetm(a): but it is unnecessary,
1839    // if b and c are correct
1840    return FALSE;
1841  }
1842  else
1843  {
1844    int i;
1845    for (i=pVariables; i>0; i--)
1846    {
1847      if(pGetExp(c,i) > pGetExp(b,i))
1848        pSetExp(a,i,pGetExp(c,i)-pGetExp(b,i));
1849      else
1850        pSetExp(a,i,0);
1851    }
1852    // here we actually might need a pSetm, if a is to be used in
1853    // comparisons
1854    return TRUE;
1855  }
1856}
1857
1858static BOOLEAN smSmaller(poly a, poly b)
1859{
1860  loop
1861  {
1862    pIter(b);
1863    if (b == NULL) return TRUE;
1864    pIter(a);
1865    if (a == NULL) return FALSE;
1866  }
1867}
1868
1869static void smCombineChain(poly *px, poly r)
1870{
1871  poly pa = *px, pb;
1872  number x;
1873  int i;
1874
1875  loop
1876  {
1877    pb = pNext(pa);
1878    if (pb == NULL)
1879    {
1880      pa = pNext(pa) = r;
1881      break;
1882    }
1883    i = pLmCmp(pb, r);
1884    if (i > 0)
1885      pa = pb;
1886    else
1887    {
1888      if (i == 0)
1889      {
1890        x = nAdd(pGetCoeff(pb), pGetCoeff(r));
1891        pLmDelete(&r);
1892        if (nIsZero(x))
1893        {
1894          pLmDelete(&pb);
1895          pNext(pa) = pAdd(pb,r);
1896        }
1897        else
1898        {
1899          pa = pb;
1900          pSetCoeff(pa,x);
1901          pNext(pa) = pAdd(pNext(pa), r);
1902        }
1903      }
1904      else
1905      {
1906        pa = pNext(pa) = r;
1907        pNext(pa) = pAdd(pb, pNext(pa));
1908      }
1909      break;
1910    }
1911  }
1912  *px = pa;
1913}
1914
1915static void smFindRef(poly *ref, poly *px, poly r)
1916{
1917  number x;
1918  int i;
1919  poly pa = *px, pp = NULL;
1920
1921  loop
1922  {
1923    i = pLmCmp(pa, r);
1924    if (i > 0)
1925    {
1926      pp = pa;
1927      pIter(pa);
1928      if (pa==NULL)
1929      {
1930        pNext(pp) = r;
1931        break;
1932      }
1933    }
1934    else
1935    {
1936      if (i == 0)
1937      {
1938        x = nAdd(pGetCoeff(pa), pGetCoeff(r));
1939        pLmDelete(&r);
1940        if (nIsZero(x))
1941        {
1942          pLmDelete(&pa);
1943          if (pp!=NULL)
1944            pNext(pp) = pAdd(pa,r);
1945          else
1946            *px = pAdd(pa,r);
1947        }
1948        else
1949        {
1950          pp = pa;
1951          pSetCoeff(pp,x);
1952          pNext(pp) = pAdd(pNext(pp), r);
1953        }
1954      }
1955      else
1956      {
1957        if (pp!=NULL)
1958          pp = pNext(pp) = r;
1959        else
1960          *px = pp = r;
1961        pNext(pp) = pAdd(pa, pNext(r));
1962      }
1963      break;
1964    }
1965  }
1966  *ref = pp;
1967}
1968
1969//disable that, as it fails with coef buckets
1970//#define X_MAS
1971#ifdef X_MAS
1972
1973/*
1974*  returns the part of (a*b)/exp(lead(c)) with nonegative exponents
1975*/
1976poly smMultDiv(poly a, poly b, const poly c)
1977{
1978  poly pa, e, res, r;
1979  BOOLEAN lead;\
1980  int la, lb, lr;
1981
1982  if ((c == NULL) || pLmIsConstantComp(c))
1983  {
1984    return ppMult_qq(a, b);
1985  }
1986
1987  pqLength(a, b, la, lb, SM_MIN_LENGTH_BUCKET);
1988
1989  // we iter over b, so, make sure b is the shortest
1990  // such that we minimize our iterations
1991  if (lb > la)
1992  {
1993    r = a;
1994    a = b;
1995    b = r;
1996    lr = la;
1997    la = lb;
1998    lb = lr;
1999  }
2000  res = NULL;
2001  e = pInit();
2002  lead = FALSE;
2003  while (!lead)
2004  {
2005    pSetCoeff0(e,pGetCoeff(b));
2006    if (smIsNegQuot(e, b, c))
2007    {
2008      lead = pLmDivisibleByNoComp(e, a);
2009      r = smSelectCopy_ExpMultDiv(a, e, b, c);
2010    }
2011    else
2012    {
2013      lead = TRUE;
2014      r = ppMult_mm(a, e);
2015    }
2016    if (lead)
2017    {
2018      if (res != NULL)
2019      {
2020        smFindRef(&pa, &res, r);
2021        if (pa == NULL)
2022          lead = FALSE;
2023      }
2024      else
2025      {
2026        pa = res = r;
2027      }
2028    }
2029    else
2030      res = pAdd(res, r);
2031    pIter(b);
2032    if (b == NULL)
2033    {
2034      pLmFree(e);
2035      return res;
2036    }
2037  }
2038
2039  if (!TEST_OPT_NOT_BUCKETS && lb >= SM_MIN_LENGTH_BUCKET)
2040  {
2041    // use buckets if minimum length is smaller than threshold
2042    spolyrec rp;
2043    poly append;
2044    // find the last monomial before pa
2045    if (res == pa)
2046    {
2047      append = &rp;
2048      pNext(append) = res;
2049    }
2050    else
2051    {
2052      append = res;
2053      while (pNext(append) != pa)
2054      {
2055        assume(pNext(append) != NULL);
2056        pIter(append);
2057      }
2058    }
2059    kBucket_pt bucket = kBucketCreate(currRing);
2060    kBucketInit(bucket, pNext(append), 0);
2061    do
2062    {
2063      pSetCoeff0(e,pGetCoeff(b));
2064      if (smIsNegQuot(e, b, c))
2065      {
2066        lr = la;
2067        r = pp_Mult_Coeff_mm_DivSelect_MultDiv(a, lr, e, b, c);
2068        if (pLmDivisibleByNoComp(e, a))
2069          append = kBucket_ExtractLarger_Add_q(bucket, append, r, &lr);
2070        else
2071          kBucket_Add_q(bucket, r, &lr);
2072      }
2073      else
2074      {
2075        r = ppMult_mm(a, e);
2076        append = kBucket_ExtractLarger_Add_q(bucket, append, r, &la);
2077      }
2078      pIter(b);
2079    } while (b != NULL);
2080    pNext(append) = kBucketClear(bucket);
2081    kBucketDestroy(&bucket);
2082    pTest(append);
2083  }
2084  else
2085  {
2086    // use old sm stuff
2087    do
2088    {
2089      pSetCoeff0(e,pGetCoeff(b));
2090      if (smIsNegQuot(e, b, c))
2091      {
2092        r = smSelectCopy_ExpMultDiv(a, e, b, c);
2093        if (pLmDivisibleByNoComp(e, a))
2094          smCombineChain(&pa, r);
2095        else
2096          pa = pAdd(pa,r);
2097      }
2098      else
2099      {
2100        r = ppMult_mm(a, e);
2101        smCombineChain(&pa, r);
2102      }
2103      pIter(b);
2104    } while (b != NULL);
2105  }
2106  pLmFree(e);
2107  return res;
2108}
2109
2110#else
2111
2112/*
2113*  returns the part of (a*b)/exp(lead(c)) with nonegative exponents
2114*/
2115poly smMultDiv(poly a, poly b, const poly c)
2116{
2117  poly pa, e, res, r;
2118  BOOLEAN lead;
2119
2120  if ((c == NULL) || pLmIsConstantComp(c))
2121  {
2122    return ppMult_qq(a, b);
2123  }
2124  if (smSmaller(a, b))
2125  {
2126    r = a;
2127    a = b;
2128    b = r;
2129  }
2130  res = NULL;
2131  e = pInit();
2132  lead = FALSE;
2133  while (!lead)
2134  {
2135    pSetCoeff0(e,pGetCoeff(b));
2136    if (smIsNegQuot(e, b, c))
2137    {
2138      lead = pLmDivisibleByNoComp(e, a);
2139      r = smSelectCopy_ExpMultDiv(a, e, b, c);
2140    }
2141    else
2142    {
2143      lead = TRUE;
2144      r = ppMult_mm(a, e);
2145    }
2146    if (lead)
2147    {
2148      if (res != NULL)
2149      {
2150        smFindRef(&pa, &res, r);
2151        if (pa == NULL)
2152          lead = FALSE;
2153      }
2154      else
2155      {
2156        pa = res = r;
2157      }
2158    }
2159    else
2160      res = pAdd(res, r);
2161    pIter(b);
2162    if (b == NULL)
2163    {
2164      pLmFree(e);
2165      return res;
2166    }
2167  }
2168  do
2169  {
2170    pSetCoeff0(e,pGetCoeff(b));
2171    if (smIsNegQuot(e, b, c))
2172    {
2173      r = smSelectCopy_ExpMultDiv(a, e, b, c);
2174      if (pLmDivisibleByNoComp(e, a))
2175        smCombineChain(&pa, r);
2176      else
2177        pa = pAdd(pa,r);
2178    }
2179    else
2180    {
2181      r = ppMult_mm(a, e);
2182      smCombineChain(&pa, r);
2183    }
2184    pIter(b);
2185  } while (b != NULL);
2186  pLmFree(e);
2187  return res;
2188}
2189#endif
2190/* ------------ internals arithmetic ------------- */
2191static void smExactPolyDiv(poly a, poly b)
2192{
2193  const number x = pGetCoeff(b);
2194  poly tail = pNext(b), e = pInit();
2195  poly h;
2196  number y, yn;
2197  int lt = pLength(tail);
2198
2199  if (lt + 1 >= SM_MIN_LENGTH_BUCKET &&  !TEST_OPT_NOT_BUCKETS)
2200  {
2201    kBucket_pt bucket = kBucketCreate(currRing);
2202    kBucketInit(bucket, pNext(a), 0);
2203    int lh = 0;
2204    do
2205    {
2206      y = nDiv(pGetCoeff(a), x);
2207      nNormalize(y);
2208      pSetCoeff(a,y);
2209      yn = nNeg(nCopy(y));
2210      pSetCoeff0(e,yn);
2211      lh = lt;
2212      if (smIsNegQuot(e, a, b))
2213      {
2214        h = pp_Mult_Coeff_mm_DivSelect_MultDiv(tail, lh, e, a, b);
2215      }
2216      else
2217        h = ppMult_mm(tail, e);
2218      nDelete(&yn);
2219      kBucket_Add_q(bucket, h, &lh);
2220
2221      a = pNext(a) = kBucketExtractLm(bucket);
2222    } while (a!=NULL);
2223    kBucketDestroy(&bucket);
2224  }
2225  else
2226  {
2227    do
2228    {
2229      y = nDiv(pGetCoeff(a), x);
2230      nNormalize(y);
2231      pSetCoeff(a,y);
2232      yn = nNeg(nCopy(y));
2233      pSetCoeff0(e,yn);
2234      if (smIsNegQuot(e, a, b))
2235        h = smSelectCopy_ExpMultDiv(tail, e, a, b);
2236      else
2237        h = ppMult_mm(tail, e);
2238      nDelete(&yn);
2239      a = pNext(a) = pAdd(pNext(a), h);
2240    } while (a!=NULL);
2241  }
2242  pLmFree(e);
2243}
2244
2245static void smPolyDivN(poly a, const number x)
2246{
2247  number y;
2248
2249  do
2250  {
2251    y = nDiv(pGetCoeff(a),x);
2252    nNormalize(y);
2253    pSetCoeff(a,y);
2254    pIter(a);
2255  } while (a != NULL);
2256}
2257
2258/*n
2259* exact division a/b
2260* a is a result of smMultDiv
2261* a destroyed, b NOT destroyed
2262*/
2263void smSpecialPolyDiv(poly a, poly b)
2264{
2265  if (pNext(b) == NULL)
2266  {
2267    smPolyDivN(a, pGetCoeff(b));
2268    return;
2269  }
2270  smExactPolyDiv(a, b);
2271}
2272
2273/* ----------------- gauss elimination ------------------ */
2274/* in structs.h */
2275typedef struct smnrec sm_nrec;
2276typedef sm_nrec * smnumber;
2277struct smnrec{
2278  smnumber n;          // the next element
2279  int pos;             // position
2280  number m;            // the element
2281};
2282
2283static omBin smnrec_bin = omGetSpecBin(sizeof(smnrec));
2284
2285/* declare internal 'C' stuff */
2286static void smNumberDelete(smnumber *);
2287static smnumber smNumberCopy(smnumber);
2288static smnumber smPoly2Smnumber(poly);
2289static poly smSmnumber2Poly(number);
2290static BOOLEAN smCheckSolv(ideal);
2291
2292/* class for sparse number matrix:
2293*/
2294class sparse_number_mat{
2295private:
2296  int nrows, ncols;    // dimension of the problem
2297  int act;             // number of unreduced columns (start: ncols)
2298  int crd;             // number of reduced columns (start: 0)
2299  int tored;           // border for rows to reduce
2300  int sing;            // indicator for singular problem
2301  int rpiv;            // row-position of the pivot
2302  int *perm;           // permutation of rows
2303  number *sol;         // field for solution
2304  int *wrw, *wcl;      // weights of rows and columns
2305  smnumber * m_act;    // unreduced columns
2306  smnumber * m_res;    // reduced columns (result)
2307  smnumber * m_row;    // reduced part of rows
2308  smnumber red;        // row to reduce
2309  smnumber piv;        // pivot
2310  smnumber dumm;       // allocated dummy
2311  void smColToRow();
2312  void smRowToCol();
2313  void smSelectPR();
2314  void smRealPivot();
2315  void smZeroToredElim();
2316  void smGElim();
2317  void smAllDel();
2318public:
2319  sparse_number_mat(ideal);
2320  ~sparse_number_mat();
2321  int smIsSing() { return sing; }
2322  void smTriangular();
2323  void smSolv();
2324  ideal smRes2Ideal();
2325};
2326
2327/* ----------------- basics (used from 'C') ------------------ */
2328/*2
2329* returns the solution of a linear equation
2330* solution of M*x = r (M has dimension nXn) =>
2331*   I = module(transprose(M)) + r*gen(n+1)
2332* uses  Gauss-elimination
2333*/
2334ideal smCallSolv(ideal I)
2335{
2336  sparse_number_mat *linsolv;
2337  ring origR;
2338  ring tmpR;
2339  ideal rr;
2340
2341  if (idIsConstant(I)==FALSE)
2342  {
2343    WerrorS("symbol in equation");
2344    return NULL;
2345  }
2346  I->rank = idRankFreeModule(I);
2347  if (smCheckSolv(I)) return NULL;
2348  tmpR=smRingChange(&origR,1);
2349  rr=idrCopyR(I,origR);
2350  linsolv = new sparse_number_mat(rr);
2351  rr=NULL;
2352  linsolv->smTriangular();
2353  if (linsolv->smIsSing() == 0)
2354  {
2355    linsolv->smSolv();
2356    rr = linsolv->smRes2Ideal();
2357  }
2358  else
2359    WerrorS("singular problem for linsolv");
2360  delete linsolv;
2361  rChangeCurrRing(origR);
2362  if (rr!=NULL)
2363    rr = idrMoveR(rr,tmpR);
2364  smKillModifiedRing(tmpR);
2365  return rr;
2366}
2367
2368/*
2369* constructor, destroy smat
2370*/
2371sparse_number_mat::sparse_number_mat(ideal smat)
2372{
2373  int i;
2374  polyset pmat;
2375
2376  crd = sing = 0;
2377  act = ncols = smat->ncols;
2378  tored = nrows = smat->rank;
2379  i = tored+1;
2380  perm = (int *)omAlloc(sizeof(int)*i);
2381  m_row = (smnumber *)omAlloc0(sizeof(smnumber)*i);
2382  wrw = (int *)omAlloc(sizeof(int)*i);
2383  i = ncols+1;
2384  wcl = (int *)omAlloc(sizeof(int)*i);
2385  m_act = (smnumber *)omAlloc(sizeof(smnumber)*i);
2386  m_res = (smnumber *)omAlloc0(sizeof(smnumber)*i);
2387  dumm = (smnumber)omAllocBin(smnrec_bin);
2388  pmat = smat->m;
2389  for(i=ncols; i; i--)
2390  {
2391    m_act[i] = smPoly2Smnumber(pmat[i-1]);
2392  }
2393  omFreeSize((ADDRESS)pmat,smat->ncols*sizeof(poly));
2394  omFreeBin((ADDRESS)smat, sip_sideal_bin);
2395}
2396
2397/*
2398* destructor
2399*/
2400sparse_number_mat::~sparse_number_mat()
2401{
2402  int i;
2403  omFreeBin((ADDRESS)dumm,  smnrec_bin);
2404  i = ncols+1;
2405  omFreeSize((ADDRESS)m_res, sizeof(smnumber)*i);
2406  omFreeSize((ADDRESS)m_act, sizeof(smnumber)*i);
2407  omFreeSize((ADDRESS)wcl, sizeof(int)*i);
2408  i = nrows+1;
2409  omFreeSize((ADDRESS)wrw, sizeof(int)*i);
2410  omFreeSize((ADDRESS)m_row, sizeof(smnumber)*i);
2411  omFreeSize((ADDRESS)perm, sizeof(int)*i);
2412}
2413
2414/*
2415* triangularization by Gauss-elimination
2416*/
2417void sparse_number_mat::smTriangular()
2418{
2419  tored--;
2420  this->smZeroToredElim();
2421  if (sing != 0) return;
2422  while (act > 1)
2423  {
2424    this->smRealPivot();
2425    this->smSelectPR();
2426    this->smGElim();
2427    crd++;
2428    this->smColToRow();
2429    act--;
2430    this->smRowToCol();
2431    this->smZeroToredElim();
2432    if (sing != 0) return;
2433  }
2434  if (TEST_OPT_PROT) PrintS(".\n");
2435  piv = m_act[1];
2436  rpiv = piv->pos;
2437  m_act[1] = piv->n;
2438  piv->n = NULL;
2439  crd++;
2440  this->smColToRow();
2441  act--;
2442  this->smRowToCol();
2443}
2444
2445/*
2446* solve the triangular system
2447*/
2448void sparse_number_mat::smSolv()
2449{
2450  int i, j;
2451  number x, y, z;
2452  smnumber s, d, r = m_row[nrows];
2453
2454  m_row[nrows] = NULL;
2455  sol = (number *)omAlloc0(sizeof(number)*(crd+1));
2456  while (r != NULL)  // expand the rigth hand side
2457  {
2458    sol[r->pos] = r->m;
2459    s = r;
2460    r = r->n;
2461    omFreeBin((ADDRESS)s,  smnrec_bin);
2462  }
2463  i = crd;  // solve triangular system
2464  if (sol[i] != NULL)
2465  {
2466    x = sol[i];
2467    sol[i] = nDiv(x, m_res[i]->m);
2468    nDelete(&x);
2469  }
2470  i--;
2471  while (i > 0)
2472  {
2473    x = NULL;
2474    d = m_res[i];
2475    s = d->n;
2476    while (s != NULL)
2477    {
2478      j = s->pos;
2479      if (sol[j] != NULL)
2480      {
2481        z = nMult(sol[j], s->m);
2482        if (x != NULL)
2483        {
2484          y = x;
2485          x = nSub(y, z);
2486          nDelete(&y);
2487          nDelete(&z);
2488        }
2489        else
2490          x = nNeg(z);
2491      }
2492      s = s->n;
2493    }
2494    if (sol[i] != NULL)
2495    {
2496      if (x != NULL)
2497      {
2498        y = nAdd(x, sol[i]);
2499        nDelete(&x);
2500        if (nIsZero(y))
2501        {
2502          nDelete(&sol[i]);
2503          sol[i] = NULL;
2504        }
2505        else
2506          sol[i] = y;
2507      }
2508    }
2509    else
2510      sol[i] = x;
2511    if (sol[i] != NULL)
2512    {
2513      x = sol[i];
2514      sol[i] = nDiv(x, d->m);
2515      nDelete(&x);
2516    }
2517    i--;
2518  }
2519  this->smAllDel();
2520}
2521
2522/*
2523* transform the result to an ideal
2524*/
2525ideal sparse_number_mat::smRes2Ideal()
2526{
2527  int i, j;
2528  ideal res = idInit(crd, 1);
2529
2530  for (i=crd; i; i--)
2531  {
2532    j = perm[i]-1;
2533    res->m[j] = smSmnumber2Poly(sol[i]);
2534  }
2535  omFreeSize((ADDRESS)sol, sizeof(number)*(crd+1));
2536  return res;
2537}
2538
2539/* ----------------- pivot method ------------------ */
2540
2541/*
2542* compute pivot
2543*/
2544void sparse_number_mat::smRealPivot()
2545{
2546  smnumber a;
2547  number x, xo;
2548  int i, copt, ropt;
2549
2550  xo=nInit(0);
2551  for (i=act; i; i--)
2552  {
2553    a = m_act[i];
2554    while ((a!=NULL) && (a->pos<=tored))
2555    {
2556      x = a->m;
2557      if (nGreaterZero(x))
2558      {
2559        if (nGreater(x,xo))
2560        {
2561          nDelete(&xo);
2562          xo = nCopy(x);
2563          copt = i;
2564          ropt = a->pos;
2565        }
2566      }
2567      else
2568      {
2569        xo = nNeg(xo);
2570        if (nGreater(xo,x))
2571        {
2572          nDelete(&xo);
2573          xo = nCopy(x);
2574          copt = i;
2575          ropt = a->pos;
2576        }
2577        xo = nNeg(xo);
2578      }
2579      a = a->n;
2580    }
2581  }
2582  rpiv = ropt;
2583  if (copt != act)
2584  {
2585    a = m_act[act];
2586    m_act[act] = m_act[copt];
2587    m_act[copt] = a;
2588  }
2589  nDelete(&xo);
2590}
2591
2592/* ----------------- elimination ------------------ */
2593
2594/* one step of Gauss-elimination */
2595void sparse_number_mat::smGElim()
2596{
2597  number p = nInvers(piv->m);  // pivotelement
2598  smnumber c = m_act[act];      // pivotcolumn
2599  smnumber r = red;             // row to reduce
2600  smnumber res, a, b;
2601  number w, ha, hb;
2602
2603  if ((c == NULL) || (r == NULL))
2604  {
2605    while (r!=NULL) smNumberDelete(&r);
2606    return;
2607  }
2608  do
2609  {
2610    a = m_act[r->pos];
2611    res = dumm;
2612    res->n = NULL;
2613    b = c;
2614    w = nMult(r->m, p);
2615    nDelete(&r->m);
2616    r->m = w;
2617    loop   // combine the chains a and b: a + w*b
2618    {
2619      if (a == NULL)
2620      {
2621        do
2622        {
2623          res = res->n = smNumberCopy(b);
2624          res->m = nMult(b->m, w);
2625          b = b->n;
2626        } while (b != NULL);
2627        break;
2628      }
2629      if (a->pos < b->pos)
2630      {
2631        res = res->n = a;
2632        a = a->n;
2633      }
2634      else if (a->pos > b->pos)
2635      {
2636        res = res->n = smNumberCopy(b);
2637        res->m = nMult(b->m, w);
2638        b = b->n;
2639      }
2640      else
2641      {
2642        hb = nMult(b->m, w);
2643        ha = nAdd(a->m, hb);
2644        nDelete(&hb);
2645        nDelete(&a->m);
2646        if (nIsZero(ha))
2647        {
2648          smNumberDelete(&a);
2649        }
2650        else
2651        {
2652          a->m = ha;
2653          res = res->n = a;
2654          a = a->n;
2655        }
2656        b = b->n;
2657      }
2658      if (b == NULL)
2659      {
2660        res->n = a;
2661        break;
2662      }
2663    }
2664    m_act[r->pos] = dumm->n;
2665    smNumberDelete(&r);
2666  } while (r != NULL);
2667  nDelete(&p);
2668}
2669
2670/* ----------------- transfer ------------------ */
2671
2672/*
2673* select the pivotrow and store it to red and piv
2674*/
2675void sparse_number_mat::smSelectPR()
2676{
2677  smnumber b = dumm;
2678  smnumber a, ap;
2679  int i;
2680
2681  if (TEST_OPT_PROT)
2682  {
2683    if ((crd+1)%10)
2684      PrintS(".");
2685    else
2686      PrintS(".\n");
2687  }
2688  a = m_act[act];
2689  if (a->pos < rpiv)
2690  {
2691    do
2692    {
2693      ap = a;
2694      a = a->n;
2695    } while (a->pos < rpiv);
2696    ap->n = a->n;
2697  }
2698  else
2699    m_act[act] = a->n;
2700  piv = a;
2701  a->n = NULL;
2702  for (i=1; i<act; i++)
2703  {
2704    a = m_act[i];
2705    if (a->pos < rpiv)
2706    {
2707      loop
2708      {
2709        ap = a;
2710        a = a->n;
2711        if ((a == NULL) || (a->pos > rpiv))
2712          break;
2713        if (a->pos == rpiv)
2714        {
2715          ap->n = a->n;
2716          a->m = nNeg(a->m);
2717          b = b->n = a;
2718          b->pos = i;
2719          break;
2720        }
2721      }
2722    }
2723    else if (a->pos == rpiv)
2724    {
2725      m_act[i] = a->n;
2726      a->m = nNeg(a->m);
2727      b = b->n = a;
2728      b->pos = i;
2729    }
2730  }
2731  b->n = NULL;
2732  red = dumm->n;
2733}
2734
2735/*
2736* store the pivotcol in m_row
2737*   m_act[cols][pos(rows)] => m_row[rows][pos(cols)]
2738*/
2739void sparse_number_mat::smColToRow()
2740{
2741  smnumber c = m_act[act];
2742  smnumber h;
2743
2744  while (c != NULL)
2745  {
2746    h = c;
2747    c = c->n;
2748    h->n = m_row[h->pos];
2749    m_row[h->pos] = h;
2750    h->pos = crd;
2751  }
2752}
2753
2754/*
2755* store the pivot and the assosiated row in m_row
2756* to m_res (result):
2757*   piv + m_row[rows][pos(cols)] => m_res[cols][pos(rows)]
2758*/
2759void sparse_number_mat::smRowToCol()
2760{
2761  smnumber r = m_row[rpiv];
2762  smnumber a, ap, h;
2763
2764  m_row[rpiv] = NULL;
2765  perm[crd] = rpiv;
2766  piv->pos = crd;
2767  m_res[crd] = piv;
2768  while (r != NULL)
2769  {
2770    ap = m_res[r->pos];
2771    loop
2772    {
2773      a = ap->n;
2774      if (a == NULL)
2775      {
2776        ap->n = h = r;
2777        r = r->n;
2778        h->n = a;
2779        h->pos = crd;
2780        break;
2781      }
2782      ap = a;
2783    }
2784  }
2785}
2786
2787/* ----------------- C++ stuff ------------------ */
2788
2789/*
2790*  check singularity
2791*/
2792void sparse_number_mat::smZeroToredElim()
2793{
2794  smnumber a;
2795  int i = act;
2796
2797  loop
2798  {
2799    if (i == 0) return;
2800    a = m_act[i];
2801    if ((a==NULL) || (a->pos>tored))
2802    {
2803      sing = 1;
2804      this->smAllDel();
2805      return;
2806    }
2807    i--;
2808  }
2809}
2810
2811/*
2812* delete all smnumber's
2813*/
2814void sparse_number_mat::smAllDel()
2815{
2816  smnumber a;
2817  int i;
2818
2819  for (i=act; i; i--)
2820  {
2821    a = m_act[i];
2822    while (a != NULL)
2823      smNumberDelete(&a);
2824  }
2825  for (i=crd; i; i--)
2826  {
2827    a = m_res[i];
2828    while (a != NULL)
2829      smNumberDelete(&a);
2830  }
2831  if (act)
2832  {
2833    for (i=nrows; i; i--)
2834    {
2835      a = m_row[i];
2836      while (a != NULL)
2837        smNumberDelete(&a);
2838    }
2839  }
2840}
2841
2842/* ----------------- internal 'C' stuff ------------------ */
2843
2844static void smNumberDelete(smnumber *r)
2845{
2846  smnumber a = *r, b = a->n;
2847
2848  nDelete(&a->m);
2849  omFreeBin((ADDRESS)a,  smnrec_bin);
2850  *r = b;
2851}
2852
2853static smnumber smNumberCopy(smnumber a)
2854{
2855  smnumber r = (smnumber)omAllocBin(smnrec_bin);
2856  memcpy(r, a, sizeof(smnrec));
2857  return r;
2858}
2859
2860/*
2861* from poly to smnumber
2862* do not destroy p
2863*/
2864static smnumber smPoly2Smnumber(poly q)
2865{
2866  smnumber a, res;
2867  poly p = q;
2868
2869  if (p == NULL)
2870    return NULL;
2871  a = res = (smnumber)omAllocBin(smnrec_bin);
2872  a->pos = pGetComp(p);
2873  a->m = pGetCoeff(p);
2874  nNew(&pGetCoeff(p));
2875  loop
2876  {
2877    pIter(p);
2878    if (p == NULL)
2879    {
2880      pDelete(&q);
2881      a->n = NULL;
2882      return res;
2883    }
2884    a = a->n = (smnumber)omAllocBin(smnrec_bin);
2885    a->pos = pGetComp(p);
2886    a->m = pGetCoeff(p);
2887    nNew(&pGetCoeff(p));
2888  }
2889}
2890
2891/*
2892* from smnumber to poly
2893* destroy a
2894*/
2895static poly smSmnumber2Poly(number a)
2896{
2897  poly res;
2898
2899  if (a == NULL) return NULL;
2900  res = pInit();
2901  pSetCoeff0(res, a);
2902  return res;
2903}
2904
2905/*2
2906* check the input
2907*/
2908static BOOLEAN smCheckSolv(ideal I)
2909{ int i = I->ncols;
2910  if ((i == 0) || (i != I->rank-1))
2911  {
2912    WerrorS("wrong dimensions for linsolv");
2913    return TRUE;
2914  }
2915  for(;i;i--)
2916  {
2917    if(I->m[i-1] == NULL)
2918    {
2919      WerrorS("singular input for linsolv");
2920      return TRUE;
2921    }
2922  }
2923  return FALSE;
2924}
Note: See TracBrowser for help on using the repository browser.