source: git/libpolys/coeffs/numbers.cc @ 88615db

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