source: git/libpolys/polys/matpol.cc @ b78996

spielwiese
Last change on this file since b78996 was b78996, checked in by Oleksandr Motsak <motsak@…>, 13 years ago
FIX: strting to fix sparse matrices (sparsmat.{h, cc})
  • Property mode set to 100644
File size: 36.3 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
33#include "coeffrings.h"
34#include "simpleideals.h"
35#include "matpol.h"
36#include "prCopy.h"
37
38#include "sparsmat.h"
39   
40//omBin ip_smatrix_bin = omGetSpecBin(sizeof(ip_smatrix));
41#define ip_smatrix_bin sip_sideal_bin
42/*0 implementation*/
43
44
45typedef int perm[100];
46static void mpReplace(int j, int n, int &sign, int *perm);
47static int mpNextperm(perm * z, int max);
48static poly mp_Leibnitz(matrix a, const ring);
49static poly minuscopy (poly p, const ring);
50static poly p_Insert(poly p1, poly p2, const ring);
51static poly mp_Exdiv ( poly m, poly d, poly vars, const ring);
52static poly mp_Select (poly fro, poly what, const ring);
53
54static void mp_PartClean(matrix, int, int, const ring);
55static void mp_FinalClean(matrix, const ring);
56static int mp_PrepareRow (matrix, int, int, const ring);
57static int mp_PreparePiv (matrix, int, int, const ring);
58static int mp_PivBar(matrix, int, int, const ring);
59static int mp_PivRow(matrix, int, int, const ring);
60static float mp_PolyWeight(poly, const ring);
61static void mp_SwapRow(matrix, int, int, int, const ring);
62static void mp_SwapCol(matrix, int, int, int, const ring);
63static void mp_ElimBar(matrix, matrix, poly, int, int, const ring);
64
65/// create a r x c zero-matrix
66matrix mpNew(int r, int c)
67{
68  if (r<=0) r=1;
69  if ( (((int)(INT_MAX/sizeof(poly))) / r) <= c)
70  {
71    Werror("internal error: creating matrix[%d][%d]",r,c);
72    return NULL;
73  }
74  matrix rc = (matrix)omAllocBin(ip_smatrix_bin);
75  rc->nrows = r;
76  rc->ncols = c;
77  rc->rank = r;
78  if (c != 0)
79  {
80    int s=r*c*sizeof(poly);
81    rc->m = (poly*)omAlloc0(s);
82    //if (rc->m==NULL)
83    //{
84    //  Werror("internal error: creating matrix[%d][%d]",r,c);
85    //  return NULL;
86    //}
87  }
88  return rc;
89}
90
91/// copies matrix a (from ring r to r)
92matrix mp_Copy (matrix a, const ring r)
93{
94  id_Test((ideal)a, r);
95  poly t;
96  int i, m=MATROWS(a), n=MATCOLS(a);
97  matrix b = mpNew(m, n);
98
99  for (i=m*n-1; i>=0; i--)
100  {
101    t = a->m[i];
102    if (t!=NULL)
103    {
104      p_Normalize(t, r);
105      b->m[i] = p_Copy(t, r);
106    }
107  }
108  b->rank=a->rank;
109  return b;
110}
111
112/// copies matrix a from rSrc into rDst
113matrix mp_Copy(const matrix a, const ring rSrc, const ring rDst)
114{
115  id_Test((ideal)a, rSrc);
116
117  poly t;
118  int i, m=MATROWS(a), n=MATCOLS(a);
119
120  matrix b = mpNew(m, n);
121
122  for (i=m*n-1; i>=0; i--)
123  {
124    t = a->m[i];
125    if (t!=NULL)
126    {
127      b->m[i] = prCopyR_NoSort(t, rSrc, rDst);
128      p_Normalize(b->m[i], rDst);
129    }
130  }
131  b->rank=a->rank;
132
133  id_Test((ideal)b, rDst);
134
135  return b;
136}
137
138
139
140/// make it a p * unit matrix
141matrix mp_InitP(int r, int c, poly p, const ring _R)
142{
143  matrix rc = mpNew(r,c);
144  int i=si_min(r,c), n = c*(i-1)+i-1, inc = c+1;
145
146  p_Normalize(p, _R);
147  while (n>0)
148  {
149    rc->m[n] = p_Copy(p, _R);
150    n -= inc;
151  }
152  rc->m[0]=p;
153  return rc;
154}
155
156/// make it a v * unit matrix
157matrix mp_InitI(int r, int c, int v, const ring R)
158{
159  return mp_InitP(r, c, p_ISet(v, R), R);
160}
161
162/// c = f*a
163matrix mp_MultI(matrix a, int f, const ring R)
164{
165  int k, n = a->nrows, m = a->ncols;
166  poly p = p_ISet(f, R);
167  matrix c = mpNew(n,m);
168
169  for (k=m*n-1; k>0; k--)
170    c->m[k] = pp_Mult_qq(a->m[k], p, R);
171  c->m[0] = p_Mult_q(p_Copy(a->m[0], R), p, R);
172  return c;
173}
174
175/// multiply a matrix 'a' by a poly 'p', destroy the args
176matrix mp_MultP(matrix a, poly p, const ring R)
177{
178  int k, n = a->nrows, m = a->ncols;
179
180  p_Normalize(p, R);
181  for (k=m*n-1; k>0; k--)
182  {
183    if (a->m[k]!=NULL)
184      a->m[k] = p_Mult_q(a->m[k], p_Copy(p, R), R);
185  }
186  a->m[0] = p_Mult_q(a->m[0], p, R);
187  return a;
188}
189
190/*2
191* multiply a poly 'p' by a matrix 'a', destroy the args
192*/
193matrix pMultMp(poly p, matrix a, const ring R)
194{
195  int k, n = a->nrows, m = a->ncols;
196
197  p_Normalize(p, R);
198  for (k=m*n-1; k>0; k--)
199  {
200    if (a->m[k]!=NULL)
201      a->m[k] = p_Mult_q(p_Copy(p, R), a->m[k], R);
202  }
203  a->m[0] = p_Mult_q(p, a->m[0], R);
204  return a;
205}
206
207matrix mp_Add(matrix a, matrix b, const ring R)
208{
209  int k, n = a->nrows, m = a->ncols;
210  if ((n != b->nrows) || (m != b->ncols))
211  {
212/*
213*    Werror("cannot add %dx%d matrix and %dx%d matrix",
214*      m,n,b->cols(),b->rows());
215*/
216    return NULL;
217  }
218  matrix c = mpNew(n,m);
219  for (k=m*n-1; k>=0; k--)
220    c->m[k] = p_Add_q(p_Copy(a->m[k], R), p_Copy(b->m[k], R), R);
221  return c;
222}
223
224matrix mp_Sub(matrix a, matrix b, const ring R)
225{
226  int k, n = a->nrows, m = a->ncols;
227  if ((n != b->nrows) || (m != b->ncols))
228  {
229/*
230*    Werror("cannot sub %dx%d matrix and %dx%d matrix",
231*      m,n,b->cols(),b->rows());
232*/
233    return NULL;
234  }
235  matrix c = mpNew(n,m);
236  for (k=m*n-1; k>=0; k--)
237    c->m[k] = p_Sub(p_Copy(a->m[k], R), p_Copy(b->m[k], R), R);
238  return c;
239}
240
241matrix mp_Mult(matrix a, matrix b, const ring R)
242{
243  int i, j, k;
244  int m = MATROWS(a);
245  int p = MATCOLS(a);
246  int q = MATCOLS(b);
247
248  if (p!=MATROWS(b))
249  {
250/*
251*   Werror("cannot multiply %dx%d matrix and %dx%d matrix",
252*     m,p,b->rows(),q);
253*/
254    return NULL;
255  }
256  matrix c = mpNew(m,q);
257
258  for (i=1; i<=m; i++)
259  {
260    for (k=1; k<=p; k++)
261    {
262      poly aik;
263      if ((aik=MATELEM(a,i,k))!=NULL)
264      {
265        for (j=1; j<=q; j++)
266        {
267          poly bkj;
268          if ((bkj=MATELEM(b,k,j))!=NULL)
269          {
270            poly *cij=&(MATELEM(c,i,j));
271            poly s = pp_Mult_qq(aik /*MATELEM(a,i,k)*/, bkj/*MATELEM(b,k,j)*/, R);
272            if (/*MATELEM(c,i,j)*/ (*cij)==NULL) (*cij)=s;
273            else (*cij) = p_Add_q((*cij) /*MATELEM(c,i,j)*/ ,s, R);
274          }
275        }
276      }
277    //  pNormalize(t);
278    //  MATELEM(c,i,j) = t;
279    }
280  }
281  for(i=m*q-1;i>=0;i--) p_Normalize(c->m[i], R);
282  return c;
283}
284
285matrix mp_Transp(matrix a, const ring R)
286{
287  int    i, j, r = MATROWS(a), c = MATCOLS(a);
288  poly *p;
289  matrix b =  mpNew(c,r);
290
291  p = b->m;
292  for (i=0; i<c; i++)
293  {
294    for (j=0; j<r; j++)
295    {
296      if (a->m[j*c+i]!=NULL) *p = p_Copy(a->m[j*c+i], R);
297      p++;
298    }
299  }
300  return b;
301}
302
303/*2
304*returns the trace of matrix a
305*/
306poly mp_Trace ( matrix a, const ring R)
307{
308  int i;
309  int n = (MATCOLS(a)<MATROWS(a)) ? MATCOLS(a) : MATROWS(a);
310  poly  t = NULL;
311
312  for (i=1; i<=n; i++)
313    t = p_Add_q(t, p_Copy(MATELEM(a,i,i), R), R);
314  return t;
315}
316
317/*2
318*returns the trace of the product of a and b
319*/
320poly TraceOfProd ( matrix a, matrix b, int n, const ring _R)
321{
322  int i, j;
323  poly  p, t = NULL;
324
325  for (i=1; i<=n; i++)
326  {
327    for (j=1; j<=n; j++)
328    {
329      p = pp_Mult_qq(MATELEM(a,i,j), MATELEM(b,j,i), _R);
330      t = p_Add_q(t, p, _R);
331    }
332  }
333  return t;
334}
335
336/*
337* C++ classes for Bareiss algorithm
338*/
339class row_col_weight
340{
341  private:
342  int ym, yn;
343  public:
344  float *wrow, *wcol;
345  row_col_weight() : ym(0) {}
346  row_col_weight(int, int);
347  ~row_col_weight();
348};
349
350/*2
351*  a submatrix M of a matrix X[m,n]:
352*    0 <= i < s_m <= a_m
353*    0 <= j < s_n <= a_n
354*    M = ( Xarray[qrow[i],qcol[j]] )
355*    if a_m = a_n and s_m = s_n
356*      det(X) = sign*div^(s_m-1)*det(M)
357*    resticted pivot for elimination
358*      0 <= j < piv_s
359*/
360class mp_permmatrix
361{
362  private:
363  int       a_m, a_n, s_m, s_n, sign, piv_s;
364  int       *qrow, *qcol;
365  poly      *Xarray;
366  const ring      _R;
367 
368  void mpInitMat();
369  poly * mpRowAdr(int);
370  poly * mpColAdr(int);
371  void mpRowWeight(float *);
372  void mpColWeight(float *);
373  void mpRowSwap(int, int);
374  void mpColSwap(int, int);
375  public:
376  mp_permmatrix() : a_m(0), _R(NULL) {}
377  mp_permmatrix(matrix, const ring);
378  mp_permmatrix(mp_permmatrix *);
379  ~mp_permmatrix();
380  int mpGetRow();
381  int mpGetCol();
382  int mpGetRdim();
383  int mpGetCdim();
384  int mpGetSign();
385  void mpSetSearch(int s);
386  void mpSaveArray();
387  poly mpGetElem(int, int);
388  void mpSetElem(poly, int, int);
389  void mpDelElem(int, int);
390  void mpElimBareiss(poly);
391  int mpPivotBareiss(row_col_weight *);
392  int mpPivotRow(row_col_weight *, int);
393  void mpToIntvec(intvec *);
394  void mpRowReorder();
395  void mpColReorder();
396};
397
398#ifndef SIZE_OF_SYSTEM_PAGE
399#define SIZE_OF_SYSTEM_PAGE 4096
400#endif
401
402/*
403/// entries of a are minors and go to result (only if not in R)
404void mp_MinorToResult(ideal result, int &elems, matrix a, int r, int c,
405                     ideal R, const ring _R)
406{
407  poly *q1;
408  int e=IDELEMS(result);
409  int i,j;
410
411  if (R != NULL)
412  {
413    for (i=r-1;i>=0;i--)
414    {
415      q1 = &(a->m)[i*a->ncols];
416      for (j=c-1;j>=0;j--)
417      {
418        if (q1[j]!=NULL) q1[j] = kNF(R,currQuotient,q1[j]);
419      }
420    }
421  }
422  for (i=r-1;i>=0;i--)
423  {
424    q1 = &(a->m)[i*a->ncols];
425    for (j=c-1;j>=0;j--)
426    {
427      if (q1[j]!=NULL)
428      {
429        if (elems>=e)
430        {
431          if(e<SIZE_OF_SYSTEM_PAGE)
432          {
433            pEnlargeSet(&(result->m),e,e);
434            e += e;
435          }
436          else
437          {
438            pEnlargeSet(&(result->m),e,SIZE_OF_SYSTEM_PAGE);
439            e += SIZE_OF_SYSTEM_PAGE;
440          }
441          IDELEMS(result) =e;
442        }
443        result->m[elems] = q1[j];
444        q1[j] = NULL;
445        elems++;
446      }
447    }
448  }
449}
450
451/// produces recursively the ideal of all arxar-minors of a
452void mp_RecMin(int ar,ideal result,int &elems,matrix a,int lr,int lc,
453              poly barDiv, ideal R, const ring _R)
454{
455  int k;
456  int kr=lr-1,kc=lc-1;
457  matrix nextLevel=mpNew(kr,kc);
458
459  loop
460  {
461// --- look for an optimal row and bring it to last position ------------
462    if(mpPrepareRow(a,lr,lc)==0) break;
463// --- now take all pivots from the last row ------------
464    k = lc;
465    loop
466    {
467      if(mpPreparePiv(a,lr,k)==0) break;
468      mpElimBar(a,nextLevel,barDiv,lr,k);
469      k--;
470      if (ar>1)
471      {
472        mpRecMin(ar-1,result,elems,nextLevel,kr,k,a->m[kr*a->ncols+k],R);
473        mpPartClean(nextLevel,kr,k);
474      }
475      else mpMinorToResult(result,elems,nextLevel,kr,k,R);
476      if (ar>k-1) break;
477    }
478    if (ar>=kr) break;
479// --- now we have to take out the last row...------------
480    lr = kr;
481    kr--;
482  }
483  mpFinalClean(nextLevel);
484}
485*/
486
487
488/*2
489*returns the determinant of the matrix m;
490*uses Bareiss algorithm
491*/
492poly mp_DetBareiss (matrix a, const ring R)
493{
494  int s;
495  poly div, res;
496  if (MATROWS(a) != MATCOLS(a))
497  {
498    Werror("det of %d x %d matrix",MATROWS(a),MATCOLS(a));
499    return NULL;
500  }
501  matrix c = mp_Copy(a, R);
502  mp_permmatrix *Bareiss = new mp_permmatrix(c, R);
503  row_col_weight w(Bareiss->mpGetRdim(), Bareiss->mpGetCdim());
504
505  /* Bareiss */
506  div = NULL;
507  while(Bareiss->mpPivotBareiss(&w))
508  {
509    Bareiss->mpElimBareiss(div);
510    div = Bareiss->mpGetElem(Bareiss->mpGetRdim(), Bareiss->mpGetCdim());
511  }
512  Bareiss->mpRowReorder();
513  Bareiss->mpColReorder();
514  Bareiss->mpSaveArray();
515  s = Bareiss->mpGetSign();
516  delete Bareiss;
517
518  /* result */
519  res = MATELEM(c,1,1);
520  MATELEM(c,1,1) = NULL;
521  id_Delete((ideal *)&c, R);
522  if (s < 0)
523    res = p_Neg(res, R);
524  return res;
525}
526
527/*2
528*returns the determinant of the matrix m;
529*uses Newtons formulea for symmetric functions
530*/
531poly mp_Det (matrix m, const ring R)
532{
533  int i,j,k,n;
534  poly p,q;
535  matrix a, s;
536  matrix ma[100];
537  number c=NULL, d=NULL, ONE=NULL;
538
539  n = MATROWS(m);
540  if (n != MATCOLS(m))
541  {
542    Werror("det of %d x %d matrix",n,MATCOLS(m));
543    return NULL;
544  }
545  k=rChar(R);
546  if ((k > 0) && (k <= n))
547    return mp_Leibnitz(m, R);
548  ONE = n_Init(1, R);
549  ma[1]=mp_Copy(m, R);
550  k = (n+1) / 2;
551  s = mpNew(1, n);
552  MATELEM(s,1,1) = mp_Trace(m, R);
553  for (i=2; i<=k; i++)
554  {
555    //ma[i] = mpNew(n,n);
556    ma[i]=mp_Mult(ma[i-1], ma[1], R);
557    MATELEM(s,1,i) = mp_Trace(ma[i], R);
558    p_Test(MATELEM(s,1,i), R);
559  }
560  for (i=k+1; i<=n; i++)
561  {
562    MATELEM(s,1,i) = TraceOfProd(ma[i / 2], ma[(i+1) / 2], n, R);
563    p_Test(MATELEM(s,1,i), R);
564  }
565  for (i=1; i<=k; i++)
566    id_Delete((ideal *)&(ma[i]), R);
567/* the array s contains the traces of the powers of the matrix m,
568*  these are the power sums of the eigenvalues of m */
569  a = mpNew(1,n);
570  MATELEM(a,1,1) = minuscopy(MATELEM(s,1,1), R);
571  for (i=2; i<=n; i++)
572  {
573    p = p_Copy(MATELEM(s,1,i), R);
574    for (j=i-1; j>=1; j--)
575    {
576      q = pp_Mult_qq(MATELEM(s,1,j), MATELEM(a,1,i-j), R);
577      p_Test(q, R);
578      p = p_Add_q(p,q, R);
579    }
580    // c= -1/i
581    d = n_Init(-(int)i, R);
582    c = n_Div(ONE, d, R);
583    n_Delete(&d, R);
584
585    p_Mult_nn(p, c, R);
586    p_Test(p, R);
587    MATELEM(a,1,i) = p;
588    n_Delete(&c, R);
589  }
590/* the array a contains the elementary symmetric functions of the
591*  eigenvalues of m */
592  for (i=1; i<=n-1; i++)
593  {
594    //p_Delete(&(MATELEM(a,1,i)), R);
595    p_Delete(&(MATELEM(s,1,i)), R);
596  }
597  p_Delete(&(MATELEM(s,1,n)), R);
598/* up to a sign, the determinant is the n-th elementary symmetric function */
599  if ((n/2)*2 < n)
600  {
601    d = n_Init(-1, R);
602    p_Mult_nn(MATELEM(a,1,n), d, R);
603    n_Delete(&d, R);
604  }
605  n_Delete(&ONE, R);
606  id_Delete((ideal *)&s, R);
607  poly result=MATELEM(a,1,n);
608  MATELEM(a,1,n)=NULL;
609  id_Delete((ideal *)&a, R);
610  return result;
611}
612
613/*2
614* compute all ar-minors of the matrix a
615*/
616matrix mp_Wedge(matrix a, int ar, const ring R)
617{
618  int     i,j,k,l;
619  int *rowchoise,*colchoise;
620  BOOLEAN rowch,colch;
621  matrix result;
622  matrix tmp;
623  poly p;
624
625  i = binom(a->nrows,ar);
626  j = binom(a->ncols,ar);
627
628  rowchoise=(int *)omAlloc(ar*sizeof(int));
629  colchoise=(int *)omAlloc(ar*sizeof(int));
630  result =mpNew(i,j);
631  tmp=mpNew(ar,ar);
632  l = 1; /* k,l:the index in result*/
633  idInitChoise(ar,1,a->nrows,&rowch,rowchoise);
634  while (!rowch)
635  {
636    k=1;
637    idInitChoise(ar,1,a->ncols,&colch,colchoise);
638    while (!colch)
639    {
640      for (i=1; i<=ar; i++)
641      {
642        for (j=1; j<=ar; j++)
643        {
644          MATELEM(tmp,i,j) = MATELEM(a,rowchoise[i-1],colchoise[j-1]);
645        }
646      }
647      p = mp_DetBareiss(tmp, R);
648      if ((k+l) & 1) p=p_Neg(p, R);
649      MATELEM(result,l,k) = p;
650      k++;
651      idGetNextChoise(ar,a->ncols,&colch,colchoise);
652    }
653    idGetNextChoise(ar,a->nrows,&rowch,rowchoise);
654    l++;
655  }
656
657  /*delete the matrix tmp*/
658  for (i=1; i<=ar; i++)
659  {
660    for (j=1; j<=ar; j++) MATELEM(tmp,i,j) = NULL;
661  }
662  id_Delete((ideal *) &tmp, R);
663  return (result);
664}
665
666///*2
667//*homogenize all elements of matrix (not the matrix itself)
668//*/
669//matrix mpHomogen(matrix a, int v)
670//{
671//  int i,j;
672//  poly p;
673//
674//  for (i=1;i<=MATROWS(a);i++)
675//  {
676//    for (j=1;j<=MATCOLS(a);j++)
677//    {
678//      p=pHomogen(MATELEM(a,i,j),v);
679//      p_Delete(&(MATELEM(a,i,j)), ?);
680//      MATELEM(a,i,j)=p;
681//    }
682//  }
683//  return a;
684//}
685
686/*2
687* corresponds to Maple's coeffs:
688* var has to be the number of a variable
689*/
690matrix mp_Coeffs (ideal I, int var, const ring R)
691{
692  poly h,f;
693  int l, i, c, m=0;
694  matrix co;
695  /* look for maximal power m of x_var in I */
696  for (i=IDELEMS(I)-1; i>=0; i--)
697  {
698    f=I->m[i];
699    while (f!=NULL)
700    {
701      l=p_GetExp(f,var, R);
702      if (l>m) m=l;
703      pIter(f);
704    }
705  }
706  co=mpNew((m+1)*I->rank,IDELEMS(I));
707  /* divide each monomial by a power of x_var,
708  * remember the power in l and the component in c*/
709  for (i=IDELEMS(I)-1; i>=0; i--)
710  {
711    f=I->m[i];
712    I->m[i]=NULL;
713    while (f!=NULL)
714    {
715      l=p_GetExp(f,var, R);
716      p_SetExp(f,var,0, R);
717      c=si_max((int)p_GetComp(f, R),1);
718      p_SetComp(f,0, R);
719      p_Setm(f, R);
720      /* now add the resulting monomial to co*/
721      h=pNext(f);
722      pNext(f)=NULL;
723      //MATELEM(co,c*(m+1)-l,i+1)
724      //  =p_Add_q(MATELEM(co,c*(m+1)-l,i+1),f, R);
725      MATELEM(co,(c-1)*(m+1)+l+1,i+1)
726        =p_Add_q(MATELEM(co,(c-1)*(m+1)+l+1,i+1),f, R);
727      /* iterate f*/
728      f=h;
729    }
730  }
731  id_Delete(&I, R);
732  return co;
733}
734
735/*2
736* given the result c of mpCoeffs(ideal/module i, var)
737* i of rank r
738* build the matrix of the corresponding monomials in m
739*/
740void   mp_Monomials(matrix c, int r, int var, matrix m, const ring R)
741{
742  /* clear contents of m*/
743  int k,l;
744  for (k=MATROWS(m);k>0;k--)
745  {
746    for(l=MATCOLS(m);l>0;l--)
747    {
748      p_Delete(&MATELEM(m,k,l), R);
749    }
750  }
751  omfreeSize((ADDRESS)m->m,MATROWS(m)*MATCOLS(m)*sizeof(poly));
752  /* allocate monoms in the right size r x MATROWS(c)*/
753  m->m=(poly*)omAlloc0(r*MATROWS(c)*sizeof(poly));
754  MATROWS(m)=r;
755  MATCOLS(m)=MATROWS(c);
756  m->rank=r;
757  /* the maximal power p of x_var: MATCOLS(m)=r*(p+1) */
758  int p=MATCOLS(m)/r-1;
759  /* fill in the powers of x_var=h*/
760  poly h=p_One(R);
761  for(k=r;k>0; k--)
762  {
763    MATELEM(m,k,k*(p+1))=p_One(R);
764  }
765  for(l=p;l>=0; l--)
766  {
767    p_SetExp(h,var,p-l, R);
768    p_Setm(h, R);
769    for(k=r;k>0; k--)
770    {
771      MATELEM(m,k,k*(p+1)-l)=p_Copy(h, R);
772    }
773  }
774  p_Delete(&h, R);
775}
776
777matrix mp_CoeffProc (poly f, poly vars, const ring R)
778{
779  assume(vars!=NULL);
780  poly sel, h;
781  int l, i;
782  int pos_of_1 = -1;
783  matrix co;
784
785  if (f==NULL)
786  {
787    co = mpNew(2, 1);
788    MATELEM(co,1,1) = p_One(R);
789    MATELEM(co,2,1) = NULL;
790    return co;
791  }
792  sel = mp_Select(f, vars, R);
793  l = pLength(sel);
794  co = mpNew(2, l);
795 
796  if (rHasLocalOrMixedOrdering(R))
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 (p_IsConstant(h, R)) 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 (p_IsConstant(h, R)) 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 = mp_Exdiv(f, MATELEM(co,1,i),vars, R);
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 = mp_Exdiv(f, MATELEM(co,1,pos_of_1),vars, R);
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 = p_Head(m, _R);
863  for (i=1; i<=rVar(_R); i++)
864  {
865    if (p_GetExp(vars,i, _R) > 0)
866    {
867      if (p_GetExp(d,i, _R) != p_GetExp(h,i, _R))
868      {
869        p_Delete(&h, _R);
870        return NULL;
871      }
872      p_SetExp(h,i,0, _R);
873    }
874  }
875  p_Setm(h, _R);
876  return h;
877}
878
879void mp_Coef2(poly v, poly mon, matrix *c, matrix *m, const ring _R)
880{
881  poly* s;
882  poly p;
883  int sl,i,j;
884  int l=0;
885  poly sel=mp_Select(v,mon, _R);
886
887  p_Vec2Polys(sel,&s,&sl, _R);
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 (p_IsConstant(p, _R)) /*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 = p_Head(p, _R);
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 = p_GetComp(v, _R);
919    loop
920    {
921      poly mp=MATELEM(*m,j,i);
922      if (mp!=NULL)
923      {
924        h = mp_Exdiv(v, mp /*MATELEM(*m,j,i)*/, mp, _R);
925        if (h!=NULL)
926        {
927          p_SetComp(h,0, _R);
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] = p_Copy(p, _R);
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 = p_Neg(elim, _R);
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, _R);
1096          if (a[jj] != NULL)
1097          {
1098            q1 = SM_MULT(a[jj], piv, div, _R);
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, _R);
1106        }
1107        if ((q2!=NULL) && div)
1108          SM_DIV(q2, div, _R);
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, _R);
1121          p_Delete(&a[jj], _R);
1122          if (div)
1123            SM_DIV(q2, div, _R);
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 = mp_PolyWeight(p, _R);
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 = mp_PolyWeight(p, _R);
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 = mp_PolyWeight(p, _R);
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 = mp_PolyWeight(p, _R);
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 += mp_PolyWeight(p, _R);
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 += mp_PolyWeight(p, _R);
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(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 = p_Cmp(a1, a2, R);
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      p_LmDelete(&a2, R);
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  p_LmDelete(&p, R);
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<=rVar(_R); 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=rVar(_R);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;
1790  poly* a1 = &a2[a->ncols*(pos-1)];
1791
1792  a2 = &a2[a->ncols*(lr-1)];
1793  for (j=lc-1; j>=0; j--)
1794  {
1795    sw = a1[j];
1796    a1[j] = a2[j];
1797    a2[j] = sw;
1798  }
1799}
1800
1801static void mpSwapCol(matrix a, int pos, int lr, int lc)
1802{
1803  poly sw;
1804  int j;
1805  poly* a2 = a->m;
1806  poly* a1 = &a2[pos-1];
1807
1808  a2 = &a2[lc-1];
1809  for (j=a->ncols*(lr-1); j>=0; j-=a->ncols)
1810  {
1811    sw = a1[j];
1812    a1[j] = a2[j];
1813    a2[j] = sw;
1814  }
1815}
1816
1817static void mp_ElimBar(matrix a0, matrix re, poly div, int lr, int lc, const ring _R)
1818{
1819  int r=lr-1, c=lc-1;
1820  poly *b = a0->m, *x = re->m;
1821  poly piv, elim, q1, q2, *ap, *a, *q;
1822  int i, j;
1823
1824  ap = &b[r*a0->ncols];
1825  piv = ap[c];
1826  for(j=c-1; j>=0; j--)
1827    if (ap[j] != NULL) ap[j] = p_Neg(ap[j], _R);
1828  for(i=r-1; i>=0; i--)
1829  {
1830    a = &b[i*a0->ncols];
1831    q = &x[i*re->ncols];
1832    if (a[c] != NULL)
1833    {
1834      elim = a[c];
1835      for (j=c-1; j>=0; j--)
1836      {
1837        q1 = NULL;
1838        if (a[j] != NULL)
1839        {
1840          q1 = SM_MULT(a[j], piv, div, _R);
1841          if (ap[j] != NULL)
1842          {
1843            q2 = SM_MULT(ap[j], elim, div, _R);
1844            q1 = p_Add_q(q1,q2, _R);
1845          }
1846        }
1847        else if (ap[j] != NULL)
1848          q1 = SM_MULT(ap[j], elim, div, _R);
1849        if (q1 != NULL)
1850        {
1851          if (div)
1852            SM_DIV(q1, div, _R);
1853          q[j] = q1;
1854        }
1855      }
1856    }
1857    else
1858    {
1859      for (j=c-1; j>=0; j--)
1860      {
1861        if (a[j] != NULL)
1862        {
1863          q1 = SM_MULT(a[j], piv, div, _R);
1864          if (div)
1865            SM_DIV(q1, div, _R);
1866          q[j] = q1;
1867        }
1868      }
1869    }
1870  }
1871}
1872
1873BOOLEAN mp_IsDiagUnit(matrix U, const ring _R)
1874{
1875  if(MATROWS(U)!=MATCOLS(U))
1876    return FALSE;
1877  for(int i=MATCOLS(U);i>=1;i--)
1878  {
1879    for(int j=MATCOLS(U); j>=1; j--)
1880    {
1881      if (i==j)
1882      {
1883        if (!p_IsUnit(MATELEM(U,i,i), _R)) return FALSE;
1884      }
1885      else if (MATELEM(U,i,j)!=NULL) return FALSE;
1886    }
1887  }
1888  return TRUE;
1889}
1890
1891void iiWriteMatrix(matrix im, const char *n, int dim, const ring r, int spaces)
1892{
1893  int i,ii = MATROWS(im)-1;
1894  int j,jj = MATCOLS(im)-1;
1895  poly *pp = im->m;
1896
1897  for (i=0; i<=ii; i++)
1898  {
1899    for (j=0; j<=jj; j++)
1900    {
1901      if (spaces>0)
1902        Print("%-*.*s",spaces,spaces," ");
1903      if (dim == 2) Print("%s[%u,%u]=",n,i+1,j+1);
1904      else if (dim == 1) Print("%s[%u]=",n,j+1);
1905      else if (dim == 0) Print("%s=",n);
1906      if ((i<ii)||(j<jj)) p_Write(*pp++, r);
1907      else                p_Write0(*pp, r);
1908    }
1909  }
1910}
1911
1912char * iiStringMatrix(matrix im, int dim, const ring r, char ch)
1913{
1914  int i,ii = MATROWS(im);
1915  int j,jj = MATCOLS(im);
1916  poly *pp = im->m;
1917  char *s=StringSetS("");
1918
1919  for (i=0; i<ii; i++)
1920  {
1921    for (j=0; j<jj; j++)
1922    {
1923      p_String0(*pp++, r);
1924      s=StringAppend("%c",ch);
1925      if (dim > 1) s = StringAppendS("\n");
1926    }
1927  }
1928  s[strlen(s)- (dim > 1 ? 2 : 1)]='\0';
1929  return s;
1930}
1931
1932void   mp_Delete(matrix* a, const ring r)
1933{
1934  id_Delete((ideal *) a, r);
1935}
Note: See TracBrowser for help on using the repository browser.