source: git/kernel/matpol.cc @ 4e35a89

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