source: git/Singular/matpol.cc @ 15d67db

fieker-DuValspielwiese
Last change on this file since 15d67db was 50cbdc, checked in by Hans Schönemann <hannes@…>, 23 years ago
*hannes: merge-2-0-2 git-svn-id: file:///usr/local/Singular/svn/trunk@5619 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 33.7 KB
Line 
1/****************************************
2*  Computer Algebra System SINGULAR     *
3****************************************/
4/* $Id: matpol.cc,v 1.43 2001-08-27 14:47:10 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 "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
35
36typedef int perm[100];
37static void mpReplace(int j, int n, int &sign, int *perm);
38static int mpNextperm(perm * z, int max);
39static poly mpLeibnitz(matrix a);
40static poly minuscopy (poly p);
41static poly pInsert(poly p1, poly p2);
42static poly mpExdiv ( poly m, poly d, poly vars);
43static poly mpSelect (poly fro, poly what);
44
45static void mpPartClean(matrix, int, int);
46static void mpFinalClean(matrix);
47static int mpPrepareRow (matrix, int, int);
48static int mpPreparePiv (matrix, int, int);
49static int mpPivBar(matrix, int, int);
50static int mpPivRow(matrix, int, int);
51static float mpPolyWeight(poly);
52static void mpSwapRow(matrix, int, int, int);
53static void mpSwapCol(matrix, int, int, int);
54static void mpElimBar(matrix, matrix, poly, int, int);
55
56/*2
57* create a r x c zero-matrix
58*/
59matrix mpNew(int r, int c)
60{
61  if (r<=0) r=1;
62  if ( (((int)(INT_MAX/sizeof(poly))) / r) <= c)
63  {
64    Werror("internal error: creating matrix[%d][%d]",r,c);
65    return NULL;
66  }
67  matrix rc = (matrix)omAllocBin(ip_smatrix_bin);
68  rc->nrows = r;
69  rc->ncols = c;
70  rc->rank = r;
71  if (c != 0)
72  {
73    int s=r*c*sizeof(poly);
74    rc->m = (polyset)omAlloc0(s);
75    //if (rc->m==NULL)
76    //{
77    //  Werror("internal error: creating matrix[%d][%d]",r,c);
78    //  return NULL;
79    //}
80  }
81  return rc;
82}
83
84/*2
85*copies matrix a to b
86*/
87matrix mpCopy (matrix a)
88{
89  idTest((ideal)a);
90  poly t;
91  int i, m=MATROWS(a), n=MATCOLS(a);
92  matrix b = mpNew(m, n);
93
94  for (i=m*n-1; i>=0; i--)
95  {
96    t = a->m[i];
97    pNormalize(t);
98    b->m[i] = pCopy(t);
99  }
100  b->rank=a->rank;
101  return b;
102}
103
104/*2
105* make it a p * unit matrix
106*/
107matrix mpInitP(int r, int c, poly p)
108{
109  matrix rc = mpNew(r,c);
110  int i=min(r,c), n = c*(i-1)+i-1, inc = c+1;
111
112  pNormalize(p);
113  while (n>0)
114  {
115    rc->m[n] = pCopy(p);
116    n -= inc;
117  }
118  rc->m[0]=p;
119  return rc;
120}
121
122/*2
123* make it a v * unit matrix
124*/
125matrix mpInitI(int r, int c, int v)
126{
127  return mpInitP(r,c,pISet(v));
128}
129
130/*2
131* c = f*a
132*/
133matrix mpMultI(matrix a, int f)
134{
135  int k, n = a->nrows, m = a->ncols;
136  poly p = pISet(f);
137  matrix c = mpNew(n,m);
138
139  for (k=m*n-1; k>0; k--)
140    c->m[k] = ppMult_qq(a->m[k], p);
141  c->m[0] = pMult(pCopy(a->m[0]), p);
142  return c;
143}
144
145/*2
146* multiply a matrix 'a' by a poly 'p', destroy the args
147*/
148matrix mpMultP(matrix a, poly p)
149{
150  int k, n = a->nrows, m = a->ncols;
151
152  pNormalize(p);
153  for (k=m*n-1; k>0; k--)
154  {
155    a->m[k] = pMult(a->m[k], pCopy(p));
156  }
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 c/*ip*/, leftv b/*in*/, 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),vars);
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),vars);
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* consider all variables in vars
874*/
875static poly mpExdiv ( poly m, poly d, poly vars)
876{
877  int i;
878  poly h = pHead(m);
879  for (i=1; i<=pVariables; i++)
880  {
881    if (pGetExp(vars,i) > 0)
882    {
883      if (pGetExp(d,i) != pGetExp(h,i))
884      {
885        pDelete(&h);
886        return NULL;
887      }
888      pSetExp(h,i,0);
889    }
890  }
891  pSetm(h);
892  return h;
893}
894
895void mpCoef2(poly v, poly mon, matrix *c, matrix *m)
896{
897  polyset s;
898  poly p;
899  int sl,i,j;
900  int l=0;
901  poly sel=mpSelect(v,mon);
902
903  pVec2Polys(sel,&s,&sl);
904  for (i=0; i<sl; i++)
905    l=max(l,pLength(s[i]));
906  *c=mpNew(sl,l);
907  *m=mpNew(sl,l);
908  poly h;
909  int isConst;
910  for (j=1; j<=sl;j++)
911  {
912    p=s[j-1];
913    if (pIsConstant(p)) /*p != NULL */
914    {
915      isConst=-1;
916      i=l;
917    }
918    else
919    {
920      isConst=1;
921      i=1;
922    }
923    while(p!=NULL)
924    {
925      h = pHead(p);
926      MATELEM(*m,j,i) = h;
927      i+=isConst;
928      p = p->next;
929    }
930  }
931  while (v!=NULL)
932  {
933    i = 1;
934    j = pGetComp(v);
935    loop
936    {
937      poly mp=MATELEM(*m,j,i);
938      if (mp!=NULL)
939      {
940        h = mpExdiv(v, mp /*MATELEM(*m,j,i)*/, mp);
941        if (h!=NULL)
942        {
943          pSetComp(h,0);
944          MATELEM(*c,j,i) = pAdd(MATELEM(*c,j,i), h);
945          break;
946        }
947      }
948      if (i < l)
949        i++;
950      else
951        break;
952    }
953    v = v->next;
954  }
955}
956
957
958BOOLEAN mpEqual(matrix a, matrix b)
959{
960  if ((MATCOLS(a)!=MATCOLS(b)) || (MATROWS(a)!=MATROWS(b)))
961    return FALSE;
962  int i=MATCOLS(a)*MATROWS(b)-1;
963  while (i>=0)
964  {
965    if (a->m[i]==NULL)
966    {
967      if (b->m[i]!=NULL) return FALSE;
968    }
969    else
970      if (pCmp(a->m[i],b->m[i])!=0) return FALSE;
971    i--;
972  }
973  i=MATCOLS(a)*MATROWS(b)-1;
974  while (i>=0)
975  {
976    if (pSub(pCopy(a->m[i]),pCopy(b->m[i]))!=NULL) return FALSE;
977    i--;
978  }
979  return TRUE;
980}
981
982/* --------------- internal stuff ------------------- */
983
984row_col_weight::row_col_weight(int i, int j)
985{
986  ym = i;
987  yn = j;
988  wrow = (float *)omAlloc(i*sizeof(float));
989  wcol = (float *)omAlloc(j*sizeof(float));
990}
991
992row_col_weight::~row_col_weight()
993{
994  if (ym!=0)
995  {
996    omFreeSize((ADDRESS)wcol, yn*sizeof(float));
997    omFreeSize((ADDRESS)wrow, ym*sizeof(float));
998  }
999}
1000
1001mp_permmatrix::mp_permmatrix(matrix A) : sign(1)
1002{
1003  a_m = A->nrows;
1004  a_n = A->ncols;
1005  this->mpInitMat();
1006  Xarray = A->m;
1007}
1008
1009mp_permmatrix::mp_permmatrix(mp_permmatrix *M)
1010{
1011  poly p, *athis, *aM;
1012  int i, j;
1013
1014  a_m = M->s_m;
1015  a_n = M->s_n;
1016  sign = M->sign;
1017  this->mpInitMat();
1018  Xarray = (poly *)omAlloc0(a_m*a_n*sizeof(poly));
1019  for (i=a_m-1; i>=0; i--)
1020  {
1021    athis = this->mpRowAdr(i);
1022    aM = M->mpRowAdr(i);
1023    for (j=a_n-1; j>=0; j--)
1024    {
1025      p = aM[M->qcol[j]];
1026      if (p)
1027      {
1028        athis[j] = pCopy(p);
1029      }
1030    }
1031  }
1032}
1033
1034mp_permmatrix::~mp_permmatrix()
1035{
1036  int k;
1037
1038  if (a_m != 0)
1039  {
1040    omFreeSize((ADDRESS)qrow,a_m*sizeof(int));
1041    omFreeSize((ADDRESS)qcol,a_n*sizeof(int));
1042    if (Xarray != NULL)
1043    {
1044      for (k=a_m*a_n-1; k>=0; k--)
1045        pDelete(&Xarray[k]);
1046      omFreeSize((ADDRESS)Xarray,a_m*a_n*sizeof(poly));
1047    }
1048  }
1049}
1050
1051int mp_permmatrix::mpGetRdim() { return s_m; }
1052
1053int mp_permmatrix::mpGetCdim() { return s_n; }
1054
1055int mp_permmatrix::mpGetSign() { return sign; }
1056
1057void mp_permmatrix::mpSetSearch(int s) { piv_s = s; }
1058
1059void mp_permmatrix::mpSaveArray() { Xarray = NULL; }
1060
1061poly mp_permmatrix::mpGetElem(int r, int c)
1062{
1063  return Xarray[a_n*qrow[r]+qcol[c]];
1064}
1065
1066void mp_permmatrix::mpSetElem(poly p, int r, int c)
1067{
1068  Xarray[a_n*qrow[r]+qcol[c]] = p;
1069}
1070
1071void mp_permmatrix::mpDelElem(int r, int c)
1072{
1073  pDelete(&Xarray[a_n*qrow[r]+qcol[c]]);
1074}
1075
1076/*
1077* the Bareiss-type elimination with division by div (div != NULL)
1078*/
1079void mp_permmatrix::mpElimBareiss(poly div)
1080{
1081  poly piv, elim, q1, q2, *ap, *a;
1082  int i, j, jj;
1083
1084  ap = this->mpRowAdr(s_m);
1085  piv = ap[qcol[s_n]];
1086  for(i=s_m-1; i>=0; i--)
1087  {
1088    a = this->mpRowAdr(i);
1089    elim = a[qcol[s_n]];
1090    if (elim != NULL)
1091    {
1092      elim = pNeg(elim);
1093      for (j=s_n-1; j>=0; j--)
1094      {
1095        q2 = NULL;
1096        jj = qcol[j];
1097        if (ap[jj] != NULL)
1098        {
1099          q2 = SM_MULT(ap[jj], elim, div);
1100          if (a[jj] != NULL)
1101          {
1102            q1 = SM_MULT(a[jj], piv, div);
1103            pDelete(&a[jj]);
1104            q2 = pAdd(q2, q1);
1105          }
1106        }
1107        else if (a[jj] != NULL)
1108        {
1109          q2 = SM_MULT(a[jj], piv, div);
1110        }
1111        if ((q2!=NULL) && div)
1112          SM_DIV(q2, div);
1113        a[jj] = q2;
1114      }
1115      pDelete(&a[qcol[s_n]]);
1116    }
1117    else
1118    {
1119      for (j=s_n-1; j>=0; j--)
1120      {
1121        jj = qcol[j];
1122        if (a[jj] != NULL)
1123        {
1124          q2 = SM_MULT(a[jj], piv, div);
1125          pDelete(&a[jj]);
1126          if (div)
1127            SM_DIV(q2, div);
1128          a[jj] = q2;
1129        }
1130      }
1131    }
1132  }
1133}
1134
1135/*2
1136* pivot strategy for Bareiss algorithm
1137*/
1138int mp_permmatrix::mpPivotBareiss(row_col_weight *C)
1139{
1140  poly p, *a;
1141  int i, j, iopt, jopt;
1142  float sum, f1, f2, fo, r, ro, lp;
1143  float *dr = C->wrow, *dc = C->wcol;
1144
1145  fo = 1.0e20;
1146  ro = 0.0;
1147  iopt = jopt = -1;
1148
1149  s_n--;
1150  s_m--;
1151  if (s_m == 0)
1152    return 0;
1153  if (s_n == 0)
1154  {
1155    for(i=s_m; i>=0; i--)
1156    {
1157      p = this->mpRowAdr(i)[qcol[0]];
1158      if (p)
1159      {
1160        f1 = mpPolyWeight(p);
1161        if (f1 < fo)
1162        {
1163          fo = f1;
1164          if (iopt >= 0)
1165            pDelete(&(this->mpRowAdr(iopt)[qcol[0]]));
1166          iopt = i;
1167        }
1168        else
1169          pDelete(&(this->mpRowAdr(i)[qcol[0]]));
1170      }
1171    }
1172    if (iopt >= 0)
1173      mpReplace(iopt, s_m, sign, qrow);
1174    return 0;
1175  }
1176  this->mpRowWeight(dr);
1177  this->mpColWeight(dc);
1178  sum = 0.0;
1179  for(i=s_m; i>=0; i--)
1180    sum += dr[i];
1181  for(i=s_m; i>=0; i--)
1182  {
1183    r = dr[i];
1184    a = this->mpRowAdr(i);
1185    for(j=s_n; j>=0; j--)
1186    {
1187      p = a[qcol[j]];
1188      if (p)
1189      {
1190        lp = mpPolyWeight(p);
1191        ro = r - lp;
1192        f1 = ro * (dc[j]-lp);
1193        if (f1 != 0.0)
1194        {
1195          f2 = lp * (sum - ro - dc[j]);
1196          f2 += f1;
1197        }
1198        else
1199          f2 = lp-r-dc[j];
1200        if (f2 < fo)
1201        {
1202          fo = f2;
1203          iopt = i;
1204          jopt = j;
1205        }
1206      }
1207    }
1208  }
1209  if (iopt < 0)
1210    return 0;
1211  mpReplace(iopt, s_m, sign, qrow);
1212  mpReplace(jopt, s_n, sign, qcol);
1213  return 1;
1214}
1215
1216/*2
1217* pivot strategy for Bareiss algorithm with defined row
1218*/
1219int mp_permmatrix::mpPivotRow(row_col_weight *C, int row)
1220{
1221  poly p, *a;
1222  int j, iopt, jopt;
1223  float sum, f1, f2, fo, r, ro, lp;
1224  float *dr = C->wrow, *dc = C->wcol;
1225
1226  fo = 1.0e20;
1227  ro = 0.0;
1228  iopt = jopt = -1;
1229
1230  s_n--;
1231  s_m--;
1232  if (s_m == 0)
1233    return 0;
1234  if (s_n == 0)
1235  {
1236    p = this->mpRowAdr(row)[qcol[0]];
1237    if (p)
1238    {
1239      f1 = mpPolyWeight(p);
1240      if (f1 < fo)
1241      {
1242        fo = f1;
1243        if (iopt >= 0)
1244        pDelete(&(this->mpRowAdr(iopt)[qcol[0]]));
1245        iopt = row;
1246      }
1247      else
1248        pDelete(&(this->mpRowAdr(row)[qcol[0]]));
1249    }
1250    if (iopt >= 0)
1251      mpReplace(iopt, s_m, sign, qrow);
1252    return 0;
1253  }
1254  this->mpRowWeight(dr);
1255  this->mpColWeight(dc);
1256  sum = 0.0;
1257  for(j=s_m; j>=0; j--)
1258    sum += dr[j];
1259  r = dr[row];
1260  a = this->mpRowAdr(row);
1261  for(j=s_n; j>=0; j--)
1262  {
1263    p = a[qcol[j]];
1264    if (p)
1265    {
1266      lp = mpPolyWeight(p);
1267      ro = r - lp;
1268      f1 = ro * (dc[j]-lp);
1269      if (f1 != 0.0)
1270      {
1271        f2 = lp * (sum - ro - dc[j]);
1272        f2 += f1;
1273      }
1274      else
1275        f2 = lp-r-dc[j];
1276      if (f2 < fo)
1277      {
1278        fo = f2;
1279        iopt = row;
1280        jopt = j;
1281      }
1282    }
1283  }
1284  if (iopt < 0)
1285    return 0;
1286  mpReplace(iopt, s_m, sign, qrow);
1287  mpReplace(jopt, s_n, sign, qcol);
1288  return 1;
1289}
1290
1291void mp_permmatrix::mpToIntvec(intvec *v)
1292{
1293  int i;
1294
1295  for (i=v->rows()-1; i>=0; i--)
1296    (*v)[i] = qcol[i]+1;
1297}
1298
1299void mp_permmatrix::mpRowReorder()
1300{
1301  int k, i, i1, i2;
1302
1303  if (a_m > a_n)
1304    k = a_m - a_n;
1305  else
1306    k = 0;
1307  for (i=a_m-1; i>=k; i--)
1308  {
1309    i1 = qrow[i];
1310    if (i1 != i)
1311    {
1312      this->mpRowSwap(i1, i);
1313      i2 = 0;
1314      while (qrow[i2] != i) i2++;
1315      qrow[i2] = i1;
1316    }
1317  }
1318}
1319
1320void mp_permmatrix::mpColReorder()
1321{
1322  int k, j, j1, j2;
1323
1324  if (a_n > a_m)
1325    k = a_n - a_m;
1326  else
1327    k = 0;
1328  for (j=a_n-1; j>=k; j--)
1329  {
1330    j1 = qcol[j];
1331    if (j1 != j)
1332    {
1333      this->mpColSwap(j1, j);
1334      j2 = 0;
1335      while (qcol[j2] != j) j2++;
1336      qcol[j2] = j1;
1337    }
1338  }
1339}
1340
1341// private
1342void mp_permmatrix::mpInitMat()
1343{
1344  int k;
1345
1346  s_m = a_m;
1347  s_n = a_n;
1348  piv_s = 0;
1349  qrow = (int *)omAlloc(a_m*sizeof(int));
1350  qcol = (int *)omAlloc(a_n*sizeof(int));
1351  for (k=a_m-1; k>=0; k--) qrow[k] = k;
1352  for (k=a_n-1; k>=0; k--) qcol[k] = k;
1353}
1354
1355poly * mp_permmatrix::mpRowAdr(int r)
1356{
1357  return &(Xarray[a_n*qrow[r]]);
1358}
1359
1360poly * mp_permmatrix::mpColAdr(int c)
1361{
1362  return &(Xarray[qcol[c]]);
1363}
1364
1365void mp_permmatrix::mpRowWeight(float *wrow)
1366{
1367  poly p, *a;
1368  int i, j;
1369  float count;
1370
1371  for (i=s_m; i>=0; i--)
1372  {
1373    a = this->mpRowAdr(i);
1374    count = 0.0;
1375    for(j=s_n; j>=0; j--)
1376    {
1377      p = a[qcol[j]];
1378      if (p)
1379        count += mpPolyWeight(p);
1380    }
1381    wrow[i] = count;
1382  }
1383}
1384
1385void mp_permmatrix::mpColWeight(float *wcol)
1386{
1387  poly p, *a;
1388  int i, j;
1389  float count;
1390
1391  for (j=s_n; j>=0; j--)
1392  {
1393    a = this->mpColAdr(j);
1394    count = 0.0;
1395    for(i=s_m; i>=0; i--)
1396    {
1397      p = a[a_n*qrow[i]];
1398      if (p)
1399        count += mpPolyWeight(p);
1400    }
1401    wcol[j] = count;
1402  }
1403}
1404
1405void mp_permmatrix::mpRowSwap(int i1, int i2)
1406{
1407   poly p, *a1, *a2;
1408   int j;
1409
1410   a1 = &(Xarray[a_n*i1]);
1411   a2 = &(Xarray[a_n*i2]);
1412   for (j=a_n-1; j>= 0; j--)
1413   {
1414     p = a1[j];
1415     a1[j] = a2[j];
1416     a2[j] = p;
1417   }
1418}
1419
1420void mp_permmatrix::mpColSwap(int j1, int j2)
1421{
1422   poly p, *a1, *a2;
1423   int i, k = a_n*a_m;
1424
1425   a1 = &(Xarray[j1]);
1426   a2 = &(Xarray[j2]);
1427   for (i=0; i< k; i+=a_n)
1428   {
1429     p = a1[i];
1430     a1[i] = a2[i];
1431     a2[i] = p;
1432   }
1433}
1434
1435int mp_permmatrix::mpGetRow()
1436{
1437  return qrow[s_m];
1438}
1439
1440int mp_permmatrix::mpGetCol()
1441{
1442  return qcol[s_n];
1443}
1444
1445/*
1446* perform replacement for pivot strategy in Bareiss algorithm
1447* change sign of determinant
1448*/
1449static void mpReplace(int j, int n, int &sign, int *perm)
1450{
1451  int k;
1452
1453  if (j != n)
1454  {
1455    k = perm[n];
1456    perm[n] = perm[j];
1457    perm[j] = k;
1458    sign = -sign;
1459  }
1460}
1461
1462static int mpNextperm(perm * z, int max)
1463{
1464  int s, i, k, t;
1465  s = max;
1466  do
1467  {
1468    s--;
1469  }
1470  while ((s > 0) && ((*z)[s] >= (*z)[s+1]));
1471  if (s==0)
1472    return 0;
1473  do
1474  {
1475    (*z)[s]++;
1476    k = 0;
1477    do
1478    {
1479      k++;
1480    }
1481    while (((*z)[k] != (*z)[s]) && (k!=s));
1482  }
1483  while (k < s);
1484  for (i=s+1; i <= max; i++)
1485  {
1486    (*z)[i]=0;
1487    do
1488    {
1489      (*z)[i]++;
1490      k=0;
1491      do
1492      {
1493        k++;
1494      }
1495      while (((*z)[k] != (*z)[i]) && (k != i));
1496    }
1497    while (k < i);
1498  }
1499  s = max+1;
1500  do
1501  {
1502    s--;
1503  }
1504  while ((s > 0) && ((*z)[s] > (*z)[s+1]));
1505  t = 1;
1506  for (i=1; i<max; i++)
1507    for (k=i+1; k<=max; k++)
1508      if ((*z)[k] < (*z)[i])
1509        t = -t;
1510  (*z)[0] = t;
1511  return s;
1512}
1513
1514static poly mpLeibnitz(matrix a)
1515{
1516  int i, e, n;
1517  poly p, d;
1518  perm z;
1519
1520  n = MATROWS(a);
1521  memset(&z,0,(n+2)*sizeof(int));
1522  p = pOne();
1523  for (i=1; i <= n; i++)
1524    p = pMult(p, pCopy(MATELEM(a, i, i)));
1525  d = p;
1526  for (i=1; i<= n; i++)
1527    z[i] = i;
1528  z[0]=1;
1529  e = 1;
1530  if (n!=1)
1531  {
1532    while (e)
1533    {
1534      e = mpNextperm((perm *)&z, n);
1535      p = pOne();
1536      for (i = 1; i <= n; i++)
1537        p = pMult(p, pCopy(MATELEM(a, i, z[i])));
1538      if (z[0] > 0)
1539        d = pAdd(d, p);
1540      else
1541        d = pSub(d, p);
1542    }
1543  }
1544  return d;
1545}
1546
1547static poly minuscopy (poly p)
1548{
1549  poly w;
1550  number  e;
1551  e = nInit(-1);
1552  w = pCopy(p);
1553  pMult_nn(w, e);
1554  nDelete(&e);
1555  return w;
1556}
1557
1558/*2
1559* insert a monomial into a list, avoid duplicates
1560* arguments are destroyed
1561*/
1562static poly pInsert(poly p1, poly p2)
1563{
1564  poly a1, p, a2, a;
1565  int c;
1566
1567  if (p1==NULL) return p2;
1568  if (p2==NULL) return p1;
1569  a1 = p1;
1570  a2 = p2;
1571  a = p  = pOne();
1572  loop
1573  {
1574    c = pCmp(a1, a2);
1575    if (c == 1)
1576    {
1577      a = pNext(a) = a1;
1578      pIter(a1);
1579      if (a1==NULL)
1580      {
1581        pNext(a) = a2;
1582        break;
1583      }
1584    }
1585    else if (c == -1)
1586    {
1587      a = pNext(a) = a2;
1588      pIter(a2);
1589      if (a2==NULL)
1590      {
1591        pNext(a) = a1;
1592        break;
1593      }
1594    }
1595    else
1596    {
1597      pDeleteLm(&a2);
1598      a = pNext(a) = a1;
1599      pIter(a1);
1600      if (a1==NULL)
1601      {
1602        pNext(a) = a2;
1603        break;
1604      }
1605      else if (a2==NULL)
1606      {
1607        pNext(a) = a1;
1608        break;
1609      }
1610    }
1611  }
1612  pDeleteLm(&p);
1613  return p;
1614}
1615
1616/*2
1617*if what == xy the result is the list of all different power products
1618*    x^i*y^j (i, j >= 0) that appear in fro
1619*/
1620static poly mpSelect (poly fro, poly what)
1621{
1622  int i;
1623  poly h, res;
1624  res = NULL;
1625  while (fro!=NULL)
1626  {
1627    h = pOne();
1628    for (i=1; i<=pVariables; i++)
1629      pSetExp(h,i, pGetExp(fro,i) * pGetExp(what, i));
1630    pSetComp(h, pGetComp(fro));
1631    pSetm(h);
1632    res = pInsert(h, res);
1633    fro = fro->next;
1634  }
1635  return res;
1636}
1637
1638/*
1639*static void ppp(matrix a)
1640*{
1641*  int j,i,r=a->nrows,c=a->ncols;
1642*  for(j=1;j<=r;j++)
1643*  {
1644*    for(i=1;i<=c;i++)
1645*    {
1646*      if(MATELEM(a,j,i)!=NULL) Print("X");
1647*      else Print("0");
1648*    }
1649*    Print("\n");
1650*  }
1651*}
1652*/
1653
1654static void mpPartClean(matrix a, int lr, int lc)
1655{
1656  poly *q1;
1657  int i,j;
1658
1659  for (i=lr-1;i>=0;i--)
1660  {
1661    q1 = &(a->m)[i*a->ncols];
1662    for (j=lc-1;j>=0;j--) if(q1[j]) pDelete(&q1[j]);
1663  }
1664}
1665
1666static void mpFinalClean(matrix a)
1667{
1668  omFreeSize((ADDRESS)a->m,a->nrows*a->ncols*sizeof(poly));
1669  omFreeBin((ADDRESS)a, ip_smatrix_bin);
1670}
1671
1672/*2
1673*  prepare one step of 'Bareiss' algorithm
1674*  for application in minor
1675*/
1676static int mpPrepareRow (matrix a, int lr, int lc)
1677{
1678  int r;
1679
1680  r = mpPivBar(a,lr,lc);
1681  if(r==0) return 0;
1682  if(r<lr) mpSwapRow(a, r, lr, lc);
1683  return 1;
1684}
1685
1686/*2
1687*  prepare one step of 'Bareiss' algorithm
1688*  for application in minor
1689*/
1690static int mpPreparePiv (matrix a, int lr, int lc)
1691{
1692  int c;
1693
1694  c = mpPivRow(a, lr, lc);
1695  if(c==0) return 0;
1696  if(c<lc) mpSwapCol(a, c, lr, lc);
1697  return 1;
1698}
1699
1700/*
1701* find best row
1702*/
1703static int mpPivBar(matrix a, int lr, int lc)
1704{
1705  float f1, f2;
1706  poly *q1;
1707  int i,j,io;
1708
1709  io = -1;
1710  f1 = 1.0e30;
1711  for (i=lr-1;i>=0;i--)
1712  {
1713    q1 = &(a->m)[i*a->ncols];
1714    f2 = 0.0;
1715    for (j=lc-1;j>=0;j--)
1716    {
1717      if (q1[j]!=NULL)
1718        f2 += mpPolyWeight(q1[j]);
1719    }
1720    if ((f2!=0.0) && (f2<f1))
1721    {
1722      f1 = f2;
1723      io = i;
1724    }
1725  }
1726  if (io<0) return 0;
1727  else return io+1;
1728}
1729
1730/*
1731* find pivot in the last row
1732*/
1733static int mpPivRow(matrix a, int lr, int lc)
1734{
1735  float f1, f2;
1736  poly *q1;
1737  int j,jo;
1738
1739  jo = -1;
1740  f1 = 1.0e30;
1741  q1 = &(a->m)[(lr-1)*a->ncols];
1742  for (j=lc-1;j>=0;j--)
1743  {
1744    if (q1[j]!=NULL)
1745    {
1746      f2 = mpPolyWeight(q1[j]);
1747      if (f2<f1)
1748      {
1749        f1 = f2;
1750        jo = j;
1751      }
1752    }
1753  }
1754  if (jo<0) return 0;
1755  else return jo+1;
1756}
1757
1758/*
1759* weigth of a polynomial, for pivot strategy
1760*/
1761static float mpPolyWeight(poly p)
1762{
1763  int i;
1764  float res;
1765
1766  if (pNext(p) == NULL)
1767  {
1768    res = (float)nSize(pGetCoeff(p));
1769    for (i=pVariables;i>0;i--)
1770    {
1771      if(pGetExp(p,i)!=0)
1772      {
1773        res += 2.0;
1774        break;
1775      }
1776    }
1777  }
1778  else
1779  {
1780    res = 0.0;
1781    do
1782    {
1783      res += (float)nSize(pGetCoeff(p))+2.0;
1784      pIter(p);
1785    }
1786    while (p);
1787  }
1788  return res;
1789}
1790
1791static void mpSwapRow(matrix a, int pos, int lr, int lc)
1792{
1793  poly sw;
1794  int j;
1795  polyset a2 = a->m, a1 = &a2[a->ncols*(pos-1)];
1796
1797  a2 = &a2[a->ncols*(lr-1)];
1798  for (j=lc-1; j>=0; j--)
1799  {
1800    sw = a1[j];
1801    a1[j] = a2[j];
1802    a2[j] = sw;
1803  }
1804}
1805
1806static void mpSwapCol(matrix a, int pos, int lr, int lc)
1807{
1808  poly sw;
1809  int j;
1810  polyset a2 = a->m, a1 = &a2[pos-1];
1811
1812  a2 = &a2[lc-1];
1813  for (j=a->ncols*(lr-1); j>=0; j-=a->ncols)
1814  {
1815    sw = a1[j];
1816    a1[j] = a2[j];
1817    a2[j] = sw;
1818  }
1819}
1820
1821static void mpElimBar(matrix a0, matrix re, poly div, int lr, int lc)
1822{
1823  int r=lr-1, c=lc-1;
1824  poly *b = a0->m, *x = re->m;
1825  poly piv, elim, q1, q2, *ap, *a, *q;
1826  int i, j;
1827
1828  ap = &b[r*a0->ncols];
1829  piv = ap[c];
1830  for(j=c-1; j>=0; j--)
1831    if (ap[j] != NULL) ap[j] = pNeg(ap[j]);
1832  for(i=r-1; i>=0; i--)
1833  {
1834    a = &b[i*a0->ncols];
1835    q = &x[i*re->ncols];
1836    if (a[c] != NULL)
1837    {
1838      elim = a[c];
1839      for (j=c-1; j>=0; j--)
1840      {
1841        q1 = NULL;
1842        if (a[j] != NULL)
1843        {
1844          q1 = SM_MULT(a[j], piv, div);
1845          if (ap[j] != NULL)
1846          {
1847            q2 = SM_MULT(ap[j], elim, div);
1848            q1 = pAdd(q1,q2);
1849          }
1850        }
1851        else if (ap[j] != NULL)
1852          q1 = SM_MULT(ap[j], elim, div);
1853        if (q1 != NULL)
1854        {
1855          if (div)
1856            SM_DIV(q1, div);
1857          q[j] = q1;
1858        }
1859      }
1860    }
1861    else
1862    {
1863      for (j=c-1; j>=0; j--)
1864      {
1865        if (a[j] != NULL)
1866        {
1867          q1 = SM_MULT(a[j], piv, div);
1868          if (div)
1869            SM_DIV(q1, div);
1870          q[j] = q1;
1871        }
1872      }
1873    }
1874  }
1875}
1876
1877BOOLEAN mpIsDiagUnit(matrix U)
1878{
1879  if(MATROWS(U)!=MATCOLS(U))
1880    return FALSE;
1881  for(int i=MATCOLS(U);i>=1;i--)
1882  {
1883    for(int j=MATCOLS(U); j>=1; j--)
1884    {
1885      if (i==j)
1886      {
1887        if (!pIsUnit(MATELEM(U,i,i))) return FALSE;
1888      }
1889      else if (MATELEM(U,i,j)!=NULL) return FALSE;
1890    }
1891  }
1892  return TRUE;
1893}
1894
Note: See TracBrowser for help on using the repository browser.