source: git/Singular/matpol.cc @ f99917f

spielwiese
Last change on this file since f99917f was f99917f, checked in by Hans Schönemann <hannes@…>, 25 years ago
* hannes: added "highcorner" for modules (iparith, ipshell) fixed rWrite (ring.cc) fixed mpCoef (matpol.cc) git-svn-id: file:///usr/local/Singular/svn/trunk@2904 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 30.8 KB
Line 
1/****************************************
2*  Computer Algebra System SINGULAR     *
3****************************************/
4/* $Id: matpol.cc,v 1.22 1999-03-11 15:58:08 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        h = mpExdiv(f, MATELEM(co,1,pos_of_1));
837        if (h!=NULL)
838        {
839          MATELEM(co,2,pos_of_1) = pAdd(MATELEM(co,2,pos_of_1), h);
840          break;
841        }
842        break;
843      } 
844      i ++;
845    }
846    pIter(f);
847  }
848  return co;
849}
850
851void mpCoef2(poly v, poly mon, matrix *c, matrix *m)
852{
853  polyset s;
854  poly p;
855  int sl,i,j;
856  int l=0;
857  poly sel=mpSelect(v,mon);
858
859  pVec2Polys(sel,&s,&sl);
860  for (i=0; i<sl; i++)
861    l=max(l,pLength(s[i]));
862  *c=mpNew(sl,l);
863  *m=mpNew(sl,l);
864  poly h;
865  int isConst;
866  for (j=1; j<=sl;j++)
867  {
868    p=s[j-1];
869    if (pIsConstant(p)) /*p != NULL */
870    {
871      isConst=-1;
872      i=l;
873    }
874    else
875    {
876      isConst=1;
877      i=1;
878    }
879    while(p!=NULL)
880    {
881      h = pHead(p);
882      MATELEM(*m,j,i) = h;
883      i+=isConst;
884      p = p->next;
885    }
886  }
887  while (v!=NULL)
888  {
889    i = 1;
890    j = pGetComp(v);
891    loop
892    {
893      poly mp=MATELEM(*m,j,i);
894      if (mp!=NULL)
895      {
896        h = mpExdiv(v, mp /*MATELEM(*m,j,i)*/);
897        if (h!=NULL)
898        {
899          pSetComp(h,0);
900          MATELEM(*c,j,i) = pAdd(MATELEM(*c,j,i), h);
901          break;
902        }
903      }
904      if (i < l)
905        i++;
906      else
907        break;
908    }
909    v = v->next;
910  }
911}
912
913
914BOOLEAN mpEqual(matrix a, matrix b)
915{
916  if ((MATCOLS(a)!=MATCOLS(b)) || (MATROWS(a)!=MATROWS(b)))
917    return FALSE;
918  int i=MATCOLS(a)*MATROWS(b)-1;
919  while (i>=0)
920  {
921    if (a->m[i]==NULL)
922    {
923      if (b->m[i]!=NULL) return FALSE;
924    }
925    else
926      if (pComp(a->m[i],b->m[i])!=0) return FALSE;
927    i--;
928  }
929  i=MATCOLS(a)*MATROWS(b)-1;
930  while (i>=0)
931  {
932    if (pSub(pCopy(a->m[i]),pCopy(b->m[i]))!=NULL) return FALSE;
933    i--;
934  }
935  return TRUE;
936}
937
938/* --------------- internal stuff ------------------- */
939
940row_col_weight::row_col_weight(int i, int j)
941{
942  ym = i;
943  yn = j;
944  wrow = (float *)Alloc(i*sizeof(float));
945  wcol = (float *)Alloc(j*sizeof(float));
946}
947
948row_col_weight::~row_col_weight()
949{
950  if (ym!=0)
951  {
952    Free((ADDRESS)wcol, yn*sizeof(float));
953    Free((ADDRESS)wrow, ym*sizeof(float));
954  }
955}
956
957mp_permmatrix::mp_permmatrix(matrix A) : sign(1)
958{
959  a_m = A->nrows;
960  a_n = A->ncols;
961  this->mpInitMat();
962  Xarray = A->m;
963}
964
965mp_permmatrix::mp_permmatrix(mp_permmatrix *M)
966{
967  poly p, *athis, *aM;
968  int i, j;
969
970  a_m = M->s_m;
971  a_n = M->s_n;
972  sign = M->sign;
973  this->mpInitMat();
974  Xarray = (poly *)Alloc0(a_m*a_n*sizeof(poly));
975  for (i=a_m-1; i>=0; i--)
976  {
977    athis = this->mpRowAdr(i);
978    aM = M->mpRowAdr(i);
979    for (j=a_n-1; j>=0; j--)
980    {
981      p = aM[M->qcol[j]];
982      if (p)
983      {
984        athis[j] = pCopy(p);
985      }
986    }
987  }
988}
989
990mp_permmatrix::~mp_permmatrix()
991{
992  int k;
993
994  if (a_m != 0)
995  {
996    Free((ADDRESS)qrow,a_m*sizeof(int));
997    Free((ADDRESS)qcol,a_n*sizeof(int));
998    if (Xarray != NULL)
999    {
1000      for (k=a_m*a_n-1; k>=0; k--)
1001        pDelete(&Xarray[k]);
1002      Free((ADDRESS)Xarray,a_m*a_n*sizeof(poly));
1003    }
1004  }
1005}
1006
1007int mp_permmatrix::mpGetRdim() { return s_m; }
1008
1009int mp_permmatrix::mpGetCdim() { return s_n; }
1010
1011int mp_permmatrix::mpGetSign() { return sign; }
1012
1013void mp_permmatrix::mpSetSearch(int s) { piv_s = s; }
1014
1015void mp_permmatrix::mpSaveArray() { Xarray = NULL; }
1016
1017poly mp_permmatrix::mpGetElem(int r, int c)
1018{
1019  return Xarray[a_n*qrow[r]+qcol[c]];
1020}
1021
1022void mp_permmatrix::mpSetElem(poly p, int r, int c)
1023{
1024  Xarray[a_n*qrow[r]+qcol[c]] = p;
1025}
1026
1027void mp_permmatrix::mpDelElem(int r, int c)
1028{
1029  pDelete(&Xarray[a_n*qrow[r]+qcol[c]]);
1030}
1031
1032/*
1033* the Bareiss-type elimination with division by div (div != NULL)
1034*/
1035void mp_permmatrix::mpElimBareiss(poly div)
1036{
1037  poly piv, elim, q1, q2, *ap, *a;
1038  int i, j, jj;
1039
1040  ap = this->mpRowAdr(s_m);
1041  piv = ap[qcol[s_n]];
1042  for(i=s_m-1; i>=0; i--)
1043  {
1044    a = this->mpRowAdr(i);
1045    elim = a[qcol[s_n]];
1046    if (elim != NULL)
1047    {
1048      for (j=s_n-1; j>=0; j--)
1049      {
1050        q2 = NULL;
1051        jj = qcol[j];
1052        q1 = a[jj];
1053        if (ap[jj] != NULL)
1054        {
1055          q2 = pNeg(pCopy(ap[jj]));
1056          q2 = pMult(q2, pCopy(elim));
1057          if (q1 != NULL)
1058          {
1059            q1 = pMult(q1,pCopy(piv));
1060            q2 = pAdd(q2, q1);
1061          }
1062        }
1063        else if (q1 != NULL)
1064        {
1065          q2 = pMult(q1, pCopy(piv));
1066        }
1067        if ((q2!=NULL) && div)
1068          q2 = mpDivide(q2, div);
1069        a[jj] = q2;
1070      }
1071      pDelete(&a[qcol[s_n]]);
1072    }
1073    else
1074    {
1075      for (j=s_n-1; j>=0; j--)
1076      {
1077        jj = qcol[j];
1078        q1 = a[jj];
1079        if (q1 != NULL)
1080        {
1081          q1 = pMult(q1, pCopy(piv));
1082          if (div)
1083            q1 = mpDivide(q1, div);
1084          a[jj] = q1;
1085        }
1086      }
1087    }
1088  }
1089}
1090
1091/*2
1092* pivot strategy for Bareiss algorithm
1093*/
1094int mp_permmatrix::mpPivotBareiss(row_col_weight *C)
1095{
1096  poly p, *a;
1097  int i, j, iopt, jopt;
1098  float sum, f1, f2, fo, r, ro, lp;
1099  float *dr = C->wrow, *dc = C->wcol;
1100
1101  fo = 1.0e20;
1102  ro = 0.0;
1103  iopt = jopt = -1;
1104
1105  s_n--;
1106  s_m--;
1107  if (s_m == 0)
1108    return 0;
1109  if (s_n == 0)
1110  {
1111    for(i=s_m; i>=0; i--)
1112    {
1113      p = this->mpRowAdr(i)[qcol[0]];
1114      if (p)
1115      {
1116        f1 = mpPolyWeight(p);
1117        if (f1 < fo)
1118        {
1119          fo = f1;
1120          if (iopt >= 0)
1121            pDelete(&(this->mpRowAdr(iopt)[qcol[0]]));
1122          iopt = i;
1123        }
1124        else
1125          pDelete(&(this->mpRowAdr(i)[qcol[0]]));
1126      }
1127    }
1128    if (iopt >= 0)
1129      mpReplace(iopt, s_m, sign, qrow);
1130    return 0;
1131  }
1132  this->mpRowWeight(dr);
1133  this->mpColWeight(dc);
1134  sum = 0.0;
1135  for(i=s_m; i>=0; i--)
1136    sum += dr[i];
1137  for(i=s_m; i>=0; i--)
1138  {
1139    r = dr[i];
1140    a = this->mpRowAdr(i);
1141    for(j=s_n; j>=0; j--)
1142    {
1143      p = a[qcol[j]];
1144      if (p)
1145      {
1146        lp = mpPolyWeight(p);
1147        ro = r - lp;
1148        f1 = ro * (dc[j]-lp);
1149        if (f1 != 0.0)
1150        {
1151          f2 = lp * (sum - ro - dc[j]);
1152          f2 += f1;
1153        }
1154        else
1155          f2 = lp-r-dc[j];
1156        if (f2 < fo)
1157        {
1158          fo = f2;
1159          iopt = i;
1160          jopt = j;
1161        }
1162      }
1163    }
1164  }
1165  if (iopt < 0)
1166    return 0;
1167  mpReplace(iopt, s_m, sign, qrow);
1168  mpReplace(jopt, s_n, sign, qcol);
1169  return 1;
1170}
1171
1172/*2
1173* pivot strategy for Bareiss algorithm with defined row
1174*/
1175int mp_permmatrix::mpPivotRow(row_col_weight *C, int row)
1176{
1177  poly p, *a;
1178  int j, iopt, jopt;
1179  float sum, f1, f2, fo, r, ro, lp;
1180  float *dr = C->wrow, *dc = C->wcol;
1181
1182  fo = 1.0e20;
1183  ro = 0.0;
1184  iopt = jopt = -1;
1185
1186  s_n--;
1187  s_m--;
1188  if (s_m == 0)
1189    return 0;
1190  if (s_n == 0)
1191  {
1192    p = this->mpRowAdr(row)[qcol[0]];
1193    if (p)
1194    {
1195      f1 = mpPolyWeight(p);
1196      if (f1 < fo)
1197      {
1198        fo = f1;
1199        if (iopt >= 0)
1200        pDelete(&(this->mpRowAdr(iopt)[qcol[0]]));
1201        iopt = row;
1202      }
1203      else
1204        pDelete(&(this->mpRowAdr(row)[qcol[0]]));
1205    }
1206    if (iopt >= 0)
1207      mpReplace(iopt, s_m, sign, qrow);
1208    return 0;
1209  }
1210  this->mpRowWeight(dr);
1211  this->mpColWeight(dc);
1212  sum = 0.0;
1213  for(j=s_m; j>=0; j--)
1214    sum += dr[j];
1215  r = dr[row];
1216  a = this->mpRowAdr(row);
1217  for(j=s_n; j>=0; j--)
1218  {
1219    p = a[qcol[j]];
1220    if (p)
1221    {
1222      lp = mpPolyWeight(p);
1223      ro = r - lp;
1224      f1 = ro * (dc[j]-lp);
1225      if (f1 != 0.0)
1226      {
1227        f2 = lp * (sum - ro - dc[j]);
1228        f2 += f1;
1229      }
1230      else
1231        f2 = lp-r-dc[j];
1232      if (f2 < fo)
1233      {
1234        fo = f2;
1235        iopt = row;
1236        jopt = j;
1237      }
1238    }
1239  }
1240  if (iopt < 0)
1241    return 0;
1242  mpReplace(iopt, s_m, sign, qrow);
1243  mpReplace(jopt, s_n, sign, qcol);
1244  return 1;
1245}
1246
1247void mp_permmatrix::mpToIntvec(intvec *v)
1248{
1249  int i;
1250
1251  for (i=v->rows()-1; i>=0; i--)
1252    (*v)[i] = qcol[i]+1;
1253}
1254
1255void mp_permmatrix::mpRowReorder()
1256{
1257  int k, i, i1, i2;
1258
1259  if (a_m > a_n)
1260    k = a_m - a_n;
1261  else
1262    k = 0;
1263  for (i=a_m-1; i>=k; i--)
1264  {
1265    i1 = qrow[i];
1266    if (i1 != i)
1267    {
1268      this->mpRowSwap(i1, i);
1269      i2 = 0;
1270      while (qrow[i2] != i) i2++;
1271      qrow[i2] = i1;
1272    }
1273  }
1274}
1275
1276void mp_permmatrix::mpColReorder()
1277{
1278  int k, j, j1, j2;
1279
1280  if (a_n > a_m)
1281    k = a_n - a_m;
1282  else
1283    k = 0;
1284  for (j=a_n-1; j>=k; j--)
1285  {
1286    j1 = qcol[j];
1287    if (j1 != j)
1288    {
1289      this->mpColSwap(j1, j);
1290      j2 = 0;
1291      while (qcol[j2] != j) j2++;
1292      qcol[j2] = j1;
1293    }
1294  }
1295}
1296
1297// private
1298void mp_permmatrix::mpInitMat()
1299{
1300  int k;
1301
1302  s_m = a_m;
1303  s_n = a_n;
1304  piv_s = 0;
1305  qrow = (int *)Alloc(a_m*sizeof(int));
1306  qcol = (int *)Alloc(a_n*sizeof(int));
1307  for (k=a_m-1; k>=0; k--) qrow[k] = k;
1308  for (k=a_n-1; k>=0; k--) qcol[k] = k;
1309}
1310
1311poly * mp_permmatrix::mpRowAdr(int r)
1312{
1313  return &(Xarray[a_n*qrow[r]]);
1314}
1315
1316poly * mp_permmatrix::mpColAdr(int c)
1317{
1318  return &(Xarray[qcol[c]]);
1319}
1320
1321void mp_permmatrix::mpRowWeight(float *wrow)
1322{
1323  poly p, *a;
1324  int i, j;
1325  float count;
1326
1327  for (i=s_m; i>=0; i--)
1328  {
1329    a = this->mpRowAdr(i);
1330    count = 0.0;
1331    for(j=s_n; j>=0; j--)
1332    {
1333      p = a[qcol[j]];
1334      if (p)
1335        count += mpPolyWeight(p);
1336    }
1337    wrow[i] = count;
1338  }
1339}
1340
1341void mp_permmatrix::mpColWeight(float *wcol)
1342{
1343  poly p, *a;
1344  int i, j;
1345  float count;
1346
1347  for (j=s_n; j>=0; j--)
1348  {
1349    a = this->mpColAdr(j);
1350    count = 0.0;
1351    for(i=s_m; i>=0; i--)
1352    {
1353      p = a[a_n*qrow[i]];
1354      if (p)
1355        count += mpPolyWeight(p);
1356    }
1357    wcol[j] = count;
1358  }
1359}
1360
1361void mp_permmatrix::mpRowSwap(int i1, int i2)
1362{
1363   poly p, *a1, *a2;
1364   int j;
1365
1366   a1 = &(Xarray[a_n*i1]);
1367   a2 = &(Xarray[a_n*i2]);
1368   for (j=a_n-1; j>= 0; j--)
1369   {
1370     p = a1[j];
1371     a1[j] = a2[j];
1372     a2[j] = p;
1373   }
1374}
1375
1376void mp_permmatrix::mpColSwap(int j1, int j2)
1377{
1378   poly p, *a1, *a2;
1379   int i, k = a_n*a_m;
1380
1381   a1 = &(Xarray[j1]);
1382   a2 = &(Xarray[j2]);
1383   for (i=0; i< k; i+=a_n)
1384   {
1385     p = a1[i];
1386     a1[i] = a2[i];
1387     a2[i] = p;
1388   }
1389}
1390
1391int mp_permmatrix::mpGetRow()
1392{
1393  return qrow[s_m];
1394}
1395
1396int mp_permmatrix::mpGetCol()
1397{
1398  return qcol[s_n];
1399}
1400
1401/*2
1402* exact division a/b, used in Bareiss algorithm
1403* a destroyed, b NOT destroyed
1404*/
1405static poly mpDivide(poly a, poly b)
1406{
1407  number x, y, z;
1408  poly r, tail, t, h, h0;
1409  int i, deg;
1410
1411  r = a;
1412  x = pGetCoeff(b);
1413  deg = pTotaldegree(b);
1414  tail = pNext(b);
1415  if (tail == NULL)
1416  {
1417    do
1418    {
1419      if (deg != 0)
1420      {
1421        for (i=pVariables; i; i--)
1422          pSubExp(r,i,  pGetExp(b,i));
1423        pSetm(r);
1424      }
1425      y = nDiv(pGetCoeff(r),x);
1426      nNormalize(y);
1427      pSetCoeff(r,y);
1428      pIter(r);
1429    } while (r != NULL);
1430    //pTest(a);
1431    return a;
1432  }
1433  h0 = pInit();
1434  do
1435  {
1436    if (deg != 0)
1437    {
1438      for (i=pVariables; i>0; i--)
1439        pSubExp(r,i,pGetExp(b,i));
1440      pSetm(r);
1441    }
1442    y = nDiv(pGetCoeff(r), x);
1443    nNormalize(y);
1444    pSetCoeff(r,y);
1445    t = tail;
1446    h = h0;
1447    do
1448    {
1449      h = pNext(h) = pInit();
1450      for (i=pVariables; i>0; i--)
1451        pSetExp(h,i, pGetExp(r,i)+pGetExp(t,i));
1452      pSetm(h);
1453      z = nMult(y, pGetCoeff(t));
1454      pSetCoeff0(h,nNeg(z));
1455      pIter(t);
1456    } while (t != NULL);
1457    pNext(h) = NULL;
1458    r = pNext(r) = pAdd(pNext(r),pNext(h0));
1459  } while (r!=NULL);
1460  pFree1(h0);
1461  //pTest(a);
1462  return a;
1463}
1464
1465/*
1466* perform replacement for pivot strategy in Bareiss algorithm
1467* change sign of determinant
1468*/
1469static void mpReplace(int j, int n, int &sign, int *perm)
1470{
1471  int k;
1472
1473  if (j != n)
1474  {
1475    k = perm[n];
1476    perm[n] = perm[j];
1477    perm[j] = k;
1478    sign = -sign;
1479  }
1480}
1481
1482/*
1483* weigth of a polynomial, for pivot strategy
1484* modify this for characteristic 0 !!!
1485*/
1486static float mpPolyWeight(poly p)
1487{
1488  int i;
1489  float res;
1490
1491  if (pNext(p) == NULL)
1492  {
1493    res = (float)nSize(pGetCoeff(p));
1494    if (pTotaldegree(p) != 0) res += 1.0;
1495  }
1496  else
1497  {
1498    i = 0;
1499    res = 0.0;
1500    do
1501    {
1502      i++;
1503      res += (float)nSize(pGetCoeff(p));
1504      pIter(p);
1505    }
1506    while (p);
1507    res += (float)i;
1508  }
1509  return res;
1510}
1511
1512static int mpNextperm(perm * z, int max)
1513{
1514  int s, i, k, t;
1515  s = max;
1516  do
1517  {
1518    s--;
1519  }
1520  while ((s > 0) && ((*z)[s] >= (*z)[s+1]));
1521  if (s==0)
1522    return 0;
1523  do
1524  {
1525    (*z)[s]++;
1526    k = 0;
1527    do
1528    {
1529      k++;
1530    }
1531    while (((*z)[k] != (*z)[s]) && (k!=s));
1532  }
1533  while (k < s);
1534  for (i=s+1; i <= max; i++)
1535  {
1536    (*z)[i]=0;
1537    do
1538    {
1539      (*z)[i]++;
1540      k=0;
1541      do
1542      {
1543        k++;
1544      }
1545      while (((*z)[k] != (*z)[i]) && (k != i));
1546    }
1547    while (k < i);
1548  }
1549  s = max+1;
1550  do
1551  {
1552    s--;
1553  }
1554  while ((s > 0) && ((*z)[s] > (*z)[s+1]));
1555  t = 1;
1556  for (i=1; i<max; i++)
1557    for (k=i+1; k<=max; k++)
1558      if ((*z)[k] < (*z)[i])
1559        t = -t;
1560  (*z)[0] = t;
1561  return s;
1562}
1563
1564static poly mpLeibnitz(matrix a)
1565{
1566  int i, e, n;
1567  poly p, d;
1568  perm z;
1569
1570  n = MATROWS(a);
1571  memset(&z,0,(n+2)*sizeof(int));
1572  p = pOne();
1573  for (i=1; i <= n; i++)
1574    p = pMult(p, pCopy(MATELEM(a, i, i)));
1575  d = p;
1576  for (i=1; i<= n; i++)
1577    z[i] = i;
1578  z[0]=1;
1579  e = 1;
1580  if (n!=1)
1581  {
1582    while (e)
1583    {
1584      e = mpNextperm((perm *)&z, n);
1585      p = pOne();
1586      for (i = 1; i <= n; i++)
1587        p = pMult(p, pCopy(MATELEM(a, i, z[i])));
1588      if (z[0] > 0)
1589        d = pAdd(d, p);
1590      else
1591        d = pSub(d, p);
1592    }
1593  }
1594  return d;
1595}
1596
1597static poly minuscopy (poly p)
1598{
1599  poly w;
1600  number  e;
1601  e = nInit(-1);
1602  w = pCopy(p);
1603  pMultN(w, e);
1604  nDelete(&e);
1605  return w;
1606}
1607
1608/*2
1609* insert a monomial into a list, avoid duplicates
1610* arguments are destroyed
1611*/
1612static poly pInsert(poly p1, poly p2)
1613{
1614  poly a1, p, a2, a;
1615  int c;
1616
1617  if (p1==NULL) return p2;
1618  if (p2==NULL) return p1;
1619  a1 = p1;
1620  a2 = p2;
1621  a = p  = pOne();
1622  loop
1623  {
1624    c = pComp(a1, a2);
1625    if (c == 1)
1626    {
1627      a = pNext(a) = a1;
1628      pIter(a1);
1629      if (a1==NULL)
1630      {
1631        pNext(a) = a2;
1632        break;
1633      }
1634    }
1635    else if (c == -1)
1636    {
1637      a = pNext(a) = a2;
1638      pIter(a2);
1639      if (a2==NULL)
1640      {
1641        pNext(a) = a1;
1642        break;
1643      }
1644    }
1645    else
1646    {
1647      pDelete1(&a2);
1648      a = pNext(a) = a1;
1649      pIter(a1);
1650      if (a1==NULL)
1651      {
1652        pNext(a) = a2;
1653        break;
1654      }
1655      else if (a2==NULL)
1656      {
1657        pNext(a) = a1;
1658        break;
1659      }
1660    }
1661  }
1662  pDelete1(&p);
1663  return p;
1664}
1665
1666/*2
1667*if what == xy the result is the list of all different power products
1668*    x^i*y^j (i, j >= 0) that appear in fro
1669*/
1670static poly mpSelect (poly fro, poly what)
1671{
1672  int i;
1673  poly h, res;
1674  res = NULL;
1675  while (fro!=NULL)
1676  {
1677    h = pOne();
1678    for (i=1; i<=pVariables; i++)
1679      pSetExp(h,i, pGetExp(fro,i) * pGetExp(what, i));
1680    pSetComp(h, pGetComp(fro));
1681    pSetm(h);
1682    res = pInsert(h, res);
1683    fro = fro->next;
1684  }
1685  return res;
1686}
1687
1688/*2
1689*exact divisor: let d  == x^i*y^j, m is thought to have only one term;
1690*    return m/d iff d divides m, and no x^k*y^l (k>i or l>j) divides m
1691*/
1692static poly mpExdiv ( poly m, poly d)
1693{
1694  int i;
1695  poly h = pHead(m);
1696  for (i=1; i<=pVariables; i++)
1697  {
1698    if (pGetExp(d,i) > 0)
1699    {
1700      if (pGetExp(d,i) != pGetExp(h,i))
1701      {
1702        pDelete(&h);
1703        return NULL;
1704      }
1705      pSetExp(h,i,0);
1706    }
1707  }
1708  pSetm(h);
1709  return h;
1710}
1711
Note: See TracBrowser for help on using the repository browser.