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