source: git/libpolys/polys/sparsmat.cc @ ab4286

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