source: git/libpolys/coeffs/rmodulo2m.cc @ 5a0b78

spielwiese
Last change on this file since 5a0b78 was 5a0b78, checked in by Martin Lee <martinlee84@…>, 11 years ago
fix: printing of coeffs Z and Z/2^m
  • Property mode set to 100644
File size: 17.2 KB
Line 
1/****************************************
2*  Computer Algebra System SINGULAR     *
3****************************************/
4/*
5* ABSTRACT: numbers modulo 2^m
6*/
7
8#include "config.h"
9#include <misc/auxiliary.h>
10
11#ifdef HAVE_RINGS
12
13#include <misc/mylimits.h>
14#include <coeffs/coeffs.h>
15#include <reporter/reporter.h>
16#include <omalloc/omalloc.h>
17#include <coeffs/numbers.h>
18#include <coeffs/longrat.h>
19#include <coeffs/mpr_complex.h>
20#include <coeffs/rmodulo2m.h>
21#include "si_gmp.h"
22
23#include <string.h>
24
25/// Our Type!
26static const n_coeffType ID = n_Z2m;
27
28extern omBin gmp_nrz_bin; /* init in rintegers*/
29
30void    nr2mCoeffWrite  (const coeffs r, BOOLEAN /*details*/)
31{
32  PrintS("//   coeff. ring is : ");
33  Print("Z/2^%lu\n", r->modExponent);
34}
35
36BOOLEAN nr2mCoeffIsEqual(const coeffs r, n_coeffType n, void * p)
37{
38  if (n==n_Z2m)
39  {
40    int m=(int)(long)(p);
41    unsigned long mm=r->mod2mMask;
42    if ((mm>>m)==1L) return TRUE;
43  }
44  return FALSE;
45}
46/* for initializing function pointers */
47BOOLEAN nr2mInitChar (coeffs r, void* p)
48{
49  assume( getCoeffType(r) == ID );
50  nr2mInitExp((int)(long)(p), r);
51  r->cfKillChar    = ndKillChar; /* dummy*/
52  r->nCoeffIsEqual = nr2mCoeffIsEqual;
53
54  r->modBase = (int_number) omAllocBin (gmp_nrz_bin);
55  mpz_init_set_si (r->modBase, 2L);
56  r->ringtype = 1;
57  r->modNumber= (int_number) omAllocBin (gmp_nrz_bin);
58  mpz_init (r->modNumber);
59  mpz_pow_ui (r->modNumber, r->modBase, r->modExponent);
60
61  /* next cast may yield an overflow as mod2mMask is an unsigned long */
62  r->ch = (int)r->mod2mMask + 1;
63
64  r->cfInit        = nr2mInit;
65  r->cfCopy        = ndCopy;
66  r->cfInt         = nr2mInt;
67  r->cfAdd         = nr2mAdd;
68  r->cfSub         = nr2mSub;
69  r->cfMult        = nr2mMult;
70  r->cfDiv         = nr2mDiv;
71  r->cfIntDiv      = nr2mIntDiv;
72  r->cfIntMod      = nr2mMod;
73  r->cfExactDiv    = nr2mDiv;
74  r->cfNeg         = nr2mNeg;
75  r->cfInvers      = nr2mInvers;
76  r->cfDivBy       = nr2mDivBy;
77  r->cfDivComp     = nr2mDivComp;
78  r->cfGreater     = nr2mGreater;
79  r->cfEqual       = nr2mEqual;
80  r->cfIsZero      = nr2mIsZero;
81  r->cfIsOne       = nr2mIsOne;
82  r->cfIsMOne      = nr2mIsMOne;
83  r->cfGreaterZero = nr2mGreaterZero;
84  r->cfWriteLong       = nr2mWrite;
85  r->cfRead        = nr2mRead;
86  r->cfPower       = nr2mPower;
87  r->cfSetMap      = nr2mSetMap;
88  r->cfNormalize   = ndNormalize;
89  r->cfLcm         = nr2mLcm;
90  r->cfGcd         = nr2mGcd;
91  r->cfIsUnit      = nr2mIsUnit;
92  r->cfGetUnit     = nr2mGetUnit;
93  r->cfExtGcd      = nr2mExtGcd;
94  r->cfName        = ndName;
95  r->cfCoeffWrite  = nr2mCoeffWrite;
96  r->cfInit_bigint = nr2mMapQ;
97#ifdef LDEBUG
98  r->cfDBTest      = nr2mDBTest;
99#endif
100  r->has_simple_Alloc=TRUE;
101  return FALSE;
102}
103
104/*
105 * Multiply two numbers
106 */
107number nr2mMult(number a, number b, const coeffs r)
108{
109  if (((NATNUMBER)a == 0) || ((NATNUMBER)b == 0))
110    return (number)0;
111  else
112    return nr2mMultM(a, b, r);
113}
114
115/*
116 * Give the smallest k, such that a * x = k = b * y has a solution
117 */
118number nr2mLcm(number a, number b, const coeffs)
119{
120  NATNUMBER res = 0;
121  if ((NATNUMBER)a == 0) a = (number) 1;
122  if ((NATNUMBER)b == 0) b = (number) 1;
123  while ((NATNUMBER)a % 2 == 0)
124  {
125    a = (number)((NATNUMBER)a / 2);
126    if ((NATNUMBER)b % 2 == 0) b = (number)((NATNUMBER)b / 2);
127    res++;
128  }
129  while ((NATNUMBER)b % 2 == 0)
130  {
131    b = (number)((NATNUMBER)b / 2);
132    res++;
133  }
134  return (number)(1L << res);  // (2**res)
135}
136
137/*
138 * Give the largest k, such that a = x * k, b = y * k has
139 * a solution.
140 */
141number nr2mGcd(number a, number b, const coeffs)
142{
143  NATNUMBER res = 0;
144  if ((NATNUMBER)a == 0 && (NATNUMBER)b == 0) return (number)1;
145  while ((NATNUMBER)a % 2 == 0 && (NATNUMBER)b % 2 == 0)
146  {
147    a = (number)((NATNUMBER)a / 2);
148    b = (number)((NATNUMBER)b / 2);
149    res++;
150  }
151//  if ((NATNUMBER)b % 2 == 0)
152//  {
153//    return (number)((1L << res)); // * (NATNUMBER) a);  // (2**res)*a    a is a unit
154//  }
155//  else
156//  {
157    return (number)((1L << res)); // * (NATNUMBER) b);  // (2**res)*b    b is a unit
158//  }
159}
160
161/*
162 * Give the largest k, such that a = x * k, b = y * k has
163 * a solution.
164 */
165number nr2mExtGcd(number a, number b, number *s, number *t, const coeffs r)
166{
167  NATNUMBER res = 0;
168  if ((NATNUMBER)a == 0 && (NATNUMBER)b == 0) return (number)1;
169  while ((NATNUMBER)a % 2 == 0 && (NATNUMBER)b % 2 == 0)
170  {
171    a = (number)((NATNUMBER)a / 2);
172    b = (number)((NATNUMBER)b / 2);
173    res++;
174  }
175  if ((NATNUMBER)b % 2 == 0)
176  {
177    *t = NULL;
178    *s = nr2mInvers(a,r);
179    return (number)((1L << res)); // * (NATNUMBER) a);  // (2**res)*a    a is a unit
180  }
181  else
182  {
183    *s = NULL;
184    *t = nr2mInvers(b,r);
185    return (number)((1L << res)); // * (NATNUMBER) b);  // (2**res)*b    b is a unit
186  }
187}
188
189void nr2mPower(number a, int i, number * result, const coeffs r)
190{
191  if (i == 0)
192  {
193    *(NATNUMBER *)result = 1;
194  }
195  else if (i == 1)
196  {
197    *result = a;
198  }
199  else
200  {
201    nr2mPower(a, i-1, result, r);
202    *result = nr2mMultM(a, *result, r);
203  }
204}
205
206/*
207 * create a number from int
208 */
209number nr2mInit(long i, const coeffs r)
210{
211  if (i == 0) return (number)(NATNUMBER)i;
212
213  long ii = i;
214  NATNUMBER j = (NATNUMBER)1;
215  if (ii < 0) { j = r->mod2mMask; ii = -ii; }
216  NATNUMBER k = (NATNUMBER)ii;
217  k = k & r->mod2mMask;
218  /* now we have: i = j * k mod 2^m */
219  return (number)nr2mMult((number)j, (number)k, r);
220}
221
222/*
223 * convert a number to an int in ]-k/2 .. k/2],
224 * where k = 2^m; i.e., an int in ]-2^(m-1) .. 2^(m-1)];
225 * note that the code computes a long which will then
226 * automatically casted to int
227 */
228static long nr2mLong(number &n, const coeffs r)
229{
230  NATNUMBER nn = (unsigned long)(NATNUMBER)n & r->mod2mMask;
231  unsigned long l = r->mod2mMask >> 1; l++; /* now: l = 2^(m-1) */
232  if ((NATNUMBER)nn > l)
233    return (long)((NATNUMBER)nn - r->mod2mMask - 1);
234  else
235    return (long)((NATNUMBER)nn);
236}
237int nr2mInt(number &n, const coeffs r)
238{
239  return (int)nr2mLong(n,r);
240}
241
242number nr2mAdd(number a, number b, const coeffs r)
243{
244  return nr2mAddM(a, b, r);
245}
246
247number nr2mSub(number a, number b, const coeffs r)
248{
249  return nr2mSubM(a, b, r);
250}
251
252BOOLEAN nr2mIsUnit(number a, const coeffs)
253{
254  return ((NATNUMBER)a % 2 == 1);
255}
256
257number nr2mGetUnit(number k, const coeffs)
258{
259  if (k == NULL) return (number)1;
260  NATNUMBER erg = (NATNUMBER)k;
261  while (erg % 2 == 0) erg = erg / 2;
262  return (number)erg;
263}
264
265BOOLEAN nr2mIsZero(number a, const coeffs)
266{
267  return 0 == (NATNUMBER)a;
268}
269
270BOOLEAN nr2mIsOne(number a, const coeffs)
271{
272  return 1 == (NATNUMBER)a;
273}
274
275BOOLEAN nr2mIsMOne(number a, const coeffs r)
276{
277  return (r->mod2mMask  == (NATNUMBER)a);
278}
279
280BOOLEAN nr2mEqual(number a, number b, const coeffs)
281{
282  return (a == b);
283}
284
285BOOLEAN nr2mGreater(number a, number b, const coeffs r)
286{
287  return nr2mDivBy(a, b,r);
288}
289
290/* Is 'a' divisible by 'b'? There are two cases:
291   1) a = 0 mod 2^m; then TRUE iff b = 0 or b is a power of 2
292   2) a, b <> 0; then TRUE iff b/gcd(a, b) is a unit mod 2^m */
293BOOLEAN nr2mDivBy (number a, number b, const coeffs r)
294{
295  if (a == NULL)
296  {
297    NATNUMBER c = r->mod2mMask + 1;
298    if (c != 0) /* i.e., if no overflow */
299      return (c % (NATNUMBER)b) == 0;
300    else
301    {
302      /* overflow: we need to check whether b
303         is zero or a power of 2: */
304      c = (NATNUMBER)b;
305      while (c != 0)
306      {
307        if ((c % 2) != 0) return FALSE;
308        c = c >> 1;
309      }
310      return TRUE;
311    }
312  }
313  else
314  {
315    number n = nr2mGcd(a, b, r);
316    n = nr2mDiv(b, n, r);
317    return nr2mIsUnit(n, r);
318  }
319}
320
321int nr2mDivComp(number as, number bs, const coeffs)
322{
323  NATNUMBER a = (NATNUMBER)as;
324  NATNUMBER b = (NATNUMBER)bs;
325  assume(a != 0 && b != 0);
326  while (a % 2 == 0 && b % 2 == 0)
327  {
328    a = a / 2;
329    b = b / 2;
330  }
331  if (a % 2 == 0)
332  {
333    return -1;
334  }
335  else
336  {
337    if (b % 2 == 1)
338    {
339      return 2;
340    }
341    else
342    {
343      return 1;
344    }
345  }
346}
347
348/* TRUE iff 0 < k <= 2^m / 2 */
349BOOLEAN nr2mGreaterZero(number k, const coeffs r)
350{
351  if ((NATNUMBER)k == 0) return FALSE;
352  if ((NATNUMBER)k > ((r->mod2mMask >> 1) + 1)) return FALSE;
353  return TRUE;
354}
355
356/* assumes that 'a' is odd, i.e., a unit in Z/2^m, and computes
357   the extended gcd of 'a' and 2^m, in order to find some 's'
358   and 't' such that a * s + 2^m * t = gcd(a, 2^m) = 1;
359   this code will always find a positive 's' */
360void specialXGCD(unsigned long& s, unsigned long a, const coeffs r)
361{
362  int_number u = (int_number)omAlloc(sizeof(mpz_t));
363  mpz_init_set_ui(u, a);
364  int_number u0 = (int_number)omAlloc(sizeof(mpz_t));
365  mpz_init(u0);
366  int_number u1 = (int_number)omAlloc(sizeof(mpz_t));
367  mpz_init_set_ui(u1, 1);
368  int_number u2 = (int_number)omAlloc(sizeof(mpz_t));
369  mpz_init(u2);
370  int_number v = (int_number)omAlloc(sizeof(mpz_t));
371  mpz_init_set_ui(v, r->mod2mMask);
372  mpz_add_ui(v, v, 1); /* now: v = 2^m */
373  int_number v0 = (int_number)omAlloc(sizeof(mpz_t));
374  mpz_init(v0);
375  int_number v1 = (int_number)omAlloc(sizeof(mpz_t));
376  mpz_init(v1);
377  int_number v2 = (int_number)omAlloc(sizeof(mpz_t));
378  mpz_init_set_ui(v2, 1);
379  int_number q = (int_number)omAlloc(sizeof(mpz_t));
380  mpz_init(q);
381  int_number rr = (int_number)omAlloc(sizeof(mpz_t));
382  mpz_init(rr);
383
384  while (mpz_cmp_ui(v, 0) != 0) /* i.e., while v != 0 */
385  {
386    mpz_div(q, u, v);
387    mpz_mod(rr, u, v);
388    mpz_set(u, v);
389    mpz_set(v, rr);
390    mpz_set(u0, u2);
391    mpz_set(v0, v2);
392    mpz_mul(u2, u2, q); mpz_sub(u2, u1, u2); /* u2 = u1 - q * u2 */
393    mpz_mul(v2, v2, q); mpz_sub(v2, v1, v2); /* v2 = v1 - q * v2 */
394    mpz_set(u1, u0);
395    mpz_set(v1, v0);
396  }
397
398  while (mpz_cmp_ui(u1, 0) < 0) /* i.e., while u1 < 0 */
399  {
400    /* we add 2^m = (2^m - 1) + 1 to u1: */
401    mpz_add_ui(u1, u1, r->mod2mMask);
402    mpz_add_ui(u1, u1, 1);
403  }
404  s = mpz_get_ui(u1); /* now: 0 <= s <= 2^m - 1 */
405
406  mpz_clear(u);  omFree((ADDRESS)u);
407  mpz_clear(u0); omFree((ADDRESS)u0);
408  mpz_clear(u1); omFree((ADDRESS)u1);
409  mpz_clear(u2); omFree((ADDRESS)u2);
410  mpz_clear(v);  omFree((ADDRESS)v);
411  mpz_clear(v0); omFree((ADDRESS)v0);
412  mpz_clear(v1); omFree((ADDRESS)v1);
413  mpz_clear(v2); omFree((ADDRESS)v2);
414  mpz_clear(q); omFree((ADDRESS)q);
415  mpz_clear(rr); omFree((ADDRESS)rr);
416}
417
418NATNUMBER InvMod(NATNUMBER a, const coeffs r)
419{
420  assume((NATNUMBER)a % 2 != 0);
421  unsigned long s;
422  specialXGCD(s, a, r);
423  return s;
424}
425//#endif
426
427inline number nr2mInversM(number c, const coeffs r)
428{
429  assume((NATNUMBER)c % 2 != 0);
430  // Table !!!
431  NATNUMBER inv;
432  inv = InvMod((NATNUMBER)c,r);
433  return (number)inv;
434}
435
436number nr2mDiv(number a, number b, const coeffs r)
437{
438  if ((NATNUMBER)a == 0) return (number)0;
439  else if ((NATNUMBER)b % 2 == 0)
440  {
441    if ((NATNUMBER)b != 0)
442    {
443      while (((NATNUMBER)b % 2 == 0) && ((NATNUMBER)a % 2 == 0))
444      {
445        a = (number)((NATNUMBER)a / 2);
446        b = (number)((NATNUMBER)b / 2);
447      }
448    }
449    if ((NATNUMBER)b % 2 == 0)
450    {
451      WerrorS("Division not possible, even by cancelling zero divisors.");
452      WerrorS("Result is integer division without remainder.");
453      return (number) ((NATNUMBER) a / (NATNUMBER) b);
454    }
455  }
456  return (number)nr2mMult(a, nr2mInversM(b,r),r);
457}
458
459number nr2mMod(number a, number b, const coeffs r)
460{
461  /*
462    We need to return the number rr which is uniquely determined by the
463    following two properties:
464      (1) 0 <= rr < |b| (with respect to '<' and '<=' performed in Z x Z)
465      (2) There exists some k in the integers Z such that a = k * b + rr.
466    Consider g := gcd(2^m, |b|). Note that then |b|/g is a unit in Z/2^m.
467    Now, there are three cases:
468      (a) g = 1
469          Then |b| is a unit in Z/2^m, i.e. |b| (and also b) divides a.
470          Thus rr = 0.
471      (b) g <> 1 and g divides a
472          Then a = (a/g) * (|b|/g)^(-1) * b (up to sign), i.e. again rr = 0.
473      (c) g <> 1 and g does not divide a
474          Let's denote the division with remainder of a by g as follows:
475          a = s * g + t. Then t = a - s * g = a - s * (|b|/g)^(-1) * |b|
476          fulfills (1) and (2), i.e. rr := t is the correct result. Hence
477          in this third case, rr is the remainder of division of a by g in Z.
478    This algorithm is the same as for the case Z/n, except that we may
479    compute the gcd of |b| and 2^m "by hand": We just extract the highest
480    power of 2 (<= 2^m) that is contained in b.
481  */
482  assume((NATNUMBER) b != 0);
483  NATNUMBER g = 1;
484  NATNUMBER b_div = (NATNUMBER) b;
485
486  /*
487   * b_div is unsigned, so that (b_div < 0) evaluates false at compile-time
488   *
489  if (b_div < 0) b_div = -b_div; // b_div now represents |b|, BUT b_div is unsigned!
490  */
491
492  NATNUMBER rr = 0;
493  while ((g < r->mod2mMask ) && (b_div > 0) && (b_div % 2 == 0))
494  {
495    b_div = b_div >> 1;
496    g = g << 1;
497  } // g is now the gcd of 2^m and |b|
498
499  if (g != 1) rr = (NATNUMBER)a % g;
500  return (number)rr;
501}
502
503number nr2mIntDiv(number a, number b, const coeffs r)
504{
505  if ((NATNUMBER)a == 0)
506  {
507    if ((NATNUMBER)b == 0)
508      return (number)1;
509    if ((NATNUMBER)b == 1)
510      return (number)0;
511    NATNUMBER c = r->mod2mMask + 1;
512    if (c != 0) /* i.e., if no overflow */
513      return (number)(c / (NATNUMBER)b);
514    else
515    {
516      /* overflow: c = 2^32 resp. 2^64, depending on platform */
517      int_number cc = (int_number)omAlloc(sizeof(mpz_t));
518      mpz_init_set_ui(cc, r->mod2mMask); mpz_add_ui(cc, cc, 1);
519      mpz_div_ui(cc, cc, (unsigned long)(NATNUMBER)b);
520      unsigned long s = mpz_get_ui(cc);
521      mpz_clear(cc); omFree((ADDRESS)cc);
522      return (number)(NATNUMBER)s;
523    }
524  }
525  else
526  {
527    if ((NATNUMBER)b == 0)
528      return (number)0;
529    return (number)((NATNUMBER) a / (NATNUMBER) b);
530  }
531}
532
533number nr2mInvers(number c, const coeffs r)
534{
535  if ((NATNUMBER)c % 2 == 0)
536  {
537    WerrorS("division by zero divisor");
538    return (number)0;
539  }
540  return nr2mInversM(c, r);
541}
542
543number nr2mNeg(number c, const coeffs r)
544{
545  if ((NATNUMBER)c == 0) return c;
546  return nr2mNegM(c, r);
547}
548
549number nr2mMapMachineInt(number from, const coeffs /*src*/, const coeffs dst)
550{
551  NATNUMBER i = ((NATNUMBER)from) % dst->mod2mMask ;
552  return (number)i;
553}
554
555number nr2mMapZp(number from, const coeffs /*src*/, const coeffs dst)
556{
557  NATNUMBER j = (NATNUMBER)1;
558  long ii = (long)from;
559  if (ii < 0) { j = dst->mod2mMask; ii = -ii; }
560  NATNUMBER i = (NATNUMBER)ii;
561  i = i & dst->mod2mMask;
562  /* now we have: from = j * i mod 2^m */
563  return (number)nr2mMult((number)i, (number)j, dst);
564}
565
566number nr2mMapQ(number from, const coeffs src, const coeffs dst)
567{
568  int_number erg = (int_number)omAllocBin(gmp_nrz_bin);
569  mpz_init(erg);
570  int_number k = (int_number)omAlloc(sizeof(mpz_t));
571  mpz_init_set_ui(k, dst->mod2mMask);
572
573  nlGMP(from, (number)erg, src);
574  mpz_and(erg, erg, k);
575  number res = (number)mpz_get_ui(erg);
576
577  mpz_clear(erg); omFree((ADDRESS)erg);
578  mpz_clear(k);   omFree((ADDRESS)k);
579
580  return (number)res;
581}
582
583number nr2mMapGMP(number from, const coeffs /*src*/, const coeffs dst)
584{
585  int_number erg = (int_number)omAllocBin(gmp_nrz_bin);
586  mpz_init(erg);
587  int_number k = (int_number)omAlloc(sizeof(mpz_t));
588  mpz_init_set_ui(k, dst->mod2mMask);
589
590  mpz_and(erg, (int_number)from, k);
591  number res = (number) mpz_get_ui(erg);
592
593  mpz_clear(erg); omFree((ADDRESS)erg);
594  mpz_clear(k);   omFree((ADDRESS)k);
595
596  return (number)res;
597}
598
599nMapFunc nr2mSetMap(const coeffs src, const coeffs dst)
600{
601  if (nCoeff_is_Ring_2toM(src)
602     && (src->mod2mMask == dst->mod2mMask))
603  {
604    return ndCopyMap;
605  }
606  if (nCoeff_is_Ring_2toM(src)
607     && (src->mod2mMask < dst->mod2mMask))
608  { /* i.e. map an integer mod 2^s into Z mod 2^t, where t < s */
609    return nr2mMapMachineInt;
610  }
611  if (nCoeff_is_Ring_2toM(src)
612     && (src->mod2mMask > dst->mod2mMask))
613  { /* i.e. map an integer mod 2^s into Z mod 2^t, where t > s */
614    // to be done
615  }
616  if (nCoeff_is_Ring_Z(src))
617  {
618    return nr2mMapGMP;
619  }
620  if (nCoeff_is_Q(src))
621  {
622    return nr2mMapQ;
623  }
624  if (nCoeff_is_Zp(src) && (src->ch == 2))
625  {
626    return nr2mMapZp;
627  }
628  if (nCoeff_is_Ring_PtoM(src) || nCoeff_is_Ring_ModN(src))
629  {
630    if (mpz_divisible_2exp_p(src->modNumber,dst->modExponent))
631      return nr2mMapGMP;
632  }
633  return NULL;      // default
634}
635
636/*
637 * set the exponent
638 */
639
640void nr2mSetExp(int m, coeffs r)
641{
642  if (m > 1)
643  {
644    /* we want mod2mMask to be the bit pattern
645       '111..1' consisting of m one's: */
646    r->modExponent= m;
647    r->mod2mMask = 1;
648    for (int i = 1; i < m; i++) r->mod2mMask = (r->mod2mMask << 1) + 1;
649  }
650  else
651  {
652    r->modExponent= 2;
653    /* code unexpectedly called with m = 1; we continue with m = 2: */
654    r->mod2mMask = 3; /* i.e., '11' in binary representation */
655  }
656}
657
658void nr2mInitExp(int m, coeffs r)
659{
660  nr2mSetExp(m, r);
661  if (m < 2)
662    WarnS("nr2mInitExp unexpectedly called with m = 1 (we continue with Z/2^2");
663}
664
665#ifdef LDEBUG
666BOOLEAN nr2mDBTest (number a, const char *, const int, const coeffs r)
667{
668  //if ((NATNUMBER)a < 0) return FALSE; // is unsigned!
669  if (((NATNUMBER)a & r->mod2mMask) != (NATNUMBER)a) return FALSE;
670  return TRUE;
671}
672#endif
673
674void nr2mWrite (number &a, const coeffs r)
675{
676  long i = nr2mLong(a, r);
677  StringAppend("%ld", i);
678}
679
680static const char* nr2mEati(const char *s, int *i, const coeffs r)
681{
682
683  if (((*s) >= '0') && ((*s) <= '9'))
684  {
685    (*i) = 0;
686    do
687    {
688      (*i) *= 10;
689      (*i) += *s++ - '0';
690      if ((*i) >= (MAX_INT_VAL / 10)) (*i) = (*i) & r->mod2mMask;
691    }
692    while (((*s) >= '0') && ((*s) <= '9'));
693    (*i) = (*i) & r->mod2mMask;
694  }
695  else (*i) = 1;
696  return s;
697}
698
699const char * nr2mRead (const char *s, number *a, const coeffs r)
700{
701  int z;
702  int n=1;
703
704  s = nr2mEati(s, &z,r);
705  if ((*s) == '/')
706  {
707    s++;
708    s = nr2mEati(s, &n,r);
709  }
710  if (n == 1)
711    *a = (number)z;
712  else
713      *a = nr2mDiv((number)z,(number)n,r);
714  return s;
715}
716#endif
717/* #ifdef HAVE_RINGS */
Note: See TracBrowser for help on using the repository browser.