source: git/libpolys/coeffs/modulop.cc @ 2206753

spielwiese
Last change on this file since 2206753 was 2206753, checked in by Oleksandr Motsak <motsak@…>, 9 years ago
Hiding all the implementation details (or adding the counting) mostly by moving internal declarations from private headers into corresponding source files rm: Remove internal includes (hiding privates) + cleanup chg: cleanup internal headers fix the usage of internal implementation functions of coeffs from outside of libpolys/coeffs (or libpolys/polys/ext_fiels) fix header includes for coeffs/AE*.{h,cc} add: FIXME&TODO mark reused privates also starting to fix bigint handling
  • Property mode set to 100644
File size: 18.0 KB
Line 
1/****************************************
2*  Computer Algebra System SINGULAR     *
3****************************************/
4/*
5* ABSTRACT: numbers modulo p (<=32003)
6*/
7
8#include <misc/auxiliary.h>
9#include <omalloc/omalloc.h>
10
11#include <factory/factory.h>
12
13#include <misc/mylimits.h>
14#include <misc/sirandom.h>
15
16#include <reporter/reporter.h>
17
18#include <coeffs/coeffs.h>
19#include <coeffs/numbers.h>
20#include <coeffs/mpr_complex.h>
21
22#include "longrat.h"
23#include "modulop.h"
24
25#include <string.h>
26
27// enable large primes (32003 < p < 2^31-)
28#define NV_OPS
29#define NV_MAX_PRIME 32003
30
31/// Our Type!
32static const n_coeffType ID = n_Zp;
33
34BOOLEAN npGreaterZero (number k, const coeffs r);
35number  npMult        (number a, number b, const coeffs r);
36number  npInit        (long i, const coeffs r);
37int     npInt         (number &n, const coeffs r);
38number  npAdd         (number a, number b,const coeffs r);
39number  npSub         (number a, number b,const coeffs r);
40void    npPower       (number a, int i, number * result,const coeffs r);
41BOOLEAN npIsZero      (number a,const coeffs r);
42BOOLEAN npIsOne       (number a,const coeffs r);
43BOOLEAN npIsMOne       (number a,const coeffs r);
44number  npDiv         (number a, number b,const coeffs r);
45number  npNeg         (number c,const coeffs r);
46number  npInvers      (number c,const coeffs r);
47BOOLEAN npGreater     (number a, number b,const coeffs r);
48BOOLEAN npEqual       (number a, number b,const coeffs r);
49void    npWrite       (number &a, const coeffs r);
50void    npCoeffWrite  (const coeffs r, BOOLEAN details);
51const char *  npRead  (const char *s, number *a,const coeffs r);
52#ifdef LDEBUG
53BOOLEAN npDBTest      (number a, const char *f, const int l, const coeffs r);
54#define npTest(A,r)     npDBTest(A,__FILE__,__LINE__, r)
55#else
56#define npTest(A,r)     (0)
57#endif
58
59//int     npGetChar();
60
61nMapFunc npSetMap(const coeffs src, const coeffs dst);
62number  npMapP(number from, const coeffs src, const coeffs r);
63
64// extern int npGen; // obsolete
65
66// int npGen=0;
67
68/*-------specials for spolys, do NOT use otherwise--------------------------*/
69/* for npMultM, npSubM, npNegM, npEqualM : */
70#ifdef HAVE_DIV_MOD
71extern unsigned short *npInvTable;
72#else
73#ifndef HAVE_MULT_MOD
74extern long npPminus1M;
75extern unsigned short *npExpTable;
76extern unsigned short *npLogTable;
77#endif
78#endif
79
80#ifdef NV_OPS
81#pragma GCC diagnostic ignored "-Wlong-long"
82static inline number nvMultM(number a, number b, const coeffs r)
83{
84  assume( getCoeffType(r) == ID );
85
86#if SIZEOF_LONG == 4
87#define ULONG64 (unsigned long long)(unsigned long)
88#else
89#define ULONG64 (unsigned long)
90#endif
91  return (number)
92      (unsigned long)((ULONG64 a)*(ULONG64 b) % (ULONG64 r->ch));
93}
94number  nvMult        (number a, number b, const coeffs r);
95number  nvDiv         (number a, number b, const coeffs r);
96number  nvInvers      (number c, const coeffs r);
97//void    nvPower       (number a, int i, number * result, const coeffs r);
98#endif
99
100
101
102
103BOOLEAN npGreaterZero (number k, const coeffs r)
104{
105  n_Test(k, r);
106
107  int h = (int)((long) k);
108  return ((int)h !=0) && (h <= (r->ch>>1));
109}
110
111//unsigned long npMultMod(unsigned long a, unsigned long b, int npPrimeM)
112//{
113//  unsigned long c = a*b;
114//  c = c % npPrimeM;
115//  assume(c == (unsigned long) npMultM((number) a, (number) b, npPrimeM));
116//  return c;
117//}
118
119number npMult (number a,number b, const coeffs r)
120{
121  n_Test(a, r);
122  n_Test(b, r);
123
124  if (((long)a == 0) || ((long)b == 0))
125    return (number)0;
126  number c = npMultM(a,b, r);
127  n_Test(c, r);
128  return c;
129}
130
131/*2
132* create a number from int
133*/
134number npInit (long i, const coeffs r)
135{
136  long ii=i % (long)r->ch;
137  if (ii <  0L)                         ii += (long)r->ch;
138
139  number c = (number)ii;
140  n_Test(c, r);
141  return c;
142
143}
144
145
146/*2
147 * convert a number to an int in (-p/2 .. p/2]
148 */
149int npInt(number &n, const coeffs r)
150{
151  n_Test(n, r);
152
153  if ((long)n > (((long)r->ch) >>1)) return (int)((long)n -((long)r->ch));
154  else                               return (int)((long)n);
155}
156
157number npAdd (number a, number b, const coeffs r)
158{
159  n_Test(a, r);
160  n_Test(b, r);
161
162  number c = npAddM(a,b, r);
163
164  n_Test(c, r);
165
166  return c;
167}
168
169number npSub (number a, number b, const coeffs r)
170{
171  n_Test(a, r);
172  n_Test(b, r);
173
174  number c = npSubM(a,b,r);
175
176  n_Test(c, r);
177
178  return c;
179}
180
181BOOLEAN npIsZero (number  a, const coeffs r)
182{
183  n_Test(a, r);
184
185  return 0 == (long)a;
186}
187
188BOOLEAN npIsOne (number a, const coeffs r)
189{
190  n_Test(a, r);
191
192  return 1 == (long)a;
193}
194
195BOOLEAN npIsMOne (number a, const coeffs r)
196{
197  n_Test(a, r);
198
199  return ((r->npPminus1M == (long)a)&&((long)1!=(long)a));
200}
201
202#ifdef HAVE_DIV_MOD
203
204#ifdef USE_NTL_XGCD
205
206//ifdef HAVE_NTL // in ntl.a
207//extern void XGCD(long& d, long& s, long& t, long a, long b);
208#include <NTL/ZZ.h>
209#ifdef NTL_CLIENT
210NTL_CLIENT
211#endif
212
213#endif
214
215long InvMod(long a, const coeffs R)
216{
217   long d, s, t;
218
219#ifdef USE_NTL_XGCD
220   XGCD(d, s, t, a, R->ch);
221   assume (d == 1);
222#else
223   long  u, v, u0, v0, u1, v1, u2, v2, q, r;
224
225   assume(a>0);
226   u1=1; u2=0;
227   u = a; v = R->ch;
228
229   while (v != 0)
230   {
231      q = u / v;
232      r = u % v;
233      u = v;
234      v = r;
235      u0 = u2;
236      u2 = u1 - q*u2;
237      u1 = u0;
238   }
239
240   assume(u==1);
241   s = u1;
242#endif
243   if (s < 0)
244      return s + R->ch;
245   else
246      return s;
247}
248#endif
249
250inline number npInversM (number c, const coeffs r)
251{
252  n_Test(c, r);
253#ifndef HAVE_DIV_MOD
254  number d = (number)(long)r->npExpTable[r->npPminus1M - r->npLogTable[(long)c]];
255#else
256  long inv=(long)r->npInvTable[(long)c];
257  if (inv==0)
258  {
259    inv=InvMod((long)c,r);
260    r->npInvTable[(long)c]=inv;
261  }
262  number d = (number)inv;
263#endif
264  n_Test(d, r);
265  return d;
266
267}
268
269number npDiv (number a,number b, const coeffs r)
270{
271  n_Test(a, r);
272  n_Test(b, r);
273
274//#ifdef NV_OPS
275//  if (r->ch>NV_MAX_PRIME)
276//    return nvDiv(a,b);
277//#endif
278  if ((long)a==0)
279    return (number)0;
280  number d;
281
282#ifndef HAVE_DIV_MOD
283  if ((long)b==0)
284  {
285    WerrorS(nDivBy0);
286    return (number)0;
287  }
288
289  int s = r->npLogTable[(long)a] - r->npLogTable[(long)b];
290  if (s < 0)
291    s += r->npPminus1M;
292  d = (number)(long)r->npExpTable[s];
293#else
294  number inv=npInversM(b,r);
295  d = npMultM(a,inv,r);
296#endif
297
298  n_Test(d, r);
299  return d;
300
301}
302number  npInvers (number c, const coeffs r)
303{
304  n_Test(c, r);
305
306  if ((long)c==0)
307  {
308    WerrorS("1/0");
309    return (number)0;
310  }
311  number d = npInversM(c,r);
312
313  n_Test(d, r);
314  return d;
315
316}
317
318number npNeg (number c, const coeffs r)
319{
320  n_Test(c, r);
321
322  if ((long)c==0) return c;
323
324#if 0
325  number d = npNegM(c,r);
326  n_Test(d, r);
327  return d;
328#else
329  c = npNegM(c,r);
330  n_Test(c, r);
331  return c;
332#endif
333}
334
335BOOLEAN npGreater (number a,number b, const coeffs r)
336{
337  n_Test(a, r);
338  n_Test(b, r);
339
340  //return (long)a != (long)b;
341  return (long)a > (long)b;
342}
343
344BOOLEAN npEqual (number a,number b, const coeffs r)
345{
346  n_Test(a, r);
347  n_Test(b, r);
348
349//  return (long)a == (long)b;
350
351  return npEqualM(a,b,r);
352}
353
354void npWrite (number &a, const coeffs r)
355{
356  n_Test(a, r);
357
358  if ((long)a>(((long)r->ch) >>1)) StringAppend("-%d",(int)(((long)r->ch)-((long)a)));
359  else                             StringAppend("%d",(int)((long)a));
360}
361
362#if 0
363void npPower (number a, int i, number * result, const coeffs r)
364{
365  n_Test(a, r);
366
367  if (i==0)
368  {
369    //npInit(1,result);
370    *(long *)result = 1;
371  }
372  else if (i==1)
373  {
374    *result = a;
375  }
376  else
377  {
378    npPower(a,i-1,result,r);
379    *result = npMultM(a,*result,r);
380  }
381}
382#endif
383
384static const char* npEati(const char *s, int *i, const coeffs r)
385{
386
387  if (((*s) >= '0') && ((*s) <= '9'))
388  {
389    unsigned long ii=0L;
390    do
391    {
392      ii *= 10;
393      ii += *s++ - '0';
394      if (ii >= (MAX_INT_VAL / 10)) ii = ii % r->ch;
395    }
396    while (((*s) >= '0') && ((*s) <= '9'));
397    if (ii >= (unsigned long)r->ch) ii = ii % r->ch;
398    *i=(int)ii;
399  }
400  else (*i) = 1;
401  return s;
402}
403
404const char * npRead (const char *s, number *a, const coeffs r)
405{
406  int z;
407  int n=1;
408
409  s = npEati(s, &z, r);
410  if ((*s) == '/')
411  {
412    s++;
413    s = npEati(s, &n, r);
414  }
415  if (n == 1)
416    *a = (number)(long)z;
417  else
418  {
419    if ((z==0)&&(n==0)) WerrorS(nDivBy0);
420    else
421    {
422#ifdef NV_OPS
423      if (r->ch>NV_MAX_PRIME)
424        *a = nvDiv((number)(long)z,(number)(long)n,r);
425      else
426#endif
427        *a = npDiv((number)(long)z,(number)(long)n,r);
428    }
429  }
430  n_Test(*a, r);
431  return s;
432}
433
434/*2
435* set the charcteristic (allocate and init tables)
436*/
437
438void npKillChar(coeffs r)
439{
440  #ifdef HAVE_DIV_MOD
441  if (r->npInvTable!=NULL)
442  omFreeSize( (void *)r->npInvTable, r->ch*sizeof(unsigned short) );
443  r->npInvTable=NULL;
444  #else
445  if (r->npExpTable!=NULL)
446  {
447    omFreeSize( (void *)r->npExpTable, r->ch*sizeof(unsigned short) );
448    omFreeSize( (void *)r->npLogTable, r->ch*sizeof(unsigned short) );
449    r->npExpTable=NULL; r->npLogTable=NULL;
450  }
451  #endif
452}
453
454static BOOLEAN npCoeffsEqual(const coeffs r, n_coeffType n, void * parameter)
455{
456  /* test, if r is an instance of nInitCoeffs(n,parameter) */
457  return (n==n_Zp) && (r->ch==(int)(long)parameter);
458}
459CanonicalForm npConvSingNFactoryN( number n, BOOLEAN setChar, const coeffs r )
460{
461  if (setChar) setCharacteristic( r->ch );
462  CanonicalForm term(npInt( n,r ));
463  return term;
464}
465
466number npConvFactoryNSingN( const CanonicalForm n, const coeffs r)
467{
468  if (n.isImm())
469  {
470    return npInit(n.intval(),r);
471  }
472  else
473  {
474    assume(0);
475    return NULL;
476  }
477}
478
479static char* npCoeffString(const coeffs r)
480{
481  char *s=(char*)omAlloc(11);
482  snprintf(s,11,"%d",r->ch);
483  return s;
484}
485
486static void npWriteFd(number n, FILE* f, const coeffs r)
487{
488  fprintf(f,"%d ",(int)(long)n);
489}
490
491static number npReadFd(s_buff f, const coeffs r)
492{
493  // read int
494  int dd;
495  dd=s_readint(f);
496  return (number)(long)dd;
497}
498
499static number npRandom(siRandProc p, number, number, const coeffs cf)
500{
501  return npInit(p(),cf);
502}
503
504BOOLEAN npInitChar(coeffs r, void* p)
505{
506  assume( getCoeffType(r) == ID );
507  const int c = (int) (long) p;
508
509  assume( c > 0 );
510
511  int i, w;
512
513  r->is_field=TRUE;
514  r->is_domain=TRUE;
515  r->rep=n_rep_int;
516
517  r->ch = c;
518  r->npPminus1M = c /*r->ch*/ - 1;
519
520  //r->cfInitChar=npInitChar;
521  r->cfKillChar=npKillChar;
522  r->nCoeffIsEqual=npCoeffsEqual;
523  r->cfCoeffString=npCoeffString;
524
525  r->cfMult  = npMult;
526  r->cfSub   = npSub;
527  r->cfAdd   = npAdd;
528  r->cfDiv   = npDiv;
529  r->cfInit = npInit;
530  //r->cfSize  = ndSize;
531  r->cfInt  = npInt;
532  #ifdef HAVE_RINGS
533  //r->cfDivComp = NULL; // only for ring stuff
534  //r->cfIsUnit = NULL; // only for ring stuff
535  //r->cfGetUnit = NULL; // only for ring stuff
536  //r->cfExtGcd = NULL; // only for ring stuff
537  // r->cfDivBy = NULL; // only for ring stuff
538  #endif
539  r->cfInpNeg   = npNeg;
540  r->cfInvers= npInvers;
541  //r->cfCopy  = ndCopy;
542  //r->cfRePart = ndCopy;
543  //r->cfImPart = ndReturn0;
544  r->cfWriteLong = npWrite;
545  r->cfRead = npRead;
546  //r->cfNormalize=ndNormalize;
547  r->cfGreater = npGreater;
548  r->cfEqual = npEqual;
549  r->cfIsZero = npIsZero;
550  r->cfIsOne = npIsOne;
551  r->cfIsMOne = npIsMOne;
552  r->cfGreaterZero = npGreaterZero;
553  //r->cfPower = npPower;
554  //r->cfGetDenom = ndGetDenom;
555  //r->cfGetNumerator = ndGetNumerator;
556  //r->cfGcd  = ndGcd;
557  //r->cfLcm  = ndGcd;
558  //r->cfDelete= ndDelete;
559  r->cfSetMap = npSetMap;
560  //r->cfName = ndName;
561  //r->cfInpMult=ndInpMult;
562#ifdef NV_OPS
563  if (c>NV_MAX_PRIME)
564  {
565    r->cfMult  = nvMult;
566    r->cfDiv   = nvDiv;
567    r->cfExactDiv= nvDiv;
568    r->cfInvers= nvInvers;
569    //r->cfPower= nvPower;
570  }
571#endif
572  r->cfCoeffWrite=npCoeffWrite;
573#ifdef LDEBUG
574  // debug stuff
575  r->cfDBTest=npDBTest;
576#endif
577
578  r->convSingNFactoryN=npConvSingNFactoryN;
579  r->convFactoryNSingN=npConvFactoryNSingN;
580
581  r->cfRandom=npRandom;
582
583  // io via ssi
584  r->cfWriteFd=npWriteFd;
585  r->cfReadFd=npReadFd;
586
587  // the variables:
588  r->nNULL = (number)0;
589  r->type = n_Zp;
590  r->ch = c;
591  r->has_simple_Alloc=TRUE;
592  r->has_simple_Inverse=TRUE;
593
594  // the tables
595#ifdef NV_OPS
596  if (r->ch <=NV_MAX_PRIME)
597#endif
598  {
599#if !defined(HAVE_DIV_MOD) || !defined(HAVE_MULT_MOD)
600    r->npExpTable=(unsigned short *)omAlloc( r->ch*sizeof(unsigned short) );
601    r->npLogTable=(unsigned short *)omAlloc( r->ch*sizeof(unsigned short) );
602    r->npExpTable[0] = 1;
603    r->npLogTable[0] = 0;
604    if (r->ch > 2)
605    {
606      w = 1;
607      loop
608      {
609        r->npLogTable[1] = 0;
610        w++;
611        i = 0;
612        loop
613        {
614          i++;
615          r->npExpTable[i] =(int)(((long)w * (long)r->npExpTable[i-1]) % r->ch);
616          r->npLogTable[r->npExpTable[i]] = i;
617          if /*(i == r->ch - 1 ) ||*/ (/*(*/ r->npExpTable[i] == 1 /*)*/)
618            break;
619        }
620        if (i == r->ch - 1)
621          break;
622      }
623    }
624    else
625    {
626      r->npExpTable[1] = 1;
627      r->npLogTable[1] = 0;
628    }
629#endif
630#ifdef HAVE_DIV_MOD
631    r->npInvTable=(unsigned short*)omAlloc0( r->ch*sizeof(unsigned short) );
632#endif
633  }
634  return FALSE;
635}
636
637#ifdef LDEBUG
638BOOLEAN npDBTest (number a, const char *f, const int l, const coeffs r)
639{
640  if (((long)a<0) || ((long)a>r->ch))
641  {
642    Print("wrong mod p number %ld at %s,%d\n",(long)a,f,l);
643    return FALSE;
644  }
645  return TRUE;
646}
647#endif
648
649number npMapP(number from, const coeffs src, const coeffs dst_r)
650{
651  long i = (long)from;
652  if (i>src->ch/2)
653  {
654    i-=src->ch;
655    while (i < 0) i+=dst_r->ch;
656  }
657  i%=dst_r->ch;
658  return (number)i;
659}
660
661static number npMapLongR(number from, const coeffs /*src*/, const coeffs dst_r)
662{
663  gmp_float *ff=(gmp_float*)from;
664  mpf_t *f=ff->_mpfp();
665  number res;
666  mpz_ptr dest,ndest;
667  int size,i;
668  int e,al,bl;
669  long iz;
670  mp_ptr qp,dd,nn;
671
672  size = (*f)[0]._mp_size;
673  if (size == 0)
674    return npInit(0,dst_r);
675  if(size<0)
676    size = -size;
677
678  qp = (*f)[0]._mp_d;
679  while(qp[0]==0)
680  {
681    qp++;
682    size--;
683  }
684
685  if(dst_r->ch>2)
686    e=(*f)[0]._mp_exp-size;
687  else
688    e=0;
689  res = ALLOC_RNUMBER();
690#if defined(LDEBUG)
691  res->debug=123456;
692#endif
693  dest = res->z;
694
695  long in=0;
696  if (e<0)
697  {
698    al = dest->_mp_size = size;
699    if (al<2) al = 2;
700    dd = (mp_ptr)omAlloc(sizeof(mp_limb_t)*al);
701    for (i=0;i<size;i++) dd[i] = qp[i];
702    bl = 1-e;
703    nn = (mp_ptr)omAlloc(sizeof(mp_limb_t)*bl);
704    nn[bl-1] = 1;
705    for (i=bl-2;i>=0;i--) nn[i] = 0;
706    ndest = res->n;
707    ndest->_mp_d = nn;
708    ndest->_mp_alloc = ndest->_mp_size = bl;
709    res->s = 0;
710    in=mpz_fdiv_ui(ndest,dst_r->ch);
711    mpz_clear(ndest);
712  }
713  else
714  {
715    al = dest->_mp_size = size+e;
716    if (al<2) al = 2;
717    dd = (mp_ptr)omAlloc(sizeof(mp_limb_t)*al);
718    for (i=0;i<size;i++) dd[i+e] = qp[i];
719    for (i=0;i<e;i++) dd[i] = 0;
720    res->s = 3;
721  }
722
723  dest->_mp_d = dd;
724  dest->_mp_alloc = al;
725  iz=mpz_fdiv_ui(dest,dst_r->ch);
726  mpz_clear(dest);
727  if(res->s==0)
728    iz=(long)npDiv((number)iz,(number)in,dst_r);
729  FREE_RNUMBER(res); // Q!?
730  return (number)iz;
731}
732
733#ifdef HAVE_RINGS
734/*2
735* convert from a GMP integer
736*/
737number npMapGMP(number from, const coeffs /*src*/, const coeffs dst)
738{
739  mpz_ptr erg = (mpz_ptr) omAlloc(sizeof(mpz_t)); // evtl. spaeter mit bin
740  mpz_init(erg);
741
742  mpz_mod_ui(erg, (mpz_ptr) from, dst->ch);
743  number r = (number) mpz_get_si(erg);
744
745  mpz_clear(erg);
746  omFree((void *) erg);
747  return (number) r;
748}
749
750number npMapZ(number from, const coeffs src, const coeffs dst)
751{
752  if (SR_HDL(from) & SR_INT)
753  {
754    long f_i=SR_TO_INT(from);
755    return npInit(f_i,dst);
756  }
757  return npMapGMP(from,src,dst);
758}
759
760/*2
761* convert from an machine long
762*/
763number npMapMachineInt(number from, const coeffs /*src*/,const coeffs dst)
764{
765  long i = (long) (((unsigned long) from) % dst->ch);
766  return (number) i;
767}
768#endif
769
770number npMapCanonicalForm (number a, const coeffs /*src*/, const coeffs dst)
771{
772  setCharacteristic (dst ->ch);
773  CanonicalForm f= CanonicalForm ((InternalCF*)(a));
774  return (number) (f.intval());
775}
776
777nMapFunc npSetMap(const coeffs src, const coeffs dst)
778{
779#ifdef HAVE_RINGS
780  if ((src->rep==n_rep_int) && nCoeff_is_Ring_2toM(src))
781  {
782    return npMapMachineInt;
783  }
784  if (src->rep==n_rep_gmp) //nCoeff_is_Ring_Z(src) || nCoeff_is_Ring_PtoM(src) || nCoeff_is_Ring_ModN(src))
785  {
786    return npMapGMP;
787  }
788  if (src->rep==n_rep_gap_gmp) //nCoeff_is_Ring_Z(src)
789  {
790    return npMapZ;
791  }
792#endif
793  if (src->rep==n_rep_gap_rat)  /* Q, Z */
794  {   
795    return nlModP; // npMap0; // FIXME? TODO? // extern number nlModP(number q, const coeffs Q, const coeffs Zp); // Map q \in QQ \to Zp // FIXME!
796  }
797  if ((src->rep==n_rep_int) &&  nCoeff_is_Zp(src) )
798  {
799    if (n_GetChar(src) == n_GetChar(dst))
800    {
801      return ndCopyMap;
802    }
803    else
804    {
805      return npMapP;
806    }
807  }
808  if ((src->rep==n_rep_gmp_float) && nCoeff_is_long_R(src))
809  {
810    return npMapLongR;
811  }
812  if (nCoeff_is_CF (src))
813  {
814    return npMapCanonicalForm;
815  }
816  return NULL;      /* default */
817}
818
819// -----------------------------------------------------------
820//  operation for very large primes (32003< p < 2^31-1)
821// ----------------------------------------------------------
822#ifdef NV_OPS
823
824number nvMult (number a,number b, const coeffs r)
825{
826  //if (((long)a == 0) || ((long)b == 0))
827  //  return (number)0;
828  //else
829    return nvMultM(a,b,r);
830}
831
832void   nvInpMult(number &a, number b, const coeffs r)
833{
834  number n=nvMultM(a,b,r);
835  a=n;
836}
837
838
839inline long nvInvMod(long a, const coeffs R)
840{
841#ifdef HAVE_DIV_MOD
842  return InvMod(a, R);
843#else
844/// TODO: use "long InvMod(long a, const coeffs R)"?!
845
846   long  s;
847
848   long  u, u0, u1, u2, q, r; // v0, v1, v2,
849
850   u1=1; // v1=0;
851   u2=0; // v2=1;
852   u = a;
853
854   long v = R->ch;
855
856   while (v != 0)
857   {
858      q = u / v;
859      r = u % v;
860      u = v;
861      v = r;
862      u0 = u2;
863//      v0 = v2;
864      u2 = u1 - q*u2;
865//      v2 = v1 - q*v2;
866      u1 = u0;
867//      v1 = v0;
868   }
869
870   s = u1;
871   //t = v1;
872   if (s < 0)
873      return s + R->ch;
874   else
875     return s;
876#endif
877}
878
879inline number nvInversM (number c, const coeffs r)
880{
881  long inv=nvInvMod((long)c,r);
882  return (number)inv;
883}
884
885number nvDiv (number a,number b, const coeffs r)
886{
887  if ((long)a==0)
888    return (number)0;
889  else if ((long)b==0)
890  {
891    WerrorS(nDivBy0);
892    return (number)0;
893  }
894  else
895  {
896    number inv=nvInversM(b,r);
897    return nvMultM(a,inv,r);
898  }
899}
900number  nvInvers (number c, const coeffs r)
901{
902  if ((long)c==0)
903  {
904    WerrorS(nDivBy0);
905    return (number)0;
906  }
907  return nvInversM(c,r);
908}
909#if 0
910void nvPower (number a, int i, number * result, const coeffs r)
911{
912  if (i==0)
913  {
914    //npInit(1,result);
915    *(long *)result = 1;
916  }
917  else if (i==1)
918  {
919    *result = a;
920  }
921  else
922  {
923    nvPower(a,i-1,result,r);
924    *result = nvMultM(a,*result,r);
925  }
926}
927#endif
928#endif
929
930void    npCoeffWrite  (const coeffs r, BOOLEAN /*details*/)
931{
932  Print("//   characteristic : %d\n",r->ch);
933}
934
Note: See TracBrowser for help on using the repository browser.