source: git/libpolys/coeffs/numbers.cc @ ac000b6

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