source: git/kernel/modulop.cc @ fd07a15

spielwiese
Last change on this file since fd07a15 was fd07a15, checked in by Hans Schönemann <hannes@…>, 18 years ago
*hannes: NV_OPS init stuff git-svn-id: file:///usr/local/Singular/svn/trunk@8420 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.2 2005-07-05 16:32:33 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) 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)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)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#ifdef NV_OPS
315  if (r->cf->npPrimeM >NV_MAX_PRIME) return;
316#endif
317  {
318//  if (c==npPrimeM) return;
319  if ((c>1) || (c<(-1)))
320  {
321    if (c>1) npPrimeM = c;
322    else     npPrimeM = -c;
323    npPminus1M = npPrimeM - 1;
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,iz,in;
438  mp_ptr qp,dd,nn;
439
440  size = (*f)[0]._mp_size;
441  if (size == 0)
442    return npInit(0);
443  if(size<0)
444    size = -size;
445
446  qp = (*f)[0]._mp_d;
447  while(qp[0]==0)
448  {
449    qp++;
450    size--;
451  }
452
453  if(npPrimeM>2)
454    e=(*f)[0]._mp_exp-size;
455  else
456    e=0;
457  res = (number)omAllocBin(rnumber_bin);
458#if defined(LDEBUG)
459  res->debug=123456;
460#endif
461  dest = &(res->z);
462
463  if (e<0)
464  {
465    al = dest->_mp_size = size;
466    if (al<2) al = 2;
467    dd = (mp_ptr)omAlloc(sizeof(mp_limb_t)*al);
468    for (i=0;i<size;i++) dd[i] = qp[i];
469    bl = 1-e;
470    nn = (mp_ptr)omAlloc(sizeof(mp_limb_t)*bl);
471    nn[bl-1] = 1;
472    for (i=bl-2;i>=0;i--) nn[i] = 0;
473    ndest = &(res->n);
474    ndest->_mp_d = nn;
475    ndest->_mp_alloc = ndest->_mp_size = bl;
476    res->s = 0;
477    in=mpz_mmod_ui(NULL,ndest,npPrimeM);
478    mpz_clear(ndest);
479  }
480  else
481  {
482    al = dest->_mp_size = size+e;
483    if (al<2) al = 2;
484    dd = (mp_ptr)omAlloc(sizeof(mp_limb_t)*al);
485    for (i=0;i<size;i++) dd[i+e] = qp[i];
486    for (i=0;i<e;i++) dd[i] = 0;
487    res->s = 3;
488  }
489
490  dest->_mp_d = dd;
491  dest->_mp_alloc = al;
492  iz=mpz_mmod_ui(NULL,dest,npPrimeM);
493  mpz_clear(dest);
494  omFreeBin((ADDRESS)res, rnumber_bin);
495  if(res->s==0)
496    iz=(int)npDiv((number)iz,(number)in);
497  return (number)iz;
498}
499
500nMapFunc npSetMap(ring src, ring dst)
501{
502  if (rField_is_Q(src))
503  {
504    return npMap0;
505  }
506  if ( rField_is_Zp(src) )
507  {
508    if (rChar(src) == rChar(dst))
509    {
510      return ndCopy;
511    }
512    else
513    {
514      npMapPrime=rChar(src);
515      return npMapP;
516    }
517  }
518  if (rField_is_long_R(src))
519  {
520    return npMapLongR;
521  }
522  return NULL;      /* default */
523}
524
525// -----------------------------------------------------------
526//  operation for very large primes (32003< p < 2^31-1)
527// ----------------------------------------------------------
528#ifdef NV_OPS
529
530number nvMult (number a,number b)
531{
532  if (((long)a == 0) || ((long)b == 0))
533    return (number)0;
534  else
535    return nvMultM(a,b);
536}
537
538long nvInvMod(long a)
539{
540   long  s, t;
541
542   long  u, v, u0, v0, u1, v1, u2, v2, q, r;
543
544   u1=1; v1=0;
545   u2=0; v2=1;
546   u = a; v = npPrimeM;
547
548   while (v != 0) {
549      q = u / v;
550      r = u % v;
551      u = v;
552      v = r;
553      u0 = u2;
554      v0 = v2;
555      u2 =  u1 - q*u2;
556      v2 = v1- q*v2;
557      u1 = u0;
558      v1 = v0;
559   }
560
561   s = u1;
562   //t = v1;
563   if (s < 0)
564      return s + npPrimeM;
565   else
566      return s;
567}
568
569inline number nvInversM (number c)
570{
571  long inv=nvInvMod((long)c);
572  return (number)inv;
573}
574
575number nvDiv (number a,number b)
576{
577  if ((long)a==0)
578    return (number)0;
579  else if ((long)b==0)
580  {
581    WerrorS("div by 0");
582    return (number)0;
583  }
584  else
585  {
586    number inv=nvInversM(b);
587    return nvMultM(a,inv);
588  }
589}
590number  nvInvers (number c)
591{
592  if ((long)c==0)
593  {
594    WerrorS("1/0");
595    return (number)0;
596  }
597  return nvInversM(c);
598}
599#endif
Note: See TracBrowser for help on using the repository browser.