source: git/Singular/matpol.cc @ c89833

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