source: git/kernel/matpol.cc @ cbeafc2

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