source: git/coeffs/modulop.cc @ 7d90aa

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