source: git/kernel/matpol.cc @ 6b4fbf7

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