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

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