source: git/kernel/matpol.cc @ f7bfe5

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