source: git/libpolys/coeffs/rmodulo2m.cc @ 12e275

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