source: git/libpolys/coeffs/modulop.cc @ 6ce030f

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