source: git/kernel/matpol.cc @ 61d32c

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