source: git/Singular/matpol.cc @ 2f436b

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