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

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