source: git/kernel/modulop.cc @ 7447d8

spielwiese
Last change on this file since 7447d8 was 7447d8, checked in by Hans Schönemann <hannes@…>, 19 years ago
*hannes: gcc 4 and 64bit git-svn-id: file:///usr/local/Singular/svn/trunk@8463 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 10.2 KB
Line 
1/****************************************
2*  Computer Algebra System SINGULAR     *
3****************************************/
4/* $Id: modulop.cc,v 1.5 2005-07-27 15:48:29 Singular Exp $ */
5/*
6* ABSTRACT: numbers modulo p (<=32003)
7*/
8
9#include <string.h>
10#include "mod2.h"
11#include <mylimits.h>
12#include "structs.h"
13#include "febase.h"
14#include "omalloc.h"
15#include "numbers.h"
16#include "longrat.h"
17#include "mpr_complex.h"
18#include "ring.h"
19#include "modulop.h"
20
21long npPrimeM=0;
22int npGen=0;
23long npPminus1M=0;
24long npMapPrime;
25
26#ifdef HAVE_DIV_MOD
27CARDINAL *npInvTable=NULL;
28#endif
29
30#if !defined(HAVE_DIV_MOD) || !defined(HAVE_MULT_MOD)
31CARDINAL *npExpTable=NULL;
32CARDINAL *npLogTable=NULL;
33#endif
34
35
36BOOLEAN npGreaterZero (number k)
37{
38  int h = (int)((long) k);
39  return ((int)h !=0) && (h <= (npPrimeM>>1));
40}
41
42//unsigned long npMultMod(unsigned long a, unsigned long b)
43//{
44//  unsigned long c = a*b;
45//  c = c % npPrimeM;
46//  assume(c == (unsigned long) npMultM((number) a, (number) b));
47//  return c;
48//}
49
50number npMult (number a,number b)
51{
52  if (((long)a == 0) || ((long)b == 0))
53    return (number)0;
54  else
55    return npMultM(a,b);
56}
57
58/*2
59* create a number from int
60*/
61number npInit (int i)
62{
63  long ii=i;
64  while (ii <  0)                    ii += npPrimeM;
65  while ((ii>1) && (ii >= npPrimeM)) ii -= npPrimeM;
66  return (number)ii;
67}
68
69/*2
70* convert a number to int (-p/2 .. p/2)
71*/
72int npInt(number &n)
73{
74  if ((long)n > (npPrimeM >>1)) return (int)((long)n -npPrimeM);
75  else                          return (int)((long)n);
76}
77
78number npAdd (number a, number b)
79{
80  return npAddM(a,b);
81}
82
83number npSub (number a, number b)
84{
85  return npSubM(a,b);
86}
87
88BOOLEAN npIsZero (number  a)
89{
90  return 0 == (long)a;
91}
92
93BOOLEAN npIsOne (number a)
94{
95  return 1 == (long)a;
96}
97
98BOOLEAN npIsMOne (number a)
99{
100  return ((npPminus1M == (long)a)&&((long)1!=(long)a));
101}
102
103#ifdef HAVE_DIV_MOD
104#if 1 //ifdef HAVE_NTL // in ntl.a
105//extern void XGCD(long& d, long& s, long& t, long a, long b);
106#include <NTL/ZZ.h>
107#ifdef NTL_CLIENT
108NTL_CLIENT
109#endif
110#else
111void XGCD(long& d, long& s, long& t, long a, long b)
112{
113   long  u, v, u0, v0, u1, v1, u2, v2, q, r;
114
115   long aneg = 0, bneg = 0;
116
117   if (a < 0) {
118      a = -a;
119      aneg = 1;
120   }
121
122   if (b < 0) {
123      b = -b;
124      bneg = 1;
125   }
126
127   u1=1; v1=0;
128   u2=0; v2=1;
129   u = a; v = b;
130
131   while (v != 0) {
132      q = u / v;
133      r = u % v;
134      u = v;
135      v = r;
136      u0 = u2;
137      v0 = v2;
138      u2 =  u1 - q*u2;
139      v2 = v1- q*v2;
140      u1 = u0;
141      v1 = v0;
142   }
143
144   if (aneg)
145      u1 = -u1;
146
147   if (bneg)
148      v1 = -v1;
149
150   d = u;
151   s = u1;
152   t = v1;
153}
154#endif
155
156long InvMod(long a)
157{
158   long d, s, t;
159
160   XGCD(d, s, t, a, npPrimeM);
161   assume (d == 1);
162   if (s < 0)
163      return s + npPrimeM;
164   else
165      return s;
166}
167#endif
168
169inline number npInversM (number c)
170{
171#ifndef HAVE_DIV_MOD
172  return (number)npExpTable[npPminus1M - npLogTable[(long)c]];
173#else
174  long inv=npInvTable[(long)c];
175  if (inv==0)
176  {
177    inv=InvMod((long)c);
178    npInvTable[(long)c]=inv;
179  }
180  return (number)inv;
181#endif
182}
183
184number npDiv (number a,number b)
185{
186  if ((long)a==0)
187    return (number)0;
188#ifndef HAVE_DIV_MOD
189  else if ((long)b==0)
190  {
191    WerrorS("div by 0");
192    return (number)0;
193  }
194  else
195  {
196    int s = npLogTable[(long)a] - npLogTable[(long)b];
197    if (s < 0)
198      s += npPminus1M;
199    return (number)npExpTable[s];
200  }
201#else
202  number inv=npInversM(b);
203  return npMultM(a,inv);
204#endif
205}
206number  npInvers (number c)
207{
208  if ((long)c==0)
209  {
210    WerrorS("1/0");
211    return (number)0;
212  }
213  return npInversM(c);
214}
215
216number npNeg (number c)
217{
218  if ((long)c==0) return c;
219  return npNegM(c);
220}
221
222BOOLEAN npGreater (number a,number b)
223{
224  //return (long)a != (long)b;
225  return (long)a > (long)b;
226}
227
228BOOLEAN npEqual (number a,number b)
229{
230//  return (long)a == (long)b;
231  return npEqualM(a,b);
232}
233
234void npWrite (number &a)
235{
236  if ((long)a > (npPrimeM >>1)) StringAppend("-%d",(int)(npPrimeM-((long)a)));
237  else                          StringAppend("%d",(int)((long)a));
238}
239
240void npPower (number a, int i, number * result)
241{
242  if (i==0)
243  {
244    //npInit(1,result);
245    *(long *)result = 1;
246  }
247  else if (i==1)
248  {
249    *result = a;
250  }
251  else
252  {
253    npPower(a,i-1,result);
254    *result = npMultM(a,*result);
255  }
256}
257
258char* npEati(char *s, int *i)
259{
260
261  if (((*s) >= '0') && ((*s) <= '9'))
262  {
263    (*i) = 0;
264    do
265    {
266      (*i) *= 10;
267      (*i) += *s++ - '0';
268      if ((*i) >= (MAX_INT_VAL / 10)) (*i) = (*i) % npPrimeM;
269    }
270    while (((*s) >= '0') && ((*s) <= '9'));
271    if ((*i) >= npPrimeM) (*i) = (*i) % npPrimeM;
272  }
273  else (*i) = 1;
274  return s;
275}
276
277char * npRead (char *s, number *a)
278{
279  int z;
280  int n=1;
281
282  s = npEati(s, &z);
283  if ((*s) == '/')
284  {
285    s++;
286    s = npEati(s, &n);
287  }
288  if (n == 1)
289    *a = (number)z;
290  else 
291#ifdef NV_OPS
292    if (npPrimeM>NV_MAX_PRIME)
293      *a = nvDiv((number)z,(number)n);
294    else
295#endif   
296      *a = npDiv((number)z,(number)n);
297  return s;
298}
299
300/*2
301* the last used charcteristic
302*/
303//int npGetChar()
304//{
305//  return npPrimeM;
306//}
307
308/*2
309* set the charcteristic (allocate and init tables)
310*/
311
312void npSetChar(int c, ring r)
313{
314
315//  if (c==npPrimeM) return;
316  if ((c>1) || (c<(-1)))
317  {
318    if (c>1) npPrimeM = c;
319    else     npPrimeM = -c;
320    npPminus1M = npPrimeM - 1;
321#ifdef NV_OPS
322    if (r->cf->npPrimeM >NV_MAX_PRIME) return;
323#endif
324#ifdef HAVE_DIV_MOD
325    npInvTable=r->cf->npInvTable;
326#endif
327#if !defined(HAVE_DIV_MOD) || !defined(HAVE_MULT_MOD)
328    npExpTable=r->cf->npExpTable;
329    npLogTable=r->cf->npLogTable;
330    npGen = npExpTable[1];
331#endif
332  }
333  else
334  {
335    npPrimeM=0;
336#ifdef HAVE_DIV_MOD
337    npInvTable=NULL;
338#endif
339#if !defined(HAVE_DIV_MOD) || !defined(HAVE_MULT_MOD)
340    npExpTable=NULL;
341    npLogTable=NULL;
342#endif
343  }
344}
345
346void npInitChar(int c, ring r)
347{
348  int i, w;
349
350  if ((c>1) || (c<(-1)))
351  {
352    if (c>1) r->cf->npPrimeM = c;
353    else     r->cf->npPrimeM = -c;
354    r->cf->npPminus1M = r->cf->npPrimeM - 1;
355#ifdef NV_OPS
356    if (r->cf->npPrimeM <=NV_MAX_PRIME)
357#endif
358    {
359#if !defined(HAVE_DIV_MOD) || !defined(HAVE_MULT_MOD)
360      r->cf->npExpTable=(CARDINAL *)omAlloc( r->cf->npPrimeM*sizeof(CARDINAL) );
361      r->cf->npLogTable=(CARDINAL *)omAlloc( r->cf->npPrimeM*sizeof(CARDINAL) );
362      r->cf->npExpTable[0] = 1;
363      r->cf->npLogTable[0] = 0;
364      if (r->cf->npPrimeM > 2)
365      {
366        w = 1;
367        loop
368        {
369          r->cf->npLogTable[1] = 0;
370          w++;
371          i = 0;
372          loop
373          {
374            i++;
375            r->cf->npExpTable[i] =(int)(((long)w * (long)r->cf->npExpTable[i-1])
376                                 % r->cf->npPrimeM);
377            r->cf->npLogTable[r->cf->npExpTable[i]] = i;
378            if (/*(i == npPrimeM - 1 ) ||*/ (r->cf->npExpTable[i] == 1))
379              break;
380          }
381          if (i == r->cf->npPrimeM - 1)
382            break;
383        }
384      }
385      else
386      {
387        r->cf->npExpTable[1] = 1;
388        r->cf->npLogTable[1] = 0;
389      }
390#endif
391#ifdef HAVE_DIV_MOD
392      r->cf->npInvTable=(CARDINAL*)omAlloc0( r->cf->npPrimeM*sizeof(CARDINAL) );
393#endif
394    }
395  }
396  else
397  {
398    WarnS("nInitChar failed");
399  }
400}
401
402#ifdef LDEBUG
403BOOLEAN npDBTest (number a, char *f, int l)
404{
405  if (((long)a<0) || ((long)a>npPrimeM))
406  {
407    return FALSE;
408  }
409  return TRUE;
410}
411#endif
412
413number npMap0(number from)
414{
415  return npInit(nlModP(from,npPrimeM));
416}
417
418number npMapP(number from)
419{
420  long i = (long)from;
421  if (i>npMapPrime/2)
422  {
423    i-=npMapPrime;
424    while (i < 0) i+=npPrimeM;
425  }
426  i%=npPrimeM;
427  return (number)i;
428}
429
430static number npMapLongR(number from)
431{
432  gmp_float *ff=(gmp_float*)from;
433  mpf_t *f=ff->_mpfp();
434  number res;
435  lint *dest,*ndest;
436  int size,i;
437  int e,al,bl,in;
438  long iz;
439  mp_ptr qp,dd,nn;
440
441  size = (*f)[0]._mp_size;
442  if (size == 0)
443    return npInit(0);
444  if(size<0)
445    size = -size;
446
447  qp = (*f)[0]._mp_d;
448  while(qp[0]==0)
449  {
450    qp++;
451    size--;
452  }
453
454  if(npPrimeM>2)
455    e=(*f)[0]._mp_exp-size;
456  else
457    e=0;
458  res = (number)omAllocBin(rnumber_bin);
459#if defined(LDEBUG)
460  res->debug=123456;
461#endif
462  dest = &(res->z);
463
464  if (e<0)
465  {
466    al = dest->_mp_size = size;
467    if (al<2) al = 2;
468    dd = (mp_ptr)omAlloc(sizeof(mp_limb_t)*al);
469    for (i=0;i<size;i++) dd[i] = qp[i];
470    bl = 1-e;
471    nn = (mp_ptr)omAlloc(sizeof(mp_limb_t)*bl);
472    nn[bl-1] = 1;
473    for (i=bl-2;i>=0;i--) nn[i] = 0;
474    ndest = &(res->n);
475    ndest->_mp_d = nn;
476    ndest->_mp_alloc = ndest->_mp_size = bl;
477    res->s = 0;
478    in=mpz_mmod_ui(NULL,ndest,npPrimeM);
479    mpz_clear(ndest);
480  }
481  else
482  {
483    al = dest->_mp_size = size+e;
484    if (al<2) al = 2;
485    dd = (mp_ptr)omAlloc(sizeof(mp_limb_t)*al);
486    for (i=0;i<size;i++) dd[i+e] = qp[i];
487    for (i=0;i<e;i++) dd[i] = 0;
488    res->s = 3;
489  }
490
491  dest->_mp_d = dd;
492  dest->_mp_alloc = al;
493  iz=mpz_mmod_ui(NULL,dest,npPrimeM);
494  mpz_clear(dest);
495  omFreeBin((ADDRESS)res, rnumber_bin);
496  if(res->s==0)
497    iz=(long)npDiv((number)iz,(number)in);
498  return (number)iz;
499}
500
501nMapFunc npSetMap(ring src, ring dst)
502{
503  if (rField_is_Q(src))
504  {
505    return npMap0;
506  }
507  if ( rField_is_Zp(src) )
508  {
509    if (rChar(src) == rChar(dst))
510    {
511      return ndCopy;
512    }
513    else
514    {
515      npMapPrime=rChar(src);
516      return npMapP;
517    }
518  }
519  if (rField_is_long_R(src))
520  {
521    return npMapLongR;
522  }
523  return NULL;      /* default */
524}
525
526// -----------------------------------------------------------
527//  operation for very large primes (32003< p < 2^31-1)
528// ----------------------------------------------------------
529#ifdef NV_OPS
530
531number nvMult (number a,number b)
532{
533  if (((long)a == 0) || ((long)b == 0))
534    return (number)0;
535  else
536    return nvMultM(a,b);
537}
538
539long nvInvMod(long a)
540{
541   long  s, t;
542
543   long  u, v, u0, v0, u1, v1, u2, v2, q, r;
544
545   u1=1; v1=0;
546   u2=0; v2=1;
547   u = a; v = npPrimeM;
548
549   while (v != 0) {
550      q = u / v;
551      r = u % v;
552      u = v;
553      v = r;
554      u0 = u2;
555      v0 = v2;
556      u2 =  u1 - q*u2;
557      v2 = v1- q*v2;
558      u1 = u0;
559      v1 = v0;
560   }
561
562   s = u1;
563   //t = v1;
564   if (s < 0)
565      return s + npPrimeM;
566   else
567      return s;
568}
569
570inline number nvInversM (number c)
571{
572  long inv=nvInvMod((long)c);
573  return (number)inv;
574}
575
576number nvDiv (number a,number b)
577{
578  if ((long)a==0)
579    return (number)0;
580  else if ((long)b==0)
581  {
582    WerrorS("div by 0");
583    return (number)0;
584  }
585  else
586  {
587    number inv=nvInversM(b);
588    return nvMultM(a,inv);
589  }
590}
591number  nvInvers (number c)
592{
593  if ((long)c==0)
594  {
595    WerrorS("1/0");
596    return (number)0;
597  }
598  return nvInversM(c);
599}
600#endif
Note: See TracBrowser for help on using the repository browser.