source: git/libpolys/coeffs/bigintmat.cc @ 84fc1f

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