source: git/libpolys/coeffs/modulop.cc @ 4c6e420

spielwiese
Last change on this file since 4c6e420 was c7e3d7, checked in by Hans Schoenemann <hannes@…>, 13 years ago
cfCoeffWrite introduced
  • Property mode set to 100644
File size: 14.1 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 "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  r->cfCoeffWrite=npCoeffWrite;
394#ifdef LDEBUG
395  // debug stuff
396  r->cfDBTest=npDBTest;
397#endif
398 
399  // the variables:
400  r->nNULL = (number)0;
401  //r->type = n_Zp;
402  r->ch = c;
403  r->has_simple_Alloc=TRUE;
404  r->has_simple_Inverse=TRUE;
405
406  // the tables
407#ifdef NV_OPS
408  if (r->npPrimeM <=NV_MAX_PRIME)
409#endif
410  {
411#if !defined(HAVE_DIV_MOD) || !defined(HAVE_MULT_MOD)
412    r->npExpTable=(unsigned short *)omAlloc( r->npPrimeM*sizeof(unsigned short) );
413    r->npLogTable=(unsigned short *)omAlloc( r->npPrimeM*sizeof(unsigned short) );
414    r->npExpTable[0] = 1;
415    r->npLogTable[0] = 0;
416    if (r->npPrimeM > 2)
417    {
418      w = 1;
419      loop
420      {
421        r->npLogTable[1] = 0;
422        w++;
423        i = 0;
424        loop
425        {
426          i++;
427          r->npExpTable[i] =(int)(((long)w * (long)r->npExpTable[i-1])
428                               % r->npPrimeM);
429          r->npLogTable[r->npExpTable[i]] = i;
430          if (/*(i == npPrimeM - 1 ) ||*/ (r->npExpTable[i] == 1))
431            break;
432        }
433        if (i == r->npPrimeM - 1)
434          break;
435      }
436    }
437    else
438    {
439      r->npExpTable[1] = 1;
440      r->npLogTable[1] = 0;
441    }
442#endif
443#ifdef HAVE_DIV_MOD
444    r->npInvTable=(unsigned short*)omAlloc0( r->npPrimeM*sizeof(unsigned short) );
445#endif
446  }
447  return FALSE;
448}
449
450#ifdef LDEBUG
451BOOLEAN npDBTest (number a, const char *f, const int l, const coeffs r)
452{
453  if (((long)a<0) || ((long)a>r->npPrimeM))
454  {
455    Print("wrong mod p number %ld at %s,%d\n",(long)a,f,l);
456    return FALSE;
457  }
458  return TRUE;
459}
460#endif
461
462number npMap0(number from, const coeffs src, const coeffs dst_r)
463{
464  int nlModP(number n, int p, const coeffs r);
465
466  return npInit(nlModP(from, dst_r->npPrimeM, src),dst_r);
467}
468
469number npMapP(number from, const coeffs src, const coeffs dst_r)
470{
471  long i = (long)from;
472  if (i>src->npPrimeM/2)
473  {
474    i-=src->npPrimeM;
475    while (i < 0) i+=dst_r->npPrimeM;
476  }
477  i%=dst_r->npPrimeM;
478  return (number)i;
479}
480
481static number npMapLongR(number from, const coeffs src, const coeffs dst_r)
482{
483  gmp_float *ff=(gmp_float*)from;
484  mpf_t *f=ff->_mpfp();
485  number res;
486  mpz_ptr dest,ndest;
487  int size,i;
488  int e,al,bl,in;
489  long iz;
490  mp_ptr qp,dd,nn;
491
492  size = (*f)[0]._mp_size;
493  if (size == 0)
494    return npInit(0,dst_r);
495  if(size<0)
496    size = -size;
497
498  qp = (*f)[0]._mp_d;
499  while(qp[0]==0)
500  {
501    qp++;
502    size--;
503  }
504
505  if(dst_r->npPrimeM>2)
506    e=(*f)[0]._mp_exp-size;
507  else
508    e=0;
509  res = ALLOC_RNUMBER();
510#if defined(LDEBUG)
511  res->debug=123456;
512#endif
513  dest = res->z;
514
515  if (e<0)
516  {
517    al = dest->_mp_size = size;
518    if (al<2) al = 2;
519    dd = (mp_ptr)omAlloc(sizeof(mp_limb_t)*al);
520    for (i=0;i<size;i++) dd[i] = qp[i];
521    bl = 1-e;
522    nn = (mp_ptr)omAlloc(sizeof(mp_limb_t)*bl);
523    nn[bl-1] = 1;
524    for (i=bl-2;i>=0;i--) nn[i] = 0;
525    ndest = res->n;
526    ndest->_mp_d = nn;
527    ndest->_mp_alloc = ndest->_mp_size = bl;
528    res->s = 0;
529    in=mpz_fdiv_ui(ndest,dst_r->npPrimeM);
530    mpz_clear(ndest);
531  }
532  else
533  {
534    al = dest->_mp_size = size+e;
535    if (al<2) al = 2;
536    dd = (mp_ptr)omAlloc(sizeof(mp_limb_t)*al);
537    for (i=0;i<size;i++) dd[i+e] = qp[i];
538    for (i=0;i<e;i++) dd[i] = 0;
539    res->s = 3;
540  }
541
542  dest->_mp_d = dd;
543  dest->_mp_alloc = al;
544  iz=mpz_fdiv_ui(dest,dst_r->npPrimeM);
545  mpz_clear(dest);
546  if(res->s==0)
547    iz=(long)npDiv((number)iz,(number)in,dst_r);
548  omFreeBin((void *)res, rnumber_bin);
549  return (number)iz;
550}
551
552#ifdef HAVE_RINGS
553/*2
554* convert from a GMP integer
555*/
556number npMapGMP(number from, const coeffs src, const coeffs dst)
557{
558  int_number erg = (int_number) omAlloc(sizeof(mpz_t)); // evtl. spaeter mit bin
559  mpz_init(erg);
560
561  mpz_mod_ui(erg, (int_number) from, dst->npPrimeM);
562  number r = (number) mpz_get_si(erg);
563
564  mpz_clear(erg);
565  omFree((void *) erg);
566  return (number) r;
567}
568
569/*2
570* convert from an machine long
571*/
572number npMapMachineInt(number from, const coeffs src,const coeffs dst)
573{
574  long i = (long) (((unsigned long) from) % dst->npPrimeM);
575  return (number) i;
576}
577#endif
578
579#ifdef HAVE_FACTORY
580number npMapCanonicalForm (number a, const coeffs src, const coeffs dst)
581{
582  setCharacteristic (dst ->npPrimeM);
583  CanonicalForm f= CanonicalForm ((InternalCF*)(a));
584  return (number) (f.intval());
585}
586#endif
587
588nMapFunc npSetMap(const coeffs src, const coeffs dst)
589{
590#ifdef HAVE_RINGS
591  if (nCoeff_is_Ring_2toM(src))
592  {
593    return npMapMachineInt;
594  }
595  if (nCoeff_is_Ring_Z(src) || nCoeff_is_Ring_PtoM(src) || nCoeff_is_Ring_ModN(src))
596  {
597    return npMapGMP;
598  }
599#endif
600  if (nCoeff_is_Q(src))
601  {
602    return npMap0;
603  }
604  if ( nCoeff_is_Zp(src) )
605  {
606    if (n_GetChar(src) == n_GetChar(dst))
607    {
608      return ndCopyMap;
609    }
610    else
611    {
612      return npMapP;
613    }
614  }
615  if (nCoeff_is_long_R(src))
616  {
617    return npMapLongR;
618  }
619#ifdef HAVE_FACTORY
620  if (nCoeff_is_CF (src))
621  {
622    return npMapCanonicalForm;
623  }
624#endif
625  return NULL;      /* default */
626}
627
628// -----------------------------------------------------------
629//  operation for very large primes (32003< p < 2^31-1)
630// ----------------------------------------------------------
631#ifdef NV_OPS
632
633number nvMult (number a,number b, const coeffs r)
634{
635  //if (((long)a == 0) || ((long)b == 0))
636  //  return (number)0;
637  //else
638    return nvMultM(a,b,r);
639}
640
641void   nvInpMult(number &a, number b, const coeffs r)
642{
643  number n=nvMultM(a,b,r);
644  a=n;
645}
646
647
648long nvInvMod(long a, const coeffs R)
649{
650   long  s, t;
651
652   long  u, v, u0, v0, u1, v1, u2, v2, q, r;
653
654   u1=1; v1=0;
655   u2=0; v2=1;
656   u = a; v = R->npPrimeM;
657
658   while (v != 0)
659   {
660      q = u / v;
661      r = u % v;
662      u = v;
663      v = r;
664      u0 = u2;
665      v0 = v2;
666      u2 =  u1 - q*u2;
667      v2 = v1- q*v2;
668      u1 = u0;
669      v1 = v0;
670   }
671
672   s = u1;
673   //t = v1;
674   if (s < 0)
675      return s + R->npPrimeM;
676   else
677      return s;
678}
679
680inline number nvInversM (number c, const coeffs r)
681{
682  long inv=nvInvMod((long)c,r);
683  return (number)inv;
684}
685
686number nvDiv (number a,number b, const coeffs r)
687{
688  if ((long)a==0)
689    return (number)0;
690  else if ((long)b==0)
691  {
692    WerrorS(nDivBy0);
693    return (number)0;
694  }
695  else
696  {
697    number inv=nvInversM(b,r);
698    return nvMultM(a,inv,r);
699  }
700}
701number  nvInvers (number c, const coeffs r)
702{
703  if ((long)c==0)
704  {
705    WerrorS(nDivBy0);
706    return (number)0;
707  }
708  return nvInversM(c,r);
709}
710void nvPower (number a, int i, number * result, const coeffs r)
711{
712  if (i==0)
713  {
714    //npInit(1,result);
715    *(long *)result = 1;
716  }
717  else if (i==1)
718  {
719    *result = a;
720  }
721  else
722  {
723    nvPower(a,i-1,result,r);
724    *result = nvMultM(a,*result,r);
725  }
726}
727#endif
728
729void    npCoeffWrite  (const coeffs r)
730{
731  Print("//   characteristic : %d\n",r->npPrimeM);
732}
733
Note: See TracBrowser for help on using the repository browser.