source: git/kernel/matpol.cc @ 670ad3

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