source: git/libpolys/polys/matpol.cc @ 0a3a629

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