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

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