source: git/kernel/matpol.cc @ b1dfaf

spielwiese
Last change on this file since b1dfaf was b1dfaf, checked in by Frank Seelisch <seelisch@…>, 14 years ago
patch from Kai (checked for problems under Windows OS: no problems) git-svn-id: file:///usr/local/Singular/svn/trunk@13210 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 34.8 KB
Line 
1/****************************************
2*  Computer Algebra System SINGULAR     *
3****************************************/
4/* $Id$ */
5
6/*
7* ABSTRACT:
8*/
9
10#include <stdio.h>
11#include <math.h>
12
13#include <kernel/mod2.h>
14#include <omalloc/mylimits.h>
15#include <kernel/structs.h>
16#include <kernel/kstd1.h>
17#include <kernel/polys.h>
18#include <omalloc/omalloc.h>
19#include <kernel/febase.h>
20#include <kernel/numbers.h>
21#include <kernel/ideals.h>
22#include <kernel/intvec.h>
23#include <kernel/ring.h>
24#include <kernel/sparsmat.h>
25#include <kernel/matpol.h>
26#include <kernel/prCopy.h>
27
28//omBin ip_smatrix_bin = omGetSpecBin(sizeof(ip_smatrix));
29#define ip_smatrix_bin sip_sideal_bin
30/*0 implementation*/
31
32
33typedef int perm[100];
34static void mpReplace(int j, int n, int &sign, int *perm);
35static int mpNextperm(perm * z, int max);
36static poly mpLeibnitz(matrix a);
37static poly minuscopy (poly p);
38static poly pInsert(poly p1, poly p2);
39static poly mpExdiv ( poly m, poly d, poly vars);
40static poly mpSelect (poly fro, poly what);
41
42static void mpPartClean(matrix, int, int);
43static void mpFinalClean(matrix);
44static int mpPrepareRow (matrix, int, int);
45static int mpPreparePiv (matrix, int, int);
46static int mpPivBar(matrix, int, int);
47static int mpPivRow(matrix, int, int);
48static float mpPolyWeight(poly);
49static void mpSwapRow(matrix, int, int, int);
50static void mpSwapCol(matrix, int, int, int);
51static void mpElimBar(matrix, matrix, poly, int, int);
52
53/*2
54* create a r x c zero-matrix
55*/
56matrix mpNew(int r, int c)
57{
58  if (r<=0) r=1;
59  if ( (((int)(INT_MAX/sizeof(poly))) / r) <= c)
60  {
61    Werror("internal error: creating matrix[%d][%d]",r,c);
62    return NULL;
63  }
64  matrix rc = (matrix)omAllocBin(ip_smatrix_bin);
65  rc->nrows = r;
66  rc->ncols = c;
67  rc->rank = r;
68  if (c != 0)
69  {
70    int s=r*c*sizeof(poly);
71    rc->m = (polyset)omAlloc0(s);
72    //if (rc->m==NULL)
73    //{
74    //  Werror("internal error: creating matrix[%d][%d]",r,c);
75    //  return NULL;
76    //}
77  }
78  return rc;
79}
80
81/*2
82*copies matrix a to b
83*/
84matrix mpCopy (matrix a)
85{
86  idTest((ideal)a);
87  poly t;
88  int i, m=MATROWS(a), n=MATCOLS(a);
89  matrix b = mpNew(m, n);
90
91  for (i=m*n-1; i>=0; i--)
92  {
93    t = a->m[i];
94    if (t!=NULL)
95    {
96      pNormalize(t);
97      b->m[i] = pCopy(t);
98    }
99  }
100  b->rank=a->rank;
101  return b;
102}
103
104/*2
105*copies matrix a from rSrc into rDst
106*/
107matrix mpCopy(const matrix a, const ring rSrc, const ring rDst)
108{
109  const ring save = currRing;
110
111  if( save != currRing )
112    rChangeCurrRing(rSrc);
113
114  idTest((ideal)a);
115
116  rChangeCurrRing(rDst);
117
118  poly t;
119  int i, m=MATROWS(a), n=MATCOLS(a);
120
121  matrix b = mpNew(m, n);
122
123  for (i=m*n-1; i>=0; i--)
124  {
125    t = a->m[i];
126    if (t!=NULL)
127    {
128      b->m[i] = prCopyR_NoSort(t, rSrc, rDst);
129      p_Normalize(b->m[i], rDst);
130    }
131  }
132  b->rank=a->rank;
133
134  idTest((ideal)b);
135
136  if( save != currRing )
137    rChangeCurrRing(save);
138
139  return b;
140}
141
142
143
144/*2
145* make it a p * unit matrix
146*/
147matrix mpInitP(int r, int c, poly p)
148{
149  matrix rc = mpNew(r,c);
150  int i=si_min(r,c), n = c*(i-1)+i-1, inc = c+1;
151
152  pNormalize(p);
153  while (n>0)
154  {
155    rc->m[n] = pCopy(p);
156    n -= inc;
157  }
158  rc->m[0]=p;
159  return rc;
160}
161
162/*2
163* make it a v * unit matrix
164*/
165matrix mpInitI(int r, int c, int v)
166{
167  return mpInitP(r,c,pISet(v));
168}
169
170/*2
171* c = f*a
172*/
173matrix mpMultI(matrix a, int f)
174{
175  int k, n = a->nrows, m = a->ncols;
176  poly p = pISet(f);
177  matrix c = mpNew(n,m);
178
179  for (k=m*n-1; k>0; k--)
180    c->m[k] = ppMult_qq(a->m[k], p);
181  c->m[0] = pMult(pCopy(a->m[0]), p);
182  return c;
183}
184
185/*2
186* multiply a matrix 'a' by a poly 'p', destroy the args
187*/
188matrix mpMultP(matrix a, poly p)
189{
190  int k, n = a->nrows, m = a->ncols;
191
192  pNormalize(p);
193  for (k=m*n-1; k>0; k--)
194  {
195    if (a->m[k]!=NULL)
196      a->m[k] = pMult(a->m[k], pCopy(p));
197  }
198  a->m[0] = pMult(a->m[0], p);
199  return a;
200}
201
202/*2
203* multiply a poly 'p' by a matrix 'a', destroy the args
204*/
205matrix pMultMp(poly p, matrix a)
206{
207  int k, n = a->nrows, m = a->ncols;
208
209  pNormalize(p);
210  for (k=m*n-1; k>0; k--)
211  {
212    if (a->m[k]!=NULL)
213      a->m[k] = pMult(pCopy(p), a->m[k]);
214  }
215  a->m[0] = pMult(p, a->m[0]);
216  return a;
217}
218
219matrix mpAdd(matrix a, matrix b)
220{
221  int k, n = a->nrows, m = a->ncols;
222  if ((n != b->nrows) || (m != b->ncols))
223  {
224/*
225*    Werror("cannot add %dx%d matrix and %dx%d matrix",
226*      m,n,b->cols(),b->rows());
227*/
228    return NULL;
229  }
230  matrix c = mpNew(n,m);
231  for (k=m*n-1; k>=0; k--)
232    c->m[k] = pAdd(pCopy(a->m[k]), pCopy(b->m[k]));
233  return c;
234}
235
236matrix mpSub(matrix a, matrix b)
237{
238  int k, n = a->nrows, m = a->ncols;
239  if ((n != b->nrows) || (m != b->ncols))
240  {
241/*
242*    Werror("cannot sub %dx%d matrix and %dx%d matrix",
243*      m,n,b->cols(),b->rows());
244*/
245    return NULL;
246  }
247  matrix c = mpNew(n,m);
248  for (k=m*n-1; k>=0; k--)
249    c->m[k] = pSub(pCopy(a->m[k]), pCopy(b->m[k]));
250  return c;
251}
252
253matrix mpMult(matrix a, matrix b)
254{
255  int i, j, k;
256  int m = MATROWS(a);
257  int p = MATCOLS(a);
258  int q = MATCOLS(b);
259
260  if (p!=MATROWS(b))
261  {
262/*
263*   Werror("cannot multiply %dx%d matrix and %dx%d matrix",
264*     m,p,b->rows(),q);
265*/
266    return NULL;
267  }
268  matrix c = mpNew(m,q);
269
270  for (i=1; i<=m; i++)
271  {
272    for (k=1; k<=p; k++)
273    {
274      poly aik;
275      if ((aik=MATELEM(a,i,k))!=NULL)
276      {
277        for (j=1; j<=q; j++)
278        {
279          poly bkj;
280          if ((bkj=MATELEM(b,k,j))!=NULL)
281          {
282            poly *cij=&(MATELEM(c,i,j));
283            poly s = ppMult_qq(aik /*MATELEM(a,i,k)*/, bkj/*MATELEM(b,k,j)*/);
284            if (/*MATELEM(c,i,j)*/ (*cij)==NULL) (*cij)=s;
285            else (*cij) = pAdd((*cij) /*MATELEM(c,i,j)*/ ,s);
286          }
287        }
288      }
289    //  pNormalize(t);
290    //  MATELEM(c,i,j) = t;
291    }
292  }
293  for(i=m*q-1;i>=0;i--) pNormalize(c->m[i]);
294  return c;
295}
296
297matrix mpTransp(matrix a)
298{
299  int    i, j, r = MATROWS(a), c = MATCOLS(a);
300  poly *p;
301  matrix b =  mpNew(c,r);
302
303  p = b->m;
304  for (i=0; i<c; i++)
305  {
306    for (j=0; j<r; j++)
307    {
308      if (a->m[j*c+i]!=NULL) *p = pCopy(a->m[j*c+i]);
309      p++;
310    }
311  }
312  return b;
313}
314
315/*2
316*returns the trace of matrix a
317*/
318poly mpTrace ( matrix a)
319{
320  int i;
321  int n = (MATCOLS(a)<MATROWS(a)) ? MATCOLS(a) : MATROWS(a);
322  poly  t = NULL;
323
324  for (i=1; i<=n; i++)
325    t = pAdd(t, pCopy(MATELEM(a,i,i)));
326  return t;
327}
328
329/*2
330*returns the trace of the product of a and b
331*/
332poly TraceOfProd ( matrix a, matrix b, int n)
333{
334  int i, j;
335  poly  p, t = NULL;
336
337  for (i=1; i<=n; i++)
338  {
339    for (j=1; j<=n; j++)
340    {
341      p = ppMult_qq(MATELEM(a,i,j), MATELEM(b,j,i));
342      t = pAdd(t, p);
343    }
344  }
345  return t;
346}
347
348/*
349* C++ classes for Bareiss algorithm
350*/
351class row_col_weight
352{
353  private:
354  int ym, yn;
355  public:
356  float *wrow, *wcol;
357  row_col_weight() : ym(0) {}
358  row_col_weight(int, int);
359  ~row_col_weight();
360};
361
362/*2
363*  a submatrix M of a matrix X[m,n]:
364*    0 <= i < s_m <= a_m
365*    0 <= j < s_n <= a_n
366*    M = ( Xarray[qrow[i],qcol[j]] )
367*    if a_m = a_n and s_m = s_n
368*      det(X) = sign*div^(s_m-1)*det(M)
369*    resticted pivot for elimination
370*      0 <= j < piv_s
371*/
372class mp_permmatrix
373{
374  private:
375  int       a_m, a_n, s_m, s_n, sign, piv_s;
376  int       *qrow, *qcol;
377  poly      *Xarray;
378  void mpInitMat();
379  poly * mpRowAdr(int);
380  poly * mpColAdr(int);
381  void mpRowWeight(float *);
382  void mpColWeight(float *);
383  void mpRowSwap(int, int);
384  void mpColSwap(int, int);
385  public:
386  mp_permmatrix() : a_m(0) {}
387  mp_permmatrix(matrix);
388  mp_permmatrix(mp_permmatrix *);
389  ~mp_permmatrix();
390  int mpGetRow();
391  int mpGetCol();
392  int mpGetRdim();
393  int mpGetCdim();
394  int mpGetSign();
395  void mpSetSearch(int s);
396  void mpSaveArray();
397  poly mpGetElem(int, int);
398  void mpSetElem(poly, int, int);
399  void mpDelElem(int, int);
400  void mpElimBareiss(poly);
401  int mpPivotBareiss(row_col_weight *);
402  int mpPivotRow(row_col_weight *, int);
403  void mpToIntvec(intvec *);
404  void mpRowReorder();
405  void mpColReorder();
406};
407
408#ifndef SIZE_OF_SYSTEM_PAGE
409#define SIZE_OF_SYSTEM_PAGE 4096
410#endif
411/*2
412* entries of a are minors and go to result (only if not in R)
413*/
414void mpMinorToResult(ideal result, int &elems, matrix a, int r, int c,
415                     ideal R)
416{
417  poly *q1;
418  int e=IDELEMS(result);
419  int i,j;
420
421  if (R != NULL)
422  {
423    for (i=r-1;i>=0;i--)
424    {
425      q1 = &(a->m)[i*a->ncols];
426      for (j=c-1;j>=0;j--)
427      {
428        if (q1[j]!=NULL) q1[j] = kNF(R,currQuotient,q1[j]);
429      }
430    }
431  }
432  for (i=r-1;i>=0;i--)
433  {
434    q1 = &(a->m)[i*a->ncols];
435    for (j=c-1;j>=0;j--)
436    {
437      if (q1[j]!=NULL)
438      {
439        if (elems>=e)
440        {
441          if(e<SIZE_OF_SYSTEM_PAGE)
442          {
443            pEnlargeSet(&(result->m),e,e);
444            e += e;
445          }
446          else
447          {
448            pEnlargeSet(&(result->m),e,SIZE_OF_SYSTEM_PAGE);
449            e += SIZE_OF_SYSTEM_PAGE;
450          }
451          IDELEMS(result) =e;
452        }
453        result->m[elems] = q1[j];
454        q1[j] = NULL;
455        elems++;
456      }
457    }
458  }
459}
460
461/*2
462* produces recursively the ideal of all arxar-minors of a
463*/
464void mpRecMin(int ar,ideal result,int &elems,matrix a,int lr,int lc,
465              poly barDiv, ideal R)
466{
467  int k;
468  int kr=lr-1,kc=lc-1;
469  matrix nextLevel=mpNew(kr,kc);
470
471  loop
472  {
473/*--- look for an optimal row and bring it to last position ------------*/
474    if(mpPrepareRow(a,lr,lc)==0) break;
475/*--- now take all pivots from the last row ------------*/
476    k = lc;
477    loop
478    {
479      if(mpPreparePiv(a,lr,k)==0) break;
480      mpElimBar(a,nextLevel,barDiv,lr,k);
481      k--;
482      if (ar>1)
483      {
484        mpRecMin(ar-1,result,elems,nextLevel,kr,k,a->m[kr*a->ncols+k],R);
485        mpPartClean(nextLevel,kr,k);
486      }
487      else mpMinorToResult(result,elems,nextLevel,kr,k,R);
488      if (ar>k-1) break;
489    }
490    if (ar>=kr) break;
491/*--- now we have to take out the last row...------------*/
492    lr = kr;
493    kr--;
494  }
495  mpFinalClean(nextLevel);
496}
497
498/*2
499*returns the determinant of the matrix m;
500*uses Bareiss algorithm
501*/
502poly mpDetBareiss (matrix a)
503{
504  int s;
505  poly div, res;
506  if (MATROWS(a) != MATCOLS(a))
507  {
508    Werror("det of %d x %d matrix",MATROWS(a),MATCOLS(a));
509    return NULL;
510  }
511  matrix c = mpCopy(a);
512  mp_permmatrix *Bareiss = new mp_permmatrix(c);
513  row_col_weight w(Bareiss->mpGetRdim(), Bareiss->mpGetCdim());
514
515  /* Bareiss */
516  div = NULL;
517  while(Bareiss->mpPivotBareiss(&w))
518  {
519    Bareiss->mpElimBareiss(div);
520    div = Bareiss->mpGetElem(Bareiss->mpGetRdim(), Bareiss->mpGetCdim());
521  }
522  Bareiss->mpRowReorder();
523  Bareiss->mpColReorder();
524  Bareiss->mpSaveArray();
525  s = Bareiss->mpGetSign();
526  delete Bareiss;
527
528  /* result */
529  res = MATELEM(c,1,1);
530  MATELEM(c,1,1) = NULL;
531  idDelete((ideal *)&c);
532  if (s < 0)
533    res = pNeg(res);
534  return res;
535}
536
537/*2
538*returns the determinant of the matrix m;
539*uses Newtons formulea for symmetric functions
540*/
541poly mpDet (matrix m)
542{
543  int i,j,k,n;
544  poly p,q;
545  matrix a, s;
546  matrix ma[100];
547  number c=NULL, d=NULL, ONE=NULL;
548
549  n = MATROWS(m);
550  if (n != MATCOLS(m))
551  {
552    Werror("det of %d x %d matrix",n,MATCOLS(m));
553    return NULL;
554  }
555  k=rChar();
556  if ((k > 0) && (k <= n))
557    return mpLeibnitz(m);
558  ONE = nInit(1);
559  ma[1]=mpCopy(m);
560  k = (n+1) / 2;
561  s = mpNew(1, n);
562  MATELEM(s,1,1) = mpTrace(m);
563  for (i=2; i<=k; i++)
564  {
565    //ma[i] = mpNew(n,n);
566    ma[i]=mpMult(ma[i-1], ma[1]);
567    MATELEM(s,1,i) = mpTrace(ma[i]);
568    pTest(MATELEM(s,1,i));
569  }
570  for (i=k+1; i<=n; i++)
571  {
572    MATELEM(s,1,i) = TraceOfProd(ma[i / 2], ma[(i+1) / 2], n);
573    pTest(MATELEM(s,1,i));
574  }
575  for (i=1; i<=k; i++)
576    idDelete((ideal *)&(ma[i]));
577/* the array s contains the traces of the powers of the matrix m,
578*  these are the power sums of the eigenvalues of m */
579  a = mpNew(1,n);
580  MATELEM(a,1,1) = minuscopy(MATELEM(s,1,1));
581  for (i=2; i<=n; i++)
582  {
583    p = pCopy(MATELEM(s,1,i));
584    for (j=i-1; j>=1; j--)
585    {
586      q = ppMult_qq(MATELEM(s,1,j), MATELEM(a,1,i-j));
587      pTest(q);
588      p = pAdd(p,q);
589    }
590    // c= -1/i
591    d = nInit(-(int)i);
592    c = nDiv(ONE, d);
593    nDelete(&d);
594
595    pMult_nn(p, c);
596    pTest(p);
597    MATELEM(a,1,i) = p;
598    nDelete(&c);
599  }
600/* the array a contains the elementary symmetric functions of the
601*  eigenvalues of m */
602  for (i=1; i<=n-1; i++)
603  {
604    //pDelete(&(MATELEM(a,1,i)));
605    pDelete(&(MATELEM(s,1,i)));
606  }
607  pDelete(&(MATELEM(s,1,n)));
608/* up to a sign, the determinant is the n-th elementary symmetric function */
609  if ((n/2)*2 < n)
610  {
611    d = nInit(-1);
612    pMult_nn(MATELEM(a,1,n), d);
613    nDelete(&d);
614  }
615  nDelete(&ONE);
616  idDelete((ideal *)&s);
617  poly result=MATELEM(a,1,n);
618  MATELEM(a,1,n)=NULL;
619  idDelete((ideal *)&a);
620  return result;
621}
622
623/*2
624* compute all ar-minors of the matrix a
625*/
626matrix mpWedge(matrix a, int ar)
627{
628  int     i,j,k,l;
629  int *rowchoise,*colchoise;
630  BOOLEAN rowch,colch;
631  matrix result;
632  matrix tmp;
633  poly p;
634
635  i = binom(a->nrows,ar);
636  j = binom(a->ncols,ar);
637
638  rowchoise=(int *)omAlloc(ar*sizeof(int));
639  colchoise=(int *)omAlloc(ar*sizeof(int));
640  result =mpNew(i,j);
641  tmp=mpNew(ar,ar);
642  l = 1; /* k,l:the index in result*/
643  idInitChoise(ar,1,a->nrows,&rowch,rowchoise);
644  while (!rowch)
645  {
646    k=1;
647    idInitChoise(ar,1,a->ncols,&colch,colchoise);
648    while (!colch)
649    {
650      for (i=1; i<=ar; i++)
651      {
652        for (j=1; j<=ar; j++)
653        {
654          MATELEM(tmp,i,j) = MATELEM(a,rowchoise[i-1],colchoise[j-1]);
655        }
656      }
657      p = mpDetBareiss(tmp);
658      if ((k+l) & 1) p=pNeg(p);
659      MATELEM(result,l,k) = p;
660      k++;
661      idGetNextChoise(ar,a->ncols,&colch,colchoise);
662    }
663    idGetNextChoise(ar,a->nrows,&rowch,rowchoise);
664    l++;
665  }
666
667  /*delete the matrix tmp*/
668  for (i=1; i<=ar; i++)
669  {
670    for (j=1; j<=ar; j++) MATELEM(tmp,i,j) = NULL;
671  }
672  idDelete((ideal *) &tmp);
673  return (result);
674}
675
676///*2
677//*homogenize all elements of matrix (not the matrix itself)
678//*/
679//matrix mpHomogen(matrix a, int v)
680//{
681//  int i,j;
682//  poly p;
683//
684//  for (i=1;i<=MATROWS(a);i++)
685//  {
686//    for (j=1;j<=MATCOLS(a);j++)
687//    {
688//      p=pHomogen(MATELEM(a,i,j),v);
689//      pDelete(&(MATELEM(a,i,j)));
690//      MATELEM(a,i,j)=p;
691//    }
692//  }
693//  return a;
694//}
695
696/*2
697* corresponds to Maple's coeffs:
698* var has to be the number of a variable
699*/
700matrix mpCoeffs (ideal I, int var)
701{
702  poly h,f;
703  int l, i, c, m=0;
704  matrix co;
705  /* look for maximal power m of x_var in I */
706  for (i=IDELEMS(I)-1; i>=0; i--)
707  {
708    f=I->m[i];
709    while (f!=NULL)
710    {
711      l=pGetExp(f,var);
712      if (l>m) m=l;
713      pIter(f);
714    }
715  }
716  co=mpNew((m+1)*I->rank,IDELEMS(I));
717  /* divide each monomial by a power of x_var,
718  * remember the power in l and the component in c*/
719  for (i=IDELEMS(I)-1; i>=0; i--)
720  {
721    f=I->m[i];
722    I->m[i]=NULL;
723    while (f!=NULL)
724    {
725      l=pGetExp(f,var);
726      pSetExp(f,var,0);
727      c=si_max((int)pGetComp(f),1);
728      pSetComp(f,0);
729      pSetm(f);
730      /* now add the resulting monomial to co*/
731      h=pNext(f);
732      pNext(f)=NULL;
733      //MATELEM(co,c*(m+1)-l,i+1)
734      //  =pAdd(MATELEM(co,c*(m+1)-l,i+1),f);
735      MATELEM(co,(c-1)*(m+1)+l+1,i+1)
736        =pAdd(MATELEM(co,(c-1)*(m+1)+l+1,i+1),f);
737      /* iterate f*/
738      f=h;
739    }
740  }
741  idDelete(&I);
742  return co;
743}
744
745/*2
746* given the result c of mpCoeffs(ideal/module i, var)
747* i of rank r
748* build the matrix of the corresponding monomials in m
749*/
750void   mpMonomials(matrix c, int r, int var, matrix m)
751{
752  /* clear contents of m*/
753  int k,l;
754  for (k=MATROWS(m);k>0;k--)
755  {
756    for(l=MATCOLS(m);l>0;l--)
757    {
758      pDelete(&MATELEM(m,k,l));
759    }
760  }
761  omfreeSize((ADDRESS)m->m,MATROWS(m)*MATCOLS(m)*sizeof(poly));
762  /* allocate monoms in the right size r x MATROWS(c)*/
763  m->m=(polyset)omAlloc0(r*MATROWS(c)*sizeof(poly));
764  MATROWS(m)=r;
765  MATCOLS(m)=MATROWS(c);
766  m->rank=r;
767  /* the maximal power p of x_var: MATCOLS(m)=r*(p+1) */
768  int p=MATCOLS(m)/r-1;
769  /* fill in the powers of x_var=h*/
770  poly h=pOne();
771  for(k=r;k>0; k--)
772  {
773    MATELEM(m,k,k*(p+1))=pOne();
774  }
775  for(l=p;l>=0; l--)
776  {
777    pSetExp(h,var,p-l);
778    pSetm(h);
779    for(k=r;k>0; k--)
780    {
781      MATELEM(m,k,k*(p+1)-l)=pCopy(h);
782    }
783  }
784  pDelete(&h);
785}
786
787matrix mpCoeffProc (poly f, poly vars)
788{
789  assume(vars!=NULL);
790  poly sel, h;
791  int l, i;
792  int pos_of_1 = -1;
793  matrix co;
794
795  if (f==NULL)
796  {
797    co = mpNew(2, 1);
798    MATELEM(co,1,1) = pOne();
799    MATELEM(co,2,1) = NULL;
800    return co;
801  }
802  sel = mpSelect(f, vars);
803  l = pLength(sel);
804  co = mpNew(2, l);
805  if (pOrdSgn==-1)
806  {
807    for (i=l; i>=1; i--)
808    {
809      h = sel;
810      pIter(sel);
811      pNext(h)=NULL;
812      MATELEM(co,1,i) = h;
813      MATELEM(co,2,i) = NULL;
814      if (pIsConstant(h)) pos_of_1 = i;
815    }
816  }
817  else
818  {
819    for (i=1; i<=l; i++)
820    {
821      h = sel;
822      pIter(sel);
823      pNext(h)=NULL;
824      MATELEM(co,1,i) = h;
825      MATELEM(co,2,i) = NULL;
826      if (pIsConstant(h)) pos_of_1 = i;
827    }
828  }
829  while (f!=NULL)
830  {
831    i = 1;
832    loop
833    {
834      if (i!=pos_of_1)
835      {
836        h = mpExdiv(f, MATELEM(co,1,i),vars);
837        if (h!=NULL)
838        {
839          MATELEM(co,2,i) = pAdd(MATELEM(co,2,i), h);
840          break;
841        }
842      }
843      if (i == l)
844      {
845        // check monom 1 last:
846        if (pos_of_1 != -1)
847        {
848          h = mpExdiv(f, MATELEM(co,1,pos_of_1),vars);
849          if (h!=NULL)
850          {
851            MATELEM(co,2,pos_of_1) = pAdd(MATELEM(co,2,pos_of_1), h);
852          }
853        }
854        break;
855      }
856      i ++;
857    }
858    pIter(f);
859  }
860  return co;
861}
862
863/*2
864*exact divisor: let d  == x^i*y^j, m is thought to have only one term;
865*    return m/d iff d divides m, and no x^k*y^l (k>i or l>j) divides m
866* consider all variables in vars
867*/
868static poly mpExdiv ( poly m, poly d, poly vars)
869{
870  int i;
871  poly h = pHead(m);
872  for (i=1; i<=pVariables; i++)
873  {
874    if (pGetExp(vars,i) > 0)
875    {
876      if (pGetExp(d,i) != pGetExp(h,i))
877      {
878        pDelete(&h);
879        return NULL;
880      }
881      pSetExp(h,i,0);
882    }
883  }
884  pSetm(h);
885  return h;
886}
887
888void mpCoef2(poly v, poly mon, matrix *c, matrix *m)
889{
890  polyset s;
891  poly p;
892  int sl,i,j;
893  int l=0;
894  poly sel=mpSelect(v,mon);
895
896  pVec2Polys(sel,&s,&sl);
897  for (i=0; i<sl; i++)
898    l=si_max(l,pLength(s[i]));
899  *c=mpNew(sl,l);
900  *m=mpNew(sl,l);
901  poly h;
902  int isConst;
903  for (j=1; j<=sl;j++)
904  {
905    p=s[j-1];
906    if (pIsConstant(p)) /*p != NULL */
907    {
908      isConst=-1;
909      i=l;
910    }
911    else
912    {
913      isConst=1;
914      i=1;
915    }
916    while(p!=NULL)
917    {
918      h = pHead(p);
919      MATELEM(*m,j,i) = h;
920      i+=isConst;
921      p = p->next;
922    }
923  }
924  while (v!=NULL)
925  {
926    i = 1;
927    j = pGetComp(v);
928    loop
929    {
930      poly mp=MATELEM(*m,j,i);
931      if (mp!=NULL)
932      {
933        h = mpExdiv(v, mp /*MATELEM(*m,j,i)*/, mp);
934        if (h!=NULL)
935        {
936          pSetComp(h,0);
937          MATELEM(*c,j,i) = pAdd(MATELEM(*c,j,i), h);
938          break;
939        }
940      }
941      if (i < l)
942        i++;
943      else
944        break;
945    }
946    v = v->next;
947  }
948}
949
950
951BOOLEAN mpEqual(matrix a, matrix b)
952{
953  if ((MATCOLS(a)!=MATCOLS(b)) || (MATROWS(a)!=MATROWS(b)))
954    return FALSE;
955  int i=MATCOLS(a)*MATROWS(b)-1;
956  while (i>=0)
957  {
958    if (a->m[i]==NULL)
959    {
960      if (b->m[i]!=NULL) return FALSE;
961    }
962    else
963      if (b->m[i]==NULL) return FALSE;
964      else if (pCmp(a->m[i],b->m[i])!=0) return FALSE;
965    i--;
966  }
967  i=MATCOLS(a)*MATROWS(b)-1;
968  while (i>=0)
969  {
970#if 0
971    poly tt=pSub(pCopy(a->m[i]),pCopy(b->m[i]));
972    if (tt!=NULL)
973    {
974      pDelete(&tt);
975      return FALSE;
976    }
977#else
978    if(!pEqualPolys(a->m[i],b->m[i])) return FALSE;
979#endif
980    i--;
981  }
982  return TRUE;
983}
984
985/* --------------- internal stuff ------------------- */
986
987row_col_weight::row_col_weight(int i, int j)
988{
989  ym = i;
990  yn = j;
991  wrow = (float *)omAlloc(i*sizeof(float));
992  wcol = (float *)omAlloc(j*sizeof(float));
993}
994
995row_col_weight::~row_col_weight()
996{
997  if (ym!=0)
998  {
999    omFreeSize((ADDRESS)wcol, yn*sizeof(float));
1000    omFreeSize((ADDRESS)wrow, ym*sizeof(float));
1001  }
1002}
1003
1004mp_permmatrix::mp_permmatrix(matrix A) : sign(1)
1005{
1006  a_m = A->nrows;
1007  a_n = A->ncols;
1008  this->mpInitMat();
1009  Xarray = A->m;
1010}
1011
1012mp_permmatrix::mp_permmatrix(mp_permmatrix *M)
1013{
1014  poly p, *athis, *aM;
1015  int i, j;
1016
1017  a_m = M->s_m;
1018  a_n = M->s_n;
1019  sign = M->sign;
1020  this->mpInitMat();
1021  Xarray = (poly *)omAlloc0(a_m*a_n*sizeof(poly));
1022  for (i=a_m-1; i>=0; i--)
1023  {
1024    athis = this->mpRowAdr(i);
1025    aM = M->mpRowAdr(i);
1026    for (j=a_n-1; j>=0; j--)
1027    {
1028      p = aM[M->qcol[j]];
1029      if (p)
1030      {
1031        athis[j] = pCopy(p);
1032      }
1033    }
1034  }
1035}
1036
1037mp_permmatrix::~mp_permmatrix()
1038{
1039  int k;
1040
1041  if (a_m != 0)
1042  {
1043    omFreeSize((ADDRESS)qrow,a_m*sizeof(int));
1044    omFreeSize((ADDRESS)qcol,a_n*sizeof(int));
1045    if (Xarray != NULL)
1046    {
1047      for (k=a_m*a_n-1; k>=0; k--)
1048        pDelete(&Xarray[k]);
1049      omFreeSize((ADDRESS)Xarray,a_m*a_n*sizeof(poly));
1050    }
1051  }
1052}
1053
1054int mp_permmatrix::mpGetRdim() { return s_m; }
1055
1056int mp_permmatrix::mpGetCdim() { return s_n; }
1057
1058int mp_permmatrix::mpGetSign() { return sign; }
1059
1060void mp_permmatrix::mpSetSearch(int s) { piv_s = s; }
1061
1062void mp_permmatrix::mpSaveArray() { Xarray = NULL; }
1063
1064poly mp_permmatrix::mpGetElem(int r, int c)
1065{
1066  return Xarray[a_n*qrow[r]+qcol[c]];
1067}
1068
1069void mp_permmatrix::mpSetElem(poly p, int r, int c)
1070{
1071  Xarray[a_n*qrow[r]+qcol[c]] = p;
1072}
1073
1074void mp_permmatrix::mpDelElem(int r, int c)
1075{
1076  pDelete(&Xarray[a_n*qrow[r]+qcol[c]]);
1077}
1078
1079/*
1080* the Bareiss-type elimination with division by div (div != NULL)
1081*/
1082void mp_permmatrix::mpElimBareiss(poly div)
1083{
1084  poly piv, elim, q1, q2, *ap, *a;
1085  int i, j, jj;
1086
1087  ap = this->mpRowAdr(s_m);
1088  piv = ap[qcol[s_n]];
1089  for(i=s_m-1; i>=0; i--)
1090  {
1091    a = this->mpRowAdr(i);
1092    elim = a[qcol[s_n]];
1093    if (elim != NULL)
1094    {
1095      elim = pNeg(elim);
1096      for (j=s_n-1; j>=0; j--)
1097      {
1098        q2 = NULL;
1099        jj = qcol[j];
1100        if (ap[jj] != NULL)
1101        {
1102          q2 = SM_MULT(ap[jj], elim, div);
1103          if (a[jj] != NULL)
1104          {
1105            q1 = SM_MULT(a[jj], piv, div);
1106            pDelete(&a[jj]);
1107            q2 = pAdd(q2, q1);
1108          }
1109        }
1110        else if (a[jj] != NULL)
1111        {
1112          q2 = SM_MULT(a[jj], piv, div);
1113        }
1114        if ((q2!=NULL) && div)
1115          SM_DIV(q2, div);
1116        a[jj] = q2;
1117      }
1118      pDelete(&a[qcol[s_n]]);
1119    }
1120    else
1121    {
1122      for (j=s_n-1; j>=0; j--)
1123      {
1124        jj = qcol[j];
1125        if (a[jj] != NULL)
1126        {
1127          q2 = SM_MULT(a[jj], piv, div);
1128          pDelete(&a[jj]);
1129          if (div)
1130            SM_DIV(q2, div);
1131          a[jj] = q2;
1132        }
1133      }
1134    }
1135  }
1136}
1137
1138/*2
1139* pivot strategy for Bareiss algorithm
1140*/
1141int mp_permmatrix::mpPivotBareiss(row_col_weight *C)
1142{
1143  poly p, *a;
1144  int i, j, iopt, jopt;
1145  float sum, f1, f2, fo, r, ro, lp;
1146  float *dr = C->wrow, *dc = C->wcol;
1147
1148  fo = 1.0e20;
1149  ro = 0.0;
1150  iopt = jopt = -1;
1151
1152  s_n--;
1153  s_m--;
1154  if (s_m == 0)
1155    return 0;
1156  if (s_n == 0)
1157  {
1158    for(i=s_m; i>=0; i--)
1159    {
1160      p = this->mpRowAdr(i)[qcol[0]];
1161      if (p)
1162      {
1163        f1 = mpPolyWeight(p);
1164        if (f1 < fo)
1165        {
1166          fo = f1;
1167          if (iopt >= 0)
1168            pDelete(&(this->mpRowAdr(iopt)[qcol[0]]));
1169          iopt = i;
1170        }
1171        else
1172          pDelete(&(this->mpRowAdr(i)[qcol[0]]));
1173      }
1174    }
1175    if (iopt >= 0)
1176      mpReplace(iopt, s_m, sign, qrow);
1177    return 0;
1178  }
1179  this->mpRowWeight(dr);
1180  this->mpColWeight(dc);
1181  sum = 0.0;
1182  for(i=s_m; i>=0; i--)
1183    sum += dr[i];
1184  for(i=s_m; i>=0; i--)
1185  {
1186    r = dr[i];
1187    a = this->mpRowAdr(i);
1188    for(j=s_n; j>=0; j--)
1189    {
1190      p = a[qcol[j]];
1191      if (p)
1192      {
1193        lp = mpPolyWeight(p);
1194        ro = r - lp;
1195        f1 = ro * (dc[j]-lp);
1196        if (f1 != 0.0)
1197        {
1198          f2 = lp * (sum - ro - dc[j]);
1199          f2 += f1;
1200        }
1201        else
1202          f2 = lp-r-dc[j];
1203        if (f2 < fo)
1204        {
1205          fo = f2;
1206          iopt = i;
1207          jopt = j;
1208        }
1209      }
1210    }
1211  }
1212  if (iopt < 0)
1213    return 0;
1214  mpReplace(iopt, s_m, sign, qrow);
1215  mpReplace(jopt, s_n, sign, qcol);
1216  return 1;
1217}
1218
1219/*2
1220* pivot strategy for Bareiss algorithm with defined row
1221*/
1222int mp_permmatrix::mpPivotRow(row_col_weight *C, int row)
1223{
1224  poly p, *a;
1225  int j, iopt, jopt;
1226  float sum, f1, f2, fo, r, ro, lp;
1227  float *dr = C->wrow, *dc = C->wcol;
1228
1229  fo = 1.0e20;
1230  ro = 0.0;
1231  iopt = jopt = -1;
1232
1233  s_n--;
1234  s_m--;
1235  if (s_m == 0)
1236    return 0;
1237  if (s_n == 0)
1238  {
1239    p = this->mpRowAdr(row)[qcol[0]];
1240    if (p)
1241    {
1242      f1 = mpPolyWeight(p);
1243      if (f1 < fo)
1244      {
1245        fo = f1;
1246        if (iopt >= 0)
1247        pDelete(&(this->mpRowAdr(iopt)[qcol[0]]));
1248        iopt = row;
1249      }
1250      else
1251        pDelete(&(this->mpRowAdr(row)[qcol[0]]));
1252    }
1253    if (iopt >= 0)
1254      mpReplace(iopt, s_m, sign, qrow);
1255    return 0;
1256  }
1257  this->mpRowWeight(dr);
1258  this->mpColWeight(dc);
1259  sum = 0.0;
1260  for(j=s_m; j>=0; j--)
1261    sum += dr[j];
1262  r = dr[row];
1263  a = this->mpRowAdr(row);
1264  for(j=s_n; j>=0; j--)
1265  {
1266    p = a[qcol[j]];
1267    if (p)
1268    {
1269      lp = mpPolyWeight(p);
1270      ro = r - lp;
1271      f1 = ro * (dc[j]-lp);
1272      if (f1 != 0.0)
1273      {
1274        f2 = lp * (sum - ro - dc[j]);
1275        f2 += f1;
1276      }
1277      else
1278        f2 = lp-r-dc[j];
1279      if (f2 < fo)
1280      {
1281        fo = f2;
1282        iopt = row;
1283        jopt = j;
1284      }
1285    }
1286  }
1287  if (iopt < 0)
1288    return 0;
1289  mpReplace(iopt, s_m, sign, qrow);
1290  mpReplace(jopt, s_n, sign, qcol);
1291  return 1;
1292}
1293
1294void mp_permmatrix::mpToIntvec(intvec *v)
1295{
1296  int i;
1297
1298  for (i=v->rows()-1; i>=0; i--)
1299    (*v)[i] = qcol[i]+1;
1300}
1301
1302void mp_permmatrix::mpRowReorder()
1303{
1304  int k, i, i1, i2;
1305
1306  if (a_m > a_n)
1307    k = a_m - a_n;
1308  else
1309    k = 0;
1310  for (i=a_m-1; i>=k; i--)
1311  {
1312    i1 = qrow[i];
1313    if (i1 != i)
1314    {
1315      this->mpRowSwap(i1, i);
1316      i2 = 0;
1317      while (qrow[i2] != i) i2++;
1318      qrow[i2] = i1;
1319    }
1320  }
1321}
1322
1323void mp_permmatrix::mpColReorder()
1324{
1325  int k, j, j1, j2;
1326
1327  if (a_n > a_m)
1328    k = a_n - a_m;
1329  else
1330    k = 0;
1331  for (j=a_n-1; j>=k; j--)
1332  {
1333    j1 = qcol[j];
1334    if (j1 != j)
1335    {
1336      this->mpColSwap(j1, j);
1337      j2 = 0;
1338      while (qcol[j2] != j) j2++;
1339      qcol[j2] = j1;
1340    }
1341  }
1342}
1343
1344// private
1345void mp_permmatrix::mpInitMat()
1346{
1347  int k;
1348
1349  s_m = a_m;
1350  s_n = a_n;
1351  piv_s = 0;
1352  qrow = (int *)omAlloc(a_m*sizeof(int));
1353  qcol = (int *)omAlloc(a_n*sizeof(int));
1354  for (k=a_m-1; k>=0; k--) qrow[k] = k;
1355  for (k=a_n-1; k>=0; k--) qcol[k] = k;
1356}
1357
1358poly * mp_permmatrix::mpRowAdr(int r)
1359{
1360  return &(Xarray[a_n*qrow[r]]);
1361}
1362
1363poly * mp_permmatrix::mpColAdr(int c)
1364{
1365  return &(Xarray[qcol[c]]);
1366}
1367
1368void mp_permmatrix::mpRowWeight(float *wrow)
1369{
1370  poly p, *a;
1371  int i, j;
1372  float count;
1373
1374  for (i=s_m; i>=0; i--)
1375  {
1376    a = this->mpRowAdr(i);
1377    count = 0.0;
1378    for(j=s_n; j>=0; j--)
1379    {
1380      p = a[qcol[j]];
1381      if (p)
1382        count += mpPolyWeight(p);
1383    }
1384    wrow[i] = count;
1385  }
1386}
1387
1388void mp_permmatrix::mpColWeight(float *wcol)
1389{
1390  poly p, *a;
1391  int i, j;
1392  float count;
1393
1394  for (j=s_n; j>=0; j--)
1395  {
1396    a = this->mpColAdr(j);
1397    count = 0.0;
1398    for(i=s_m; i>=0; i--)
1399    {
1400      p = a[a_n*qrow[i]];
1401      if (p)
1402        count += mpPolyWeight(p);
1403    }
1404    wcol[j] = count;
1405  }
1406}
1407
1408void mp_permmatrix::mpRowSwap(int i1, int i2)
1409{
1410   poly p, *a1, *a2;
1411   int j;
1412
1413   a1 = &(Xarray[a_n*i1]);
1414   a2 = &(Xarray[a_n*i2]);
1415   for (j=a_n-1; j>= 0; j--)
1416   {
1417     p = a1[j];
1418     a1[j] = a2[j];
1419     a2[j] = p;
1420   }
1421}
1422
1423void mp_permmatrix::mpColSwap(int j1, int j2)
1424{
1425   poly p, *a1, *a2;
1426   int i, k = a_n*a_m;
1427
1428   a1 = &(Xarray[j1]);
1429   a2 = &(Xarray[j2]);
1430   for (i=0; i< k; i+=a_n)
1431   {
1432     p = a1[i];
1433     a1[i] = a2[i];
1434     a2[i] = p;
1435   }
1436}
1437
1438int mp_permmatrix::mpGetRow()
1439{
1440  return qrow[s_m];
1441}
1442
1443int mp_permmatrix::mpGetCol()
1444{
1445  return qcol[s_n];
1446}
1447
1448/*
1449* perform replacement for pivot strategy in Bareiss algorithm
1450* change sign of determinant
1451*/
1452static void mpReplace(int j, int n, int &sign, int *perm)
1453{
1454  int k;
1455
1456  if (j != n)
1457  {
1458    k = perm[n];
1459    perm[n] = perm[j];
1460    perm[j] = k;
1461    sign = -sign;
1462  }
1463}
1464
1465static int mpNextperm(perm * z, int max)
1466{
1467  int s, i, k, t;
1468  s = max;
1469  do
1470  {
1471    s--;
1472  }
1473  while ((s > 0) && ((*z)[s] >= (*z)[s+1]));
1474  if (s==0)
1475    return 0;
1476  do
1477  {
1478    (*z)[s]++;
1479    k = 0;
1480    do
1481    {
1482      k++;
1483    }
1484    while (((*z)[k] != (*z)[s]) && (k!=s));
1485  }
1486  while (k < s);
1487  for (i=s+1; i <= max; i++)
1488  {
1489    (*z)[i]=0;
1490    do
1491    {
1492      (*z)[i]++;
1493      k=0;
1494      do
1495      {
1496        k++;
1497      }
1498      while (((*z)[k] != (*z)[i]) && (k != i));
1499    }
1500    while (k < i);
1501  }
1502  s = max+1;
1503  do
1504  {
1505    s--;
1506  }
1507  while ((s > 0) && ((*z)[s] > (*z)[s+1]));
1508  t = 1;
1509  for (i=1; i<max; i++)
1510    for (k=i+1; k<=max; k++)
1511      if ((*z)[k] < (*z)[i])
1512        t = -t;
1513  (*z)[0] = t;
1514  return s;
1515}
1516
1517static poly mpLeibnitz(matrix a)
1518{
1519  int i, e, n;
1520  poly p, d;
1521  perm z;
1522
1523  n = MATROWS(a);
1524  memset(&z,0,(n+2)*sizeof(int));
1525  p = pOne();
1526  for (i=1; i <= n; i++)
1527    p = pMult(p, pCopy(MATELEM(a, i, i)));
1528  d = p;
1529  for (i=1; i<= n; i++)
1530    z[i] = i;
1531  z[0]=1;
1532  e = 1;
1533  if (n!=1)
1534  {
1535    while (e)
1536    {
1537      e = mpNextperm((perm *)&z, n);
1538      p = pOne();
1539      for (i = 1; i <= n; i++)
1540        p = pMult(p, pCopy(MATELEM(a, i, z[i])));
1541      if (z[0] > 0)
1542        d = pAdd(d, p);
1543      else
1544        d = pSub(d, p);
1545    }
1546  }
1547  return d;
1548}
1549
1550static poly minuscopy (poly p)
1551{
1552  poly w;
1553  number  e;
1554  e = nInit(-1);
1555  w = pCopy(p);
1556  pMult_nn(w, e);
1557  nDelete(&e);
1558  return w;
1559}
1560
1561/*2
1562* insert a monomial into a list, avoid duplicates
1563* arguments are destroyed
1564*/
1565static poly pInsert(poly p1, poly p2)
1566{
1567  poly a1, p, a2, a;
1568  int c;
1569
1570  if (p1==NULL) return p2;
1571  if (p2==NULL) return p1;
1572  a1 = p1;
1573  a2 = p2;
1574  a = p  = pOne();
1575  loop
1576  {
1577    c = pCmp(a1, a2);
1578    if (c == 1)
1579    {
1580      a = pNext(a) = a1;
1581      pIter(a1);
1582      if (a1==NULL)
1583      {
1584        pNext(a) = a2;
1585        break;
1586      }
1587    }
1588    else if (c == -1)
1589    {
1590      a = pNext(a) = a2;
1591      pIter(a2);
1592      if (a2==NULL)
1593      {
1594        pNext(a) = a1;
1595        break;
1596      }
1597    }
1598    else
1599    {
1600      pLmDelete(&a2);
1601      a = pNext(a) = a1;
1602      pIter(a1);
1603      if (a1==NULL)
1604      {
1605        pNext(a) = a2;
1606        break;
1607      }
1608      else if (a2==NULL)
1609      {
1610        pNext(a) = a1;
1611        break;
1612      }
1613    }
1614  }
1615  pLmDelete(&p);
1616  return p;
1617}
1618
1619/*2
1620*if what == xy the result is the list of all different power products
1621*    x^i*y^j (i, j >= 0) that appear in fro
1622*/
1623static poly mpSelect (poly fro, poly what)
1624{
1625  int i;
1626  poly h, res;
1627  res = NULL;
1628  while (fro!=NULL)
1629  {
1630    h = pOne();
1631    for (i=1; i<=pVariables; i++)
1632      pSetExp(h,i, pGetExp(fro,i) * pGetExp(what, i));
1633    pSetComp(h, pGetComp(fro));
1634    pSetm(h);
1635    res = pInsert(h, res);
1636    fro = fro->next;
1637  }
1638  return res;
1639}
1640
1641/*
1642*static void ppp(matrix a)
1643*{
1644*  int j,i,r=a->nrows,c=a->ncols;
1645*  for(j=1;j<=r;j++)
1646*  {
1647*    for(i=1;i<=c;i++)
1648*    {
1649*      if(MATELEM(a,j,i)!=NULL) Print("X");
1650*      else Print("0");
1651*    }
1652*    Print("\n");
1653*  }
1654*}
1655*/
1656
1657static void mpPartClean(matrix a, int lr, int lc)
1658{
1659  poly *q1;
1660  int i,j;
1661
1662  for (i=lr-1;i>=0;i--)
1663  {
1664    q1 = &(a->m)[i*a->ncols];
1665    for (j=lc-1;j>=0;j--) if(q1[j]) pDelete(&q1[j]);
1666  }
1667}
1668
1669static void mpFinalClean(matrix a)
1670{
1671  omFreeSize((ADDRESS)a->m,a->nrows*a->ncols*sizeof(poly));
1672  omFreeBin((ADDRESS)a, ip_smatrix_bin);
1673}
1674
1675/*2
1676*  prepare one step of 'Bareiss' algorithm
1677*  for application in minor
1678*/
1679static int mpPrepareRow (matrix a, int lr, int lc)
1680{
1681  int r;
1682
1683  r = mpPivBar(a,lr,lc);
1684  if(r==0) return 0;
1685  if(r<lr) mpSwapRow(a, r, lr, lc);
1686  return 1;
1687}
1688
1689/*2
1690*  prepare one step of 'Bareiss' algorithm
1691*  for application in minor
1692*/
1693static int mpPreparePiv (matrix a, int lr, int lc)
1694{
1695  int c;
1696
1697  c = mpPivRow(a, lr, lc);
1698  if(c==0) return 0;
1699  if(c<lc) mpSwapCol(a, c, lr, lc);
1700  return 1;
1701}
1702
1703/*
1704* find best row
1705*/
1706static int mpPivBar(matrix a, int lr, int lc)
1707{
1708  float f1, f2;
1709  poly *q1;
1710  int i,j,io;
1711
1712  io = -1;
1713  f1 = 1.0e30;
1714  for (i=lr-1;i>=0;i--)
1715  {
1716    q1 = &(a->m)[i*a->ncols];
1717    f2 = 0.0;
1718    for (j=lc-1;j>=0;j--)
1719    {
1720      if (q1[j]!=NULL)
1721        f2 += mpPolyWeight(q1[j]);
1722    }
1723    if ((f2!=0.0) && (f2<f1))
1724    {
1725      f1 = f2;
1726      io = i;
1727    }
1728  }
1729  if (io<0) return 0;
1730  else return io+1;
1731}
1732
1733/*
1734* find pivot in the last row
1735*/
1736static int mpPivRow(matrix a, int lr, int lc)
1737{
1738  float f1, f2;
1739  poly *q1;
1740  int j,jo;
1741
1742  jo = -1;
1743  f1 = 1.0e30;
1744  q1 = &(a->m)[(lr-1)*a->ncols];
1745  for (j=lc-1;j>=0;j--)
1746  {
1747    if (q1[j]!=NULL)
1748    {
1749      f2 = mpPolyWeight(q1[j]);
1750      if (f2<f1)
1751      {
1752        f1 = f2;
1753        jo = j;
1754      }
1755    }
1756  }
1757  if (jo<0) return 0;
1758  else return jo+1;
1759}
1760
1761/*
1762* weigth of a polynomial, for pivot strategy
1763*/
1764static float mpPolyWeight(poly p)
1765{
1766  int i;
1767  float res;
1768
1769  if (pNext(p) == NULL)
1770  {
1771    res = (float)nSize(pGetCoeff(p));
1772    for (i=pVariables;i>0;i--)
1773    {
1774      if(pGetExp(p,i)!=0)
1775      {
1776        res += 2.0;
1777        break;
1778      }
1779    }
1780  }
1781  else
1782  {
1783    res = 0.0;
1784    do
1785    {
1786      res += (float)nSize(pGetCoeff(p))+2.0;
1787      pIter(p);
1788    }
1789    while (p);
1790  }
1791  return res;
1792}
1793
1794static void mpSwapRow(matrix a, int pos, int lr, int lc)
1795{
1796  poly sw;
1797  int j;
1798  polyset a2 = a->m, a1 = &a2[a->ncols*(pos-1)];
1799
1800  a2 = &a2[a->ncols*(lr-1)];
1801  for (j=lc-1; j>=0; j--)
1802  {
1803    sw = a1[j];
1804    a1[j] = a2[j];
1805    a2[j] = sw;
1806  }
1807}
1808
1809static void mpSwapCol(matrix a, int pos, int lr, int lc)
1810{
1811  poly sw;
1812  int j;
1813  polyset a2 = a->m, a1 = &a2[pos-1];
1814
1815  a2 = &a2[lc-1];
1816  for (j=a->ncols*(lr-1); j>=0; j-=a->ncols)
1817  {
1818    sw = a1[j];
1819    a1[j] = a2[j];
1820    a2[j] = sw;
1821  }
1822}
1823
1824static void mpElimBar(matrix a0, matrix re, poly div, int lr, int lc)
1825{
1826  int r=lr-1, c=lc-1;
1827  poly *b = a0->m, *x = re->m;
1828  poly piv, elim, q1, q2, *ap, *a, *q;
1829  int i, j;
1830
1831  ap = &b[r*a0->ncols];
1832  piv = ap[c];
1833  for(j=c-1; j>=0; j--)
1834    if (ap[j] != NULL) ap[j] = pNeg(ap[j]);
1835  for(i=r-1; i>=0; i--)
1836  {
1837    a = &b[i*a0->ncols];
1838    q = &x[i*re->ncols];
1839    if (a[c] != NULL)
1840    {
1841      elim = a[c];
1842      for (j=c-1; j>=0; j--)
1843      {
1844        q1 = NULL;
1845        if (a[j] != NULL)
1846        {
1847          q1 = SM_MULT(a[j], piv, div);
1848          if (ap[j] != NULL)
1849          {
1850            q2 = SM_MULT(ap[j], elim, div);
1851            q1 = pAdd(q1,q2);
1852          }
1853        }
1854        else if (ap[j] != NULL)
1855          q1 = SM_MULT(ap[j], elim, div);
1856        if (q1 != NULL)
1857        {
1858          if (div)
1859            SM_DIV(q1, div);                               
1860          q[j] = q1;
1861        }
1862      }
1863    }
1864    else
1865    {
1866      for (j=c-1; j>=0; j--)
1867      {
1868        if (a[j] != NULL)
1869        {
1870          q1 = SM_MULT(a[j], piv, div);
1871          if (div)
1872            SM_DIV(q1, div);                               
1873          q[j] = q1;
1874        }
1875      }
1876    }
1877  }
1878}
1879
1880BOOLEAN mpIsDiagUnit(matrix U)
1881{
1882  if(MATROWS(U)!=MATCOLS(U))
1883    return FALSE;
1884  for(int i=MATCOLS(U);i>=1;i--)
1885  {
1886    for(int j=MATCOLS(U); j>=1; j--)
1887    {
1888      if (i==j)
1889      {
1890        if (!pIsUnit(MATELEM(U,i,i))) return FALSE;
1891      }
1892      else if (MATELEM(U,i,j)!=NULL) return FALSE;
1893    }
1894  }
1895  return TRUE;
1896}
1897
1898void iiWriteMatrix(matrix im, const char *n, int dim,int spaces)
1899{
1900  int i,ii = MATROWS(im)-1;
1901  int j,jj = MATCOLS(im)-1;
1902  poly *pp = im->m;
1903
1904  for (i=0; i<=ii; i++)
1905  {
1906    for (j=0; j<=jj; j++)
1907    {
1908      if (spaces>0)
1909        Print("%-*.*s",spaces,spaces," ");
1910      if (dim == 2) Print("%s[%u,%u]=",n,i+1,j+1);
1911      else if (dim == 1) Print("%s[%u]=",n,j+1);
1912      else if (dim == 0) Print("%s=",n);
1913      if ((i<ii)||(j<jj)) pWrite(*pp++);
1914      else                pWrite0(*pp);
1915    }
1916  }
1917}
1918
1919char * iiStringMatrix(matrix im, int dim,char ch)
1920{
1921  int i,ii = MATROWS(im);
1922  int j,jj = MATCOLS(im);
1923  poly *pp = im->m;
1924  char *s=StringSetS("");
1925
1926  for (i=0; i<ii; i++)
1927  {
1928    for (j=0; j<jj; j++)
1929    {
1930      pString0(*pp++);
1931      s=StringAppend("%c",ch);
1932      if (dim > 1) s = StringAppendS("\n");
1933    }
1934  }
1935  s[strlen(s)- (dim > 1 ? 2 : 1)]='\0';
1936  return s;
1937}
1938
1939void   mpDelete(matrix* a, const ring r)
1940{
1941  id_Delete((ideal *) a, r);
1942}
Note: See TracBrowser for help on using the repository browser.