source: git/Singular/matpol.cc @ 00f47b

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