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

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