source: git/kernel/sparsmat.cc @ f2b6f0b

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