source: git/coeffs/modulop.cc @ 2d805a

spielwiese
Last change on this file since 2d805a was 2d805a, checked in by Oleksandr Motsak <motsak@…>, 13 years ago
Fixed to "#include <component/header.h>" (even for config.h!)
  • Property mode set to 100644
File size: 14.0 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/config.h>
11#include <omalloc/omalloc.h>
12#include <coeffs/coeffs.h>
13#include <reporter/reporter.h>
14#include <coeffs/numbers.h>
15#include <coeffs/longrat.h>
16#include <coeffs/mpr_complex.h>
17#include <misc/mylimits.h>
18#include <coeffs/modulop.h>
19#ifdef HAVE_FACTORY
20#include <factory/factory.h>
21#endif
22
23// int npGen=0;
24
25
26#ifdef HAVE_DIV_MOD
27unsigned short *npInvTable=NULL;
28#endif
29
30#if !defined(HAVE_DIV_MOD) || !defined(HAVE_MULT_MOD)
31unsigned short *npExpTable=NULL;
32unsigned short *npLogTable=NULL;
33#endif
34
35
36BOOLEAN npGreaterZero (number k, const coeffs r)
37{
38  int h = (int)((long) k);
39  return ((int)h !=0) && (h <= (r->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, const coeffs r)
51{
52  if (((long)a == 0) || ((long)b == 0))
53    return (number)0;
54  else
55    return npMultM(a,b, r);
56}
57
58/*2
59* create a number from int
60*/
61number npInit (int i, const coeffs r)
62{
63  long ii=i;
64  long p=(long)ABS(r->ch);
65  while (ii <  0L)             ii += p;
66  while ((ii>1L) && (ii >= p)) ii -= p;
67  return (number)ii;
68}
69
70/*2
71* convert a number to int (-p/2 .. p/2)
72*/
73int npInt(number &n, const coeffs r)
74{
75  if ((long)n > (((long)r->ch) >>1)) return (int)((long)n -((long)r->ch));
76  else                               return (int)((long)n);
77}
78
79number npAdd (number a, number b, const coeffs r)
80{
81  return npAddM(a,b, r);
82}
83
84number npSub (number a, number b, const coeffs r)
85{
86  return npSubM(a,b,r);
87}
88
89BOOLEAN npIsZero (number  a, const coeffs r)
90{
91  return 0 == (long)a;
92}
93
94BOOLEAN npIsOne (number a, const coeffs r)
95{
96  return 1 == (long)a;
97}
98
99BOOLEAN npIsMOne (number a, const coeffs r)
100{
101  return ((r->npPminus1M == (long)a)&&((long)1!=(long)a));
102}
103
104#ifdef HAVE_DIV_MOD
105#ifdef USE_NTL_XGCD
106//ifdef HAVE_NTL // in ntl.a
107//extern void XGCD(long& d, long& s, long& t, long a, long b);
108#include <NTL/ZZ.h>
109#ifdef NTL_CLIENT
110NTL_CLIENT
111#endif
112#endif
113
114long InvMod(long a, const coeffs R)
115{
116   long d, s, t;
117
118#ifdef USE_NTL_XGCD
119   XGCD(d, s, t, a, R->npPrimeM);
120   assume (d == 1);
121#else
122   long  u, v, u0, v0, u1, v1, u2, v2, q, r;
123
124   assume(a>0);
125   u1=1; u2=0;
126   u = a; v = R->npPrimeM;
127
128   while (v != 0)
129   {
130      q = u / v;
131      r = u % v;
132      u = v;
133      v = r;
134      u0 = u2;
135      u2 = u1 - q*u2;
136      u1 = u0;
137   }
138
139   assume(u==1);
140   s = u1;
141#endif
142   if (s < 0)
143      return s + R->npPrimeM;
144   else
145      return s;
146}
147#endif
148
149inline number npInversM (number c, const coeffs r)
150{
151#ifndef HAVE_DIV_MOD
152  return (number)(long)r->npExpTable[r->npPminus1M - r->npLogTable[(long)c]];
153#else
154  long inv=(long)r->npInvTable[(long)c];
155  if (inv==0)
156  {
157    inv=InvMod((long)c,r);
158    r->npInvTable[(long)c]=inv;
159  }
160  return (number)inv;
161#endif
162}
163
164number npDiv (number a,number b, const coeffs r)
165{
166//#ifdef NV_OPS
167//  if (npPrimeM>NV_MAX_PRIME)
168//    return nvDiv(a,b);
169//#endif
170  if ((long)a==0)
171    return (number)0;
172#ifndef HAVE_DIV_MOD
173  if ((long)b==0)
174  {
175    WerrorS(nDivBy0);
176    return (number)0;
177  }
178  else
179  {
180    int s = r->npLogTable[(long)a] - r->npLogTable[(long)b];
181    if (s < 0)
182      s += r->npPminus1M;
183    return (number)(long)r->npExpTable[s];
184  }
185#else
186  number inv=npInversM(b,r);
187  return npMultM(a,inv,r);
188#endif
189}
190number  npInvers (number c, const coeffs r)
191{
192  if ((long)c==0)
193  {
194    WerrorS("1/0");
195    return (number)0;
196  }
197  return npInversM(c,r);
198}
199
200number npNeg (number c, const coeffs r)
201{
202  if ((long)c==0) return c;
203  return npNegM(c,r);
204}
205
206BOOLEAN npGreater (number a,number b, const coeffs r)
207{
208  //return (long)a != (long)b;
209  return (long)a > (long)b;
210}
211
212BOOLEAN npEqual (number a,number b, const coeffs r)
213{
214//  return (long)a == (long)b;
215  return npEqualM(a,b,r);
216}
217
218void npWrite (number &a, const coeffs r)
219{
220  if ((long)a>(((long)r->ch) >>1)) StringAppend("-%d",(int)(((long)r->ch)-((long)a)));
221  else                             StringAppend("%d",(int)((long)a));
222}
223
224void npPower (number a, int i, number * result, const coeffs r)
225{
226  if (i==0)
227  {
228    //npInit(1,result);
229    *(long *)result = 1;
230  }
231  else if (i==1)
232  {
233    *result = a;
234  }
235  else
236  {
237    npPower(a,i-1,result,r);
238    *result = npMultM(a,*result,r);
239  }
240}
241
242static const char* npEati(const char *s, int *i, const coeffs r)
243{
244
245  if (((*s) >= '0') && ((*s) <= '9'))
246  {
247    unsigned long ii=0L;
248    do
249    {
250      ii *= 10;
251      ii += *s++ - '0';
252      if (ii >= (MAX_INT / 10)) ii = ii % r->npPrimeM;
253    }
254    while (((*s) >= '0') && ((*s) <= '9'));
255    if (ii >= npPrimeM) ii = ii % r->npPrimeM;
256    *i=(int)ii;
257  }
258  else (*i) = 1;
259  return s;
260}
261
262const char * npRead (const char *s, number *a, const coeffs r)
263{
264  int z;
265  int n=1;
266
267  s = npEati(s, &z, r);
268  if ((*s) == '/')
269  {
270    s++;
271    s = npEati(s, &n, r);
272  }
273  if (n == 1)
274    *a = (number)z;
275  else
276  {
277    if ((z==0)&&(n==0)) WerrorS(nDivBy0);
278    else
279    {
280#ifdef NV_OPS
281      if (r->npPrimeM>NV_MAX_PRIME)
282        *a = nvDiv((number)z,(number)n,r);
283      else
284#endif
285        *a = npDiv((number)z,(number)n,r);
286    }
287  }
288  return s;
289}
290
291/*2
292* set the charcteristic (allocate and init tables)
293*/
294
295void npSetChar(const coeffs r)
296{
297#if !defined(HAVE_DIV_MOD) || !defined(HAVE_MULT_MOD)
298//    npGen = npExpTable[1];
299#endif
300}
301
302void npKillChar(coeffs r)
303{
304  #ifdef HAVE_DIV_MOD
305  if (r->npInvTable!=NULL)
306  omFreeSize( (void *)r->npInvTable, r->npPrimeM*sizeof(unsigned short) );
307  r->npInvTable=NULL;
308  #else
309  if (r->npExpTable!=NULL)
310  {
311    omFreeSize( (void *)r->npExpTable, r->npPrimeM*sizeof(unsigned short) );
312    omFreeSize( (void *)r->npLogTable, r->npPrimeM*sizeof(unsigned short) );
313    r->npExpTable=NULL; r->npLogTable=NULL;
314  }
315  #endif
316}
317
318static BOOLEAN npCoeffsEqual(const coeffs r, n_coeffType n, void * parameter)
319{
320  /* test, if r is an instance of nInitCoeffs(n,parameter) */
321  return (n==n_Zp) && (r->ch==(int)(long)parameter);
322}
323
324BOOLEAN npInitChar(coeffs r, void* p)
325{
326  const int c = (int) (long) p;
327
328  assume( c > 0 );
329 
330  int i, w;
331
332  r->npPrimeM = c;
333  r->npPminus1M = c /*r->npPrimeM*/ - 1;
334
335  //r->cfInitChar=npInitChar;
336  r->cfKillChar=npKillChar;
337  r->cfSetChar=npSetChar;
338  r->nCoeffIsEqual=npCoeffsEqual;
339
340  r->cfMult  = npMult;
341  r->cfSub   = npSub;
342  r->cfAdd   = npAdd;
343  r->cfDiv   = npDiv;
344  r->cfIntDiv= npDiv;
345  //r->cfIntMod= ndIntMod;
346  r->cfExactDiv= npDiv;
347  r->cfInit = npInit;
348  //r->cfPar = ndPar;
349  //r->cfParDeg = ndParDeg;
350  //r->cfSize  = ndSize;
351  r->cfInt  = npInt;
352  #ifdef HAVE_RINGS
353  //r->cfDivComp = NULL; // only for ring stuff
354  //r->cfIsUnit = NULL; // only for ring stuff
355  //r->cfGetUnit = NULL; // only for ring stuff
356  //r->cfExtGcd = NULL; // only for ring stuff
357  // r->cfDivBy = NULL; // only for ring stuff
358  #endif
359  r->cfNeg   = npNeg;
360  r->cfInvers= npInvers;
361  //r->cfCopy  = ndCopy;
362  //r->cfRePart = ndCopy;
363  //r->cfImPart = ndReturn0;
364  r->cfWrite = npWrite;
365  r->cfRead = npRead;
366  //r->cfNormalize=ndNormalize;
367  r->cfGreater = npGreater;
368  r->cfEqual = npEqual;
369  r->cfIsZero = npIsZero;
370  r->cfIsOne = npIsOne;
371  r->cfIsMOne = npIsMOne;
372  r->cfGreaterZero = npGreaterZero;
373  r->cfPower = npPower;
374  r->cfGetDenom = ndGetDenom;
375  r->cfGetNumerator = ndGetNumerator;
376  //r->cfGcd  = ndGcd;
377  //r->cfLcm  = ndGcd;
378  //r->cfDelete= ndDelete;
379  r->cfSetMap = npSetMap;
380  //r->cfName = ndName;
381  r->cfInpMult=ndInpMult;
382  r->cfInit_bigint= npMap0;
383#ifdef NV_OPS
384  if (c>NV_MAX_PRIME)
385  {
386    r->cfMult  = nvMult;
387    r->cfDiv   = nvDiv;
388    r->cfExactDiv= nvDiv;
389    r->cfInvers= nvInvers;
390    r->cfPower= nvPower;
391  }
392#endif
393#ifdef LDEBUG
394  // debug stuff
395  r->cfDBTest=npDBTest;
396#endif
397 
398  // the variables:
399  r->nNULL = (number)0;
400  //r->type = n_Zp;
401  r->ch = c;
402  r->has_simple_Alloc=TRUE;
403  r->has_simple_Inverse=TRUE;
404
405  // the tables
406#ifdef NV_OPS
407  if (r->npPrimeM <=NV_MAX_PRIME)
408#endif
409  {
410#if !defined(HAVE_DIV_MOD) || !defined(HAVE_MULT_MOD)
411    r->npExpTable=(unsigned short *)omAlloc( r->npPrimeM*sizeof(unsigned short) );
412    r->npLogTable=(unsigned short *)omAlloc( r->npPrimeM*sizeof(unsigned short) );
413    r->npExpTable[0] = 1;
414    r->npLogTable[0] = 0;
415    if (r->npPrimeM > 2)
416    {
417      w = 1;
418      loop
419      {
420        r->npLogTable[1] = 0;
421        w++;
422        i = 0;
423        loop
424        {
425          i++;
426          r->npExpTable[i] =(int)(((long)w * (long)r->npExpTable[i-1])
427                               % r->npPrimeM);
428          r->npLogTable[r->npExpTable[i]] = i;
429          if (/*(i == npPrimeM - 1 ) ||*/ (r->npExpTable[i] == 1))
430            break;
431        }
432        if (i == r->npPrimeM - 1)
433          break;
434      }
435    }
436    else
437    {
438      r->npExpTable[1] = 1;
439      r->npLogTable[1] = 0;
440    }
441#endif
442#ifdef HAVE_DIV_MOD
443    r->npInvTable=(unsigned short*)omAlloc0( r->npPrimeM*sizeof(unsigned short) );
444#endif
445  }
446  return FALSE;
447}
448
449#ifdef LDEBUG
450BOOLEAN npDBTest (number a, const char *f, const int l, const coeffs r)
451{
452  if (((long)a<0) || ((long)a>r->npPrimeM))
453  {
454    Print("wrong mod p number %ld at %s,%d\n",(long)a,f,l);
455    return FALSE;
456  }
457  return TRUE;
458}
459#endif
460
461number npMap0(number from, const coeffs src, const coeffs dst_r)
462{
463  int nlModP(number n, int p, const coeffs r);
464
465  return npInit(nlModP(from, dst_r->npPrimeM, src),dst_r);
466}
467
468number npMapP(number from, const coeffs src, const coeffs dst_r)
469{
470  long i = (long)from;
471  if (i>src->npPrimeM/2)
472  {
473    i-=src->npPrimeM;
474    while (i < 0) i+=dst_r->npPrimeM;
475  }
476  i%=dst_r->npPrimeM;
477  return (number)i;
478}
479
480static number npMapLongR(number from, const coeffs src, const coeffs dst_r)
481{
482  gmp_float *ff=(gmp_float*)from;
483  mpf_t *f=ff->_mpfp();
484  number res;
485  mpz_ptr dest,ndest;
486  int size,i;
487  int e,al,bl,in;
488  long iz;
489  mp_ptr qp,dd,nn;
490
491  size = (*f)[0]._mp_size;
492  if (size == 0)
493    return npInit(0,dst_r);
494  if(size<0)
495    size = -size;
496
497  qp = (*f)[0]._mp_d;
498  while(qp[0]==0)
499  {
500    qp++;
501    size--;
502  }
503
504  if(dst_r->npPrimeM>2)
505    e=(*f)[0]._mp_exp-size;
506  else
507    e=0;
508  res = ALLOC_RNUMBER();
509#if defined(LDEBUG)
510  res->debug=123456;
511#endif
512  dest = res->z;
513
514  if (e<0)
515  {
516    al = dest->_mp_size = size;
517    if (al<2) al = 2;
518    dd = (mp_ptr)omAlloc(sizeof(mp_limb_t)*al);
519    for (i=0;i<size;i++) dd[i] = qp[i];
520    bl = 1-e;
521    nn = (mp_ptr)omAlloc(sizeof(mp_limb_t)*bl);
522    nn[bl-1] = 1;
523    for (i=bl-2;i>=0;i--) nn[i] = 0;
524    ndest = res->n;
525    ndest->_mp_d = nn;
526    ndest->_mp_alloc = ndest->_mp_size = bl;
527    res->s = 0;
528    in=mpz_fdiv_ui(ndest,dst_r->npPrimeM);
529    mpz_clear(ndest);
530  }
531  else
532  {
533    al = dest->_mp_size = size+e;
534    if (al<2) al = 2;
535    dd = (mp_ptr)omAlloc(sizeof(mp_limb_t)*al);
536    for (i=0;i<size;i++) dd[i+e] = qp[i];
537    for (i=0;i<e;i++) dd[i] = 0;
538    res->s = 3;
539  }
540
541  dest->_mp_d = dd;
542  dest->_mp_alloc = al;
543  iz=mpz_fdiv_ui(dest,dst_r->npPrimeM);
544  mpz_clear(dest);
545  if(res->s==0)
546    iz=(long)npDiv((number)iz,(number)in,dst_r);
547  omFreeBin((void *)res, rnumber_bin);
548  return (number)iz;
549}
550
551#ifdef HAVE_RINGS
552/*2
553* convert from a GMP integer
554*/
555number npMapGMP(number from, const coeffs src, const coeffs dst)
556{
557  int_number erg = (int_number) omAlloc(sizeof(mpz_t)); // evtl. spaeter mit bin
558  mpz_init(erg);
559
560  mpz_mod_ui(erg, (int_number) from, dst->npPrimeM);
561  number r = (number) mpz_get_si(erg);
562
563  mpz_clear(erg);
564  omFree((void *) erg);
565  return (number) r;
566}
567
568/*2
569* convert from an machine long
570*/
571number npMapMachineInt(number from, const coeffs src,const coeffs dst)
572{
573  long i = (long) (((unsigned long) from) % dst->npPrimeM);
574  return (number) i;
575}
576#endif
577
578#ifdef HAVE_FACTORY
579number npMapCanonicalForm (number a, const coeffs src, const coeffs dst)
580{
581  setCharacteristic (dst ->npPrimeM);
582  CanonicalForm f= CanonicalForm ((InternalCF*)(a));
583  return (number) (f.intval());
584}
585#endif
586
587nMapFunc npSetMap(const coeffs src, const coeffs dst)
588{
589#ifdef HAVE_RINGS
590  if (nCoeff_is_Ring_2toM(src))
591  {
592    return npMapMachineInt;
593  }
594  if (nCoeff_is_Ring_Z(src) || nCoeff_is_Ring_PtoM(src) || nCoeff_is_Ring_ModN(src))
595  {
596    return npMapGMP;
597  }
598#endif
599  if (nCoeff_is_Q(src))
600  {
601    return npMap0;
602  }
603  if ( nCoeff_is_Zp(src) )
604  {
605    if (n_GetChar(src) == n_GetChar(dst))
606    {
607      return ndCopyMap;
608    }
609    else
610    {
611      return npMapP;
612    }
613  }
614  if (nCoeff_is_long_R(src))
615  {
616    return npMapLongR;
617  }
618#ifdef HAVE_FACTORY
619  if (nCoeff_is_CF (src))
620  {
621    return npMapCanonicalForm;
622  }
623#endif
624  return NULL;      /* default */
625}
626
627// -----------------------------------------------------------
628//  operation for very large primes (32003< p < 2^31-1)
629// ----------------------------------------------------------
630#ifdef NV_OPS
631
632number nvMult (number a,number b, const coeffs r)
633{
634  //if (((long)a == 0) || ((long)b == 0))
635  //  return (number)0;
636  //else
637    return nvMultM(a,b,r);
638}
639
640void   nvInpMult(number &a, number b, const coeffs r)
641{
642  number n=nvMultM(a,b,r);
643  a=n;
644}
645
646
647long nvInvMod(long a, const coeffs R)
648{
649   long  s, t;
650
651   long  u, v, u0, v0, u1, v1, u2, v2, q, r;
652
653   u1=1; v1=0;
654   u2=0; v2=1;
655   u = a; v = R->npPrimeM;
656
657   while (v != 0)
658   {
659      q = u / v;
660      r = u % v;
661      u = v;
662      v = r;
663      u0 = u2;
664      v0 = v2;
665      u2 =  u1 - q*u2;
666      v2 = v1- q*v2;
667      u1 = u0;
668      v1 = v0;
669   }
670
671   s = u1;
672   //t = v1;
673   if (s < 0)
674      return s + R->npPrimeM;
675   else
676      return s;
677}
678
679inline number nvInversM (number c, const coeffs r)
680{
681  long inv=nvInvMod((long)c,r);
682  return (number)inv;
683}
684
685number nvDiv (number a,number b, const coeffs r)
686{
687  if ((long)a==0)
688    return (number)0;
689  else if ((long)b==0)
690  {
691    WerrorS(nDivBy0);
692    return (number)0;
693  }
694  else
695  {
696    number inv=nvInversM(b,r);
697    return nvMultM(a,inv,r);
698  }
699}
700number  nvInvers (number c, const coeffs r)
701{
702  if ((long)c==0)
703  {
704    WerrorS(nDivBy0);
705    return (number)0;
706  }
707  return nvInversM(c,r);
708}
709void nvPower (number a, int i, number * result, const coeffs r)
710{
711  if (i==0)
712  {
713    //npInit(1,result);
714    *(long *)result = 1;
715  }
716  else if (i==1)
717  {
718    *result = a;
719  }
720  else
721  {
722    nvPower(a,i-1,result,r);
723    *result = nvMultM(a,*result,r);
724  }
725}
726#endif
Note: See TracBrowser for help on using the repository browser.