source: git/libpolys/polys/sparsmat.cc @ 805d0b1

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