source: git/libpolys/coeffs/rmodulo2m.cc @ 6bf3eb

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