source: git/kernel/modulop.cc @ 603aebf

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