source: git/Singular/matpol.cc @ 138f0c

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