source: git/libpolys/coeffs/numbers.cc @ 560a3d

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