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
RevLine 
[35aab3]1/****************************************
2*  Computer Algebra System SINGULAR     *
3****************************************/
4/*
[a1299c]5* ABSTRACT: numbers modulo p (<=32749)
[35aab3]6*/
7
[22a09d]8#include <misc/auxiliary.h>
[2206753]9#include <omalloc/omalloc.h>
[22a09d]10
11#include <factory/factory.h>
12
[2206753]13#include <misc/mylimits.h>
14#include <misc/sirandom.h>
15
[31213a4]16#include <reporter/reporter.h>
[2206753]17
18#include <coeffs/coeffs.h>
[2d805a]19#include <coeffs/numbers.h>
20#include <coeffs/mpr_complex.h>
[35aab3]21
[2206753]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);
[777f8b]30long    npInt         (number &n, const coeffs r);
[2206753]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);
[6d92ca]42void    npWrite       (number a, const coeffs r);
[2206753]43void    npCoeffWrite  (const coeffs r, BOOLEAN details);
44const char *  npRead  (const char *s, number *a,const coeffs r);
[fc2acf]45
[2206753]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
[40e88db]52#ifdef NV_OPS
53#pragma GCC diagnostic ignored "-Wlong-long"
54static inline number nvMultM(number a, number b, const coeffs r)
55{
[6d0515d]56  assume( getCoeffType(r) == n_Zp );
[601105]57
[40e88db]58#if SIZEOF_LONG == 4
59#define ULONG64 (unsigned long long)(unsigned long)
60#else
61#define ULONG64 (unsigned long)
62#endif
[601105]63  return (number)
[40e88db]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);
[cc16f0]69//void    nvPower       (number a, int i, number * result, const coeffs r);
[40e88db]70#endif
71
[7d90aa]72BOOLEAN npGreaterZero (number k, const coeffs r)
[35aab3]73{
[eb55f8a]74  n_Test(k, r);
[601105]75
[7447d8]76  int h = (int)((long) k);
[e77676]77  return ((int)h !=0) && (h <= (r->ch>>1));
[35aab3]78}
79
[e77676]80//unsigned long npMultMod(unsigned long a, unsigned long b, int npPrimeM)
[35aab3]81//{
82//  unsigned long c = a*b;
83//  c = c % npPrimeM;
[e77676]84//  assume(c == (unsigned long) npMultM((number) a, (number) b, npPrimeM));
[35aab3]85//  return c;
86//}
87
[7d90aa]88number npMult (number a,number b, const coeffs r)
[35aab3]89{
[eb55f8a]90  n_Test(a, r);
91  n_Test(b, r);
[0461f0]92
[35aab3]93  if (((long)a == 0) || ((long)b == 0))
94    return (number)0;
[0461f0]95  number c = npMultM(a,b, r);
[eb55f8a]96  n_Test(c, r);
[601105]97  return c;
[35aab3]98}
99
100/*2
101* create a number from int
102*/
[2f3764]103number npInit (long i, const coeffs r)
[35aab3]104{
[d8b0997]105  long ii=i % (long)r->ch;
106  if (ii <  0L)                         ii += (long)r->ch;
107
[0461f0]108  number c = (number)ii;
[eb55f8a]109  n_Test(c, r);
[0461f0]110  return c;
[35aab3]111}
112
[0461f0]113
[35aab3]114/*2
[0461f0]115 * convert a number to an int in (-p/2 .. p/2]
116 */
[777f8b]117long npInt(number &n, const coeffs r)
[35aab3]118{
[eb55f8a]119  n_Test(n, r);
[601105]120
[777f8b]121  if ((long)n > (((long)r->ch) >>1)) return ((long)n -((long)r->ch));
122  else                               return ((long)n);
[35aab3]123}
124
[7d90aa]125number npAdd (number a, number b, const coeffs r)
[35aab3]126{
[eb55f8a]127  n_Test(a, r);
128  n_Test(b, r);
[601105]129
[0461f0]130  number c = npAddM(a,b, r);
131
[eb55f8a]132  n_Test(c, r);
[601105]133
[0461f0]134  return c;
[35aab3]135}
136
[7d90aa]137number npSub (number a, number b, const coeffs r)
[35aab3]138{
[eb55f8a]139  n_Test(a, r);
140  n_Test(b, r);
[601105]141
[0461f0]142  number c = npSubM(a,b,r);
143
[eb55f8a]144  n_Test(c, r);
[0461f0]145
146  return c;
[35aab3]147}
148
[0461f0]149BOOLEAN npIsZero (number  a, const coeffs r)
[35aab3]150{
[eb55f8a]151  n_Test(a, r);
[601105]152
[35aab3]153  return 0 == (long)a;
154}
155
[0461f0]156BOOLEAN npIsOne (number a, const coeffs r)
[35aab3]157{
[eb55f8a]158  n_Test(a, r);
[601105]159
[35aab3]160  return 1 == (long)a;
161}
162
[7d90aa]163BOOLEAN npIsMOne (number a, const coeffs r)
[35aab3]164{
[eb55f8a]165  n_Test(a, r);
[601105]166
[961c76]167  return ((r->npPminus1M == (long)a) &&(1L!=(long)a))/*for char 2*/;
[35aab3]168}
169
170#ifdef HAVE_DIV_MOD
[a74143]171
[1fc18b]172#ifdef USE_NTL_XGCD
[a74143]173
[1fc18b]174//ifdef HAVE_NTL // in ntl.a
[35aab3]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
[a74143]180
[1fc18b]181#endif
[35aab3]182
[7d90aa]183long InvMod(long a, const coeffs R)
[1fc18b]184{
185   long d, s, t;
[35aab3]186
[1fc18b]187#ifdef USE_NTL_XGCD
[e77676]188   XGCD(d, s, t, a, R->ch);
[1fc18b]189   assume (d == 1);
190#else
191   long  u, v, u0, v0, u1, v1, u2, v2, q, r;
[35aab3]192
[1fc18b]193   assume(a>0);
194   u1=1; u2=0;
[e77676]195   u = a; v = R->ch;
[35aab3]196
[1fc18b]197   while (v != 0)
198   {
[35aab3]199      q = u / v;
200      r = u % v;
201      u = v;
202      v = r;
203      u0 = u2;
[1fc18b]204      u2 = u1 - q*u2;
[35aab3]205      u1 = u0;
206   }
207
[1fc18b]208   assume(u==1);
[35aab3]209   s = u1;
210#endif
211   if (s < 0)
[e77676]212      return s + R->ch;
[35aab3]213   else
214      return s;
215}
216#endif
217
[7d90aa]218inline number npInversM (number c, const coeffs r)
[35aab3]219{
[eb55f8a]220  n_Test(c, r);
[35aab3]221#ifndef HAVE_DIV_MOD
[0461f0]222  number d = (number)(long)r->npExpTable[r->npPminus1M - r->npLogTable[(long)c]];
[35aab3]223#else
[7d90aa]224  long inv=(long)r->npInvTable[(long)c];
[35aab3]225  if (inv==0)
226  {
[7d90aa]227    inv=InvMod((long)c,r);
228    r->npInvTable[(long)c]=inv;
[35aab3]229  }
[0461f0]230  number d = (number)inv;
[35aab3]231#endif
[eb55f8a]232  n_Test(d, r);
[0461f0]233  return d;
234
[35aab3]235}
236
[7d90aa]237number npDiv (number a,number b, const coeffs r)
[35aab3]238{
[eb55f8a]239  n_Test(a, r);
240  n_Test(b, r);
[0461f0]241
[6c15ec]242//#ifdef NV_OPS
[e77676]243//  if (r->ch>NV_MAX_PRIME)
[6c15ec]244//    return nvDiv(a,b);
245//#endif
[9b88e6]246  if ((long)a==0L)
247    return (number)0L;
[0461f0]248  number d;
[601105]249
[35aab3]250#ifndef HAVE_DIV_MOD
[9b88e6]251  if ((long)b==0L)
[35aab3]252  {
[b7e838]253    WerrorS(nDivBy0);
[9b88e6]254    return (number)0L;
[35aab3]255  }
[601105]256
[0461f0]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];
[35aab3]261#else
[7d90aa]262  number inv=npInversM(b,r);
[0461f0]263  d = npMultM(a,inv,r);
[35aab3]264#endif
[0461f0]265
[eb55f8a]266  n_Test(d, r);
[0461f0]267  return d;
[601105]268
[35aab3]269}
[7d90aa]270number  npInvers (number c, const coeffs r)
[35aab3]271{
[eb55f8a]272  n_Test(c, r);
[601105]273
[9b88e6]274  if ((long)c==0L)
[35aab3]275  {
276    WerrorS("1/0");
[9b88e6]277    return (number)0L;
[35aab3]278  }
[0461f0]279  number d = npInversM(c,r);
[601105]280
[eb55f8a]281  n_Test(d, r);
[0461f0]282  return d;
[35aab3]283}
284
[7d90aa]285number npNeg (number c, const coeffs r)
[35aab3]286{
[eb55f8a]287  n_Test(c, r);
[601105]288
[9b88e6]289  if ((long)c==0L) return c;
[0461f0]290
[601105]291#if 0
292  number d = npNegM(c,r);
[eb55f8a]293  n_Test(d, r);
[0461f0]294  return d;
295#else
[601105]296  c = npNegM(c,r);
[eb55f8a]297  n_Test(c, r);
[0461f0]298  return c;
[601105]299#endif
[35aab3]300}
301
[0461f0]302BOOLEAN npGreater (number a,number b, const coeffs r)
[35aab3]303{
[eb55f8a]304  n_Test(a, r);
305  n_Test(b, r);
[0461f0]306
[35aab3]307  //return (long)a != (long)b;
[9b88e6]308  return ((long)a) > ((long)b);
[35aab3]309}
310
[7d90aa]311BOOLEAN npEqual (number a,number b, const coeffs r)
[35aab3]312{
[eb55f8a]313  n_Test(a, r);
314  n_Test(b, r);
[601105]315
[35aab3]316//  return (long)a == (long)b;
[601105]317
[7d90aa]318  return npEqualM(a,b,r);
[35aab3]319}
320
[6d92ca]321void npWrite (number a, const coeffs r)
[35aab3]322{
[eb55f8a]323  n_Test(a, r);
[601105]324
[493225]325  if ((long)a>(((long)r->ch) >>1)) StringAppend("-%d",(int)(((long)r->ch)-((long)a)));
326  else                             StringAppend("%d",(int)((long)a));
[35aab3]327}
328
[cc16f0]329#if 0
[7d90aa]330void npPower (number a, int i, number * result, const coeffs r)
[35aab3]331{
[eb55f8a]332  n_Test(a, r);
[0461f0]333
[35aab3]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  {
[7d90aa]345    npPower(a,i-1,result,r);
346    *result = npMultM(a,*result,r);
[35aab3]347  }
348}
[cc16f0]349#endif
[35aab3]350
[7d90aa]351static const char* npEati(const char *s, int *i, const coeffs r)
[35aab3]352{
353  if (((*s) >= '0') && ((*s) <= '9'))
354  {
[923b64]355    unsigned long ii=0L;
[35aab3]356    do
357    {
[923b64]358      ii *= 10;
359      ii += *s++ - '0';
[e77676]360      if (ii >= (MAX_INT_VAL / 10)) ii = ii % r->ch;
[35aab3]361    }
362    while (((*s) >= '0') && ((*s) <= '9'));
[95eeda]363    if (ii >= (unsigned long)r->ch) ii = ii % r->ch;
[923b64]364    *i=(int)ii;
[35aab3]365  }
366  else (*i) = 1;
367  return s;
368}
369
[7d90aa]370const char * npRead (const char *s, number *a, const coeffs r)
[35aab3]371{
372  int z;
373  int n=1;
374
[7d90aa]375  s = npEati(s, &z, r);
[35aab3]376  if ((*s) == '/')
377  {
378    s++;
[7d90aa]379    s = npEati(s, &n, r);
[35aab3]380  }
381  if (n == 1)
[e2202ee]382    *a = (number)(long)z;
[6c15ec]383  else
[100025]384  {
385    if ((z==0)&&(n==0)) WerrorS(nDivBy0);
[35aab3]386    else
[100025]387    {
388#ifdef NV_OPS
[e77676]389      if (r->ch>NV_MAX_PRIME)
[e2202ee]390        *a = nvDiv((number)(long)z,(number)(long)n,r);
[100025]391      else
[6c15ec]392#endif
[e2202ee]393        *a = npDiv((number)(long)z,(number)(long)n,r);
[100025]394    }
395  }
[eb55f8a]396  n_Test(*a, r);
[35aab3]397  return s;
398}
399
400/*2
401* set the charcteristic (allocate and init tables)
402*/
403
[8c484e]404void npKillChar(coeffs r)
405{
406  #ifdef HAVE_DIV_MOD
407  if (r->npInvTable!=NULL)
[e77676]408  omFreeSize( (void *)r->npInvTable, r->ch*sizeof(unsigned short) );
[8c484e]409  r->npInvTable=NULL;
410  #else
411  if (r->npExpTable!=NULL)
412  {
[e77676]413    omFreeSize( (void *)r->npExpTable, r->ch*sizeof(unsigned short) );
414    omFreeSize( (void *)r->npLogTable, r->ch*sizeof(unsigned short) );
[8c484e]415    r->npExpTable=NULL; r->npLogTable=NULL;
416  }
417  #endif
418}
419
[aff5ae]420static BOOLEAN npCoeffsEqual(const coeffs r, n_coeffType n, void * parameter)
[d2cf18]421{
422  /* test, if r is an instance of nInitCoeffs(n,parameter) */
[aff5ae]423  return (n==n_Zp) && (r->ch==(int)(long)parameter);
[d2cf18]424}
[abb4787]425CanonicalForm npConvSingNFactoryN( number n, BOOLEAN setChar, const coeffs r )
[eca225]426{
[e77676]427  if (setChar) setCharacteristic( r->ch );
[eca225]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  {
[a934fc8]436    return npInit(n.intval(),r);
[eca225]437  }
438  else
439  {
440    assume(0);
[c262d5]441    return NULL;
[eca225]442  }
443}
[d2cf18]444
[9a1960]445static char* npCoeffName(const coeffs cf)
[45cc512]446{
[9a1960]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));
[45cc512]455}
456
[f5e732]457static void npWriteFd(number n, FILE* f, const coeffs)
[850277]458{
459  fprintf(f,"%d ",(int)(long)n);
460}
461
[f5e732]462static number npReadFd(s_buff f, const coeffs)
[850277]463{
464  // read int
465  int dd;
466  dd=s_readint(f);
467  return (number)(long)dd;
468}
469
[0d97a85]470static number npRandom(siRandProc p, number, number, const coeffs cf)
[14ace0]471{
[0d97a85]472  return npInit(p(),cf);
[14ace0]473}
474
[1cce47]475BOOLEAN npInitChar(coeffs r, void* p)
[35aab3]476{
[6d0515d]477  assume( getCoeffType(r) == n_Zp );
[11206af]478  const int c = (int) (long) p;
479
480  assume( c > 0 );
[601105]481
[35aab3]482  int i, w;
483
[36a8e9]484  r->is_field=TRUE;
485  r->is_domain=TRUE;
[6a1aa7]486  r->rep=n_rep_int;
[36a8e9]487
[e77676]488  r->ch = c;
489  r->npPminus1M = c /*r->ch*/ - 1;
[d2cf18]490
491  //r->cfInitChar=npInitChar;
492  r->cfKillChar=npKillChar;
493  r->nCoeffIsEqual=npCoeffsEqual;
[45cc512]494  r->cfCoeffString=npCoeffString;
[9a1960]495  r->cfCoeffName=npCoeffName;
496  r->cfCoeffWrite=npCoeffWrite;
[d2cf18]497
[7bbbef]498  r->cfMult  = npMult;
499  r->cfSub   = npSub;
500  r->cfAdd   = npAdd;
501  r->cfDiv   = npDiv;
[d2cf18]502  r->cfInit = npInit;
[7bbbef]503  //r->cfSize  = ndSize;
504  r->cfInt  = npInt;
[d2cf18]505  #ifdef HAVE_RINGS
[7bbbef]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
[d2cf18]511  #endif
[ec89bb4]512  r->cfInpNeg   = npNeg;
[7bbbef]513  r->cfInvers= npInvers;
[aff5ae]514  //r->cfCopy  = ndCopy;
[7bbbef]515  //r->cfRePart = ndCopy;
516  //r->cfImPart = ndReturn0;
[ce1f78]517  r->cfWriteLong = npWrite;
[7bbbef]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;
[cc16f0]526  //r->cfPower = npPower;
[ac000b6]527  //r->cfGetDenom = ndGetDenom;
528  //r->cfGetNumerator = ndGetNumerator;
[7bbbef]529  //r->cfGcd  = ndGcd;
530  //r->cfLcm  = ndGcd;
[aff5ae]531  //r->cfDelete= ndDelete;
[d2cf18]532  r->cfSetMap = npSetMap;
[7bbbef]533  //r->cfName = ndName;
[ac000b6]534  //r->cfInpMult=ndInpMult;
[d2cf18]535#ifdef NV_OPS
536  if (c>NV_MAX_PRIME)
[35aab3]537  {
[7bbbef]538    r->cfMult  = nvMult;
539    r->cfDiv   = nvDiv;
540    r->cfExactDiv= nvDiv;
541    r->cfInvers= nvInvers;
[cc16f0]542    //r->cfPower= nvPower;
[d2cf18]543  }
544#endif
545#ifdef LDEBUG
546  // debug stuff
[7bbbef]547  r->cfDBTest=npDBTest;
[d2cf18]548#endif
[eca225]549
550  r->convSingNFactoryN=npConvSingNFactoryN;
551  r->convFactoryNSingN=npConvFactoryNSingN;
[601105]552
[14ace0]553  r->cfRandom=npRandom;
554
[850277]555  // io via ssi
556  r->cfWriteFd=npWriteFd;
557  r->cfReadFd=npReadFd;
558
[d2cf18]559  // the variables:
560  r->nNULL = (number)0;
[f0797c]561  r->type = n_Zp;
[d2cf18]562  r->ch = c;
563  r->has_simple_Alloc=TRUE;
564  r->has_simple_Inverse=TRUE;
565
566  // the tables
[35aab3]567#ifdef NV_OPS
[e77676]568  if (r->ch <=NV_MAX_PRIME)
[35aab3]569#endif
[aff5ae]570  {
[35aab3]571#if !defined(HAVE_DIV_MOD) || !defined(HAVE_MULT_MOD)
[e77676]572    r->npExpTable=(unsigned short *)omAlloc( r->ch*sizeof(unsigned short) );
573    r->npLogTable=(unsigned short *)omAlloc( r->ch*sizeof(unsigned short) );
[aff5ae]574    r->npExpTable[0] = 1;
575    r->npLogTable[0] = 0;
[e77676]576    if (r->ch > 2)
[aff5ae]577    {
578      w = 1;
579      loop
[35aab3]580      {
[aff5ae]581        r->npLogTable[1] = 0;
582        w++;
583        i = 0;
[35aab3]584        loop
585        {
[aff5ae]586          i++;
[2f864f]587          r->npExpTable[i] =(int)(((long)w * (long)r->npExpTable[i-1]) % r->ch);
[aff5ae]588          r->npLogTable[r->npExpTable[i]] = i;
[601105]589          if /*(i == r->ch - 1 ) ||*/ (/*(*/ r->npExpTable[i] == 1 /*)*/)
[35aab3]590            break;
591        }
[e77676]592        if (i == r->ch - 1)
[aff5ae]593          break;
[35aab3]594      }
[aff5ae]595    }
596    else
597    {
598      r->npExpTable[1] = 1;
599      r->npLogTable[1] = 0;
600    }
[35aab3]601#endif
602#ifdef HAVE_DIV_MOD
[e77676]603    r->npInvTable=(unsigned short*)omAlloc0( r->ch*sizeof(unsigned short) );
[35aab3]604#endif
[aff5ae]605  }
[5d594a9]606  return FALSE;
[35aab3]607}
608
609#ifdef LDEBUG
[2b957a]610BOOLEAN npDBTest (number a, const char *f, const int l, const coeffs r)
[35aab3]611{
[9b88e6]612  if (((long)a<0L) || ((long)a>(long)r->ch))
[35aab3]613  {
[f1e33bb]614    Print("wrong mod p number %ld at %s,%d\n",(long)a,f,l);
[35aab3]615    return FALSE;
616  }
617  return TRUE;
618}
619#endif
620
[29fc71e]621static number npMapP(number from, const coeffs src, const coeffs dst_r)
[35aab3]622{
623  long i = (long)from;
[e77676]624  if (i>src->ch/2)
[35aab3]625  {
[e77676]626    i-=src->ch;
627    while (i < 0) i+=dst_r->ch;
[35aab3]628  }
[e77676]629  i%=dst_r->ch;
[35aab3]630  return (number)i;
631}
632
[c262d5]633static number npMapLongR(number from, const coeffs /*src*/, const coeffs dst_r)
[35aab3]634{
635  gmp_float *ff=(gmp_float*)from;
636  mpf_t *f=ff->_mpfp();
637  number res;
[a604c3]638  mpz_ptr dest,ndest;
[35aab3]639  int size,i;
[c262d5]640  int e,al,bl;
[7447d8]641  long iz;
[35aab3]642  mp_ptr qp,dd,nn;
643
644  size = (*f)[0]._mp_size;
645  if (size == 0)
[7d90aa]646    return npInit(0,dst_r);
[35aab3]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
[e77676]657  if(dst_r->ch>2)
[35aab3]658    e=(*f)[0]._mp_exp-size;
659  else
660    e=0;
[896561]661  res = ALLOC_RNUMBER();
[35aab3]662#if defined(LDEBUG)
663  res->debug=123456;
664#endif
[a604c3]665  dest = res->z;
[35aab3]666
[e2202ee]667  long in=0;
[35aab3]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;
[a604c3]678    ndest = res->n;
[35aab3]679    ndest->_mp_d = nn;
680    ndest->_mp_alloc = ndest->_mp_size = bl;
681    res->s = 0;
[e77676]682    in=mpz_fdiv_ui(ndest,dst_r->ch);
[35aab3]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;
[e77676]697  iz=mpz_fdiv_ui(dest,dst_r->ch);
[35aab3]698  mpz_clear(dest);
699  if(res->s==0)
[8c484e]700    iz=(long)npDiv((number)iz,(number)in,dst_r);
[d663f2]701  FREE_RNUMBER(res); // Q!?
[35aab3]702  return (number)iz;
703}
704
[894f5b1]705#ifdef HAVE_RINGS
706/*2
707* convert from a GMP integer
708*/
[29fc71e]709static number npMapGMP(number from, const coeffs /*src*/, const coeffs dst)
[894f5b1]710{
[6a70f3]711  mpz_ptr erg = (mpz_ptr) omAlloc(sizeof(mpz_t)); // evtl. spaeter mit bin
[894f5b1]712  mpz_init(erg);
713
[6a70f3]714  mpz_mod_ui(erg, (mpz_ptr) from, dst->ch);
[894f5b1]715  number r = (number) mpz_get_si(erg);
716
717  mpz_clear(erg);
[7d90aa]718  omFree((void *) erg);
[894f5b1]719  return (number) r;
720}
721
[29fc71e]722static number npMapZ(number from, const coeffs src, const coeffs dst)
[6a1aa7]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
[894f5b1]732/*2
733* convert from an machine long
734*/
[29fc71e]735static number npMapMachineInt(number from, const coeffs /*src*/,const coeffs dst)
[894f5b1]736{
[e77676]737  long i = (long) (((unsigned long) from) % dst->ch);
[894f5b1]738  return (number) i;
739}
740#endif
741
[29fc71e]742static number npMapCanonicalForm (number a, const coeffs /*src*/, const coeffs dst)
[e9d796]743{
[e77676]744  setCharacteristic (dst ->ch);
[e9d796]745  CanonicalForm f= CanonicalForm ((InternalCF*)(a));
746  return (number) (f.intval());
747}
748
[7d90aa]749nMapFunc npSetMap(const coeffs src, const coeffs dst)
[35aab3]750{
[894f5b1]751#ifdef HAVE_RINGS
[6a1aa7]752  if ((src->rep==n_rep_int) && nCoeff_is_Ring_2toM(src))
[894f5b1]753  {
754    return npMapMachineInt;
755  }
[6a1aa7]756  if (src->rep==n_rep_gmp) //nCoeff_is_Ring_Z(src) || nCoeff_is_Ring_PtoM(src) || nCoeff_is_Ring_ModN(src))
[894f5b1]757  {
758    return npMapGMP;
759  }
[6a1aa7]760  if (src->rep==n_rep_gap_gmp) //nCoeff_is_Ring_Z(src)
761  {
762    return npMapZ;
763  }
[894f5b1]764#endif
[6a1aa7]765  if (src->rep==n_rep_gap_rat)  /* Q, Z */
[75f460]766  {
[2206753]767    return nlModP; // npMap0; // FIXME? TODO? // extern number nlModP(number q, const coeffs Q, const coeffs Zp); // Map q \in QQ \to Zp // FIXME!
[35aab3]768  }
[6a1aa7]769  if ((src->rep==n_rep_int) &&  nCoeff_is_Zp(src) )
[35aab3]770  {
[7d90aa]771    if (n_GetChar(src) == n_GetChar(dst))
[35aab3]772    {
[8c484e]773      return ndCopyMap;
[35aab3]774    }
775    else
776    {
777      return npMapP;
778    }
779  }
[6a1aa7]780  if ((src->rep==n_rep_gmp_float) && nCoeff_is_long_R(src))
[35aab3]781  {
782    return npMapLongR;
783  }
[1cce47]784  if (nCoeff_is_CF (src))
[e9d796]785  {
786    return npMapCanonicalForm;
787  }
[35aab3]788  return NULL;      /* default */
789}
790
791// -----------------------------------------------------------
[a1299c]792//  operation for very large primes (32749< p < 2^31-1)
[35aab3]793// ----------------------------------------------------------
794#ifdef NV_OPS
795
[7d90aa]796number nvMult (number a,number b, const coeffs r)
[35aab3]797{
[2e1b74]798  //if (((long)a == 0) || ((long)b == 0))
799  //  return (number)0;
800  //else
[4d92d7]801    return nvMultM(a,b,r);
[35aab3]802}
803
[4d92d7]804void   nvInpMult(number &a, number b, const coeffs r)
[2e1b74]805{
[4d92d7]806  number n=nvMultM(a,b,r);
[2e1b74]807  a=n;
808}
809
810
[a74143]811inline long nvInvMod(long a, const coeffs R)
[35aab3]812{
[a74143]813#ifdef HAVE_DIV_MOD
814  return InvMod(a, R);
815#else
816/// TODO: use "long InvMod(long a, const coeffs R)"?!
[601105]817
[c262d5]818   long  s;
[35aab3]819
[601105]820   long  u, u0, u1, u2, q, r; // v0, v1, v2,
[35aab3]821
[a74143]822   u1=1; // v1=0;
823   u2=0; // v2=1;
824   u = a;
825
826   long v = R->ch;
[35aab3]827
[9c8927]828   while (v != 0)
829   {
[35aab3]830      q = u / v;
831      r = u % v;
832      u = v;
833      v = r;
834      u0 = u2;
[a74143]835//      v0 = v2;
836      u2 = u1 - q*u2;
837//      v2 = v1 - q*v2;
[35aab3]838      u1 = u0;
[a74143]839//      v1 = v0;
[35aab3]840   }
841
842   s = u1;
843   //t = v1;
844   if (s < 0)
[e77676]845      return s + R->ch;
[35aab3]846   else
[a74143]847     return s;
848#endif
[35aab3]849}
850
[7d90aa]851inline number nvInversM (number c, const coeffs r)
[35aab3]852{
[7d90aa]853  long inv=nvInvMod((long)c,r);
[35aab3]854  return (number)inv;
855}
856
[7d90aa]857number nvDiv (number a,number b, const coeffs r)
[35aab3]858{
[9b88e6]859  if ((long)a==0L)
860    return (number)0L;
861  else if ((long)b==0L)
[35aab3]862  {
[b7e838]863    WerrorS(nDivBy0);
[9b88e6]864    return (number)0L;
[35aab3]865  }
866  else
867  {
[7d90aa]868    number inv=nvInversM(b,r);
869    return nvMultM(a,inv,r);
[35aab3]870  }
871}
[7d90aa]872number  nvInvers (number c, const coeffs r)
[35aab3]873{
[9b88e6]874  if ((long)c==0L)
[35aab3]875  {
[b7e838]876    WerrorS(nDivBy0);
[9b88e6]877    return (number)0L;
[35aab3]878  }
[7d90aa]879  return nvInversM(c,r);
[35aab3]880}
[cc16f0]881#if 0
[7d90aa]882void nvPower (number a, int i, number * result, const coeffs r)
[9c8927]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  {
[7d90aa]895    nvPower(a,i-1,result,r);
896    *result = nvMultM(a,*result,r);
[9c8927]897  }
898}
[35aab3]899#endif
[cc16f0]900#endif
[c7e3d7]901
[03f7b5]902void    npCoeffWrite  (const coeffs r, BOOLEAN /*details*/)
[c7e3d7]903{
[8d1432e]904  Print("ZZ/%d",r->ch);
[c7e3d7]905}
906
Note: See TracBrowser for help on using the repository browser.