source: git/Singular/matpol.cc @ c232af

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