bigintmat.cc
Go to the documentation of this file.
1 /*****************************************
2  * Computer Algebra System SINGULAR *
3  *****************************************/
4 /*
5  * * ABSTRACT: class bigintmat: matrices of numbers.
6  * * a few functinos might be limited to bigint or euclidean rings.
7  * */
8 
9 
10 #include <misc/auxiliary.h>
11 
12 #include "bigintmat.h"
13 #include <misc/intvec.h>
14 
15 #include "rmodulon.h"
16 
17 #include <math.h>
18 #include <string.h>
19 
20 ///create Z/nA of type n_Zn
21 static coeffs numbercoeffs(number n, coeffs c) // TODO: FIXME: replace with n_CoeffRingQuot1
22 {
23  mpz_t p;
24  number2mpz(n, c, p);
25  ZnmInfo *pp = new ZnmInfo;
26  pp->base = p;
27  pp->exp = 1;
28  coeffs nc = nInitChar(n_Zn, (void*)pp);
29  mpz_clear(p);
30  delete pp;
31  return nc;
32 }
33 
34 //#define BIMATELEM(M,I,J) (M)[ (M).index(I,J) ]
35 
37 {
38  bigintmat * t = new bigintmat(col, row, basecoeffs());
39  for (int i=1; i<=row; i++)
40  {
41  for (int j=1; j<=col; j++)
42  {
43  t->set(j, i, BIMATELEM(*this,i,j));
44  }
45  }
46  return t;
47 }
48 
50 {
51  int n = row,
52  m = col,
53  nm = n<m?n : m; // the min, describing the square part of the matrix
54  //CF: this is not optimal, but so far, it seems to work
55 
56 #define swap(_i, _j) \
57  int __i = (_i), __j=(_j); \
58  number c = v[__i]; \
59  v[__i] = v[__j]; \
60  v[__j] = c \
61 
62  for (int i=0; i< nm; i++)
63  for (int j=i+1; j< nm; j++) {
64  swap(i*m+j, j*n+i);
65  }
66  if (n<m)
67  for (int i=nm; i<m; i++)
68  for(int j=0; j<n; j++) {
69  swap(j*n+i, i*m+j);
70  }
71  if (n>m)
72  for (int i=nm; i<n; i++)
73  for(int j=0; j<m; j++) {
74  swap(i*m+j, j*n+i);
75  }
76 #undef swap
77  row = m;
78  col = n;
79 }
80 
81 
82 // Beginnt bei [0]
83 void bigintmat::set(int i, number n, const coeffs C)
84 {
85  assume (C == NULL || C == basecoeffs());
86 
87  rawset(i, n_Copy(n, basecoeffs()), basecoeffs());
88 }
89 
90 // Beginnt bei [1,1]
91 void bigintmat::set(int i, int j, number n, const coeffs C)
92 {
93  assume (C == NULL || C == basecoeffs());
94  assume (i > 0 && j > 0);
95  assume (i <= rows() && j <= cols());
96  set(index(i, j), n, C);
97 }
98 
99 number bigintmat::get(int i) const
100 {
101  assume (i >= 0);
102  assume (i<rows()*cols());
103 
104  return n_Copy(v[i], basecoeffs());
105 }
106 
107 number bigintmat::view(int i) const
108 {
109  assume (i >= 0);
110  assume (i<rows()*cols());
111 
112  return v[i];
113 }
114 
115 number bigintmat::get(int i, int j) const
116 {
117  assume (i > 0 && j > 0);
118  assume (i <= rows() && j <= cols());
119 
120  return get(index(i, j));
121 }
122 
123 number bigintmat::view(int i, int j) const
124 {
125  assume (i >= 0 && j >= 0);
126  assume (i <= rows() && j <= cols());
127 
128  return view(index(i, j));
129 }
130 // Ueberladener *=-Operator (für int und bigint)
131 // Frage hier: *= verwenden oder lieber = und * einzeln?
132 void bigintmat::operator*=(int intop)
133 {
134  number iop = n_Init(intop, basecoeffs());
135 
136  inpMult(iop, basecoeffs());
137 
138  n_Delete(&iop, basecoeffs());
139 }
140 
141 void bigintmat::inpMult(number bintop, const coeffs C)
142 {
143  assume (C == NULL || C == basecoeffs());
144 
145  const int l = rows() * cols();
146 
147  for (int i=0; i < l; i++)
148  n_InpMult(v[i], bintop, basecoeffs());
149 }
150 
151 // Stimmen Parameter?
152 // Welche der beiden Methoden?
153 // Oder lieber eine comp-Funktion?
154 
155 bool operator==(const bigintmat & lhr, const bigintmat & rhr)
156 {
157  if (&lhr == &rhr) { return true; }
158  if (lhr.cols() != rhr.cols()) { return false; }
159  if (lhr.rows() != rhr.rows()) { return false; }
160  if (lhr.basecoeffs() != rhr.basecoeffs()) { return false; }
161 
162  const int l = (lhr.rows())*(lhr.cols());
163 
164  for (int i=0; i < l; i++)
165  {
166  if (!n_Equal(lhr[i], rhr[i], lhr.basecoeffs())) { return false; }
167  }
168 
169  return true;
170 }
171 
172 bool operator!=(const bigintmat & lhr, const bigintmat & rhr)
173 {
174  return !(lhr==rhr);
175 }
176 
177 // Matrix-Add/-Sub/-Mult so oder mit operator+/-/* ?
179 {
180  if (a->cols() != b->cols()) return NULL;
181  if (a->rows() != b->rows()) return NULL;
182  if (a->basecoeffs() != b->basecoeffs()) { return NULL; }
183 
184  const coeffs basecoeffs = a->basecoeffs();
185 
186  int i;
187 
188  bigintmat * bim = new bigintmat(a->rows(), a->cols(), basecoeffs);
189 
190  for (i=a->rows()*a->cols()-1;i>=0; i--)
191  bim->rawset(i, n_Add((*a)[i], (*b)[i], basecoeffs), basecoeffs);
192 
193  return bim;
194 }
196 {
197 
198  const int mn = a->rows()*a->cols();
199 
200  const coeffs basecoeffs = a->basecoeffs();
201  number bb=n_Init(b,basecoeffs);
202 
203  int i;
204 
205  bigintmat * bim = new bigintmat(a->rows(),a->cols() , basecoeffs);
206 
207  for (i=0; i<mn; i++)
208  bim->rawset(i, n_Add((*a)[i], bb, basecoeffs), basecoeffs);
209 
210  n_Delete(&bb,basecoeffs);
211  return bim;
212 }
213 
215 {
216  if (a->cols() != b->cols()) return NULL;
217  if (a->rows() != b->rows()) return NULL;
218  if (a->basecoeffs() != b->basecoeffs()) { return NULL; }
219 
220  const coeffs basecoeffs = a->basecoeffs();
221 
222  int i;
223 
224  bigintmat * bim = new bigintmat(a->rows(), a->cols(), basecoeffs);
225 
226  for (i=a->rows()*a->cols()-1;i>=0; i--)
227  bim->rawset(i, n_Sub((*a)[i], (*b)[i], basecoeffs), basecoeffs);
228 
229  return bim;
230 }
231 
233 {
234  const int mn = a->rows()*a->cols();
235 
236  const coeffs basecoeffs = a->basecoeffs();
237  number bb=n_Init(b,basecoeffs);
238 
239  int i;
240 
241  bigintmat * bim = new bigintmat(a->rows(),a->cols() , basecoeffs);
242 
243  for (i=0; i<mn; i++)
244  bim->rawset(i, n_Sub((*a)[i], bb, basecoeffs), basecoeffs);
245 
246  n_Delete(&bb,basecoeffs);
247  return bim;
248 }
249 
250 //TODO: make special versions for certain rings!
252 {
253  const int ca = a->cols();
254  const int cb = b->cols();
255 
256  const int ra = a->rows();
257  const int rb = b->rows();
258 
259  if (ca != rb)
260  {
261 #ifndef SING_NDEBUG
262  Werror("wrong bigintmat sizes at multiplication a * b: acols: %d != brows: %d\n", ca, rb);
263 #endif
264  return NULL;
265  }
266 
267  assume (ca == rb);
268 
269  if (a->basecoeffs() != b->basecoeffs()) { return NULL; }
270 
271  const coeffs basecoeffs = a->basecoeffs();
272 
273  int i, j, k;
274 
275  number sum;
276 
277  bigintmat * bim = new bigintmat(ra, cb, basecoeffs);
278 
279  for (i=1; i<=ra; i++)
280  for (j=1; j<=cb; j++)
281  {
282  sum = n_Init(0, basecoeffs);
283 
284  for (k=1; k<=ca; k++)
285  {
286  number prod = n_Mult( BIMATELEM(*a, i, k), BIMATELEM(*b, k, j), basecoeffs);
287 
288  number sum2 = n_Add(sum, prod, basecoeffs); // no inplace add :(
289 
290  n_Delete(&sum, basecoeffs); n_Delete(&prod, basecoeffs);
291 
292  sum = sum2;
293  }
294  bim->rawset(i, j, sum, basecoeffs);
295  }
296  return bim;
297 }
298 
300 {
301 
302  const int mn = a->rows()*a->cols();
303 
304  const coeffs basecoeffs = a->basecoeffs();
305  number bb=n_Init(b,basecoeffs);
306 
307  int i;
308 
309  bigintmat * bim = new bigintmat(a->rows(),a->cols() , basecoeffs);
310 
311  for (i=0; i<mn; i++)
312  bim->rawset(i, n_Mult((*a)[i], bb, basecoeffs), basecoeffs);
313 
314  n_Delete(&bb,basecoeffs);
315  return bim;
316 }
317 
318 bigintmat * bimMult(bigintmat * a, number b, const coeffs cf)
319 {
320  if (cf!=a->basecoeffs()) return NULL;
321 
322  const int mn = a->rows()*a->cols();
323 
324  const coeffs basecoeffs = a->basecoeffs();
325 
326  int i;
327 
328  bigintmat * bim = new bigintmat(a->rows(),a->cols() , basecoeffs);
329 
330  for (i=0; i<mn; i++)
331  bim->rawset(i, n_Mult((*a)[i], b, basecoeffs), basecoeffs);
332 
333  return bim;
334 }
335 
336 // ----------------------------------------------------------------- //
337 // Korrekt?
338 
340 {
341  intvec * iv = new intvec(b->rows(), b->cols(), 0);
342  for (int i=0; i<(b->rows())*(b->cols()); i++)
343  (*iv)[i] = n_Int((*b)[i], b->basecoeffs()); // Geht das so?
344  return iv;
345 }
346 
348 {
349  const int l = (b->rows())*(b->cols());
350  bigintmat * bim = new bigintmat(b->rows(), b->cols(), C);
351 
352  for (int i=0; i < l; i++)
353  bim->rawset(i, n_Init((*b)[i], C), C);
354 
355  return bim;
356 }
357 
358 // ----------------------------------------------------------------- //
359 
360 int bigintmat::compare(const bigintmat* op) const
361 {
362  assume (basecoeffs() == op->basecoeffs() );
363 
364 #ifndef SING_NDEBUG
365  if (basecoeffs() != op->basecoeffs() )
366  WerrorS("wrong bigintmat comparison: different basecoeffs!\n");
367 #endif
368 
369  if ((col!=1) ||(op->cols()!=1))
370  {
371  if((col!=op->cols())
372  || (row!=op->rows()))
373  return -2;
374  }
375 
376  int i;
377  for (i=0; i<si_min(row*col,op->rows()*op->cols()); i++)
378  {
379  if ( n_Greater(v[i], (*op)[i], basecoeffs()) )
380  return 1;
381  else if (! n_Equal(v[i], (*op)[i], basecoeffs()))
382  return -1;
383  }
384 
385  for (; i<row; i++)
386  {
387  if ( n_GreaterZero(v[i], basecoeffs()) )
388  return 1;
389  else if (! n_IsZero(v[i], basecoeffs()) )
390  return -1;
391  }
392  for (; i<op->rows(); i++)
393  {
394  if ( n_GreaterZero((*op)[i], basecoeffs()) )
395  return -1;
396  else if (! n_IsZero((*op)[i], basecoeffs()) )
397  return 1;
398  }
399  return 0;
400 }
401 
402 
404 {
405  if (b == NULL)
406  return NULL;
407 
408  return new bigintmat(b);
409 }
410 
412 {
413  int n = cols(), m=rows();
414 
415  StringAppendS("[ ");
416  for(int i=1; i<= m; i++) {
417  StringAppendS("[ ");
418  for(int j=1; j< n; j++) {
419  n_Write(v[(i-1)*n+j-1], basecoeffs());
420  StringAppendS(", ");
421  }
422  if (n) n_Write(v[i*n-1], basecoeffs());
423  StringAppendS(" ]");
424  if (i<m) {
425  StringAppendS(", ");
426  }
427  }
428  StringAppendS(" ] ");
429 }
430 
432 {
433  StringSetS("");
434  Write();
435  return StringEndS();
436 }
437 
439 {
440  char * s = String();
441  PrintS(s);
442  omFree(s);
443 }
444 
445 
447 {
448  if ((col==0) || (row==0))
449  return NULL;
450  else
451  {
452  int * colwid = getwid(80);
453  if (colwid == NULL)
454  {
455  WerrorS("not enough space to print bigintmat");
456  WerrorS("try string(...) for a unformatted output");
457  return NULL;
458  }
459  char * ps;
460  int slength = 0;
461  for (int j=0; j<col; j++)
462  slength += colwid[j]*row;
463  slength += col*row+row;
464  ps = (char*) omAlloc0(sizeof(char)*(slength));
465  int pos = 0;
466  for (int i=0; i<col*row; i++)
467  {
468  StringSetS("");
469  n_Write(v[i], basecoeffs());
470  char * ts = StringEndS();
471  const int _nl = strlen(ts);
472  int cj = i%col;
473  if (_nl > colwid[cj])
474  {
475  StringSetS("");
476  int ci = i/col;
477  StringAppend("[%d,%d]", ci+1, cj+1);
478  char * ph = StringEndS();
479  int phl = strlen(ph);
480  if (phl > colwid[cj])
481  {
482  for (int j=0; j<colwid[cj]-1; j++)
483  ps[pos+j] = ' ';
484  ps[pos+colwid[cj]-1] = '*';
485  }
486  else
487  {
488  for (int j=0; j<colwid[cj]-phl; j++)
489  ps[pos+j] = ' ';
490  for (int j=0; j<phl; j++)
491  ps[pos+colwid[cj]-phl+j] = ph[j];
492  }
493  omFree(ph);
494  }
495  else // Mit Leerzeichen auffüllen und zahl reinschreiben
496  {
497  for (int j=0; j<(colwid[cj]-_nl); j++)
498  ps[pos+j] = ' ';
499  for (int j=0; j<_nl; j++)
500  ps[pos+colwid[cj]-_nl+j] = ts[j];
501  }
502  // ", " und (evtl) "\n" einfügen
503  if ((i+1)%col == 0)
504  {
505  if (i != col*row-1)
506  {
507  ps[pos+colwid[cj]] = ',';
508  ps[pos+colwid[cj]+1] = '\n';
509  pos += colwid[cj]+2;
510  }
511  }
512  else
513  {
514  ps[pos+colwid[cj]] = ',';
515  pos += colwid[cj]+1;
516  }
517 
518  omFree(ts); // Hier ts zerstören
519  }
520  return(ps);
521  // omFree(ps);
522 }
523 }
524 
525 static int intArrSum(int * a, int length)
526 {
527  int sum = 0;
528  for (int i=0; i<length; i++)
529  sum += a[i];
530  return sum;
531 }
532 
533 static int findLongest(int * a, int length)
534 {
535  int l = 0;
536  int index;
537  for (int i=0; i<length; i++)
538  {
539  if (a[i] > l)
540  {
541  l = a[i];
542  index = i;
543  }
544  }
545  return index;
546 }
547 
548 static int getShorter (int * a, int l, int j, int cols, int rows)
549 {
550  int sndlong = 0;
551  int min;
552  for (int i=0; i<rows; i++)
553  {
554  int index = cols*i+j;
555  if ((a[index] > sndlong) && (a[index] < l))
556  {
557  min = floor(log10((double)cols))+floor(log10((double)rows))+5;
558  if ((a[index] < min) && (min < l))
559  sndlong = min;
560  else
561  sndlong = a[index];
562  }
563  }
564  if (sndlong == 0)
565  {
566  min = floor(log10((double)cols))+floor(log10((double)rows))+5;
567  if (min < l)
568  sndlong = min;
569  else
570  sndlong = 1;
571  }
572  return sndlong;
573 }
574 
575 
576 int * bigintmat::getwid(int maxwid)
577 {
578  int const c = /*2**/(col-1)+1;
579  if (col + c > maxwid-1) return NULL;
580  int * wv = (int*)omAlloc(sizeof(int)*col*row);
581  int * cwv = (int*)omAlloc(sizeof(int)*col);
582  for (int j=0; j<col; j++)
583  {
584  cwv[j] = 0;
585  for (int i=0; i<row; i++)
586  {
587  StringSetS("");
588  n_Write(v[col*i+j], basecoeffs());
589  char * tmp = StringEndS();
590  const int _nl = strlen(tmp);
591  wv[col*i+j] = _nl;
592  if (_nl > cwv[j])
593  cwv[j]=_nl;
594  omFree(tmp);
595  }
596  }
597 
598  // Groesse verkleinern, bis < maxwid
599  while (intArrSum(cwv, col)+c > maxwid)
600  {
601  int j = findLongest(cwv, col);
602  cwv[j] = getShorter(wv, cwv[j], j, col, row);
603  }
604  omFree(wv);
605 return cwv;
606 }
607 
608 void bigintmat::pprint(int maxwid)
609 {
610  if ((col==0) || (row==0))
611  PrintS("");
612  else
613  {
614  int * colwid = getwid(maxwid);
615  if (colwid == NULL)
616  {
617  WerrorS("not enough space to print bigintmat");
618  return;
619  }
620  char * ps;
621  int slength = 0;
622  for (int j=0; j<col; j++)
623  slength += colwid[j]*row;
624  slength += col*row+row;
625  ps = (char*) omAlloc0(sizeof(char)*(slength));
626  int pos = 0;
627  for (int i=0; i<col*row; i++)
628  {
629  StringSetS("");
630  n_Write(v[i], basecoeffs());
631  char * ts = StringEndS();
632  const int _nl = strlen(ts);
633  int cj = i%col;
634  if (_nl > colwid[cj])
635  {
636  StringSetS("");
637  int ci = i/col;
638  StringAppend("[%d,%d]", ci+1, cj+1);
639  char * ph = StringEndS();
640  int phl = strlen(ph);
641  if (phl > colwid[cj])
642  {
643  for (int j=0; j<colwid[cj]-1; j++)
644  ps[pos+j] = ' ';
645  ps[pos+colwid[cj]-1] = '*';
646  }
647  else
648  {
649  for (int j=0; j<colwid[cj]-phl; j++)
650  ps[pos+j] = ' ';
651  for (int j=0; j<phl; j++)
652  ps[pos+colwid[cj]-phl+j] = ph[j];
653  }
654  omFree(ph);
655  }
656  else // Mit Leerzeichen auffüllen und zahl reinschreiben
657  {
658  for (int j=0; j<colwid[cj]-_nl; j++)
659  ps[pos+j] = ' ';
660  for (int j=0; j<_nl; j++)
661  ps[pos+colwid[cj]-_nl+j] = ts[j];
662  }
663  // ", " und (evtl) "\n" einfügen
664  if ((i+1)%col == 0)
665  {
666  if (i != col*row-1)
667  {
668  ps[pos+colwid[cj]] = ',';
669  ps[pos+colwid[cj]+1] = '\n';
670  pos += colwid[cj]+2;
671  }
672  }
673  else
674  {
675  ps[pos+colwid[cj]] = ',';
676  pos += colwid[cj]+1;
677  }
678 
679  omFree(ts); // Hier ts zerstören
680  }
681  PrintS(ps);
682  omFree(ps);
683  }
684 }
685 
686 
687 //swaps columns i and j
688 void bigintmat::swap(int i, int j) {
689  if ((i <= col) && (j <= col) && (i>0) && (j>0)) {
690  number tmp;
691  number t;
692  for (int k=1; k<=row; k++) {
693  tmp = get(k, i);
694  t = view(k, j);
695  set(k, i, t);
696  set(k, j, tmp);
697  n_Delete(&tmp, basecoeffs());
698  }
699  } else
700  Werror("Error in swap");
701 }
702 
703 void bigintmat::swaprow(int i, int j) {
704  if ((i <= row) && (j <= row) && (i>0) && (j>0)) {
705  number tmp;
706  number t;
707  for (int k=1; k<=col; k++) {
708  tmp = get(i, k);
709  t = view(j, k);
710  set(i, k, t);
711  set(j, k, tmp);
712  n_Delete(&tmp, basecoeffs());
713  }
714  }
715  else
716  Werror("Error in swaprow");
717 }
718 
720 {
721  for (int j=1; j<=col; j++) {
722  if (!n_IsZero(view(i,j), basecoeffs()))
723  {
724  return j;
725  }
726  }
727  return 0;
728 }
729 
731 {
732  for (int i=row; i>=1; i--) {
733  if (!n_IsZero(view(i,j), basecoeffs()))
734  {
735  return i;
736  }
737  }
738  return 0;
739 }
740 
742 {
743  assume((j<=col) && (j>=1));
744  if (((a->rows() != row) || (a->cols() != 1)) && ((a->rows() != 1) || (a->cols() != row))) {
745  assume(0);
746  Werror("Error in getcol. Dimensions must agree!");
747  return;
748  }
749  if (!nCoeffs_are_equal(basecoeffs(), a->basecoeffs())) {
751  number t1, t2;
752  for (int i=1; i<=row;i++) {
753  t1 = get(i,j);
754  t2 = f(t1, basecoeffs(), a->basecoeffs());
755  a->set(i-1,t1);
756  n_Delete(&t1, basecoeffs());
757  n_Delete(&t2, a->basecoeffs());
758  }
759  return;
760  }
761  number t1;
762  for (int i=1; i<=row;i++) {
763  t1 = view(i,j);
764  a->set(i-1,t1);
765  }
766 }
767 
768 void bigintmat::getColRange(int j, int no, bigintmat *a)
769 {
770  number t1;
771  for(int ii=0; ii< no; ii++) {
772  for (int i=1; i<=row;i++) {
773  t1 = view(i, ii+j);
774  a->set(i, ii+1, t1);
775  }
776  }
777 }
778 
780 {
781  if ((i>row) || (i<1)) {
782  Werror("Error in getrow: Index out of range!");
783  return;
784  }
785  if (((a->rows() != 1) || (a->cols() != col)) && ((a->rows() != col) || (a->cols() != 1))) {
786  Werror("Error in getrow. Dimensions must agree!");
787  return;
788  }
789  if (!nCoeffs_are_equal(basecoeffs(), a->basecoeffs())) {
791  number t1, t2;
792  for (int j=1; j<=col;j++) {
793  t1 = get(i,j);
794  t2 = f(t1, basecoeffs(), a->basecoeffs());
795  a->set(j-1,t2);
796  n_Delete(&t1, basecoeffs());
797  n_Delete(&t2, a->basecoeffs());
798  }
799  return;
800  }
801  number t1;
802  for (int j=1; j<=col;j++) {
803  t1 = get(i,j);
804  a->set(j-1,t1);
805  n_Delete(&t1, basecoeffs());
806  }
807 }
808 
809 
811 {
812  if ((j>col) || (j<1)) {
813  Werror("Error in setcol: Index out of range!");
814  return;
815  }
816  if (((m->rows() != row) || (m->cols() != 1)) && ((m->rows() != 1) || (m->cols() != row))) {
817  Werror("Error in setcol. Dimensions must agree!");
818  return;
819  }
820  if (!nCoeffs_are_equal(basecoeffs(), m->basecoeffs())) {
822  number t1,t2;
823  for (int i=1; i<=row; i++) {
824  t1 = m->get(i-1);
825  t2 = f(t1, m->basecoeffs(),basecoeffs());
826  set(i, j, t2);
827  n_Delete(&t2, basecoeffs());
828  n_Delete(&t1, m->basecoeffs());
829  }
830  return;
831  }
832  number t1;
833  for (int i=1; i<=row; i++) {
834  t1 = m->view(i-1);
835  set(i, j, t1);
836  }
837 }
838 
840  if ((j>row) || (j<1)) {
841  Werror("Error in setrow: Index out of range!");
842  return;
843  }
844  if (((m->rows() != 1) || (m->cols() != col)) && ((m->rows() != col) || (m->cols() != 1))) {
845  Werror("Error in setrow. Dimensions must agree!");
846  return;
847  }
848  if (!nCoeffs_are_equal(basecoeffs(), m->basecoeffs())) {
850  number tmp1,tmp2;
851  for (int i=1; i<=col; i++) {
852  tmp1 = m->get(i-1);
853  tmp2 = f(tmp1, m->basecoeffs(),basecoeffs());
854  set(j, i, tmp2);
855  n_Delete(&tmp2, basecoeffs());
856  n_Delete(&tmp1, m->basecoeffs());
857  }
858  return;
859  }
860  number tmp;
861  for (int i=1; i<=col; i++) {
862  tmp = m->view(i-1);
863  set(j, i, tmp);
864  }
865 
866 }
867 
869 {
870  if ((b->rows() != row) || (b->cols() != col)) {
871  Werror("Error in bigintmat::add. Dimensions do not agree!");
872  return false;
873  }
874  if (!nCoeffs_are_equal(basecoeffs(), b->basecoeffs())) {
875  Werror("Error in bigintmat::add. coeffs do not agree!");
876  return false;
877  }
878  for (int i=1; i<=row; i++) {
879  for (int j=1; j<=col; j++) {
880  rawset(i, j, n_Add(b->view(i,j), view(i,j), basecoeffs()));
881  }
882  }
883  return true;
884 }
885 
887 {
888  if ((b->rows() != row) || (b->cols() != col)) {
889  Werror("Error in bigintmat::sub. Dimensions do not agree!");
890  return false;
891  }
892  if (!nCoeffs_are_equal(basecoeffs(), b->basecoeffs())) {
893  Werror("Error in bigintmat::sub. coeffs do not agree!");
894  return false;
895  }
896  for (int i=1; i<=row; i++) {
897  for (int j=1; j<=col; j++) {
898  rawset(i, j, n_Sub(view(i,j), b->view(i,j), basecoeffs()));
899  }
900  }
901  return true;
902 }
903 
904 bool bigintmat::skalmult(number b, coeffs c)
905 {
906  if (!nCoeffs_are_equal(c, basecoeffs()))
907  {
908  Werror("Wrong coeffs\n");
909  return false;
910  }
911  number t1, t2;
912  if ( n_IsOne(b,c)) return true;
913  for (int i=1; i<=row; i++)
914  {
915  for (int j=1; j<=col; j++)
916  {
917  t1 = view(i, j);
918  t2 = n_Mult(t1, b, basecoeffs());
919  rawset(i, j, t2);
920  }
921  }
922  return true;
923 }
924 
925 bool bigintmat::addcol(int i, int j, number a, coeffs c)
926 {
927  if ((i>col) || (j>col) || (i<1) || (j<1)) {
928  Werror("Error in addcol: Index out of range!");
929  return false;
930  }
931  if (!nCoeffs_are_equal(c, basecoeffs())) {
932  Werror("Error in addcol: coeffs do not agree!");
933  return false;
934  }
935  number t1, t2, t3, t4;
936  for (int k=1; k<=row; k++)
937  {
938  t1 = view(k, j);
939  t2 = view(k, i);
940  t3 = n_Mult(t1, a, basecoeffs());
941  t4 = n_Add(t3, t2, basecoeffs());
942  rawset(k, i, t4);
943  n_Delete(&t3, basecoeffs());
944  }
945  return true;
946 }
947 
948 bool bigintmat::addrow(int i, int j, number a, coeffs c)
949 {
950  if ((i>row) || (j>row) || (i<1) || (j<1)) {
951  Werror("Error in addrow: Index out of range!");
952  return false;
953  }
954  if (!nCoeffs_are_equal(c, basecoeffs())) {
955  Werror("Error in addrow: coeffs do not agree!");
956  return false;
957  }
958  number t1, t2, t3, t4;
959  for (int k=1; k<=col; k++)
960  {
961  t1 = view(j, k);
962  t2 = view(i, k);
963  t3 = n_Mult(t1, a, basecoeffs());
964  t4 = n_Add(t3, t2, basecoeffs());
965  rawset(i, k, t4);
966  n_Delete(&t3, basecoeffs());
967  }
968  return true;
969 }
970 
971 void bigintmat::colskalmult(int i, number a, coeffs c) {
972  if ((i>=1) && (i<=col) && (nCoeffs_are_equal(c, basecoeffs()))) {
973  number t, tmult;
974  for (int j=1; j<=row; j++) {
975  t = view(j, i);
976  tmult = n_Mult(a, t, basecoeffs());
977  rawset(j, i, tmult);
978  }
979  }
980  else
981  Werror("Error in colskalmult");
982 }
983 
984 void bigintmat::rowskalmult(int i, number a, coeffs c) {
985  if ((i>=1) && (i<=row) && (nCoeffs_are_equal(c, basecoeffs()))) {
986  number t, tmult;
987  for (int j=1; j<=col; j++) {
988  t = view(i, j);
989  tmult = n_Mult(a, t, basecoeffs());
990  rawset(i, j, tmult);
991  }
992  }
993  else
994  Werror("Error in rowskalmult");
995 }
996 
998  int ay = a->cols();
999  int ax = a->rows();
1000  int by = b->cols();
1001  int bx = b->rows();
1002  number tmp;
1003  if (!((col == ay) && (col == by) && (ax+bx == row))) {
1004  Werror("Error in concatrow. Dimensions must agree!");
1005  return;
1006  }
1008  Werror("Error in concatrow. coeffs do not agree!");
1009  return;
1010  }
1011  for (int i=1; i<=ax; i++) {
1012  for (int j=1; j<=ay; j++) {
1013  tmp = a->get(i,j);
1014  set(i, j, tmp);
1015  n_Delete(&tmp, basecoeffs());
1016  }
1017  }
1018  for (int i=1; i<=bx; i++) {
1019  for (int j=1; j<=by; j++) {
1020  tmp = b->get(i,j);
1021  set(i+ax, j, tmp);
1022  n_Delete(&tmp, basecoeffs());
1023  }
1024  }
1025 }
1026 
1028  bigintmat * tmp = new bigintmat(rows(), i, basecoeffs());
1029  appendCol(tmp);
1030  delete tmp;
1031 }
1033  coeffs R = basecoeffs();
1034  int ay = a->cols();
1035  int ax = a->rows();
1036  assume(row == ax);
1037 
1039 
1040  bigintmat * tmp = new bigintmat(rows(), cols() + ay, R);
1041  tmp->concatcol(this, a);
1042  this->swapMatrix(tmp);
1043  delete tmp;
1044 }
1045 
1046 
1048  int ay = a->cols();
1049  int ax = a->rows();
1050  int by = b->cols();
1051  int bx = b->rows();
1052  number tmp;
1053 
1054  assume(row==ax && row == bx && ay+by ==col);
1055 
1057 
1058  for (int i=1; i<=ax; i++) {
1059  for (int j=1; j<=ay; j++) {
1060  tmp = a->view(i,j);
1061  set(i, j, tmp);
1062  }
1063  }
1064  for (int i=1; i<=bx; i++) {
1065  for (int j=1; j<=by; j++) {
1066  tmp = b->view(i,j);
1067  set(i, j+ay, tmp);
1068  }
1069  }
1070 }
1071 
1073  int ay = a->cols();
1074  int ax = a->rows();
1075  int by = b->cols();
1076  int bx = b->rows();
1077  number tmp;
1078  if (!(ax + bx == row)) {
1079  Werror("Error in splitrow. Dimensions must agree!");
1080  }
1081  else if (!((col == ay) && (col == by))) {
1082  Werror("Error in splitrow. Dimensions must agree!");
1083  }
1085  Werror("Error in splitrow. coeffs do not agree!");
1086  }
1087  else {
1088  for(int i = 1; i<=ax; i++) {
1089  for(int j = 1; j<=ay;j++) {
1090  tmp = get(i,j);
1091  a->set(i,j,tmp);
1092  n_Delete(&tmp, basecoeffs());
1093  }
1094  }
1095  for (int i =1; i<=bx; i++) {
1096  for (int j=1;j<=col;j++) {
1097  tmp = get(i+ax, j);
1098  b->set(i,j,tmp);
1099  n_Delete(&tmp, basecoeffs());
1100  }
1101  }
1102  }
1103 }
1104 
1106  int ay = a->cols();
1107  int ax = a->rows();
1108  int by = b->cols();
1109  int bx = b->rows();
1110  number tmp;
1111  if (!((row == ax) && (row == bx))) {
1112  Werror("Error in splitcol. Dimensions must agree!");
1113  }
1114  else if (!(ay+by == col)) {
1115  Werror("Error in splitcol. Dimensions must agree!");
1116  }
1118  Werror("Error in splitcol. coeffs do not agree!");
1119  }
1120  else {
1121  for (int i=1; i<=ax; i++) {
1122  for (int j=1; j<=ay; j++) {
1123  tmp = view(i,j);
1124  a->set(i,j,tmp);
1125  }
1126  }
1127  for (int i=1; i<=bx; i++) {
1128  for (int j=1; j<=by; j++) {
1129  tmp = view(i,j+ay);
1130  b->set(i,j,tmp);
1131  }
1132  }
1133  }
1134 }
1135 
1137  number tmp;
1138  if ((a->rows() != row) || (a->cols()+i-1 > col) || (i<1)) {
1139  Werror("Error in splitcol. Dimensions must agree!");
1140  return;
1141  }
1142  if (!(nCoeffs_are_equal(a->basecoeffs(), basecoeffs()))) {
1143  Werror("Error in splitcol. coeffs do not agree!");
1144  return;
1145  }
1146  int width = a->cols();
1147  for (int j=1; j<=width; j++) {
1148  for (int k=1; k<=row; k++) {
1149  tmp = get(k, j+i-1);
1150  a->set(k, j, tmp);
1151  n_Delete(&tmp, basecoeffs());
1152  }
1153  }
1154 }
1155 
1157  number tmp;
1158  if ((a->cols() != col) || (a->rows()+i-1 > row) || (i<1)) {
1159  Werror("Error in Marco-splitrow");
1160  return;
1161  }
1162 
1163  if (!(nCoeffs_are_equal(a->basecoeffs(), basecoeffs()))) {
1164  Werror("Error in splitrow. coeffs do not agree!");
1165  return;
1166  }
1167  int height = a->rows();
1168  for (int j=1; j<=height; j++) {
1169  for (int k=1; k<=col; k++) {
1170  tmp = view(j+i-1, k);
1171  a->set(j, k, tmp);
1172  }
1173  }
1174 }
1175 
1177 {
1178  if ((b->rows() != row) || (b->cols() != col)) {
1179  Werror("Error in bigintmat::copy. Dimensions do not agree!");
1180  return false;
1181  }
1182  if (!nCoeffs_are_equal(basecoeffs(), b->basecoeffs())) {
1183  Werror("Error in bigintmat::copy. coeffs do not agree!");
1184  return false;
1185  }
1186  number t1;
1187  for (int i=1; i<=row; i++)
1188  {
1189  for (int j=1; j<=col; j++)
1190  {
1191  t1 = b->view(i, j);
1192  set(i, j, t1);
1193  }
1194  }
1195  return true;
1196 }
1197 
1198 /// copy the submatrix of b, staring at (a,b) having n rows, m cols into
1199 /// the given matrix at pos. (c,d)
1200 /// needs c+n, d+m <= rows, cols
1201 /// a+n, b+m <= b.rows(), b.cols()
1202 void bigintmat::copySubmatInto(bigintmat *B, int a, int b, int n, int m, int c, int d)
1203 {
1204  number t1;
1205  for (int i=1; i<=n; i++)
1206  {
1207  for (int j=1; j<=m; j++)
1208  {
1209  t1 = B->view(a+i-1, b+j-1);
1210  set(c+i-1, d+j-1, t1);
1211  }
1212  }
1213 }
1214 
1215 
1217  coeffs r = basecoeffs();
1218  if (row==col) {
1219  for (int i=1; i<=row; i++) {
1220  for (int j=1; j<=col; j++) {
1221  if (i==j) {
1222  if (!n_IsOne(view(i, j), r))
1223  return 0;
1224  }
1225  else {
1226  if (!n_IsZero(view(i,j), r))
1227  return 0;
1228  }
1229  }
1230  }
1231  }
1232  return 1;
1233 }
1234 
1235 
1237  if (row==col) {
1238  number one = n_Init(1, basecoeffs()),
1239  zero = n_Init(0, basecoeffs());
1240  for (int i=1; i<=row; i++) {
1241  for (int j=1; j<=col; j++) {
1242  if (i==j) {
1243  set(i, j, one);
1244  } else {
1245  set(i, j, zero);
1246  }
1247  }
1248  }
1249  n_Delete(&one, basecoeffs());
1250  n_Delete(&zero, basecoeffs());
1251  }
1252 }
1253 
1255  number tmp = n_Init(0, basecoeffs());
1256  for (int i=1; i<=row; i++) {
1257  for (int j=1; j<=col; j++) {
1258  set(i, j, tmp);
1259  }
1260  }
1261  n_Delete(&tmp,basecoeffs());
1262 }
1263 
1265  for (int i=1; i<=row; i++) {
1266  for (int j=1; j<=col; j++) {
1267  if (!n_IsZero(view(i,j), basecoeffs()))
1268  return FALSE;
1269  }
1270  }
1271  return TRUE;
1272 }
1273 //****************************************************************************
1274 //
1275 //****************************************************************************
1276 
1277 //used in the det function. No idea what it does.
1278 //looks like it return the submatrix where the i-th row
1279 //and j-th column has been removed in the LaPlace generic
1280 //determinant algorithm
1282 {
1283  if ((i<=0) || (i>row) || (j<=0) || (j>col))
1284  return NULL;
1285  int cx, cy;
1286  cx=1;
1287  cy=1;
1288  number t;
1289  bigintmat *b = new bigintmat(row-1, col-1, basecoeffs());
1290  for (int k=1; k<=row; k++) {
1291  if (k!=i)
1292  {
1293  cy=1;
1294  for (int l=1; l<=col; l++)
1295  {
1296  if (l!=j)
1297  {
1298  t = get(k, l);
1299  b->set(cx, cy, t);
1300  n_Delete(&t, basecoeffs());
1301  cy++;
1302  }
1303  }
1304  cx++;
1305  }
1306  }
1307  return b;
1308 }
1309 
1310 
1311 //returns d such that a/d is the inverse of the input
1312 //TODO: make work for p not prime using the euc stuff.
1313 //long term: rewrite for Z using p-adic lifting
1314 //and Dixon. Possibly even the sparse recent Storjohann stuff
1316 
1317  // Falls Matrix über reellen Zahlen nicht invertierbar, breche ab
1318  assume((a->rows() == row) && (a->rows() == a->cols()) && (row == col));
1319 
1320  number det = this->det(); //computes the HNF, so should e reused.
1321  if ((n_IsZero(det, basecoeffs())))
1322  return det;
1323 
1324  // Hänge Einheitsmatrix über Matrix und wendet HNF an. An Stelle der Einheitsmatrix steht im Ergebnis die Transformationsmatrix dazu
1325  a->one();
1326  bigintmat *m = new bigintmat(2*row, col, basecoeffs());
1327  m->concatrow(a,this);
1328  m->hnf();
1329  // Arbeite weiterhin mit der zusammengehängten Matrix
1330  // Laufe durch die Diagonalelemente, und multipliziere jede Spalte rechts davon damit, speichere aber den alten Eintrag der Spalte, temp, der in der Zeile des Diagonalelements liegt, zwischen. Dann addiere das -temp-Fache der Diagonalspalte zur entsprechenenden Spalte rechts davon. Dadurch entsteht überall rechts der Diagonalen eine 0
1331  number diag;
1332  number temp, ttemp;
1333  for (int i=1; i<=col; i++) {
1334  diag = m->get(row+i, i);
1335  for (int j=i+1; j<=col; j++) {
1336  temp = m->get(row+i, j);
1337  m->colskalmult(j, diag, basecoeffs());
1338  temp = n_InpNeg(temp, basecoeffs());
1339  m->addcol(j, i, temp, basecoeffs());
1340  n_Delete(&temp, basecoeffs());
1341  }
1342  n_Delete(&diag, basecoeffs());
1343  }
1344  // Falls wir nicht modulo n arbeiten, können wir die Spalten durch den ggT teilen, um die Einträge kleiner zu bekommen
1345  // Bei Z/n sparen wir uns das, da es hier sinnlos ist
1346  number g;
1347  number gcd;
1348  for (int j=1; j<=col; j++) {
1349  g = n_Init(0, basecoeffs());
1350  for (int i=1; i<=2*row; i++) {
1351  temp = m->get(i,j);
1352  gcd = n_Gcd(g, temp, basecoeffs());
1353  n_Delete(&g, basecoeffs());
1354  n_Delete(&temp, basecoeffs());
1355  g = n_Copy(gcd, basecoeffs());
1356  n_Delete(&gcd, basecoeffs());
1357  }
1358  if (!(n_IsOne(g, basecoeffs())))
1359  m->colskaldiv(j, g);
1360  n_Delete(&g, basecoeffs());
1361  }
1362 
1363  // Nun müssen die Diagonalelemente durch Spaltenmultiplikation gleich gesett werden. Bei Z können wir mit dem kgV arbeiten, bei Z/n bringen wir jedes Diagonalelement auf 1 (wir arbeiten immer mit n = Primzahl. Für n != Primzahl muss noch an anderen Stellen etwas geändert werden)
1364 
1365  g = n_Init(0, basecoeffs());
1366  number prod = n_Init(1, basecoeffs());
1367  for (int i=1; i<=col; i++) {
1368  gcd = n_Gcd(g, m->get(row+i, i), basecoeffs());
1369  n_Delete(&g, basecoeffs());
1370  g = n_Copy(gcd, basecoeffs());
1371  n_Delete(&gcd, basecoeffs());
1372  ttemp = n_Copy(prod, basecoeffs());
1373  temp = m->get(row+i, i);
1374  n_Delete(&prod, basecoeffs());
1375  prod = n_Mult(ttemp, temp, basecoeffs());
1376  n_Delete(&ttemp, basecoeffs());
1377  n_Delete(&temp, basecoeffs());
1378  }
1379  number lcm;
1380  lcm = n_Div(prod, g, basecoeffs());
1381  for (int j=1; j<=col; j++) {
1382  ttemp = m->get(row+j,j);
1383  temp = n_QuotRem(lcm, ttemp, NULL, basecoeffs());
1384  m->colskalmult(j, temp, basecoeffs());
1385  n_Delete(&ttemp, basecoeffs());
1386  n_Delete(&temp, basecoeffs());
1387  }
1388  n_Delete(&lcm, basecoeffs());
1389  n_Delete(&prod, basecoeffs());
1390 
1391  number divisor = m->get(row+1, 1);
1392  m->splitrow(a, 1);
1393  delete m;
1394  n_Delete(&det, basecoeffs());
1395  return divisor;
1396 }
1397 
1399 {
1400  assume (col == row);
1401  number t = get(1,1),
1402  h;
1403  coeffs r = basecoeffs();
1404  for(int i=2; i<= col; i++) {
1405  h = n_Add(t, view(i,i), r);
1406  n_Delete(&t, r);
1407  t = h;
1408  }
1409  return t;
1410 }
1411 
1413 {
1414  assume (row==col);
1415 
1416  if (col == 1)
1417  return get(1, 1);
1418  // should work as well in Z/pZ of type n_Zp?
1419  // relies on XExtGcd and the other euc. functinos.
1420  if ( getCoeffType(basecoeffs())== n_Z || getCoeffType(basecoeffs() )== n_Zn) {
1421  return hnfdet();
1422  }
1423  number sum = n_Init(0, basecoeffs());
1424  number t1, t2, t3, t4;
1425  bigintmat *b;
1426  for (int i=1; i<=row; i++) {
1427  b = elim(i, 1);
1428  t1 = get(i, 1);
1429  t2 = b->det();
1430  t3 = n_Mult(t1, t2, basecoeffs());
1431  t4 = n_Copy(sum, basecoeffs());
1432  n_Delete(&sum, basecoeffs());
1433  if ((i+1)>>1<<1==(i+1))
1434  sum = n_Add(t4, t3, basecoeffs());
1435  else
1436  sum = n_Sub(t4, t3, basecoeffs());
1437  n_Delete(&t1, basecoeffs());
1438  n_Delete(&t2, basecoeffs());
1439  n_Delete(&t3, basecoeffs());
1440  n_Delete(&t4, basecoeffs());
1441  }
1442  return sum;
1443 }
1444 
1446 {
1447  assume (col == row);
1448 
1449  if (col == 1)
1450  return get(1, 1);
1451  bigintmat *m = new bigintmat(this);
1452  m->hnf();
1453  number prod = n_Init(1, basecoeffs());
1454  number temp, temp2;
1455  for (int i=1; i<=col; i++) {
1456  temp = m->get(i, i);
1457  temp2 = n_Mult(temp, prod, basecoeffs());
1458  n_Delete(&prod, basecoeffs());
1459  prod = temp2;
1460  n_Delete(&temp, basecoeffs());
1461  }
1462  delete m;
1463  return prod;
1464 }
1465 
1467 {
1468  int n = rows(), m = cols();
1469  row = a->rows();
1470  col = a->cols();
1471  number * V = v;
1472  v = a->v;
1473  a->v = V;
1474  a->row = n;
1475  a->col = m;
1476 }
1478 {
1479  coeffs R = basecoeffs();
1480  for(int i=1; i<=rows(); i++)
1481  if (!n_IsZero(view(i, j), R)) return FALSE;
1482  return TRUE;
1483 }
1484 
1486 {
1487  coeffs R = basecoeffs();
1488  hnf(); // as a starting point...
1489  if (getCoeffType(R)== n_Z) return; //wrong, need to prune!
1490 
1491  int n = cols(), m = rows(), i, j, k;
1492 
1493  //make sure, the matrix has enough space. We need no rows+1 columns.
1494  //The resulting Howell form will be pruned to be at most square.
1495  bigintmat * t = new bigintmat(m, m+1, R);
1496  t->copySubmatInto(this, 1, n>m ? n-m+1 : 1, m, n>m ? m : n, 1, n>m ? 2 : m+2-n );
1497  swapMatrix(t);
1498  delete t;
1499  for(i=1; i<= cols(); i++) {
1500  if (!colIsZero(i)) break;
1501  }
1502  assume (i>1);
1503  if (i>cols()) {
1504  t = new bigintmat(rows(), 0, R);
1505  swapMatrix(t);
1506  delete t;
1507  return; // zero matrix found, clearly normal.
1508  }
1509 
1510  int last_zero_col = i-1;
1511  for (int c = cols(); c>0; c--) {
1512  for(i=rows(); i>0; i--) {
1513  if (!n_IsZero(view(i, c), R)) break;
1514  }
1515  if (i==0) break; // matrix SHOULD be zero from here on
1516  number a = n_Ann(view(i, c), R);
1517  addcol(last_zero_col, c, a, R);
1518  n_Delete(&a, R);
1519  for(j = c-1; j>last_zero_col; j--) {
1520  for(k=rows(); k>0; k--) {
1521  if (!n_IsZero(view(k, j), R)) break;
1522  if (!n_IsZero(view(k, last_zero_col), R)) break;
1523  }
1524  if (k==0) break;
1525  if (!n_IsZero(view(k, last_zero_col), R)) {
1526  number gcd, co1, co2, co3, co4;
1527  gcd = n_XExtGcd(view(k, last_zero_col), view(k, j), &co1, &co2, &co3, &co4, R);
1528  if (n_Equal(gcd, view(k, j), R)) {
1529  number q = n_Div(view(k, last_zero_col), gcd, R);
1530  q = n_InpNeg(q, R);
1531  addcol(last_zero_col, j, q, R);
1532  n_Delete(&q, R);
1533  } else if (n_Equal(gcd, view(k, last_zero_col), R)) {
1534  swap(last_zero_col, k);
1535  number q = n_Div(view(k, last_zero_col), gcd, R);
1536  q = n_InpNeg(q, R);
1537  addcol(last_zero_col, j, q, R);
1538  n_Delete(&q, R);
1539  } else {
1540  coltransform(last_zero_col, j, co3, co4, co1, co2);
1541  }
1542  n_Delete(&gcd, R);
1543  n_Delete(&co1, R);
1544  n_Delete(&co2, R);
1545  n_Delete(&co3, R);
1546  n_Delete(&co4, R);
1547  }
1548  }
1549  for(k=rows(); k>0; k--) {
1550  if (!n_IsZero(view(k, last_zero_col), R)) break;
1551  }
1552  if (k) last_zero_col--;
1553  }
1554  t = new bigintmat(rows(), cols()-last_zero_col, R);
1555  t->copySubmatInto(this, 1, last_zero_col+1, rows(), cols()-last_zero_col, 1, 1);
1556  swapMatrix(t);
1557  delete t;
1558 }
1559 
1561 {
1562  // Laufen von unten nach oben und von links nach rechts
1563  // CF: TODO: for n_Z: write a recursive version. This one will
1564  // have exponential blow-up. Look at Michianchio
1565  // Alternatively, do p-adic det and modular method
1566 
1567 #if 0
1568  char * s;
1569  ::Print("mat over Z is \n");
1570  ::Print("%s\n", s = nCoeffString(basecoeffs()));
1571  omFree(s);
1572  Print();
1573  ::Print("\n(%d x %d)\n", rows(), cols());
1574 #endif
1575 
1576  int i = rows();
1577  int j = cols();
1578  number q = n_Init(0, basecoeffs());
1579  number one = n_Init(1, basecoeffs());
1580  number minusone = n_Init(-1, basecoeffs());
1581  number tmp1 = n_Init(0, basecoeffs());
1582  number tmp2 = n_Init(0, basecoeffs());
1583  number co1, co2, co3, co4;
1584  number ggt = n_Init(0, basecoeffs());
1585 
1586  while ((i>0) && (j>0)) {
1587  // Falls erstes Nicht-Null-Element in Zeile i nicht existiert, oder hinter Spalte j vorkommt, gehe in nächste Zeile
1588  if ((findnonzero(i)==0) || (findnonzero(i)>j)) {
1589  i--;
1590  } else {
1591  // Laufe von links nach rechts durch die Zeile:
1592  for (int l=1; l<=j-1; l++) {
1593  n_Delete(&tmp1, basecoeffs());
1594  tmp1 = get(i, l);
1595  // Falls Eintrag (im folgenden x genannt) gleich 0, gehe eine Spalte weiter. Ansonsten...
1596  if (!n_IsZero(tmp1, basecoeffs())) {
1597  n_Delete(&tmp2, basecoeffs());
1598  tmp2 = get(i, l+1);
1599  // Falls Eintrag (i.f. y g.) rechts daneben gleich 0, tausche beide Spalten, sonst...
1600  if (!n_IsZero(tmp2, basecoeffs())) {
1601  n_Delete(&ggt, basecoeffs());
1602  ggt = n_XExtGcd(tmp1, tmp2, &co1, &co2, &co3, &co4, basecoeffs());
1603  // Falls x=ggT(x, y), tausche die beiden Spalten und ziehe die (neue) rechte Spalte so häufig von der linken ab, dass an der ehemaligen Stelle von x nun eine 0 steht. Dazu:
1604  if (n_Equal(tmp1, ggt, basecoeffs())) {
1605  swap(l, l+1);
1606  n_Delete(&q, basecoeffs());
1607  q = n_Div(tmp2, ggt, basecoeffs());
1608  q = n_InpNeg(q, basecoeffs());
1609  // Dann addiere das -q-fache der (neuen) rechten Spalte zur linken dazu. Damit erhalten wir die gewünschte 0
1610 
1611  addcol(l, l+1, q, basecoeffs());
1612  n_Delete(&q, basecoeffs());
1613  }
1614  else if (n_Equal(tmp1, minusone, basecoeffs())) {
1615  // Falls x=-1, so ist x=-ggt(x, y). Dann gehe wie oben vor, multipliziere aber zuerst die neue rechte Spalte (die mit x) mit -1
1616  // Die Berechnung von q (=y/ggt) entfällt, da ggt=1
1617  swap(l, l+1);
1618  colskalmult(l+1, minusone, basecoeffs());
1619  tmp2 = n_InpNeg(tmp2, basecoeffs());
1620  addcol(l, l+1, tmp2, basecoeffs());
1621  }
1622  else {
1623  // CF: use the 2x2 matrix (co1, co2)(co3, co4) to
1624  // get the gcd in position and the 0 in the other:
1625 #ifdef CF_DEB
1626  ::Print("applying trafo\n");
1627  StringSetS("");
1628  n_Write(co1, basecoeffs()); StringAppendS("\t");
1629  n_Write(co2, basecoeffs()); StringAppendS("\t");
1630  n_Write(co3, basecoeffs()); StringAppendS("\t");
1631  n_Write(co4, basecoeffs()); StringAppendS("\t");
1632  ::Print("%s\nfor l=%d\n", StringEndS(), l);
1633  {char * s = String();
1634  ::Print("to %s\n", s);omFree(s);};
1635 #endif
1636  coltransform(l, l+1, co3, co4, co1, co2);
1637 #ifdef CF_DEB
1638  {char * s = String();
1639  ::Print("gives %s\n", s);}
1640 #endif
1641  }
1642  n_Delete(&co1, basecoeffs());
1643  n_Delete(&co2, basecoeffs());
1644  n_Delete(&co3, basecoeffs());
1645  n_Delete(&co4, basecoeffs());
1646  }
1647  else {
1648  swap(l, l+1);
1649  }
1650  // Dann betrachte die vormals rechte Spalte als neue linke, und die rechts daneben als neue rechte.
1651  }
1652  }
1653 
1654  // normalize by units:
1655  if (!n_IsZero(view(i, j), basecoeffs())) {
1656  number u = n_GetUnit(view(i, j), basecoeffs());
1657  if (!n_IsOne(u, basecoeffs())) {
1658  colskaldiv(j, u);
1659  }
1660  n_Delete(&u, basecoeffs());
1661  }
1662  // Zum Schluss mache alle Einträge rechts vom Diagonalelement betragsmäßig kleiner als dieses
1663  for (int l=j+1; l<=col; l++) {
1664  n_Delete(&q, basecoeffs());
1665  q = n_QuotRem(view(i, l), view(i, j), NULL, basecoeffs());
1666  q = n_InpNeg(q, basecoeffs());
1667  addcol(l, j, q, basecoeffs());
1668  }
1669  i--;
1670  j--;
1671  // Dann betrachte die Zeile darüber und gehe dort wie vorher vor
1672  }
1673  }
1674  n_Delete(&q, basecoeffs());
1675  n_Delete(&tmp1, basecoeffs());
1676  n_Delete(&tmp2, basecoeffs());
1677  n_Delete(&ggt, basecoeffs());
1678  n_Delete(&one, basecoeffs());
1679  n_Delete(&minusone, basecoeffs());
1680 
1681 #if 0
1682  ::Print("hnf over Z is \n");
1683  Print();
1684  ::Print("\n(%d x %d)\n", rows(), cols());
1685 #endif
1686 }
1687 
1689 {
1690  coeffs cold = a->basecoeffs();
1691  bigintmat *b = new bigintmat(a->rows(), a->cols(), cnew);
1692  // Erzeugt Karte von alten coeffs nach neuen
1693  nMapFunc f = n_SetMap(cold, cnew);
1694  number t1;
1695  number t2;
1696  // apply map to all entries.
1697  for (int i=1; i<=a->rows(); i++)
1698  {
1699  for (int j=1; j<=a->cols(); j++)
1700  {
1701  t1 = a->get(i, j);
1702  t2 = f(t1, cold, cnew);
1703  b->set(i, j, t2);
1704  n_Delete(&t1, cold);
1705  n_Delete(&t2, cnew);
1706  }
1707  }
1708  return b;
1709 }
1710 
1711 //OK: a HNF of (this | p*I)
1712 //so the result will always have FULL rank!!!!
1713 //(This is different form a lift of the HNF mod p: consider the matrix (p)
1714 //to see the difference. It CAN be computed as HNF mod p^2 usually..)
1716 {
1717  coeffs Rp = numbercoeffs(p, R); // R/pR
1718  bigintmat *m = bimChangeCoeff(this, Rp);
1719  m->howell();
1720  bigintmat *a = bimChangeCoeff(m, R);
1721  delete m;
1722  bigintmat *C = new bigintmat(rows(), rows(), R);
1723  int piv = rows(), i = a->cols();
1724  while (piv) {
1725  if (!i || n_IsZero(a->view(piv, i), R)) {
1726  C->set(piv, piv, p, R);
1727  } else {
1728  C->copySubmatInto(a, 1, i, rows(), 1, 1, piv);
1729  i--;
1730  }
1731  piv--;
1732  }
1733  delete a;
1734  return C;
1735 }
1736 
1737 
1738 //exactly divide matrix by b
1739 void bigintmat::skaldiv(number b)
1740 {
1741  number tmp1, tmp2;
1742  for (int i=1; i<=row; i++)
1743  {
1744  for (int j=1; j<=col; j++)
1745  {
1746  tmp1 = view(i, j);
1747  tmp2 = n_Div(tmp1, b, basecoeffs());
1748  rawset(i, j, tmp2);
1749  }
1750  }
1751 }
1752 
1753 //exactly divide col j by b
1754 void bigintmat::colskaldiv(int j, number b)
1755 {
1756  number tmp1, tmp2;
1757  for (int i=1; i<=row; i++)
1758  {
1759  tmp1 = view(i, j);
1760  tmp2 = n_Div(tmp1, b, basecoeffs());
1761  rawset(i, j, tmp2);
1762  }
1763 }
1764 
1765 // col(j, k) <- col(j,k)*matrix((a, c)(b, d))
1766 // mostly used internally in the hnf and Howell stuff
1767 void bigintmat::coltransform(int j, int k, number a, number b, number c, number d)
1768 {
1769  number tmp1, tmp2, tmp3, tmp4;
1770  for (int i=1; i<=row; i++)
1771  {
1772  tmp1 = get(i, j);
1773  tmp2 = get(i, k);
1774  tmp3 = n_Mult(tmp1, a, basecoeffs());
1775  tmp4 = n_Mult(tmp2, b, basecoeffs());
1776  n_InpAdd(tmp3, tmp4, basecoeffs());
1777  n_Delete(&tmp4, basecoeffs());
1778 
1779  n_InpMult(tmp1, c, basecoeffs());
1780  n_InpMult(tmp2, d, basecoeffs());
1781  n_InpAdd(tmp1, tmp2, basecoeffs());
1782  n_Delete(&tmp2, basecoeffs());
1783 
1784  set(i, j, tmp3);
1785  set(i, k, tmp1);
1786  n_Delete(&tmp1, basecoeffs());
1787  n_Delete(&tmp3, basecoeffs());
1788  }
1789 }
1790 
1791 
1792 
1793 //reduce all entries mod p. Does NOT change the coeffs type
1794 void bigintmat::mod(number p, coeffs c)
1795 {
1796  // produce the matrix in Z/pZ
1797  // CF: TODO rewrite using QuotRem and not the map
1798  coeffs coe = numbercoeffs(p, c);
1799  nMapFunc f1 = n_SetMap(basecoeffs(), coe);
1800  nMapFunc f2 = n_SetMap(coe, basecoeffs());
1801  number tmp1, tmp2;
1802  for (int i=1; i<=row; i++)
1803  {
1804  for (int j=1; j<=col; j++)
1805  {
1806  tmp1 = get(i, j);
1807  tmp2 = f1(tmp1, basecoeffs(), coe);
1808  n_Delete(&tmp1, basecoeffs());
1809  tmp1 = f2(tmp2, coe, basecoeffs());
1810  set(i, j, tmp1);
1811  n_Delete(&tmp1, basecoeffs());
1812  n_Delete(&tmp2, coe);
1813  }
1814  }
1815  nKillChar(coe);
1816 }
1817 
1819 {
1820  if (!nCoeffs_are_equal(a->basecoeffs(), b->basecoeffs())) {
1821  Werror("Error in bimMult. Coeffs do not agree!");
1822  return;
1823  }
1824  if ((a->rows() != c->rows()) || (b->cols() != c->cols()) || (a->cols() != b->rows())) {
1825  Werror("Error in bimMult. Dimensions do not agree!");
1826  return;
1827  }
1828  bigintmat *tmp = bimMult(a, b);
1829  c->copy(tmp);
1830 
1831  delete tmp;
1832 }
1833 
1835  //write b = Ax + eps where eps is "small" in the sense of bounded by the
1836  //pivot entries in H. H does not need to be Howell (or HNF) but need
1837  //to be triagonal in the same direction.
1838  //b can have multiple columns.
1839 #if 0
1840  Print("reduce_mod_howell: A:\n");
1841  A->Print();
1842  Print("\nb:\n");
1843  b->Print();
1844 #endif
1845 
1846  coeffs R = A->basecoeffs();
1847  assume(x->basecoeffs() == R);
1848  assume(b->basecoeffs() == R);
1849  assume(eps->basecoeffs() == R);
1850  if (!A->cols()) {
1851  x->zero();
1852  eps->copy(b);
1853 
1854 #if 0
1855  Print("\nx:\n");
1856  x->Print();
1857  Print("\neps:\n");
1858  eps->Print();
1859  Print("\n****************************************\n");
1860 #endif
1861  return;
1862  }
1863 
1864  bigintmat * B = new bigintmat(b->rows(), 1, R);
1865  for(int i=1; i<= b->cols(); i++) {
1866  int A_col = A->cols();
1867  b->getcol(i, B);
1868  for(int j = B->rows(); j>0; j--) {
1869  number Ai = A->view(A->rows() - B->rows() + j, A_col);
1870  if (n_IsZero(Ai, R) &&
1871  n_IsZero(B->view(j, 1), R)) {
1872  continue; //all is fine: 0*x = 0
1873  } else if (n_IsZero(B->view(j, 1), R)) {
1874  x->rawset(x->rows() - B->rows() + j, i, n_Init(0, R));
1875  A_col--;
1876  } else if (n_IsZero(Ai, R)) {
1877  A_col--;
1878  } else {
1879  // "solve" ax=b, possibly enlarging d
1880  number Bj = B->view(j, 1);
1881  number q = n_Div(Bj, Ai, R);
1882  x->rawset(x->rows() - B->rows() + j, i, q);
1883  for(int k=j; k>B->rows() - A->rows(); k--) {
1884  //B[k] = B[k] - x[k]A[k][j]
1885  number s = n_Mult(q, A->view(A->rows() - B->rows() + k, A_col), R);
1886  B->rawset(k, 1, n_Sub(B->view(k, 1), s, R));
1887  n_Delete(&s, R);
1888  }
1889  A_col--;
1890  }
1891  if (!A_col) {
1892  break;
1893  }
1894  }
1895  eps->setcol(i, B);
1896  }
1897  delete B;
1898 #if 0
1899  Print("\nx:\n");
1900  x->Print();
1901  Print("\neps:\n");
1902  eps->Print();
1903  Print("\n****************************************\n");
1904 #endif
1905 }
1906 
1908 {
1909  coeffs R = A->basecoeffs();
1910  bigintmat *m = new bigintmat(A->rows()+A->cols(), A->cols(), R);
1911  m->copySubmatInto(A, 1, 1, A->rows(), A->cols(), A->cols()+1, 1);
1912  number one = n_Init(1, R);
1913  for(int i=1; i<= A->cols(); i++)
1914  m->set(i,i,one);
1915  n_Delete(&one, R);
1916  return m;
1917 }
1918 
1919 static number bimFarey(bigintmat *A, number N, bigintmat *L) {
1920  coeffs Z = A->basecoeffs(),
1921  Q = nInitChar(n_Q, 0);
1922  number den = n_Init(1, Z);
1923  nMapFunc f = n_SetMap(Q, Z);
1924 
1925  for(int i=1; i<= A->rows(); i++) {
1926  for(int j=1; j<= A->cols(); j++) {
1927  number ad = n_Mult(den, A->view(i, j), Z);
1928  number re = n_IntMod(ad, N, Z);
1929  n_Delete(&ad, Z);
1930  number q = n_Farey(re, N, Z);
1931  n_Delete(&re, Z);
1932  if (!q) {
1933  n_Delete(&ad, Z);
1934  n_Delete(&den, Z);
1935  return NULL;
1936  }
1937 
1938  number d = n_GetDenom(q, Q),
1939  n = n_GetNumerator(q, Q);
1940 
1941  n_Delete(&q, Q);
1942  n_Delete(&ad, Z);
1943  number dz = f(d, Q, Z),
1944  nz = f(n, Q, Z);
1945  n_Delete(&d, Q);
1946  n_Delete(&n, Q);
1947 
1948  if (!n_IsOne(dz, Z)) {
1949  L->skalmult(dz, Z);
1950  n_InpMult(den, dz, Z);
1951 #if 0
1952  Print("den increasing to ");
1953  n_Print(den, Z);
1954  Print("\n");
1955 #endif
1956  }
1957  n_Delete(&dz, Z);
1958  L->rawset(i, j, nz);
1959  }
1960  }
1961 
1962  nKillChar(Q);
1963  Print("bimFarey worked\n");
1964 #if 0
1965  L->Print();
1966  Print("\n * 1/");
1967  n_Print(den, Z);
1968  Print("\n");
1969 #endif
1970  return den;
1971 }
1972 
1973 static number solveAx_dixon(bigintmat *A, bigintmat *B, bigintmat *x, bigintmat *kern) {
1974  coeffs R = A->basecoeffs();
1975 
1976  assume(getCoeffType(R) == n_Z);
1977 
1978  number p = n_Init(536870909, R); // PreviousPrime(2^29); not clever
1979  coeffs Rp = numbercoeffs(p, R); // R/pR
1980  bigintmat *Ap = bimChangeCoeff(A, Rp),
1981  *m = prependIdentity(Ap),
1982  *Tp, *Hp;
1983  delete Ap;
1984 
1985  m->howell();
1986  Hp = new bigintmat(A->rows(), A->cols(), Rp);
1987  Hp->copySubmatInto(m, A->cols()+1, 1, A->rows(), A->cols(), 1, 1);
1988  Tp = new bigintmat(A->cols(), A->cols(), Rp);
1989  Tp->copySubmatInto(m, 1, 1, A->cols(), A->cols(), 1, 1);
1990 
1991  int i, j;
1992 
1993  for(i=1; i<= A->cols(); i++) {
1994  for(j=m->rows(); j>A->cols(); j--) {
1995  if (!n_IsZero(m->view(j, i), Rp)) break;
1996  }
1997  if (j>A->cols()) break;
1998  }
1999 // Print("Found nullity (kern dim) of %d\n", i-1);
2000  bigintmat * kp = new bigintmat(A->cols(), i-1, Rp);
2001  kp->copySubmatInto(Tp, 1, 1, A->cols(), i-1, 1, 1);
2002  kp->howell();
2003 
2004  delete m;
2005 
2006  //Hp is the mod-p howell form
2007  //Tp the transformation, mod p
2008  //kp a basis for the kernel, in howell form, mod p
2009 
2010  bigintmat * eps_p = new bigintmat(B->rows(), B->cols(), Rp),
2011  * x_p = new bigintmat(A->cols(), B->cols(), Rp),
2012  * fps_p = new bigintmat(kp->cols(), B->cols(), Rp);
2013 
2014  //initial solution
2015 
2016  number zero = n_Init(0, R);
2017  x->skalmult(zero, R);
2018  n_Delete(&zero, R);
2019 
2020  bigintmat * b = new bigintmat(B);
2021  number pp = n_Init(1, R);
2022  i = 1;
2023  do {
2024  bigintmat * b_p = bimChangeCoeff(b, Rp), * s;
2025  bigintmat * t1, *t2;
2026  reduce_mod_howell(Hp, b_p, eps_p, x_p);
2027  delete b_p;
2028  if (!eps_p->isZero()) {
2029  Print("no solution, since no modular solution\n");
2030 
2031  delete eps_p;
2032  delete x_p;
2033  delete Hp;
2034  delete kp;
2035  delete Tp;
2036  delete b;
2037  n_Delete(&pp, R);
2038  n_Delete(&p, R);
2039  nKillChar(Rp);
2040 
2041  return NULL;
2042  }
2043  t1 = bimMult(Tp, x_p);
2044  delete x_p;
2045  x_p = t1;
2046  reduce_mod_howell(kp, x_p, x_p, fps_p); //we're not all interested in fps_p
2047  s = bimChangeCoeff(x_p, R);
2048  t1 = bimMult(A, s);
2049  t2 = bimSub(b, t1);
2050  t2->skaldiv(p);
2051  delete b;
2052  delete t1;
2053  b = t2;
2054  s->skalmult(pp, R);
2055  t1 = bimAdd(x, s);
2056  delete s;
2057  x->swapMatrix(t1);
2058  delete t1;
2059 
2060  if(kern && i==1) {
2061  bigintmat * ker = bimChangeCoeff(kp, R);
2062  t1 = bimMult(A, ker);
2063  t1->skaldiv(p);
2064  t1->skalmult(n_Init(-1, R), R);
2065  b->appendCol(t1);
2066  delete t1;
2067  x->appendCol(ker);
2068  delete ker;
2069  x_p->extendCols(kp->cols());
2070  eps_p->extendCols(kp->cols());
2071  fps_p->extendCols(kp->cols());
2072  }
2073 
2074  n_InpMult(pp, p, R);
2075 
2076  if (b->isZero()) {
2077  //exact solution found, stop
2078  delete eps_p;
2079  delete fps_p;
2080  delete x_p;
2081  delete Hp;
2082  delete kp;
2083  delete Tp;
2084  delete b;
2085  n_Delete(&pp, R);
2086  n_Delete(&p, R);
2087  nKillChar(Rp);
2088 
2089  return n_Init(1, R);
2090  } else {
2091  bigintmat *y = new bigintmat(x->rows(), x->cols(), R);
2092  number d = bimFarey(x, pp, y);
2093  if (d) {
2094  bigintmat *c = bimMult(A, y);
2095  bigintmat *bd = new bigintmat(B);
2096  bd->skalmult(d, R);
2097  if (kern) {
2098  bd->extendCols(kp->cols());
2099  }
2100  if (*c == *bd) {
2101  x->swapMatrix(y);
2102  delete y;
2103  delete c;
2104  if (kern) {
2105  y = new bigintmat(x->rows(), B->cols(), R);
2106  c = new bigintmat(x->rows(), kp->cols(), R);
2107  x->splitcol(y, c);
2108  x->swapMatrix(y);
2109  delete y;
2110  kern->swapMatrix(c);
2111  delete c;
2112  }
2113 
2114  delete bd;
2115 
2116  delete eps_p;
2117  delete fps_p;
2118  delete x_p;
2119  delete Hp;
2120  delete kp;
2121  delete Tp;
2122  delete b;
2123  n_Delete(&pp, R);
2124  n_Delete(&p, R);
2125  nKillChar(Rp);
2126 
2127  return d;
2128  }
2129  delete c;
2130  delete bd;
2131  n_Delete(&d, R);
2132  }
2133  delete y;
2134  }
2135  i++;
2136  } while (1);
2137  delete eps_p;
2138  delete fps_p;
2139  delete x_p;
2140  delete Hp;
2141  delete kp;
2142  delete Tp;
2143  n_Delete(&pp, R);
2144  n_Delete(&p, R);
2145  nKillChar(Rp);
2146  return NULL;
2147 }
2148 
2149 //TODO: re-write using reduce_mod_howell
2151  // try to solve Ax=b, more precisely, find
2152  // number d
2153  // bigintmat x
2154  // sth. Ax=db
2155  // where d is small-ish (divides the determinant of A if this makes sense)
2156  // return 0 if there is no solution.
2157  //
2158  // if kern is non-NULL, return a basis for the kernel
2159 
2160  //Algo: we do row-howell (triangular matrix). The idea is
2161  // Ax = b <=> AT T^-1x = b
2162  // y := T^-1 x, solve AT y = b
2163  // and return Ty.
2164  //Howell does not compute the trafo, hence we need to cheat:
2165  //B := (I_n | A^t)^t, then the top part of the Howell form of
2166  //B will give a useful trafo
2167  //Then we can find x by back-substitution and lcm/gcd to find the denominator
2168  //The defining property of Howell makes this work.
2169 
2170  coeffs R = A->basecoeffs();
2171  bigintmat *m = prependIdentity(A);
2172  m->howell(); // since m contains the identity, we'll have A->cols()
2173  // many cols.
2174  number den = n_Init(1, R);
2175 
2176  bigintmat * B = new bigintmat(A->rows(), 1, R);
2177  for(int i=1; i<= b->cols(); i++) {
2178  int A_col = A->cols();
2179  b->getcol(i, B);
2180  B->skalmult(den, R);
2181  for(int j = B->rows(); j>0; j--) {
2182  number Ai = m->view(m->rows()-B->rows() + j, A_col);
2183  if (n_IsZero(Ai, R) &&
2184  n_IsZero(B->view(j, 1), R)) {
2185  continue; //all is fine: 0*x = 0
2186  } else if (n_IsZero(B->view(j, 1), R)) {
2187  x->rawset(x->rows() - B->rows() + j, i, n_Init(0, R));
2188  A_col--;
2189  } else if (n_IsZero(Ai, R)) {
2190  delete m;
2191  delete B;
2192  n_Delete(&den, R);
2193  return 0;
2194  } else {
2195  // solve ax=db, possibly enlarging d
2196  // so x = db/a
2197  number Bj = B->view(j, 1);
2198  number g = n_Gcd(Bj, Ai, R);
2199  number xi;
2200  if (n_Equal(Ai, g, R)) { //good: den stable!
2201  xi = n_Div(Bj, Ai, R);
2202  } else { //den <- den * (a/g), so old sol. needs to be adjusted
2203  number inc_d = n_Div(Ai, g, R);
2204  n_InpMult(den, inc_d, R);
2205  x->skalmult(inc_d, R);
2206  B->skalmult(inc_d, R);
2207  xi = n_Div(Bj, g, R);
2208  n_Delete(&inc_d, R);
2209  } //now for the back-substitution:
2210  x->rawset(x->rows() - B->rows() + j, i, xi);
2211  for(int k=j; k>0; k--) {
2212  //B[k] = B[k] - x[k]A[k][j]
2213  number s = n_Mult(xi, m->view(m->rows()-B->rows() + k, A_col), R);
2214  B->rawset(k, 1, n_Sub(B->view(k, 1), s, R));
2215  n_Delete(&s, R);
2216  }
2217  n_Delete(&g, R);
2218  A_col--;
2219  }
2220  if (!A_col) {
2221  if (B->isZero()) break;
2222  else {
2223  delete m;
2224  delete B;
2225  n_Delete(&den, R);
2226  return 0;
2227  }
2228  }
2229  }
2230  }
2231  delete B;
2232  bigintmat *T = new bigintmat(A->cols(), A->cols(), R);
2233  T->copySubmatInto(m, 1, 1, A->cols(), A->cols(), 1, 1);
2234  if (kern) {
2235  int i, j;
2236  for(i=1; i<= A->cols(); i++) {
2237  for(j=m->rows(); j>A->cols(); j--) {
2238  if (!n_IsZero(m->view(j, i), R)) break;
2239  }
2240  if (j>A->cols()) break;
2241  }
2242  Print("Found nullity (kern dim) of %d\n", i-1);
2243  bigintmat * ker = new bigintmat(A->rows(), i-1, R);
2244  ker->copySubmatInto(T, 1, 1, A->rows(), i-1, 1, 1);
2245  kern->swapMatrix(ker);
2246  delete ker;
2247  }
2248  delete m;
2249  bigintmat * y = bimMult(T, x);
2250  x->swapMatrix(y);
2251  delete y;
2252  x->simplifyContentDen(&den);
2253 #if 0
2254  Print("sol = 1/");
2255  n_Print(den, R);
2256  Print(" *\n");
2257  x->Print();
2258  Print("\n");
2259 #endif
2260  return den;
2261 }
2262 
2264 #if 0
2265  Print("Solve Ax=b for A=\n");
2266  A->Print();
2267  Print("\nb = \n");
2268  b->Print();
2269  Print("\nx = \n");
2270  x->Print();
2271  Print("\n");
2272 #endif
2273 
2274  coeffs R = A->basecoeffs();
2275  assume (R == b->basecoeffs());
2276  assume (R == x->basecoeffs());
2277  assume ((x->cols() == b->cols()) && (x->rows() == A->cols()) && (A->rows() == b->rows()));
2278 
2279  switch (getCoeffType(R)) {
2280  case n_Z:
2281  return solveAx_dixon(A, b, x, NULL);
2282  case n_Zn:
2283  case n_Znm:
2284  case n_Z2m:
2285  return solveAx_howell(A, b, x, NULL);
2286  case n_Zp:
2287  case n_Q:
2288  case n_GF:
2289  case n_algExt:
2290  case n_transExt:
2291  Warn("have field, should use Gauss or better");
2292  default:
2293  if (R->cfXExtGcd && R->cfAnn) { //assume it's Euclidean
2294  return solveAx_howell(A, b, x, NULL);
2295  }
2296  Werror("have no solve algorithm");
2297  }
2298  return NULL;
2299 }
2300 
2302 {
2303  bigintmat * t, *s, *a=A;
2304  coeffs R = a->basecoeffs();
2305  if (T) {
2306  *T = new bigintmat(a->cols(), a->cols(), R),
2307  (*T)->one();
2308  t = new bigintmat(*T);
2309  } else {
2310  t = *T;
2311  }
2312 
2313  if (S) {
2314  *S = new bigintmat(a->rows(), a->rows(), R);
2315  (*S)->one();
2316  s = new bigintmat(*S);
2317  } else {
2318  s = *S;
2319  }
2320 
2321  int flip=0;
2322  do {
2323  bigintmat * x, *X;
2324  if (flip) {
2325  x = s;
2326  X = *S;
2327  } else {
2328  x = t;
2329  X = *T;
2330  }
2331 
2332  if (x) {
2333  x->one();
2334  bigintmat * r = new bigintmat(a->rows()+a->cols(), a->cols(), R);
2335  bigintmat * rw = new bigintmat(1, a->cols(), R);
2336  for(int i=0; i<a->cols(); i++) {
2337  x->getrow(i+1, rw);
2338  r->setrow(i+1, rw);
2339  }
2340  for (int i=0; i<a->rows(); i++) {
2341  a->getrow(i+1, rw);
2342  r->setrow(i+a->cols()+1, rw);
2343  }
2344  r->hnf();
2345  for(int i=0; i<a->cols(); i++) {
2346  r->getrow(i+1, rw);
2347  x->setrow(i+1, rw);
2348  }
2349  for(int i=0; i<a->rows(); i++) {
2350  r->getrow(i+a->cols()+1, rw);
2351  a->setrow(i+1, rw);
2352  }
2353  delete rw;
2354  delete r;
2355 
2356 #if 0
2357  Print("X: %ld\n", X);
2358  X->Print();
2359  Print("\nx: %ld\n", x);
2360  x->Print();
2361 #endif
2362  bimMult(X, x, X);
2363 #if 0
2364  Print("\n2:X: %ld %ld %ld\n", X, *S, *T);
2365  X->Print();
2366  Print("\n2:x: %ld\n", x);
2367  x->Print();
2368  Print("\n");
2369 #endif
2370  } else {
2371  a->hnf();
2372  }
2373 
2374  int diag = 1;
2375  for(int i=a->rows(); diag && i>0; i--) {
2376  for(int j=a->cols(); j>0; j--) {
2377  if ((a->rows()-i)!=(a->cols()-j) && !n_IsZero(a->view(i, j), R)) {
2378  diag = 0;
2379  break;
2380  }
2381  }
2382  }
2383 #if 0
2384  Print("Diag ? %d\n", diag);
2385  a->Print();
2386  Print("\n");
2387 #endif
2388  if (diag) break;
2389 
2390  a = a->transpose(); // leaks - I need to write inpTranspose
2391  flip = 1-flip;
2392  } while (1);
2393  if (flip)
2394  a = a->transpose();
2395 
2396  if (S) *S = (*S)->transpose();
2397  if (s) delete s;
2398  if (t) delete t;
2399  A->copy(a);
2400 }
2401 
2402 //a "q-base" for the kernel of a.
2403 //Should be re-done to use Howell rather than smith.
2404 //can be done using solveAx now.
2405 int kernbase (bigintmat *a, bigintmat *c, number p, coeffs q) {
2406 #if 0
2407  Print("Kernel of ");
2408  a->Print();
2409  Print(" modulo ");
2410  n_Print(p, q);
2411  Print("\n");
2412 #endif
2413 
2414  coeffs coe = numbercoeffs(p, q);
2415  bigintmat *m = bimChangeCoeff(a, coe), *U, *V;
2416  diagonalForm(m, &U, &V);
2417 #if 0
2418  Print("\ndiag form: ");
2419  m->Print();
2420  Print("\nU:\n");
2421  U->Print();
2422  Print("\nV:\n");
2423  V->Print();
2424  Print("\n");
2425 #endif
2426 
2427  int rg = 0;
2428 #undef MIN
2429 #define MIN(a,b) (a < b ? a : b)
2430  for(rg=0; rg<MIN(m->rows(), m->cols()) && !n_IsZero(m->view(m->rows()-rg,m->cols()-rg), coe); rg++);
2431 
2432 #undef MAX
2433 #define MAX(a,b) (a > b ? a : b)
2434  bigintmat * k = new bigintmat(m->cols(), m->rows(), coe);
2435  for(int i=0; i<rg; i++) {
2436  number A = n_Ann(m->view(m->rows()-i, m->cols()-i), coe);
2437  k->set(m->cols()-i, i+1, A);
2438  n_Delete(&A, coe);
2439  }
2440  for(int i=rg; i<m->cols(); i++) {
2441  k->set(m->cols()-i, i+1-rg, n_Init(1, coe));
2442  }
2443  bimMult(V, k, k);
2444  c->copy(bimChangeCoeff(k, q));
2445  return c->cols();
2446 }
2447 
2448 
2450  if ((r == NULL) || (s == NULL))
2451  return false;
2452  if ((getCoeffType(r)==n_Z) && (getCoeffType(s)==n_Z))
2453  return true;
2454  if ((getCoeffType(r)==n_Zp) && (getCoeffType(s)==n_Zp)) {
2455  if (r->ch == s->ch)
2456  return true;
2457  else
2458  return false;
2459  }
2460  // n_Zn stimmt wahrscheinlich noch nicht
2461  if ((getCoeffType(r)==n_Zn) && (getCoeffType(s)==n_Zn)) {
2462  if (r->ch == s->ch)
2463  return true;
2464  else
2465  return false;
2466  }
2467  if ((getCoeffType(r)==n_Q) && (getCoeffType(s)==n_Q))
2468  return true;
2469  // FALL n_Zn FEHLT NOCH!
2470  //if ((getCoeffType(r)==n_Zn) && (getCoeffType(s)==n_Zn))
2471  return false;
2472 }
2473 
2475 {
2476  coeffs r = basecoeffs();
2477  number g = get(1,1), h;
2478  int n=rows()*cols();
2479  for(int i=1; i<n && !n_IsOne(g, r); i++) {
2480  h = n_Gcd(g, view(i), r);
2481  n_Delete(&g, r);
2482  g=h;
2483  }
2484  return g;
2485 }
2487 {
2488  coeffs r = basecoeffs();
2489  number g = n_Copy(*d, r), h;
2490  int n=rows()*cols();
2491  for(int i=0; i<n && !n_IsOne(g, r); i++) {
2492  h = n_Gcd(g, view(i), r);
2493  n_Delete(&g, r);
2494  g=h;
2495  }
2496  *d = n_Div(*d, g, r);
2497  if (!n_IsOne(g, r))
2498  skaldiv(g);
2499 }
mpz_ptr base
Definition: rmodulon.h:18
void operator*=(int intop)
UEberladener *=-Operator (fuer int und bigint) Frage hier: *= verwenden oder lieber = und * einzeln...
Definition: bigintmat.cc:132
static FORCE_INLINE number n_Sub(number a, number b, const coeffs r)
return the difference of 'a' and 'b', i.e., a-b
Definition: coeffs.h:666
bigintmat * transpose()
Definition: bigintmat.cc:36
void concatcol(bigintmat *a, bigintmat *b)
Definition: bigintmat.cc:1047
void skaldiv(number b)
Macht Ganzzahldivision aller Matrixeinträge mit b.
Definition: bigintmat.cc:1739
number view(int i, int j) const
view an entry an entry. NOTE: starts at [1,1]
Definition: bigintmat.cc:123
static number solveAx_dixon(bigintmat *A, bigintmat *B, bigintmat *x, bigintmat *kern)
Definition: bigintmat.cc:1973
static FORCE_INLINE BOOLEAN n_Greater(number a, number b, const coeffs r)
ordered fields: TRUE iff 'a' is larger than 'b'; in Z/pZ: TRUE iff la > lb, where la and lb are the l...
Definition: coeffs.h:511
static int findLongest(int *a, int length)
Definition: bigintmat.cc:533
static FORCE_INLINE number n_IntMod(number a, number b, const coeffs r)
for r a field, return n_Init(0,r) otherwise: n_Div(a,b,r)*b+n_IntMod(a,b,r)==a
Definition: coeffs.h:625
static FORCE_INLINE number n_GetNumerator(number &n, const coeffs r)
return the numerator of n (if elements of r are by nature not fractional, result is n) ...
Definition: coeffs.h:607
int compare(const bigintmat *op) const
Definition: bigintmat.cc:360
static FORCE_INLINE number n_GetUnit(number n, const coeffs r)
in Z: 1 in Z/kZ (where k is not a prime): largest divisor of n (taken in Z) that is co-prime with k i...
Definition: coeffs.h:529
static FORCE_INLINE number n_Gcd(number a, number b, const coeffs r)
in Z: return the gcd of 'a' and 'b' in Z/nZ, Z/2^kZ: computed as in the case Z in Z/pZ...
Definition: coeffs.h:683
void splitcol(bigintmat *a, bigintmat *b)
... linken ... rechten ...
Definition: bigintmat.cc:1105
const CanonicalForm int s
Definition: facAbsFact.cc:55
void concatrow(bigintmat *a, bigintmat *b)
Fügt zwei Matrixen untereinander/nebeneinander in gegebene Matrix ein, bzw spaltet gegebenen Matrix a...
Definition: bigintmat.cc:997
const CanonicalForm int const CFList const Variable & y
Definition: facAbsFact.cc:57
int lcm(unsigned long *l, unsigned long *a, unsigned long *b, unsigned long p, int dega, int degb)
Definition: minpoly.cc:711
int colIsZero(int i)
Definition: bigintmat.cc:1477
const poly a
Definition: syzextra.cc:212
#define Print
Definition: emacs.cc:83
only used if HAVE_RINGS is defined: ?
Definition: coeffs.h:42
void swaprow(int i, int j)
swap rows i and j
Definition: bigintmat.cc:703
bigintmat * bimSub(bigintmat *a, bigintmat *b)
Definition: bigintmat.cc:214
static FORCE_INLINE number n_XExtGcd(number a, number b, number *s, number *t, number *u, number *v, const coeffs r)
Definition: coeffs.h:692
number det()
det (via LaPlace in general, hnf for euc. rings)
Definition: bigintmat.cc:1412
static bigintmat * prependIdentity(bigintmat *A)
Definition: bigintmat.cc:1907
bool addcol(int i, int j, number a, coeffs c)
addiert a-faches der j-ten Spalte zur i-ten dazu
Definition: bigintmat.cc:925
void colskaldiv(int j, number b)
Macht Ganzzahldivision aller j-ten Spalteneinträge mit b.
Definition: bigintmat.cc:1754
void getrow(int i, bigintmat *a)
Schreibt i-te Zeile in Vektor (Matrix) a.
Definition: bigintmat.cc:779
only used if HAVE_RINGS is defined: ?
Definition: coeffs.h:44
used for all transcendental extensions, i.e., the top-most extension in an extension tower is transce...
Definition: coeffs.h:37
static int min(int a, int b)
Definition: fast_mult.cc:268
static int si_min(const int a, const int b)
Definition: auxiliary.h:167
void simplifyContentDen(number *den)
ensures that Gcd(den, content)=1 < enden hier wieder
Definition: bigintmat.cc:2486
#define FALSE
Definition: auxiliary.h:140
static FORCE_INLINE void n_InpMult(number &a, number b, const coeffs r)
multiplication of 'a' and 'b'; replacement of 'a' by the product a*b
Definition: coeffs.h:638
return P p
Definition: myNF.cc:203
static FORCE_INLINE BOOLEAN n_IsOne(number n, const coeffs r)
TRUE iff 'n' represents the one element.
Definition: coeffs.h:468
Matrices of numbers.
Definition: bigintmat.h:32
f
Definition: cfModGcd.cc:4022
void inpTranspose()
transpose in place
Definition: bigintmat.cc:49
void setcol(int j, bigintmat *m)
Setzt j-te Spalte gleich übergebenem Vektor (Matrix) m.
Definition: bigintmat.cc:810
bigintmat * iv2bim(intvec *b, const coeffs C)
Definition: bigintmat.cc:347
void appendCol(bigintmat *a)
horizontally join the matrices, m <- m|a
Definition: bigintmat.cc:1032
bool sub(bigintmat *b)
Subtrahiert ...
Definition: bigintmat.cc:886
int isOne()
is matrix is identity
Definition: bigintmat.cc:1216
void rowskalmult(int i, number a, coeffs c)
... Zeile ...
Definition: bigintmat.cc:984
rational (GMP) numbers
Definition: coeffs.h:30
static FORCE_INLINE number n_Init(long i, const coeffs r)
a number representing i in the given coeff field/ring r
Definition: coeffs.h:537
int row
Definition: bigintmat.h:37
{p < 2^31}
Definition: coeffs.h:29
const CanonicalForm CFMap CFMap int &both_non_zero int n
Definition: cfEzgcd.cc:52
bigintmat * bimAdd(bigintmat *a, bigintmat *b)
Matrix-Add/-Sub/-Mult so oder mit operator+/-/* ? : NULL as a result means an error (non-compatible m...
Definition: bigintmat.cc:178
void zero()
Setzt alle Einträge auf 0.
Definition: bigintmat.cc:1254
int findnonzero(int i)
find index of 1st non-zero entry in row i
Definition: bigintmat.cc:719
char * StringAsPrinted()
Returns a string as it would have been printed in the interpreter.
Definition: bigintmat.cc:446
#define TRUE
Definition: auxiliary.h:144
number solveAx(bigintmat *A, bigintmat *b, bigintmat *x)
solve Ax=b*d. x needs to be pre-allocated to the same number of columns as b. the minimal denominator...
Definition: bigintmat.cc:2263
void getColRange(int j, int no, bigintmat *a)
copies the no-columns staring by j (so j...j+no-1) into the pre-allocated a
Definition: bigintmat.cc:768
void setrow(int i, bigintmat *m)
Setzt i-te Zeile gleich übergebenem Vektor (Matrix) m.
Definition: bigintmat.cc:839
g
Definition: cfModGcd.cc:4031
void WerrorS(const char *s)
Definition: feFopen.cc:23
static int intArrSum(int *a, int length)
Definition: bigintmat.cc:525
int k
Definition: cfEzgcd.cc:93
char * StringEndS()
Definition: reporter.cc:151
#define Q
Definition: sirandom.c:25
int findcolnonzero(int j)
find index of 1st non-zero entry in column j
Definition: bigintmat.cc:730
#define MIN(a, b)
#define omAlloc(size)
Definition: omAllocDecl.h:210
int * getwid(int maxwid)
Definition: bigintmat.cc:576
static FORCE_INLINE void n_InpAdd(number &a, number b, const coeffs r)
addition of 'a' and 'b'; replacement of 'a' by the sum a+b
Definition: coeffs.h:643
poly pp
Definition: myNF.cc:296
static FORCE_INLINE void number2mpz(number n, coeffs c, mpz_t m)
Definition: coeffs.h:986
static FORCE_INLINE number n_Ann(number a, const coeffs r)
if r is a ring with zero divisors, return an annihilator!=0 of b otherwise return NULL ...
Definition: coeffs.h:698
void set(int i, int j, number n, const coeffs C=NULL)
replace an entry with a copy (delete old + copy new!). NOTE: starts at [1,1]
Definition: bigintmat.cc:91
void Write()
IO: writes the matrix into the current internal string buffer which must be started/ allocated before...
Definition: bigintmat.cc:411
int kernbase(bigintmat *a, bigintmat *c, number p, coeffs q)
a basis for the nullspace of a mod p: only used internally in Round2. Don't use it.
Definition: bigintmat.cc:2405
void rawset(int i, number n, const coeffs C=NULL)
replace an entry with the given number n (only delete old). NOTE: starts at [0]. Should be named set_...
Definition: bigintmat.h:180
int index(int r, int c) const
helper function to map from 2-dim coordinates, starting by 1 to 1-dim coordinate, starting by 0 ...
Definition: bigintmat.h:145
static FORCE_INLINE number n_Mult(number a, number b, const coeffs r)
return the product of 'a' and 'b', i.e., a*b
Definition: coeffs.h:633
static coeffs numbercoeffs(number n, coeffs c)
create Z/nA of type n_Zn
Definition: bigintmat.cc:21
const ring r
Definition: syzextra.cc:208
intvec * bim2iv(bigintmat *b)
Definition: bigintmat.cc:339
static int getShorter(int *a, int l, int j, int cols, int rows)
Definition: bigintmat.cc:548
Definition: intvec.h:16
static FORCE_INLINE long n_Int(number &n, const coeffs r)
conversion of n to an int; 0 if not possible in Z/pZ: the representing int lying in (-p/2 ...
Definition: coeffs.h:546
const CanonicalForm CFMap CFMap & N
Definition: cfEzgcd.cc:49
void copySubmatInto(bigintmat *, int sr, int sc, int nr, int nc, int tr, int tc)
copy the submatrix of b, staring at (a,b) having n rows, m cols into the given matrix at pos...
Definition: bigintmat.cc:1202
bool addrow(int i, int j, number a, coeffs c)
... Zeile ...
Definition: bigintmat.cc:948
int j
Definition: myNF.cc:70
only used if HAVE_RINGS is defined: ?
Definition: coeffs.h:43
bigintmat * bimCopy(const bigintmat *b)
same as copy constructor - apart from it being able to accept NULL as input
Definition: bigintmat.cc:403
bigintmat * bimMult(bigintmat *a, bigintmat *b)
Definition: bigintmat.cc:251
#define omFree(addr)
Definition: omAllocDecl.h:261
static number bimFarey(bigintmat *A, number N, bigintmat *L)
Definition: bigintmat.cc:1919
static void reduce_mod_howell(bigintmat *A, bigintmat *b, bigintmat *eps, bigintmat *x)
Definition: bigintmat.cc:1834
void extendCols(int i)
append i zero-columns to the matrix
Definition: bigintmat.cc:1027
#define assume(x)
Definition: mod2.h:405
void swapMatrix(bigintmat *a)
Definition: bigintmat.cc:1466
The main handler for Singular numbers which are suitable for Singular polynomials.
static FORCE_INLINE number n_Add(number a, number b, const coeffs r)
return the sum of 'a' and 'b', i.e., a+b
Definition: coeffs.h:653
void StringSetS(const char *st)
Definition: reporter.cc:128
void StringAppendS(const char *st)
Definition: reporter.cc:107
#define A
Definition: sirandom.c:23
void pprint(int maxwid)
Definition: bigintmat.cc:608
number(* nMapFunc)(number a, const coeffs src, const coeffs dst)
maps "a", which lives in src, into dst
Definition: coeffs.h:71
bool skalmult(number b, coeffs c)
Multipliziert zur Matrix den Skalar b hinzu.
Definition: bigintmat.cc:904
void swap(int i, int j)
swap columns i and j
Definition: bigintmat.cc:688
bool operator==(const bigintmat &lhr, const bigintmat &rhr)
Definition: bigintmat.cc:155
static FORCE_INLINE void n_Write(number &n, const coeffs r, const BOOLEAN bShortOut=TRUE)
Definition: coeffs.h:590
All the auxiliary stuff.
int m
Definition: cfEzgcd.cc:119
static FORCE_INLINE number n_QuotRem(number a, number b, number *q, const coeffs r)
Definition: coeffs.h:700
static FORCE_INLINE number n_InpNeg(number n, const coeffs r)
in-place negation of n MUST BE USED: n = n_InpNeg(n) (no copy is returned)
Definition: coeffs.h:556
void hnf()
transforms INPLACE to HNF
Definition: bigintmat.cc:1560
only used if HAVE_RINGS is defined: ?
Definition: coeffs.h:41
unsigned long exp
Definition: rmodulon.h:18
#define StringAppend
Definition: emacs.cc:82
int i
Definition: cfEzgcd.cc:123
void PrintS(const char *s)
Definition: reporter.cc:294
static number solveAx_howell(bigintmat *A, bigintmat *b, bigintmat *x, bigintmat *kern)
Definition: bigintmat.cc:2150
void mod(number p, coeffs c)
Reduziert komplette Matrix modulo p.
Definition: bigintmat.cc:1794
static FORCE_INLINE BOOLEAN n_IsZero(number n, const coeffs r)
TRUE iff 'n' represents the zero element.
Definition: coeffs.h:464
static FORCE_INLINE nMapFunc n_SetMap(const coeffs src, const coeffs dst)
set the mapping function pointers for translating numbers from src to dst
Definition: coeffs.h:718
CFList tmp2
Definition: facFqBivar.cc:70
bigintmat * bimChangeCoeff(bigintmat *a, coeffs cnew)
Liefert Kopier von Matrix a zurück, mit coeffs cnew statt den ursprünglichen.
Definition: bigintmat.cc:1688
void diagonalForm(bigintmat *A, bigintmat **S, bigintmat **T)
Definition: bigintmat.cc:2301
int cols() const
Definition: bigintmat.h:128
static FORCE_INLINE n_coeffType getCoeffType(const coeffs r)
Returns the type of coeffs domain.
Definition: coeffs.h:421
void Print()
IO: simply prints the matrix to the current output (screen?)
Definition: bigintmat.cc:438
static int index(p_Length length, p_Ord ord)
Definition: p_Procs_Impl.h:597
#define BIMATELEM(M, I, J)
Definition: bigintmat.h:117
static FORCE_INLINE number n_Farey(number a, number b, const coeffs r)
Definition: coeffs.h:783
number content()
the content, the gcd of all entries. Only makes sense for Euclidean rings (or possibly constructive P...
Definition: bigintmat.cc:2474
std::pair< ideal, ring > flip(const ideal I, const ring r, const gfan::ZVector interiorPoint, const gfan::ZVector facetNormal, const gfan::ZVector adjustedInteriorPoint, const gfan::ZVector adjustedFacetNormal)
Definition: flip.cc:40
bool operator!=(const bigintmat &lhr, const bigintmat &rhr)
Definition: bigintmat.cc:172
void getcol(int j, bigintmat *a)
copies the j-th column into the matrix a - which needs to be pre-allocated with the correct size...
Definition: bigintmat.cc:741
int rows() const
Definition: bigintmat.h:129
bigintmat * modhnf(number p, coeffs c)
computes HNF(this | p*I)
Definition: bigintmat.cc:1715
int col
Definition: bigintmat.h:38
CanonicalForm cf
Definition: cfModGcd.cc:4024
number trace()
the trace ....
Definition: bigintmat.cc:1398
void colskalmult(int i, number a, coeffs c)
Multipliziert zur i-ten Spalte den Skalar a hinzu.
Definition: bigintmat.cc:971
number * v
Definition: bigintmat.h:36
#define NULL
Definition: omList.c:10
int cols() const
Definition: intvec.h:86
bigintmat()
Definition: bigintmat.h:41
{p^n < 2^16}
Definition: coeffs.h:32
static FORCE_INLINE number n_Copy(number n, const coeffs r)
return a copy of 'n'
Definition: coeffs.h:451
CanonicalForm den(const CanonicalForm &f)
used for all algebraic extensions, i.e., the top-most extension in an extension tower is algebraic ...
Definition: coeffs.h:34
static FORCE_INLINE number n_Div(number a, number b, const coeffs r)
return the quotient of 'a' and 'b', i.e., a/b; raises an error if 'b' is not invertible in r exceptio...
Definition: coeffs.h:613
int rows() const
Definition: intvec.h:87
b *CanonicalForm B
Definition: facBivar.cc:51
int gcd(int a, int b)
Definition: walkSupport.cc:839
fq_nmod_poly_t prod
Definition: facHensel.cc:95
char * String()
IO: String returns a singular string containing the matrix, needs freeing afterwards.
Definition: bigintmat.cc:431
coeffs basecoeffs() const
Definition: bigintmat.h:130
#define R
Definition: sirandom.c:26
CFList tmp1
Definition: facFqBivar.cc:70
bool copy(bigintmat *b)
Kopiert Einträge von b auf Bigintmat.
Definition: bigintmat.cc:1176
void inpMult(number bintop, const coeffs C=NULL)
inplace versio of skalar mult. CHANGES input.
Definition: bigintmat.cc:141
Variable x
Definition: cfModGcd.cc:4023
static FORCE_INLINE number n_GetDenom(number &n, const coeffs r)
return the denominator of n (if elements of r are by nature not fractional, result is 1) ...
Definition: coeffs.h:602
static FORCE_INLINE BOOLEAN n_Equal(number a, number b, const coeffs r)
TRUE iff 'a' and 'b' represent the same number; they may have different representations.
Definition: coeffs.h:460
number hnfdet()
det via HNF Primzahlen als long long int, müssen noch in number umgewandelt werden?
Definition: bigintmat.cc:1445
bigintmat * elim(int i, int j)
Liefert Streichungsmatrix (i-te Zeile und j-te Spalte gestrichen) zurück.
Definition: bigintmat.cc:1281
void coltransform(int i, int j, number a, number b, number c, number d)
transforms cols (i,j) using the 2x2 matrix ((a,b)(c,d)) (hopefully)
Definition: bigintmat.cc:1767
void splitrow(bigintmat *a, bigintmat *b)
Speichert in Matrix a den oberen, in b den unteren Teil der Matrix, vorausgesetzt die Dimensionen sti...
Definition: bigintmat.cc:1072
static FORCE_INLINE void n_Delete(number *p, const coeffs r)
delete 'p'
Definition: coeffs.h:455
static FORCE_INLINE BOOLEAN n_GreaterZero(number n, const coeffs r)
ordered fields: TRUE iff 'n' is positive; in Z/pZ: TRUE iff 0 < m <= roundedBelow(p/2), where m is the long representing n in C: TRUE iff (Im(n) != 0 and Im(n) >= 0) or (Im(n) == 0 and Re(n) >= 0) in K(a)/: TRUE iff (n != 0 and (LC(n) > 0 or deg(n) > 0)) in K(t_1, ..., t_n): TRUE iff (LC(numerator(n) is a constant and > 0) or (LC(numerator(n) is not a constant) in Z/2^kZ: TRUE iff 0 < n <= 2^(k-1) in Z/mZ: TRUE iff the internal mpz is greater than zero in Z: TRUE iff n > 0
Definition: coeffs.h:494
number pseudoinv(bigintmat *a)
Speichert in Matrix a die Pseudoinverse, liefert den Nenner zurück.
Definition: bigintmat.cc:1315
static FORCE_INLINE char * nCoeffString(const coeffs cf)
TODO: make it a virtual method of coeffs, together with: Decompose & Compose, rParameter & rPar...
Definition: coeffs.h:958
static jList * T
Definition: janet.cc:37
int isZero()
Definition: bigintmat.cc:1264
static Poly * h
Definition: janet.cc:978
const poly b
Definition: syzextra.cc:213
void howell()
dito, but Howell form (only different for zero-divsors)
Definition: bigintmat.cc:1485
void nKillChar(coeffs r)
undo all initialisations
Definition: numbers.cc:477
bool add(bigintmat *b)
Addiert zur Matrix die Matrix b dazu. Return false => an error occured.
Definition: bigintmat.cc:868
void Werror(const char *fmt,...)
Definition: reporter.cc:199
void one()
Macht Matrix (Falls quadratisch) zu Einheitsmatrix.
Definition: bigintmat.cc:1236
#define omAlloc0(size)
Definition: omAllocDecl.h:211
int l
Definition: cfEzgcd.cc:94
number get(int i, int j) const
get a copy of an entry. NOTE: starts at [1,1]
Definition: bigintmat.cc:115
void n_Print(number &a, const coeffs r)
print a number (BEWARE of string buffers!) mostly for debugging
Definition: numbers.cc:538
coeffs nInitChar(n_coeffType t, void *parameter)
one-time initialisations for new coeffs in case of an error return NULL
Definition: numbers.cc:316
bool nCoeffs_are_equal(coeffs r, coeffs s)
Definition: bigintmat.cc:2449
#define Warn
Definition: emacs.cc:80