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

spielwiese
Last change on this file since e3f523 was e3f523, checked in by Oleksandr Motsak <motsak@…>, 11 years ago
Misc changes to BS and others fix: GMP-checking will looks at CPATH add: remarks due to C. Fieker
  • Property mode set to 100644
File size: 17.4 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// Ungetestet
18static void bimRowContent(bigintmat *bimat, int rowpos, int colpos);
19static void bimReduce(bigintmat *bimat, int rpiv, int colpos,
20                      int ready, int all);
21
22
23
24//#define BIMATELEM(M,I,J) (M)[ (M).index(I,J) ]
25
26bigintmat * bigintmat::transpose()
27{
28  bigintmat * t = new bigintmat(col, row, basecoeffs());
29  for (int i=1; i<=row; i++)
30  {
31    for (int j=1; j<=col; j++)
32    {
33      t->set(j, i, BIMATELEM(*this,i,j));
34    }
35  }
36  return t;
37}
38
39// Beginnt bei [0]
40void bigintmat::set(int i, number n, const coeffs C)
41{
42  assume (C == NULL || C == basecoeffs());
43
44  rawset(i, n_Copy(n, basecoeffs()), basecoeffs());
45}
46
47// Beginnt bei [1,1]
48void bigintmat::set(int i, int j, number n, const coeffs C)
49{
50  assume (C == NULL || C == basecoeffs());
51  assume (i >= 0 && j >= 0);
52  assume (i <= rows() && j <= cols());
53
54  set(index(i, j), n, C);
55}
56
57number bigintmat::get(int i) const
58{
59  assume (i >= 0);
60  assume (i<rows()*cols());
61
62  return n_Copy(v[i], basecoeffs());
63}
64
65number bigintmat::get(int i, int j) const
66{
67  assume (i >= 0 && j >= 0);
68  assume (i <= rows() && j <= cols());
69
70  return get(index(i, j));
71}
72
73// Überladener *=-Operator (fÃŒr int und bigint)
74// Frage hier: *= verwenden oder lieber = und * einzeln?
75void bigintmat::operator*=(int intop)
76{
77  number iop = n_Init(intop, basecoeffs());
78
79  inpMult(iop, basecoeffs());
80
81  n_Delete(&iop, basecoeffs());
82}
83
84void bigintmat::inpMult(number bintop, const coeffs C)
85{
86  assume (C == NULL || C == basecoeffs());
87
88  const int l = rows() * cols();
89
90  for (int i=0; i < l; i++)
91    n_InpMult(v[i], bintop, basecoeffs());
92}
93
94// Stimmen Parameter?
95// Welche der beiden Methoden?
96// Oder lieber eine comp-Funktion?
97
98bool operator==(const bigintmat & lhr, const bigintmat & rhr)
99{
100  if (&lhr == &rhr) { return true; }
101  if (lhr.cols() != rhr.cols()) { return false; }
102  if (lhr.rows() != rhr.rows()) { return false; }
103  if (lhr.basecoeffs() != rhr.basecoeffs()) { return false; }
104
105  const int l = (lhr.rows())*(lhr.cols());
106
107  for (int i=0; i < l; i++)
108  {
109    if (!n_Equal(lhr[i], rhr[i], lhr.basecoeffs())) { return false; }
110  }
111
112  return true;
113}
114
115bool operator!=(const bigintmat & lhr, const bigintmat & rhr)
116{
117  return !(lhr==rhr);
118}
119
120// Matrix-Add/-Sub/-Mult so oder mit operator+/-/* ?
121bigintmat * bimAdd(bigintmat * a, bigintmat * b)
122{
123  if (a->cols() != b->cols()) return NULL;
124  if (a->rows() != b->rows()) return NULL;
125  if (a->basecoeffs() != b->basecoeffs()) { return NULL; }
126
127  const coeffs basecoeffs = a->basecoeffs();
128
129  int i;
130
131  bigintmat * bim = new bigintmat(a->rows(), a->cols(), basecoeffs);
132
133  for (i=a->rows()*a->cols()-1;i>=0; i--)
134    bim->rawset(i, n_Add((*a)[i], (*b)[i], basecoeffs), basecoeffs);
135
136  return bim;
137}
138bigintmat * bimAdd(bigintmat * a, int b)
139{
140
141  const int mn = a->rows()*a->cols();
142
143  const coeffs basecoeffs = a->basecoeffs();
144  number bb=n_Init(b,basecoeffs);
145
146  int i;
147
148  bigintmat * bim = new bigintmat(a->rows(),a->cols() , basecoeffs);
149
150  for (i=0; i<mn; i++)
151    bim->rawset(i, n_Add((*a)[i], bb, basecoeffs), basecoeffs);
152
153  n_Delete(&bb,basecoeffs);
154  return bim;
155}
156
157bigintmat * bimSub(bigintmat * a, bigintmat * b)
158{
159  if (a->cols() != b->cols()) return NULL;
160  if (a->rows() != b->rows()) return NULL;
161  if (a->basecoeffs() != b->basecoeffs()) { return NULL; }
162
163  const coeffs basecoeffs = a->basecoeffs();
164
165  int i;
166
167  bigintmat * bim = new bigintmat(a->rows(), a->cols(), basecoeffs);
168
169  for (i=a->rows()*a->cols()-1;i>=0; i--)
170    bim->rawset(i, n_Sub((*a)[i], (*b)[i], basecoeffs), basecoeffs);
171
172  return bim;
173}
174
175bigintmat * bimSub(bigintmat * a, int b)
176{
177
178  const int mn = a->rows()*a->cols();
179
180  const coeffs basecoeffs = a->basecoeffs();
181  number bb=n_Init(b,basecoeffs);
182
183  int i;
184
185  bigintmat * bim = new bigintmat(a->rows(),a->cols() , basecoeffs);
186
187  for (i=0; i<mn; i++)
188    bim->rawset(i, n_Sub((*a)[i], bb, basecoeffs), basecoeffs);
189
190  n_Delete(&bb,basecoeffs);
191  return bim;
192}
193
194bigintmat * bimMult(bigintmat * a, bigintmat * b)
195{
196  const int ca = a->cols();
197  const int cb = b->cols();
198
199  const int ra = a->rows();
200  const int rb = b->rows();
201
202  if (ca != rb)
203  {
204#ifndef NDEBUG
205    Werror("wrong bigintmat sizes at multiplication a * b: acols: %d != brows: %d\n", ca, rb);
206#endif
207    return NULL;
208  }
209
210  assume (ca == rb);
211
212  if (a->basecoeffs() != b->basecoeffs()) { return NULL; }
213
214  const coeffs basecoeffs = a->basecoeffs();
215
216  int i, j, k;
217
218  number sum;
219
220  bigintmat * bim = new bigintmat(ra, cb, basecoeffs);
221
222  for (i=1; i<=ra; i++)
223    for (j=1; j<=cb; j++)
224    {
225      sum = n_Init(0, basecoeffs);
226
227      for (k=1; k<=ca; k++)
228      {
229        number prod = n_Mult( BIMATELEM(*a, i, k), BIMATELEM(*b, k, j), basecoeffs);
230
231        number sum2 = n_Add(sum, prod, basecoeffs); // no inplace add :(
232
233        n_Delete(&sum, basecoeffs); n_Delete(&prod, basecoeffs);
234
235        sum = sum2;
236      }
237      bim->rawset(i, j, sum, basecoeffs);
238    }
239  return bim;
240}
241
242bigintmat * bimMult(bigintmat * a, int b)
243{
244
245  const int mn = a->rows()*a->cols();
246
247  const coeffs basecoeffs = a->basecoeffs();
248  number bb=n_Init(b,basecoeffs);
249
250  int i;
251
252  bigintmat * bim = new bigintmat(a->rows(),a->cols() , basecoeffs);
253
254  for (i=0; i<mn; i++)
255    bim->rawset(i, n_Mult((*a)[i], bb, basecoeffs), basecoeffs);
256
257  n_Delete(&bb,basecoeffs);
258  return bim;
259}
260
261bigintmat * bimMult(bigintmat * a, number b, const coeffs cf)
262{
263  if (cf!=a->basecoeffs()) return NULL;
264
265  const int mn = a->rows()*a->cols();
266
267  const coeffs basecoeffs = a->basecoeffs();
268
269  int i;
270
271  bigintmat * bim = new bigintmat(a->rows(),a->cols() , basecoeffs);
272
273  for (i=0; i<mn; i++)
274    bim->rawset(i, n_Mult((*a)[i], b, basecoeffs), basecoeffs);
275
276  return bim;
277}
278
279// ----------------------------------------------------------------- //
280// Korrekt?
281
282intvec * bim2iv(bigintmat * b)
283{
284  intvec * iv = new intvec(b->rows(), b->cols(), 0);
285  for (int i=0; i<(b->rows())*(b->cols()); i++)
286    (*iv)[i] = n_Int((*b)[i], b->basecoeffs()); // Geht das so?
287  return iv;
288}
289
290bigintmat * iv2bim(intvec * b, const coeffs C)
291{
292  const int l = (b->rows())*(b->cols());
293  bigintmat * bim = new bigintmat(b->rows(), b->cols(), C);
294
295  for (int i=0; i < l; i++)
296    bim->rawset(i, n_Init((*b)[i], C), C);
297
298  return bim;
299}
300
301// ----------------------------------------------------------------- //
302
303int bigintmat::compare(const bigintmat* op) const
304{
305  assume (basecoeffs() == op->basecoeffs() );
306
307#ifndef NDEBUG
308  if (basecoeffs() != op->basecoeffs() )
309    WerrorS("wrong bigintmat comparison: different basecoeffs!\n");
310#endif
311
312  if ((col!=1) ||(op->cols()!=1))
313  {
314    if((col!=op->cols())
315       || (row!=op->rows()))
316      return -2;
317  }
318
319  int i;
320  for (i=0; i<si_min(row*col,op->rows()*op->cols()); i++)
321  {
322    if ( n_Greater(v[i], (*op)[i], basecoeffs()) )
323      return 1;
324    else if (! n_Equal(v[i], (*op)[i], basecoeffs()))
325      return -1;
326  }
327
328  for (; i<row; i++)
329  {
330    if ( n_GreaterZero(v[i], basecoeffs()) )
331      return 1;
332    else if (! n_IsZero(v[i], basecoeffs()) )
333      return -1;
334  }
335  for (; i<op->rows(); i++)
336  {
337    if ( n_GreaterZero((*op)[i], basecoeffs()) )
338      return -1;
339    else if (! n_IsZero((*op)[i], basecoeffs()) )
340      return 1;
341  }
342  return 0;
343}
344
345
346bigintmat * bimCopy(const bigintmat * b)
347{
348  if (b == NULL)
349    return NULL;
350
351  return new bigintmat(b);
352}
353
354char* bigintmat::String()
355{
356  StringSetS("");
357  const int l = cols()*rows();
358
359  n_Write(v[0], basecoeffs());
360  for (int i = 1; i < l; i++)
361  {
362    StringAppendS(","); n_Write(v[i], basecoeffs());
363  }
364  /* if (i != col*row-1)
365  {
366  StringAppendS(",");
367  if ((i+1)%col == 0)
368  StringAppendS("\n");
369  }   */
370  return StringEndS();
371}
372
373char* bigintmat::StringAsPrinted()
374{
375  if ((col==0) || (row==0))
376    PrintS("");
377  else
378  {
379    int * colwid = getwid(80);
380    char * ps;
381    if (colwid == NULL)
382    {
383      WerrorS("not enough space to print bigintmat");
384      WerrorS("try string(...) for a unformatted output");
385      return ps;
386    }
387    int slength = 0;
388    for (int j=0; j<col; j++)
389      slength += colwid[j]*row;
390    slength += col*row+row;
391    ps = (char*) omAlloc0(sizeof(char)*(slength));
392    int pos = 0;
393    for (int i=0; i<col*row; i++)
394    {
395      StringSetS("");
396      n_Write(v[i], basecoeffs());
397      char * ts = StringEndS();
398      const int _nl = strlen(ts);
399      int cj = i%col;
400      if (_nl > colwid[cj])
401      {
402        StringSetS("");
403        int ci = i/col;
404        StringAppend("[%d,%d]", ci+1, cj+1);
405        char * ph = StringEndS();
406        int phl = strlen(ph);
407        if (phl > colwid[cj])
408        {
409          for (int j=0; j<colwid[cj]-1; j++)
410            ps[pos+j] = ' ';
411          ps[pos+colwid[cj]-1] = '*';
412        }
413        else
414        {
415          for (int j=0; j<colwid[cj]-phl; j++)
416            ps[pos+j] = ' ';
417          for (int j=0; j<phl; j++)
418            ps[pos+colwid[cj]-phl+j] = ph[j];
419        }
420        omFree(ph);
421      }
422      else  // Mit Leerzeichen auffÃŒllen und zahl reinschreiben
423      {
424        for (int j=0; j<colwid[cj]-_nl; j++)
425          ps[pos+j] = ' ';
426        for (int j=0; j<_nl; j++)
427          ps[pos+colwid[cj]-_nl+j] = ts[j];
428      }
429      // ", " und (evtl) "\n" einfÃŒgen
430      if ((i+1)%col == 0)
431      {
432        if (i != col*row-1)
433        {
434          ps[pos+colwid[cj]] = ',';
435          ps[pos+colwid[cj]+1] = '\n';
436          pos += colwid[cj]+2;
437        }
438      }
439      else
440      {
441        ps[pos+colwid[cj]] = ',';
442        pos += colwid[cj]+1;
443      }
444
445      omFree(ts);  // Hier ts zerstören
446    }
447    return(ps);
448    // omFree(ps);
449  }
450  // if ((col==0) || (row==0))
451  //   return 0;
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 0;
458  // }
459  // char * ps;
460  // int slength = 0;
461  // for (int j=0; j<col; j++)
462  //   slength += colwid[j]*row;
463  // slength += 2*(col-1)*row+2*row-1;
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 * temp = StringAppendS("");
471  //   char * ts = omStrDup(temp);
472  //   int nl = strlen(ts);
473  //   int cj = i%col;
474  //   if (nl > colwid[cj])
475  //   {
476  //     StringSetS("");
477  //     int ci = floor(i/col);
478  //     StringAppend("[%d,%d]", ci+1, cj+1);
479  //     char *tmp = StringAppendS("");
480  //     char * ph = omStrDup(tmp);
481  //     int phl = strlen(ph);
482  //     if (phl > colwid[cj])
483  //     {
484  //       for (int j=0; j<colwid[cj]; j++)
485  //         ps[pos+j] = '*';
486  //     }
487  //     else
488  //     {
489  //       for (int j=0; j<colwid[cj]-phl; j++)
490  //         ps[pos+j] = ' ';
491  //       for (int j=0; j<phl; j++)
492  //         ps[pos+colwid[cj]-phl+j] = ph[j];
493  //     }
494  //     omFree(ph);
495  //   }
496  //   else  // Mit Leerzeichen auffÃŒllen und Zahl reinschreiben
497  //   {
498  //     for (int j=0; j<colwid[cj]-nl; j++)
499  //       ps[pos+j] = ' ';
500  //     for (int j=0; j<nl; j++)
501  //       ps[pos+colwid[cj]-nl+j] = ts[j];
502  //   }
503  //   // ", " oder "\n" einfÃŒgen
504  //   if ((i+1)%col == 0)
505  //   {
506  //     if (i != col*row-1)
507  //     {
508  //       ps[pos+colwid[cj]] = ',';
509  //       ps[pos+colwid[cj]+1] = '\n';
510  //       pos += colwid[cj]+2;
511  //     }
512  //   }
513  //   else
514  //   {
515  //     ps[pos+colwid[cj]] = ',';
516  //     ps[pos+colwid[cj]+1] = ' ';
517  //     pos += colwid[cj]+2;
518  //   }
519  //   omFree(ts);
520  // }
521  // return ps;
522}
523
524int intArrSum(int * a, int length)
525{
526  int sum = 0;
527  for (int i=0; i<length; i++)
528    sum += a[i];
529  return sum;
530}
531
532int findLongest(int * a, int length)
533{
534  int l = 0;
535  int index;
536  for (int i=0; i<length; i++)
537  {
538    if (a[i] > l)
539    {
540      l = a[i];
541      index = i;
542    }
543  }
544  return index;
545}
546
547int getShorter (int * a, int l, int j, int cols, int rows)
548{
549  int sndlong = 0;
550  int min;
551  for (int i=0; i<rows; i++)
552  {
553    int index = cols*i+j;
554    if ((a[index] > sndlong) && (a[index] < l))
555    {
556      min = floor(log10((double)cols))+floor(log10((double)rows))+5;
557      if ((a[index] < min) && (min < l))
558        sndlong = min;
559      else
560        sndlong = a[index];
561    }
562  }
563  if (sndlong == 0)
564  {
565    min = floor(log10((double)cols))+floor(log10((double)rows))+5;
566    if (min < l)
567      sndlong = min;
568    else
569      sndlong = 1;
570  }
571  return sndlong;
572}
573
574
575int * bigintmat::getwid(int maxwid)
576{
577  int const c = /*2**/(col-1)+1;
578  if (col + c > maxwid-1) return NULL;
579  int * wv = (int*)omAlloc(sizeof(int)*col*row);
580  int * cwv = (int*)omAlloc(sizeof(int)*col);
581  for (int j=0; j<col; j++)
582  {
583    cwv[j] = 0;
584    for (int i=0; i<row; i++)
585    {
586      StringSetS("");
587      n_Write(v[col*i+j], basecoeffs());
588      char * tmp = StringEndS();
589      const int _nl = strlen(tmp);
590      wv[col*i+j] = _nl;
591      if (_nl > cwv[j])
592        cwv[j]=_nl;
593      omFree(tmp);
594    }
595  }
596
597  // Groesse verkleinern, bis < maxwid
598  while (intArrSum(cwv, col)+c > maxwid)
599  {
600    int j = findLongest(cwv, col);
601    cwv[j] = getShorter(wv, cwv[j], j, col, row);
602  }
603  omFree(wv);
604  return cwv;
605}
606
607void bigintmat::pprint(int maxwid)
608{
609  if ((col==0) || (row==0))
610    PrintS("");
611  else
612  {
613    int * colwid = getwid(maxwid);
614    if (colwid == NULL)
615    {
616      WerrorS("not enough space to print bigintmat");
617      return;
618    }
619    char * ps;
620    int slength = 0;
621    for (int j=0; j<col; j++)
622      slength += colwid[j]*row;
623    slength += col*row+row;
624    ps = (char*) omAlloc0(sizeof(char)*(slength));
625    int pos = 0;
626    for (int i=0; i<col*row; i++)
627    {
628      StringSetS("");
629      n_Write(v[i], basecoeffs());
630      char * ts = StringEndS();
631      const int _nl = strlen(ts);
632      int cj = i%col;
633      if (_nl > colwid[cj])
634      {
635        StringSetS("");
636        int ci = i/col;
637        StringAppend("[%d,%d]", ci+1, cj+1);
638        char * ph = StringEndS();
639        int phl = strlen(ph);
640        if (phl > colwid[cj])
641        {
642          for (int j=0; j<colwid[cj]-1; j++)
643            ps[pos+j] = ' ';
644          ps[pos+colwid[cj]-1] = '*';
645        }
646        else
647        {
648          for (int j=0; j<colwid[cj]-phl; j++)
649            ps[pos+j] = ' ';
650          for (int j=0; j<phl; j++)
651            ps[pos+colwid[cj]-phl+j] = ph[j];
652        }
653        omFree(ph);
654      }
655      else  // Mit Leerzeichen auffÃŒllen und zahl reinschreiben
656      {
657        for (int j=0; j<colwid[cj]-_nl; j++)
658          ps[pos+j] = ' ';
659        for (int j=0; j<_nl; j++)
660          ps[pos+colwid[cj]-_nl+j] = ts[j];
661      }
662      // ", " und (evtl) "\n" einfÃŒgen
663      if ((i+1)%col == 0)
664      {
665        if (i != col*row-1)
666        {
667          ps[pos+colwid[cj]] = ',';
668          ps[pos+colwid[cj]+1] = '\n';
669          pos += colwid[cj]+2;
670        }
671      }
672      else
673      {
674        ps[pos+colwid[cj]] = ',';
675        pos += colwid[cj]+1;
676      }
677
678      omFree(ts);  // Hier ts zerstören
679    }
680    PrintS(ps);
681   // omFree(ps);
682  }
683}
684
685// Ungetestet
686// (According to C. Fieker) Seems to have a lot of memory leaks (pure adaptation of the
687// corresponding method for intmat) due to return statements
688static void bimRowContent(bigintmat *bimat, int rowpos, int colpos)
689{
690  const coeffs basecoeffs = bimat->basecoeffs();
691
692  number tgcd, m;
693  int i=bimat->cols();
694
695  loop
696  {
697    tgcd = n_Copy(BIMATELEM(*bimat,rowpos,i--), basecoeffs);
698    if (! n_IsZero(tgcd, basecoeffs)) break;
699    if (i<colpos) return;
700  }
701  if ((! n_GreaterZero(tgcd, basecoeffs)) && (! n_IsZero(tgcd, basecoeffs))) tgcd = n_Neg(tgcd, basecoeffs);
702  if ( n_IsOne(tgcd,basecoeffs)) return;
703  loop
704  {
705    m = n_Copy(BIMATELEM(*bimat,rowpos,i--), basecoeffs);
706    if (! n_IsZero(m,basecoeffs))
707    {
708      number tp1 = n_Gcd(tgcd, m, basecoeffs);
709      n_Delete(&tgcd, basecoeffs);
710      tgcd = tp1;
711    }
712    if ( n_IsOne(tgcd,basecoeffs)) return;
713    if (i<colpos) break;
714  }
715  for (i=bimat->cols();i>=colpos;i--)
716  {
717    number tp2 = n_Div(BIMATELEM(*bimat,rowpos,i), tgcd,basecoeffs);
718    n_Delete(&BIMATELEM(*bimat,rowpos,i), basecoeffs);
719    BIMATELEM(*bimat,rowpos,i) = tp2;
720  }
721  n_Delete(&tgcd, basecoeffs);
722  n_Delete(&m, basecoeffs);
723}
724
725static void bimReduce(bigintmat *bimat, int rpiv, int colpos,
726                      int ready, int all)
727{
728  const coeffs basecoeffs = bimat->basecoeffs();
729
730  number tgcd, ce, m1, m2;
731  int j, i;
732  number piv = BIMATELEM(*bimat,rpiv,colpos);
733
734  for (j=all;j>ready;j--)
735  {
736    ce = n_Copy(BIMATELEM(*bimat,j,colpos),basecoeffs);
737    if (! n_IsZero(ce, basecoeffs))
738    {
739      n_Delete(&BIMATELEM(*bimat,j,colpos), basecoeffs);
740      BIMATELEM(*bimat,j,colpos) = n_Init(0, basecoeffs);
741      m1 = n_Copy(piv,basecoeffs);
742      m2 = n_Copy(ce,basecoeffs);
743      tgcd = n_Gcd(m1, m2, basecoeffs);
744      if (! n_IsOne(tgcd,basecoeffs))
745      {
746        number tp1 = n_Div(m1, tgcd,basecoeffs);
747        number tp2 = n_Div(m2, tgcd,basecoeffs);
748        n_Delete(&m1, basecoeffs);
749        n_Delete(&m2, basecoeffs);
750        m1 = tp1;
751        m2 = tp2;
752      }
753      for (i=bimat->cols();i>colpos;i--)
754      {
755        n_Delete(&BIMATELEM(*bimat,j,i), basecoeffs);
756        number tp1 = n_Mult(BIMATELEM(*bimat,j,i), m1,basecoeffs);
757        number tp2 = n_Mult(BIMATELEM(*bimat,rpiv,i), m2,basecoeffs);
758        BIMATELEM(*bimat,j,i) = n_Sub(tp1, tp2,basecoeffs);
759        n_Delete(&tp1, basecoeffs);
760        n_Delete(&tp2, basecoeffs);
761      }
762      bimRowContent(bimat, j, colpos+1);
763      n_Delete(&m1, basecoeffs);
764      n_Delete(&m2, basecoeffs);
765    }
766    n_Delete(&ce, basecoeffs);
767  }
768}
769
770
771
772
773
Note: See TracBrowser for help on using the repository browser.