source: git/Singular/matpol.cc @ bfbc32

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