source: git/kernel/matpol.cc @ c8f1b4

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