source: git/libpolys/polys/matpol.cc @ 5d9aa6

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