source: git/libpolys/coeffs/rmodulo2m.cc @ f0af17

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