source: git/libpolys/coeffs/numbers.cc @ 414cce5

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