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

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