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

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