source: git/libpolys/coeffs/numbers.cc @ 7fe9e13

spielwiese
Last change on this file since 7fe9e13 was 7fe9e13, checked in by Oleksandr Motsak <motsak@…>, 10 years ago
Renamed NDEBUG -> SING_NDEBUG in order to avoid confusion with GCC macro
  • Property mode set to 100644
File size: 13.5 KB
RevLine 
[35aab3]1/*****************************************
2*  Computer Algebra System SINGULAR      *
3*****************************************/
4
5/*
6* ABSTRACT: interface to coefficient aritmetics
7*/
8
[22a09d]9#include <string.h>
10#include <stdlib.h>
11
[16f511]12#ifdef HAVE_CONFIG_H
[ba5e9e]13#include "libpolysconfig.h"
[16f511]14#endif /* HAVE_CONFIG_H */
[18cb65]15#include <misc/auxiliary.h>
[1112b76]16
[22a09d]17#include <factory/factory.h>
[1112b76]18
[e3b233]19#include "coeffs.h"
[2d805a]20#include <coeffs/numbers.h>
[1112b76]21
[18cb65]22#include <reporter/reporter.h>
23#include <omalloc/omalloc.h>
[2d805a]24#include <coeffs/numbers.h>
25#include <coeffs/longrat.h>
26#include <coeffs/modulop.h>
27#include <coeffs/gnumpfl.h>
28#include <coeffs/gnumpc.h>
29#include <coeffs/ffields.h>
30#include <coeffs/shortfl.h>
[047597]31
[c90b43]32#ifdef HAVE_RINGS
[2d805a]33#include <coeffs/rmodulo2m.h>
34#include <coeffs/rmodulon.h>
35#include <coeffs/rintegers.h>
[1e579c6]36#endif
[9eb0f9]37
[7af488e]38#ifdef HAVE_POLYEXTENSIONS
39#include <polys/ext_fields/algext.h>
[047597]40#include <polys/ext_fields/transext.h>
[7af488e]41#endif
42
[3aae0e]43
44
[35aab3]45//static int characteristic = 0;
[ce7f16]46//extern int IsPrime(int p);
[35aab3]47
48n_Procs_s *cf_root=NULL;
49
[b19a41d]50void   nNew(number* d) { *d=NULL; }
[9bb5457]51void   ndDelete(number* d, const coeffs) { *d=NULL; }
[45cc512]52char* ndCoeffString(const coeffs r)
53{
54  char *s=(char *)omAlloc(11);snprintf(s,11,"Coeffs(%d)",r->type);
55  return s;
56}
[7d90aa]57void   ndInpMult(number &a, number b, const coeffs r)
[35aab3]58{
59  number n=n_Mult(a,b,r);
60  n_Delete(&a,r);
61  a=n;
62}
[35eaf8]63void ndInpAdd(number &a, number b, const coeffs r)
[e8a0aa]64{
65  number n=n_Add(a,b,r);
66  n_Delete(&a,r);
67  a=n;
68}
[35aab3]69
70#ifdef LDEBUG
[9bb5457]71void   nDBDummy1(number* d,char *, int) { *d=NULL; }
72BOOLEAN ndDBTest(number, const char *, const int, const coeffs)
[85e68dd]73{
74  return TRUE;
75}
[35aab3]76#endif
77
[7938a0f]78number ndFarey(number,number,const coeffs r)
79{
80  Werror("farey not implemented for (c=%d)",getCoeffType(r));
81  return NULL;
82}
[de27d8]83number ndChineseRemainder(number *,number *,int,BOOLEAN,const coeffs r)
[7938a0f]84{
85  Werror("ChineseRemainder not implemented for (c=%d)",getCoeffType(r));
86  return n_Init(0,r); 
87}
88
[da5d77]89static int ndParDeg(number n, const coeffs r)
[48a41a]90{
91  return (-n_IsZero(n,r));
92}
93
[b807aa0]94static number ndParameter(const int, const coeffs r)
[7fee876]95{
96  Werror("ndParameter: n_Parameter is not implemented/relevant for (coeff_type = %d)",getCoeffType(r));
97  return NULL;
98}
[e5422d]99
[6c084af]100BOOLEAN n_IsZeroDivisor( number a, const coeffs r)
[e5422d]101{
102  int c = n_GetChar(r);
103  BOOLEAN ret = n_IsZero(a, r);
104  if( (c != 0) && !ret )
105  {
106    number ch = n_Init( c, r ); 
107    number g = n_Gcd( ch, a, r );
108    ret = !n_IsOne (g, r);
109    n_Delete(&ch, r);
110    n_Delete(&g, r);
111  }
112  return ret; 
113}
114
[9bb5457]115void   ndNormalize(number&, const coeffs) { }
[35aab3]116
[9bb5457]117char * ndName(number, const coeffs) { return NULL; }
[35aab3]118
[9bb5457]119number ndReturn0(number, const coeffs r) { return n_Init(0,r); }
[35aab3]120
[121fd9]121number ndGcd(number, number, const coeffs r) { return n_Init(1,r); }
[35aab3]122
[121fd9]123number ndIntMod(number, number, const coeffs r) { return n_Init(0,r); }
[35aab3]124
[121fd9]125number ndGetDenom(number &, const coeffs r) { return n_Init(1,r); }
[7d90aa]126number ndGetNumerator(number &a,const coeffs r) { return n_Copy(a,r); }
[35aab3]127
[7d90aa]128int ndSize(number a, const coeffs r) { return (int)n_IsZero(a,r)==FALSE; }
[35aab3]129
[de88371]130void ndClearContent(ICoeffsEnumerator& numberCollectionEnumerator, number& c, const coeffs r)
[98474f]131{
132  assume(r != NULL);
133
134  // no fractions
[dc79bd]135  assume(!(  nCoeff_is_Q(r) ));
[98474f]136  // all coeffs are given by integers!!!
137
138  numberCollectionEnumerator.Reset();
[9952bd]139
140  if( !numberCollectionEnumerator.MoveNext() ) // empty zero polynomial?
141  {
142    c = n_Init(1, r);
143    return;
144  } 
145
146  number &curr = numberCollectionEnumerator.Current();
[98474f]147 
148#ifdef HAVE_RINGS
149  /// TODO: move to a separate implementation
150  if (nCoeff_is_Ring(r))
151  {
152    if (nCoeff_has_Units(r))
153    {
[9952bd]154      c = n_GetUnit(curr, r);
[98474f]155     
156      if (!n_IsOne(c, r))
157      {
158        number inv = n_Invers(c, r);
159
[9952bd]160        n_InpMult(curr, inv, r);
161       
162        while( numberCollectionEnumerator.MoveNext() )
[98474f]163        {
[9952bd]164          number &n = numberCollectionEnumerator.Current();
165          n_Normalize(n, r); // ?
166          n_InpMult(n, inv, r); // TODO: either this or directly divide!!!?
[98474f]167        }
168
169        n_Delete(&inv, r);       
170      }     
171    } else c = n_Init(1, r);
172   
173    return;
174  }
175#endif
176
177  assume(!nCoeff_is_Ring(r));
[dc79bd]178  assume(nCoeff_is_Zp(r) || nCoeff_is_numeric(r) || nCoeff_is_GF(r) || nCoeff_is_Zp_a(r) || nCoeff_is_Q_algext(r));
[98474f]179
[dc79bd]180  n_Normalize(curr, r); // Q: good/bad/ugly??
181
182  if (!n_IsOne(curr, r))
183  {
184    number t = curr; // takes over the curr! note: not a reference!!!
[98474f]185
[9952bd]186    curr = n_Init(1, r); // ???
[98474f]187   
[dc79bd]188    number inv = n_Invers(t, r);
[98474f]189   
190    while( numberCollectionEnumerator.MoveNext() )
191    {
192      number &n = numberCollectionEnumerator.Current();
[9952bd]193      n_InpMult(n, inv, r); // TODO: either this or directly divide!!!?
[dc79bd]194//      n_Normalize(n, r); // ?
[98474f]195    }
196   
197    n_Delete(&inv, r);
[dc79bd]198
199    c = t;
200  } else
201    c = n_Copy(curr, r); // c == 1 and nothing else to do...
[98474f]202}
203
[de88371]204void ndClearDenominators(ICoeffsEnumerator& /*numberCollectionEnumerator*/, number& d, const coeffs r)
[98474f]205{
206  assume( r != NULL );
[560a3d]207  assume( !(nCoeff_is_Q(r) || nCoeff_is_transExt(r) || nCoeff_is_algExt(r)) );
208  assume( nCoeff_is_Ring(r) || nCoeff_is_Zp(r) || nCoeff_is_numeric(r) || nCoeff_is_GF(r) );
[98474f]209
210  d = n_Init(1, r);
211}
212
[3aae0e]213number ndCopy(number a, const coeffs) { return a; }
[dc093ce]214number ndCopyMap(number a, const coeffs aRing, const coeffs r)
[3aae0e]215{
216  assume( getCoeffType(r) == getCoeffType(aRing) );
[2cc7c7]217  if ( nCoeff_has_simple_Alloc(r) && nCoeff_has_simple_Alloc(aRing) )
218    return a;
219        else
220    return n_Copy(a, r);
[3aae0e]221}
[b19ab84]222void ndKillChar(coeffs) {}
[32cc7e]223void ndSetChar(const coeffs) {}
[3aae0e]224
225number nd_Copy(number a, const coeffs r) { return n_Copy(a, r); }
[35aab3]226
[009d80]227#ifdef HAVE_RINGS
[9bb5457]228BOOLEAN ndDivBy(number, number, const coeffs) { return TRUE; } // assume a,b !=0
229int ndDivComp(number, number, const coeffs) { return 2; }
[8e12467]230BOOLEAN ndIsUnit(number a, const coeffs r) { return !n_IsZero(a,r); }
[9bb5457]231number  ndExtGcd (number, number, number *, number *, const coeffs r) { return n_Init(1,r); }
[009d80]232#endif
233
[9bb5457]234CanonicalForm ndConvSingNFactoryN( number, BOOLEAN /*setChar*/, const coeffs)
[eca225]235{
236  CanonicalForm term(0);
237  Werror("no conversion to factory");
238  return term;
239}
240
[9bb5457]241number ndConvFactoryNSingN( const CanonicalForm, const coeffs)
[eca225]242{
243  Werror("no conversion from factory");
244  return NULL;
245}
246
[121fd9]247number  ndInit_bigint(number, const coeffs, const coeffs)
[2544e7]248{
249  Werror("no conversion from bigint to this field");
250  return NULL;
251}
[eca225]252
[045efb]253/**< [in, out] a bigint number >= 0  */
254/**< [out] the GMP equivalent    */
255/// Converts a non-negative bigint number into a GMP number.
256void ndMPZ(mpz_t result, number &n, const coeffs r)
257{
258  mpz_init_set_si( result, n_Int(n, r) );
259}
260
261number ndInitMPZ(mpz_t m, const coeffs r)
262{ 
263  return n_Init( mpz_get_si(m), r);
264}
265
[121fd9]266
267BOOLEAN ndCoeffIsEqual(const coeffs r, n_coeffType n, void *)
268{
269  /* test, if r is an instance of nInitCoeffs(n,parameter) */
270  /* if paramater is not needed */
271  return (n==r->type);
272}
273
[7af488e]274static n_coeffType nLastCoeffs=n_CF;
275cfInitCharProc nInitCharTableDefault[]=
276{ NULL,        /*n_unknown */
277 npInitChar,   /* n_Zp */
278 nlInitChar,   /* n_Q */
279 nrInitChar,   /* n_R */
280 nfInitChar,   /* n_GF */
281 ngfInitChar,  /* n_long_R */
282 #ifdef HAVE_POLYEXTENSIONS
283 naInitChar,  /* n_algExt */
[047597]284 ntInitChar,  /* n_transExt */
[7af488e]285 #else
286 NULL,        /* n_algExt */
[047597]287 NULL,        /* n_transExt */
288 #endif   
[7af488e]289 ngcInitChar,  /* n_long_C */
290 #ifdef HAVE_RINGS
291 nrzInitChar,  /* n_Z */
292 nrnInitChar,  /* n_Zn */
[ea25bc]293 nrnInitChar,  /* n_Znm */
[7af488e]294 nr2mInitChar, /* n_Z2m */
295 #else
296 NULL,         /* n_Z */
297 NULL,         /* n_Zn */
[ea25bc]298 NULL,         /* n_Znm */
[7af488e]299 NULL,         /* n_Z2m */
300 #endif
301 NULL   /* n_CF */
302};
303
304static cfInitCharProc *nInitCharTable=nInitCharTableDefault;
[35aab3]305/*2
[7d90aa]306* init operations for coeffs r
[35aab3]307*/
[aff5ae]308coeffs nInitChar(n_coeffType t, void * parameter)
[35aab3]309{
310  n_Procs_s *n=cf_root;
[1112b76]311
312  while((n!=NULL) && (n->nCoeffIsEqual!=NULL) && (!n->nCoeffIsEqual(n,t,parameter)))
[35aab3]313      n=n->next;
[1112b76]314
[35aab3]315  if (n==NULL)
316  {
317    n=(n_Procs_s*)omAlloc0(sizeof(n_Procs_s));
318    n->next=cf_root;
319    n->ref=1;
320    n->type=t;
[aff5ae]321
322    // default entries (different from NULL) for some routines:
[34bed3]323    n->nCoeffIsEqual = ndCoeffIsEqual;
[7bbbef]324    n->cfSize = ndSize;
[aff5ae]325    n->cfGetDenom= ndGetDenom;
326    n->cfGetNumerator= ndGetNumerator;
[7bbbef]327    n->cfName =  ndName;
328    n->cfImPart=ndReturn0;
[aff5ae]329    n->cfDelete= ndDelete;
[45cc512]330    n->cfCoeffString = ndCoeffString; // should alway be changed!
[7bbbef]331    n->cfInpMult=ndInpMult;
[240295]332    n->cfInpAdd=ndInpAdd;
[3159bc]333    n->cfCopy = ndCopy;
[7bbbef]334    n->cfIntMod=ndIntMod; /* dummy !! */
335    n->cfNormalize=ndNormalize;
336    n->cfGcd  = ndGcd;
337    n->cfLcm  = ndGcd; /* tricky, isn't it ?*/
[2544e7]338    n->cfInit_bigint = ndInit_bigint;
[045efb]339    n->cfInitMPZ = ndInitMPZ;
340    n->cfMPZ = ndMPZ;
341
[0bfec5]342    // n->cfKillChar = ndKillChar; /* dummy */
[32cc7e]343    n->cfSetChar = ndSetChar; /* dummy */
[b19ab84]344    // temp. removed to catch all the coeffs which miss to implement this!
[1112b76]345
[e8c8d5]346    n->cfChineseRemainder = ndChineseRemainder;
[7938a0f]347    n->cfFarey = ndFarey;
[48a41a]348    n->cfParDeg = ndParDeg;
[7fee876]349   
350    n->cfParameter = ndParameter;
[e8c8d5]351
[98474f]352    n->cfClearContent = ndClearContent;
353    n->cfClearDenominators = ndClearDenominators;
354
[009d80]355#ifdef HAVE_RINGS
[7bbbef]356    n->cfDivComp = ndDivComp;
357    n->cfDivBy = ndDivBy;
358    n->cfIsUnit = ndIsUnit;
359    n->cfExtGcd = ndExtGcd;
360    //n->cfGetUnit = (nMapFunc)NULL;
[009d80]361#endif
[eca225]362
363#ifdef fACTORY
364    n->convSingNFactoryN=ndConvSingNFactoryN;
365    n->convFactoryNSingN=ndConvFactoryNSingN;
366#endif
[1cce47]367   
368    BOOLEAN nOK=TRUE;
[aff5ae]369    // init
[7af488e]370    if ((t<=nLastCoeffs) && (nInitCharTable[t]!=NULL))
[1cce47]371      nOK = (nInitCharTable[t])(n,parameter);
372    else
[047597]373       Werror("Sorry: the coeff type [%d] was not registered: it is missing in nInitCharTable", (int)t);
[1cce47]374    if (nOK)
[fb0a699]375    {
376      omFreeSize(n,sizeof(*n));
377      return NULL;
378    }
[1cce47]379    cf_root=n;
[aff5ae]380    // post init settings:
[7bbbef]381    if (n->cfRePart==NULL) n->cfRePart=n->cfCopy;
382    if (n->cfIntDiv==NULL) n->cfIntDiv=n->cfDiv;
[1112b76]383   
[c90b43]384#ifdef HAVE_RINGS
[b19ab84]385    if (n->cfGetUnit==NULL) n->cfGetUnit=n->cfCopy;
[740417]386#endif
[ce1f78]387
388    if(n->cfWriteShort==NULL)
389      n->cfWriteShort = n->cfWriteLong;
[f630e4]390
[b19ab84]391    assume(n->nCoeffIsEqual!=NULL);
[f630e4]392    assume(n->cfSetChar!=NULL);
[45cc512]393    assume(n->cfCoeffString!=ndCoeffString);
[b19ab84]394    assume(n->cfMult!=NULL);
395    assume(n->cfSub!=NULL);
396    assume(n->cfAdd!=NULL);
397    assume(n->cfDiv!=NULL);
398    assume(n->cfIntDiv!=NULL);
399    assume(n->cfIntMod!=NULL);
400    assume(n->cfExactDiv!=NULL);
401    assume(n->cfInit!=NULL);
[045efb]402    assume(n->cfInitMPZ!=NULL);
[b19ab84]403    assume(n->cfSize!=NULL);
404    assume(n->cfInt!=NULL);
[045efb]405    assume(n->cfMPZ!=NULL);
[b19ab84]406    //assume(n->n->cfDivComp!=NULL);
407    //assume(n->cfIsUnit!=NULL);
408    //assume(n->cfGetUnit!=NULL);
409    //assume(n->cfExtGcd!=NULL);
410    assume(n->cfNeg!=NULL);
411    assume(n->cfCopy!=NULL);
412    assume(n->cfRePart!=NULL);
413    assume(n->cfImPart!=NULL);
[ce1f78]414
415    assume(n->cfWriteLong!=NULL);
416    assume(n->cfWriteShort!=NULL);
417
[7fee876]418    assume(n->iNumberOfParameters>= 0);
419
420    assume( (n->iNumberOfParameters == 0 && n->pParameterNames == NULL) ||
421            (n->iNumberOfParameters >  0 && n->pParameterNames != NULL) );           
422
423    assume(n->cfParameter!=NULL);
424    assume(n->cfParDeg!=NULL);
[f630e4]425     
[b19ab84]426    assume(n->cfRead!=NULL);
427    assume(n->cfNormalize!=NULL);
428    assume(n->cfGreater!=NULL);
429    //assume(n->cfDivBy!=NULL);
430    assume(n->cfEqual!=NULL);
431    assume(n->cfIsZero!=NULL);
432    assume(n->cfIsOne!=NULL);
433    assume(n->cfIsMOne!=NULL);
434    assume(n->cfGreaterZero!=NULL);
435    assume(n->cfPower!=NULL);
436    assume(n->cfGetDenom!=NULL);
437    assume(n->cfGetNumerator!=NULL);
438    assume(n->cfGcd!=NULL);
439    assume(n->cfLcm!=NULL);
440    assume(n->cfDelete!=NULL);
441    assume(n->cfSetMap!=NULL);
442    assume(n->cfName!=NULL);
443    assume(n->cfInpMult!=NULL);
[045efb]444//    assume(n->cfInit_bigint!=NULL);
[b19ab84]445    assume(n->cfCoeffWrite != NULL);
[98474f]446
447    assume(n->cfClearContent != NULL);
448    assume(n->cfClearDenominators != NULL);
449   
[1112b76]450#ifdef LDEBUG
[5b5409b]451    if(n->cfDBTest==NULL)
452    { n->cfDBTest=ndDBTest;Warn("cfDBTest is NULL for coeff %d",t); }
[1112b76]453#endif
[b19ab84]454    assume(n->type==t);
[f630e4]455     
[7fe9e13]456#ifndef SING_NDEBUG
[f630e4]457    if(n->cfKillChar==NULL) Warn("cfKillChar is NULL for coeff %d",t);
458    if(n->cfWriteLong==NULL) Warn("cfWrite is NULL for coeff %d",t);
459    if(n->cfWriteShort==NULL) Warn("cfWriteShort is NULL for coeff %d",t);
[45cc512]460    if(n->cfCoeffString==ndCoeffString) Warn("cfCoeffString is undefined for coeff %d",t);
[1e579c6]461#endif
[f630e4]462     
463   if( n->nNULL == NULL )
464     n->nNULL = n_Init(0, n); // may still remain NULL
[1e579c6]465  }
[6cee1d]466  else
[35aab3]467  {
[aff5ae]468    n->ref++;
[35aab3]469  }
[aff5ae]470  return n;
[35aab3]471}
472
[7d90aa]473void nKillChar(coeffs r)
[35aab3]474{
475  if (r!=NULL)
476  {
[7d90aa]477    r->ref--;
478    if (r->ref<=0)
[35aab3]479    {
[7d90aa]480      n_Procs_s tmp;
481      n_Procs_s* n=&tmp;
482      tmp.next=cf_root;
483      while((n->next!=NULL) && (n->next!=r)) n=n->next;
484      if (n->next==r)
[35aab3]485      {
[7d90aa]486        n->next=n->next->next;
487        if (cf_root==r) cf_root=n->next;
488        r->cfDelete(&(r->nNULL),r);
[7a95e91]489        if (r->cfKillChar!=NULL) r->cfKillChar(r);
490        omFreeSize((void *)r, sizeof(n_Procs_s));
491        r=NULL;
492      }
493      else
494      {
495        WarnS("cf_root list destroyed");
[35aab3]496      }
497    }
498  }
499}
[b6f15a]500
[7af488e]501
[b6f15a]502n_coeffType nRegister(n_coeffType n, cfInitCharProc p)
503{
504  if (n==n_unknown)
505  {
506    nLastCoeffs=(n_coeffType)(int(nLastCoeffs)+1);
[7af488e]507    if (nInitCharTable==nInitCharTableDefault)
[b6f15a]508    {
509      nInitCharTable=(cfInitCharProc*)omAlloc0(
510                                          nLastCoeffs*sizeof(cfInitCharProc));
[7af488e]511      memcpy(nInitCharTable,nInitCharTableDefault,
512              (nLastCoeffs-1)*sizeof(cfInitCharProc));
[b6f15a]513    }
514    else
515    {
516      nInitCharTable=(cfInitCharProc*)omReallocSize(nInitCharTable,
517                                          (((int)nLastCoeffs)-1)*sizeof(cfInitCharProc),
518                                          ((int)nLastCoeffs)*sizeof(cfInitCharProc));
519    }
520
521    nInitCharTable[nLastCoeffs]=p;
522    return nLastCoeffs;
523  }
524  else
525  {
[7af488e]526    if (nInitCharTable[n]!=NULL) Print("coeff %d already initialized\n",n);
[b6f15a]527    nInitCharTable[n]=p;
528    return n;
529  }
530}
531
[21b9ef]532
533void n_Print(number& a,  const coeffs r)
534{ 
535   assume(r != NULL); 
536   n_Test(a,r); 
537   
538   StringSetS(""); 
539   n_Write(a, r); 
540   { char* s = StringEndS(); Print("%s", s); omFree(s); }
541}
Note: See TracBrowser for help on using the repository browser.