source: git/kernel/rmodulo2m.cc @ 0959dc

spielwiese
Last change on this file since 0959dc was 0959dc, checked in by Oliver Wienand <wienand@…>, 16 years ago
Maps getestet git-svn-id: file:///usr/local/Singular/svn/trunk@10864 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 9.9 KB
Line 
1/****************************************
2*  Computer Algebra System SINGULAR     *
3****************************************/
4/* $Id: rmodulo2m.cc,v 1.20 2008-07-15 07:24:10 wienand Exp $ */
5/*
6* ABSTRACT: numbers modulo 2^m
7*/
8
9#include <string.h>
10#include "mod2.h"
11
12#ifdef HAVE_RING2TOM
13#include <mylimits.h>
14#include "structs.h"
15#include "febase.h"
16#include "omalloc.h"
17#include "numbers.h"
18#include "longrat.h"
19#include "mpr_complex.h"
20#include "ring.h"
21#include "rmodulo2m.h"
22#include "gmp.h"
23
24typedef MP_INT *int_number;
25
26int nr2mExp;
27NATNUMBER nr2mModul;
28
29/*
30 * Multiply two numbers
31 */
32number nr2mMult (number a,number b)
33{
34  if (((NATNUMBER)a == 0) || ((NATNUMBER)b == 0))
35    return (number)0;
36  else
37    return nr2mMultM(a,b);
38}
39
40/*
41 * Give the smallest non unit k, such that a * x = k = b * y has a solution
42 */
43number nr2mLcm (number a,number b,ring r)
44{
45  NATNUMBER res = 0;
46  if ((NATNUMBER) a == 0) a = (number) 1;
47  if ((NATNUMBER) b == 0) b = (number) 1;
48  while ((NATNUMBER) a % 2 == 0)
49  {
50    a = (number) ((NATNUMBER) a / 2);
51    if ((NATNUMBER) b % 2 == 0) b = (number) ((NATNUMBER) b / 2);
52    res++;
53  }
54  while ((NATNUMBER) b % 2 == 0)
55  {
56    b = (number) ((NATNUMBER) b / 2);
57    res++;
58  }
59  return (number) (1L << res);  // (2**res)
60}
61
62/*
63 * Give the largest non unit k, such that a = x * k, b = y * k has
64 * a solution.
65 */
66number nr2mGcd (number a,number b,ring r)
67{
68  NATNUMBER res = 0;
69  if ((NATNUMBER) a == 0 && (NATNUMBER) b == 0) return (number) 1;
70  while ((NATNUMBER) a % 2 == 0 && (NATNUMBER) b % 2 == 0)
71  {
72    a = (number) ((NATNUMBER) a / 2);
73    b = (number) ((NATNUMBER) b / 2);
74    res++;
75  }
76//  if ((NATNUMBER) b % 2 == 0)
77//  {
78//    return (number) ((1L << res));// * (NATNUMBER) a);  // (2**res)*a    a ist Einheit
79//  }
80//  else
81//  {
82    return (number) ((1L << res));// * (NATNUMBER) b);  // (2**res)*b    b ist Einheit
83//  }
84}
85
86/*
87 * Give the largest non unit k, such that a = x * k, b = y * k has
88 * a solution.
89 */
90number nr2mExtGcd (number a, number b, number *s, number *t)
91{
92  NATNUMBER res = 0;
93  if ((NATNUMBER) a == 0 && (NATNUMBER) b == 0) return (number) 1;
94  while ((NATNUMBER) a % 2 == 0 && (NATNUMBER) b % 2 == 0)
95  {
96    a = (number) ((NATNUMBER) a / 2);
97    b = (number) ((NATNUMBER) b / 2);
98    res++;
99  }
100  if ((NATNUMBER) b % 2 == 0)
101  {
102    *t = NULL;
103    *s = nr2mInvers(a);
104    return (number) ((1L << res));// * (NATNUMBER) a);  // (2**res)*a    a ist Einheit
105  }
106  else
107  {
108    *s = NULL;
109    *t = nr2mInvers(b);
110    return (number) ((1L << res));// * (NATNUMBER) b);  // (2**res)*b    b ist Einheit
111  }
112}
113
114void nr2mPower (number a, int i, number * result)
115{
116  if (i==0)
117  {
118    //npInit(1,result);
119    *(NATNUMBER *)result = 1;
120  }
121  else if (i==1)
122  {
123    *result = a;
124  }
125  else
126  {
127    nr2mPower(a,i-1,result);
128    *result = nr2mMultM(a,*result);
129  }
130}
131
132/*
133 * create a number from int
134 */
135number nr2mInit (int i)
136{
137  long ii = i;
138  while (ii < 0) ii += nr2mModul;
139  while ((ii>1) && (ii >= nr2mModul)) ii -= nr2mModul;
140  return (number) ii;
141}
142
143/*
144 * convert a number to int (-p/2 .. p/2)
145 */
146int nr2mInt(number &n)
147{
148  if ((NATNUMBER)n > (nr2mModul >>1)) return (int)((NATNUMBER)n - nr2mModul);
149  else return (int)((NATNUMBER)n);
150}
151
152number nr2mAdd (number a, number b)
153{
154  return nr2mAddM(a,b);
155}
156
157number nr2mSub (number a, number b)
158{
159  return nr2mSubM(a,b);
160}
161
162BOOLEAN nr2mIsUnit (number a)
163{
164  return ((NATNUMBER) a % 2 == 1);
165}
166
167number  nr2mGetUnit (number k)
168{
169  if (k == NULL) 
170    return (number) 1;
171  NATNUMBER tmp = (NATNUMBER) k;
172  while (tmp % 2 == 0)
173    tmp = tmp / 2;
174  return (number) tmp;
175}
176
177BOOLEAN nr2mIsZero (number  a)
178{
179  return 0 == (NATNUMBER)a;
180}
181
182BOOLEAN nr2mIsOne (number a)
183{
184  return 1 == (NATNUMBER)a;
185}
186
187BOOLEAN nr2mIsMOne (number a)
188{
189  return (nr2mModul == (NATNUMBER)a + 1) && (nr2mModul != 2);
190}
191
192BOOLEAN nr2mEqual (number a,number b)
193{
194  return nr2mEqualM(a,b);
195}
196
197BOOLEAN nr2mGreater (number a,number b)
198{
199  return nr2mDivBy(a, b);
200}
201
202BOOLEAN nr2mDivBy (number a,number b)
203{
204  if (a == NULL)
205    return (nr2mModul % (NATNUMBER) b) == 0;
206  else
207    return ((NATNUMBER) a % (NATNUMBER) b) == 0;
208  /*
209  if ((NATNUMBER) a == 0) return TRUE;
210  if ((NATNUMBER) b == 0) return FALSE;
211  while ((NATNUMBER) a % 2 == 0 && (NATNUMBER) b % 2 == 0)
212  {
213    a = (number) ((NATNUMBER) a / 2);
214    b = (number) ((NATNUMBER) b / 2);
215}
216  return ((NATNUMBER) b % 2 == 1);
217  */
218}
219
220int nr2mDivComp(number as, number bs)
221{
222  NATNUMBER a = (NATNUMBER) as;
223  NATNUMBER b = (NATNUMBER) bs;
224  assume(a != 0 && b != 0);
225  while (a % 2 == 0 && b % 2 == 0)
226  {
227    a = a / 2;
228    b = b / 2;
229  }
230  if (a % 2 == 0)
231  {
232    return -1;
233  }
234  else
235  {
236    if (b % 2 == 1)
237    {
238      return 0;
239    }
240    else
241    {
242      return 1;
243    }
244  }
245}
246
247BOOLEAN nr2mGreaterZero (number k)
248{
249  return ((NATNUMBER) k !=0) && ((NATNUMBER) k <= (nr2mModul>>1));
250}
251
252//#ifdef HAVE_DIV_MOD
253#if 1 //ifdef HAVE_NTL // in ntl.a
254//extern void XGCD(long& d, long& s, long& t, long a, long b);
255#include <NTL/ZZ.h>
256#ifdef NTL_CLIENT
257NTL_CLIENT
258#endif
259#else
260void XGCD(long& d, long& s, long& t, long a, long b)
261{
262   long  u, v, u0, v0, u1, v1, u2, v2, q, r;
263
264   long aneg = 0, bneg = 0;
265
266   if (a < 0) {
267      a = -a;
268      aneg = 1;
269   }
270
271   if (b < 0) {
272      b = -b;
273      bneg = 1;
274   }
275
276   u1=1; v1=0;
277   u2=0; v2=1;
278   u = a; v = b;
279
280   while (v != 0) {
281      q = u / v;
282      r = u % v;
283      u = v;
284      v = r;
285      u0 = u2;
286      v0 = v2;
287      u2 =  u1 - q*u2;
288      v2 = v1- q*v2;
289      u1 = u0;
290      v1 = v0;
291   }
292
293   if (aneg)
294      u1 = -u1;
295
296   if (bneg)
297      v1 = -v1;
298
299   d = u;
300   s = u1;
301   t = v1;
302}
303#endif
304
305NATNUMBER InvMod(NATNUMBER a)
306{
307   long d, s, t;
308
309   XGCD(d, s, t, a, nr2mModul);
310   assume (d == 1);
311   if (s < 0)
312      return s + nr2mModul;
313   else
314      return s;
315}
316//#endif
317
318inline number nr2mInversM (number c)
319{
320  // Table !!!
321  NATNUMBER inv;
322  inv = InvMod((NATNUMBER)c);
323  return (number) inv;
324}
325
326number nr2mDiv (number a,number b)
327{
328  if ((NATNUMBER)a==0)
329    return (number)0;
330  else if ((NATNUMBER)b%2==0)
331  {
332    if ((NATNUMBER)b != 0)
333    {
334      while ((NATNUMBER) b%2 == 0 && (NATNUMBER) a%2 == 0)
335      {
336        a = (number) ((NATNUMBER) a / 2);
337        b = (number) ((NATNUMBER) b / 2);
338      }
339    }
340    if ((NATNUMBER) b%2 == 0)
341    {
342      WerrorS("div by zero divisor");
343      return (number)0;
344    }
345  }
346  return (number) nr2mMult(a, nr2mInversM(b));
347}
348
349number nr2mIntDiv (number a,number b)
350{
351  if ((NATNUMBER)a==0)
352  {
353    if ((NATNUMBER)b==0)
354      return (number) 1;
355    if ((NATNUMBER)b==1)
356      return (number) 0;
357    return (number) (nr2mModul / (NATNUMBER) b);
358  }
359  else
360  {
361    if ((NATNUMBER)b==0)
362      return (number) 0;
363    return (number) ((NATNUMBER) a / (NATNUMBER) b);
364  }
365}
366
367number  nr2mInvers (number c)
368{
369  if ((NATNUMBER)c%2==0)
370  {
371    WerrorS("division by zero divisor");
372    return (number)0;
373  }
374  return nr2mInversM(c);
375}
376
377number nr2mNeg (number c)
378{
379  if ((NATNUMBER)c==0) return c;
380  return nr2mNegM(c);
381}
382
383number nr2mMapMachineInt(number from)
384{
385  NATNUMBER i = ((NATNUMBER) from) % nr2mModul;
386  return (number) i;
387}
388
389number nr2mMapZp(number from)
390{
391  long ii = (long) from;
392  while (ii < 0) ii += nr2mModul;
393  while ((ii>1) && (ii >= nr2mModul)) ii -= nr2mModul;
394  return (number) ii;
395}
396
397number nr2mMapQ(number from)
398{
399  int_number erg = (int_number) omAlloc(sizeof(MP_INT)); // evtl. spaeter mit bin
400  mpz_init(erg);
401
402  nlGMP(from, (number) erg);
403  mpz_mod_ui(erg, erg, nr2mModul);
404  number r = (number) mpz_get_ui(erg);
405
406  mpz_clear(erg);
407  omFree((ADDRESS) erg);
408  return (number) r;
409}
410
411number nr2mMapGMP(number from)
412{
413  int_number erg = (int_number) omAlloc(sizeof(MP_INT)); // evtl. spaeter mit bin
414  mpz_init(erg);
415
416  mpz_mod_ui(erg, (int_number) from, nr2mModul);
417  number r = (number) mpz_get_ui(erg);
418
419  mpz_clear(erg);
420  omFree((ADDRESS) erg);
421  return (number) r;
422}
423
424nMapFunc nr2mSetMap(ring src, ring dst)
425{
426  if (rField_is_Ring_2toM(src)
427     && (src->ringflagb >= dst->ringflagb))
428  {
429    return nr2mMapMachineInt;
430  }
431  if (rField_is_Ring_Z(src))
432  {
433    return nr2mMapGMP;
434  }
435  if (rField_is_Q(src))
436  {
437    return nr2mMapQ;
438  }
439  if (rField_is_Zp(src)
440     && (src->ch == 2)
441     && (dst->ringflagb == 1))
442  {
443    return nr2mMapZp;
444  }
445  if (rField_is_Ring_PtoM(src) || rField_is_Ring_ModN(src))
446  {
447    // Computing the n of Z/n
448    int_number modul = (int_number) omAlloc(sizeof(MP_INT)); // evtl. spaeter mit bin
449    mpz_init(modul);
450    mpz_set_ui(modul, src->ringflaga);
451    mpz_pow_ui(modul, modul, src->ringflagb);
452    if (mpz_divisible_2exp_p(modul, dst->ringflagb))
453    {
454      mpz_clear(modul);
455      omFree((ADDRESS) modul);
456      return nr2mMapGMP;
457    }
458    mpz_clear(modul);
459    omFree((ADDRESS) modul);
460  }
461  return NULL;      // default
462}
463
464/*
465 * set the exponent (allocate and init tables) (TODO)
466 */
467
468void nr2mSetExp(int m, ring r)
469{
470  if (m>1)
471  {
472    nr2mExp = m;
473    nr2mModul = 2;
474    for (int i = 1; i < m; i++) {
475      nr2mModul = nr2mModul * 2;
476    }
477  }
478  else
479  {
480    nr2mExp=2;
481    nr2mModul=4;
482  }
483}
484
485void nr2mInitExp(int m, ring r)
486{
487  nr2mSetExp(m, r);
488  if (m<2) WarnS("nInitExp failed: using Z/2^2");
489}
490
491#ifdef LDEBUG
492BOOLEAN nr2mDBTest (number a, const char *f, const int l)
493{
494  if (((NATNUMBER)a<0) || ((NATNUMBER)a>nr2mModul))
495  {
496    return FALSE;
497  }
498  return TRUE;
499}
500#endif
501
502void nr2mWrite (number &a)
503{
504  if ((NATNUMBER)a > (nr2mModul >>1)) StringAppend("-%d",(int)(nr2mModul-((NATNUMBER)a)));
505  else                          StringAppend("%d",(int)((NATNUMBER)a));
506}
507
508static const char* nr2mEati(const char *s, int *i)
509{
510
511  if (((*s) >= '0') && ((*s) <= '9'))
512  {
513    (*i) = 0;
514    do
515    {
516      (*i) *= 10;
517      (*i) += *s++ - '0';
518      if ((*i) >= (MAX_INT_VAL / 10)) (*i) = (*i) % nr2mModul;
519    }
520    while (((*s) >= '0') && ((*s) <= '9'));
521    if ((*i) >= nr2mModul) (*i) = (*i) % nr2mModul;
522  }
523  else (*i) = 1;
524  return s;
525}
526
527const char * nr2mRead (const char *s, number *a)
528{
529  int z;
530  int n=1;
531
532  s = nr2mEati(s, &z);
533  if ((*s) == '/')
534  {
535    s++;
536    s = nr2mEati(s, &n);
537  }
538  if (n == 1)
539    *a = (number)z;
540  else
541      *a = nr2mDiv((number)z,(number)n);
542  return s;
543}
544#endif
Note: See TracBrowser for help on using the repository browser.