source: git/Singular/matpol.cc @ d3ce7de

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