source: git/kernel/matpol.cc @ 59b9615

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