source: git/libpolys/coeffs/modulop.cc @ 29fc71e

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