source: git/libpolys/polys/matpol.cc @ 85bcd6

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