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

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