source: git/kernel/matpol.cc @ 18ff4c

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