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