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

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