source: git/libpolys/coeffs/modulop.cc @ 961c76

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