source: git/libpolys/coeffs/modulop.cc @ 81384b

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