source: git/libpolys/coeffs/bigintmat.cc @ fe02b1

spielwiese
Last change on this file since fe02b1 was fe02b1, checked in by Oleksandr Motsak <motsak@…>, 12 years ago
my rewrite of bigintmat as a matrix of numbers from any coeff. domain fix: several bugs and mem. leaks add: improved interface (mostly backward compatible) chg: many minor improvements add: started documenting with doxygen comments add: lots of assumes NOTE: NULL should NOT be used as a coeff. domain (use coeffs_BIGINT for Q!)
  • Property mode set to 100644
File size: 11.6 KB
Line 
1/*****************************************
2 *  Computer Algebra System SINGULAR      *
3 *****************************************/
4/*
5 * ABSTRACT: class bigintmat: matrizes of big integers
6 */
7#include "bigintmat.h"
8
9#include <misc/intvec.h>
10
11//#include <kernel/mod2.h>
12//#include <kernel/options.h>
13
14#include <math.h>
15#include <string.h>
16
17#define BIMATELEM(M,I,J) (M)[ (M).index(I,J) ]
18
19
20// Beginnt bei [0]
21void bigintmat::set(int i, number n, const coeffs C)
22{
23  assume (C == NULL || C == basecoeffs());
24
25  rawset(i, n_Copy(n, basecoeffs()), basecoeffs());
26}
27
28// Beginnt bei [1,1]
29void bigintmat::set(int i, int j, number n, const coeffs C)
30{
31  assume (C == NULL || C == basecoeffs());
32  assume (i > 0 && j > 0);
33  assume (i <= rows() && j <= cols());
34 
35  set(index(i, j), n, C);
36}
37
38number bigintmat::get(int i) const
39{
40  assume (i >= 0);
41  assume (i<rows()*cols());
42 
43  return n_Copy(v[i], basecoeffs());
44}
45
46number bigintmat::get(int i, int j) const
47{
48  assume (i > 0 && j > 0);
49  assume (i <= rows() && j <= cols());
50 
51  return get(index(i, j));
52}
53
54// Überladener *=-Operator (fÃŒr int und bigint)
55// Frage hier: *= verwenden oder lieber = und * einzeln?
56void bigintmat::operator*=(int intop)
57{
58  number iop = n_Init(intop, basecoeffs());
59 
60  inpMult(iop, basecoeffs());
61 
62  n_Delete(&iop, basecoeffs());
63}
64
65void bigintmat::inpMult(number bintop, const coeffs C)
66{
67  assume (C == NULL || C == basecoeffs());
68 
69  const int l = rows() * cols();
70
71  for (int i=0; i < l; i++)
72    n_InpMult(v[i], bintop, basecoeffs());
73}
74
75// Stimmen Parameter?
76// Welche der beiden Methoden?
77// Oder lieber eine comp-Funktion?
78
79bool operator==(const bigintmat & lhr, const bigintmat & rhr)
80{
81  if (&lhr == &rhr) { return true; }
82  if (lhr.cols() != rhr.cols()) { return false; }
83  if (lhr.rows() != rhr.rows()) { return false; }
84  if (lhr.basecoeffs() != rhr.basecoeffs()) { return false; }
85
86  const int l = (lhr.rows())*(lhr.cols());
87 
88  for (int i=0; i < l; i++)
89  {
90    if (!n_Equal(lhr[i], rhr[i], lhr.basecoeffs())) { return false; }
91  }
92 
93  return true;
94}
95
96bool operator!=(const bigintmat & lhr, const bigintmat & rhr)
97{
98  return !(lhr==rhr);
99}
100
101// Matrix-Add/-Sub/-Mult so oder mit operator+/-/* ?
102bigintmat * bimAdd(bigintmat * a, bigintmat * b)
103{
104  if (a->cols() != b->cols()) return NULL;
105  if (a->basecoeffs() != b->basecoeffs()) { return NULL; }
106 
107  const int mn = si_min(a->rows(),b->rows());
108  const int ma = si_max(a->rows(),b->rows());
109
110  const coeffs basecoeffs = a->basecoeffs();
111 
112  int i;
113
114  if (a->cols() == 1)
115  {
116    bigintmat * bim = new bigintmat(ma, 1, basecoeffs);
117   
118    for (i=0; i<mn; i++)
119      bim->rawset(i, n_Add((*a)[i], (*b)[i], basecoeffs), basecoeffs);
120   
121    if (ma > mn)
122    {
123      if (ma == a->rows())
124        for(i=mn; i<ma; i++)
125          bim->set(i, (*a)[i], basecoeffs);
126      else
127        for(i=mn; i<ma; i++)
128          bim->set(i, (*b)[i], basecoeffs);
129    }
130    return bim;
131  }
132 
133  if (mn != ma) return NULL;
134
135  bigintmat * bim = new bigintmat(mn, a->cols(), basecoeffs);
136 
137  for (i=0; i<mn*a->cols(); i++)
138    bim->rawset(i, n_Add((*a)[i], (*b)[i], basecoeffs), basecoeffs);
139 
140  return bim;
141}
142
143bigintmat * bimSub(bigintmat * a, bigintmat * b)
144{
145  if (a->cols() != b->cols()) return NULL;
146  if (a->basecoeffs() != b->basecoeffs()) { return NULL; }
147
148  const int mn = si_min(a->rows(),b->rows());
149  const int ma = si_max(a->rows(),b->rows());
150
151  const coeffs basecoeffs = a->basecoeffs();
152
153  int i;
154
155  if (a->cols() == 1)
156  {
157    bigintmat * bim = new bigintmat(ma, 1, basecoeffs);
158   
159    for (i=0; i<mn; i++)
160      bim->rawset(i, n_Sub((*a)[i], (*b)[i], basecoeffs), basecoeffs);
161
162    if (ma > mn)
163    {
164      if (ma == a->rows())
165      {
166        for(i=mn; i<ma; i++)
167          bim->set(i, (*a)[i], basecoeffs);
168      }
169      else
170        for(i=mn; i<ma; i++)
171        {
172          number n = b->get(i);
173          n = n_Neg(n, basecoeffs);
174          bim->rawset(i, n, basecoeffs);
175        }
176    }
177    return bim;
178  }
179 
180  if (mn != ma) return NULL;
181 
182  bigintmat * bim = new bigintmat(mn, a->cols(), basecoeffs);
183 
184  for (i=0; i<mn*a->cols(); i++)
185    bim->rawset(i, n_Sub((*a)[i], (*b)[i], basecoeffs), basecoeffs);
186 
187  return bim;
188}
189
190bigintmat * bimMult(bigintmat * a, bigintmat * b)
191{
192  const int ca = a->cols();
193  const int cb = b->cols();
194
195  const int ra = a->rows();
196  const int rb = b->rows();
197 
198  if (ca != rb)
199  {
200#ifndef NDEBUG
201    Werror("wrong bigintmat sizes at multiplication a * b: acols: %d != brows: %d\n", ca, rb);
202#endif
203    return NULL;
204  }
205 
206  assume (ca == rb);
207 
208  if (a->basecoeffs() != b->basecoeffs()) { return NULL; }
209 
210  const coeffs basecoeffs = a->basecoeffs();
211
212  int i, j, k;
213 
214  number sum;
215 
216  bigintmat * bim = new bigintmat(ra, cb, basecoeffs);
217 
218  for (i=0; i<ra; i++)
219    for (j=0; j<cb; j++)
220    {
221      sum = n_Init(0, basecoeffs);
222     
223      for (k=0; k<ca; k++)
224      {
225        number prod = n_Mult( BIMATELEM(*a, i, k), BIMATELEM(*b, k, j), basecoeffs);
226       
227        number sum2 = n_Add(sum, prod, basecoeffs); // no inplace add :(
228       
229        n_Delete(&sum, basecoeffs); n_Delete(&prod, basecoeffs);
230       
231        sum = sum2;
232      }
233      bim->rawset(i+1, j+1, sum, basecoeffs);
234    }
235  return bim;
236}
237
238// ----------------------------------------------------------------- //
239// Korrekt?
240
241intvec * bim2iv(bigintmat * b)
242{
243  intvec * iv = new intvec(b->rows(), b->cols(), 0);
244  for (int i=0; i<(b->rows())*(b->cols()); i++)
245    (*iv)[i] = n_Int((*b)[i], b->basecoeffs()); // Geht das so?
246  return iv;
247}
248
249bigintmat * iv2bim(intvec * b, const coeffs C)
250{
251  const int l = (b->rows())*(b->cols());
252  bigintmat * bim = new bigintmat(b->rows(), b->cols(), C);
253 
254  for (int i=0; i < l; i++)
255    bim->rawset(i, n_Init((*b)[i], C), C);
256 
257  return bim;
258}
259
260// ----------------------------------------------------------------- //
261
262int bigintmat::compare(const bigintmat* op) const
263{
264  assume (basecoeffs() == op->basecoeffs() );
265
266#ifndef NDEBUG
267  if (basecoeffs() != op->basecoeffs() )
268    WerrorS("wrong bigintmat comparison: different basecoeffs!\n");
269#endif
270
271  if ((col!=1) ||(op->cols()!=1))
272  {
273    if((col!=op->cols())
274       || (row!=op->rows()))
275      return -2;
276  }
277
278  int i;
279  for (i=0; i<si_min(row*col,op->rows()*op->cols()); i++)
280  {
281    if ( n_Greater(v[i], (*op)[i], basecoeffs()) )
282      return 1;
283    else if (! n_Equal(v[i], (*op)[i], basecoeffs()))
284      return -1;
285  }
286
287  for (; i<row; i++)
288  {
289    if ( n_GreaterZero(v[i], basecoeffs()) )
290      return 1;
291    else if (! n_IsZero(v[i], basecoeffs()) )
292      return -1;
293  }
294  for (; i<op->rows(); i++)
295  {
296    if ( n_GreaterZero((*op)[i], basecoeffs()) )
297      return -1;
298    else if (! n_IsZero((*op)[i], basecoeffs()) )
299      return 1;
300  }
301  return 0;
302}
303
304
305bigintmat * bimCopy(const bigintmat * b)
306{
307  if (b == NULL)
308    return NULL;
309   
310  return new bigintmat(b);
311}
312
313char* bigintmat::String()
314{
315  assume (rows() > 0);
316  assume (cols() > 0);
317
318  StringSetS("");
319  const int l = cols()*rows();
320
321  n_Write(v[0], basecoeffs());
322  for (int i = 1; i < l; i++)
323  {
324    StringAppendS(","); n_Write(v[i], basecoeffs());
325  }
326  /* if (i != col*row-1)
327  {
328  StringAppendS(",");
329  if ((i+1)%col == 0)
330  StringAppendS("\n");
331  }   */
332  return StringAppendS("");
333}
334
335int bigintmat::getwid(int maxwid)
336{
337  int wid=0;
338  int colwid = floor((maxwid-2*(col-1))/col);
339  for (int i=0; i<col*row; i++)
340  {
341    StringSetS("");
342    n_Write(v[i], basecoeffs());
343    char * tmp = StringAppendS("");
344//    char * ts = omStrDup(tmp);
345    const int _nl = strlen(tmp); // ts?
346    if (_nl > wid)
347    {
348      if (_nl > colwid)
349      {
350        int phwid = floor(log10(row))+floor(log10(col))+5;
351        if ((colwid > phwid) && (wid < phwid))
352          wid = phwid;
353      }
354      else
355        wid = _nl;
356    }
357  }
358  return wid;
359}
360
361void bigintmat::pprint(int maxwid)
362{
363  if ((col==0) || (row==0))
364    PrintS("");
365  else
366  {
367    int colwid = getwid(maxwid);
368    if (colwid*col+2*(col-1) > maxwid)
369      colwid = floor((maxwid-2*(col-1))/col);
370    char * ps;
371    ps = (char*) omAlloc0(sizeof(char)*(colwid*col*row+2*(col-1)*row+row));
372    int pos = 0;
373    for (int i=0; i<col*row; i++)
374    {
375      StringSetS("");
376      n_Write(v[i], basecoeffs());
377      char * temp = StringAppendS("");
378      char * ts = omStrDup(temp);
379      const int _nl = strlen(ts);
380      if (_nl > colwid)
381      {
382        StringSetS("");
383        int cj = i%col;
384        int ci = floor(i/col);
385        StringAppend("[%d,%d]", ci+1, cj+1);
386        char *tmp = StringAppendS("");
387        char * ph = omStrDup(tmp);
388        int phl = strlen(ph);
389        if (phl > colwid)
390        {
391          for (int j=0; j<colwid; j++)
392            ps[pos+j] = '*';
393        }
394        else
395        {
396          for (int j=0; j<colwid-phl; j++)
397            ps[pos+j] = ' ';
398          for (int j=0; j<phl; j++)
399            ps[pos+colwid-phl+j] = ph[j];
400        }
401        omFree(ph);
402      }
403      else  // Mit Leerzeichen auffÃŒllen und zahl reinschreiben
404      {
405        for (int j=0; j<colwid-_nl; j++)
406          ps[pos+j] = ' ';
407        for (int j=0; j<_nl; j++)
408          ps[pos+colwid-_nl+j] = ts[j];
409      }
410      // ", " oder "\n" einfÃŒgen
411      if ((i+1)%col == 0)
412      {
413        if (i != col*row-1)
414        {
415          ps[pos+colwid] = '\n';
416          pos += colwid+1;
417        }
418      }
419      else
420      {
421        ps[pos+colwid] = ',';
422        ps[pos+colwid+1] = ' ';
423        pos += colwid+2;
424      }
425      // Hier ts zerstören
426    }
427    PrintS(ps);
428    omFree(ps);
429  }
430}
431
432// Ungetestet
433static void bimRowContent(bigintmat *bimat, int rowpos, int colpos)
434{
435  const coeffs basecoeffs = bimat->basecoeffs();
436 
437  number tgcd, m;
438  int i=bimat->cols();
439
440  loop
441  {
442    tgcd = n_Copy(BIMATELEM(*bimat,rowpos,i--), basecoeffs);
443    if (! n_IsZero(tgcd, basecoeffs)) break;
444    if (i<colpos) return;
445  }
446  if ((! n_GreaterZero(tgcd, basecoeffs)) && (! n_IsZero(tgcd, basecoeffs))) tgcd = n_Neg(tgcd, basecoeffs);
447  if ( n_IsOne(tgcd,basecoeffs)) return;
448  loop
449  {
450    m = n_Copy(BIMATELEM(*bimat,rowpos,i--), basecoeffs);
451    if (! n_IsZero(m,basecoeffs))
452    {
453      number tp1 = n_Gcd(tgcd, m, basecoeffs);
454      n_Delete(&tgcd, basecoeffs);
455      tgcd = tp1;
456    }
457    if ( n_IsOne(tgcd,basecoeffs)) return;
458    if (i<colpos) break;
459  }
460  for (i=bimat->cols();i>=colpos;i--)
461  {
462    number tp2 = n_Div(BIMATELEM(*bimat,rowpos,i), tgcd,basecoeffs);
463    n_Delete(&BIMATELEM(*bimat,rowpos,i), basecoeffs);
464    BIMATELEM(*bimat,rowpos,i) = tp2;
465  }
466  n_Delete(&tgcd, basecoeffs);
467  n_Delete(&m, basecoeffs);
468}
469
470static void bimReduce(bigintmat *bimat, int rpiv, int colpos,
471                      int ready, int all)
472{
473  const coeffs basecoeffs = bimat->basecoeffs();
474
475  number tgcd, ce, m1, m2;
476  int j, i;
477  number piv = BIMATELEM(*bimat,rpiv,colpos);
478
479  for (j=all;j>ready;j--)
480  {
481    ce = n_Copy(BIMATELEM(*bimat,j,colpos),basecoeffs);
482    if (! n_IsZero(ce, basecoeffs))
483    {
484      n_Delete(&BIMATELEM(*bimat,j,colpos), basecoeffs);
485      BIMATELEM(*bimat,j,colpos) = n_Init(0, basecoeffs);
486      m1 = n_Copy(piv,basecoeffs);
487      m2 = n_Copy(ce,basecoeffs);
488      tgcd = n_Gcd(m1, m2, basecoeffs);
489      if (! n_IsOne(tgcd,basecoeffs))
490      {
491        number tp1 = n_Div(m1, tgcd,basecoeffs);
492        number tp2 = n_Div(m2, tgcd,basecoeffs);
493        n_Delete(&m1, basecoeffs);
494        n_Delete(&m2, basecoeffs);
495        m1 = tp1;
496        m2 = tp2;
497      }
498      for (i=bimat->cols();i>colpos;i--)
499      {
500        n_Delete(&BIMATELEM(*bimat,j,i), basecoeffs);
501        number tp1 = n_Mult(BIMATELEM(*bimat,j,i), m1,basecoeffs);
502        number tp2 = n_Mult(BIMATELEM(*bimat,rpiv,i), m2,basecoeffs);
503        BIMATELEM(*bimat,j,i) = n_Sub(tp1, tp2,basecoeffs);
504        n_Delete(&tp1, basecoeffs);
505        n_Delete(&tp2, basecoeffs);
506      }
507      bimRowContent(bimat, j, colpos+1);
508      n_Delete(&m1, basecoeffs);
509      n_Delete(&m2, basecoeffs);
510    }
511    n_Delete(&ce, basecoeffs);
512  }
513}
514
515
516
517
518
Note: See TracBrowser for help on using the repository browser.