1 /*! \file coeffs/coeffs.h Coefficient rings, fields and other domains suitable for Singular polynomials
2
3 The main interface for Singular coefficients: \ref coeffs is the main handler for Singular numbers
4 */
5 /****************************************
6 * Computer Algebra System SINGULAR *
7 ****************************************/
8
9 #ifndef COEFFS_H
10 #define COEFFS_H
11
12 #include "misc/auxiliary.h"
13 #include "omalloc/omalloc.h"
14
15 #include "misc/sirandom.h"
16 /* for assume: */
17 #include "reporter/reporter.h"
18 #include "reporter/s_buff.h"
19 #include "factory/factory.h"
20
21 #include "coeffs/si_gmp.h"
22 #include "coeffs/Enumerator.h"
23 #include "coeffs/numstats.h" // for STATISTIC(F) counting macro
24
25 class CanonicalForm;
26
27 enum n_coeffType
28 {
29 n_unknown=0,
30 n_Zp, /**< \F{p < 2^31} */
31 n_Q, /**< rational (GMP) numbers */
32 n_R, /**< single prescision (6,6) real numbers */
33 n_GF, /**< \GF{p^n < 2^16} */
34 n_long_R, /**< real floating point (GMP) numbers */
35 n_polyExt, /**< used to represent polys as coeffcients */
36 n_algExt, /**< used for all algebraic extensions, i.e.,
37 the top-most extension in an extension tower
38 is algebraic */
39 n_transExt, /**< used for all transcendental extensions, i.e.,
40 the top-most extension in an extension tower
41 is transcendental */
42 n_long_C, /**< complex floating point (GMP) numbers */
43 n_nTupel, /**< n-tupel of cf: ZZ/p1,... ZZ/pn, R, long_R */
44 n_Z, /**< only used if HAVE_RINGS is defined */
45 n_Zn, /**< only used if HAVE_RINGS is defined */
46 n_Znm, /**< only used if HAVE_RINGS is defined */
47 n_Z2m, /**< only used if HAVE_RINGS is defined */
48 n_FlintQrat, /**< rational funtion field over Q */
49 n_CF /**< ? */
50 };
51
52 extern const unsigned short fftable[];
53
54 struct snumber;
55 typedef struct snumber * number;
56
57 /* standard types */
58 //struct ip_sring;
59 //typedef struct ip_sring * ring; /* already needed in s_buff.h*/
60
61 /// @class coeffs coeffs.h coeffs/coeffs.h
62 ///
63 /// The main handler for Singular numbers which are suitable for Singular polynomials.
64 ///
65 /// With it one may implement a ring, a field, a domain etc.
66 ///
67 struct n_Procs_s;
68 typedef struct n_Procs_s *coeffs;
69 typedef struct n_Procs_s const * const_coeffs;
70
71 typedef number (*numberfunc)(number a, number b, const coeffs r);
72
73 /// maps "a", which lives in src, into dst
74 typedef number (*nMapFunc)(number a, const coeffs src, const coeffs dst);
75
76
77 /// Abstract interface for an enumerator of number coefficients for an
78 /// object, e.g. a polynomial
79 typedef IEnumerator<number> ICoeffsEnumerator;
80
81 /// goes over coeffs given by the ICoeffsEnumerator and changes them.
82 /// Additionally returns a number;
83 typedef void (*nCoeffsEnumeratorFunc)(ICoeffsEnumerator& numberCollectionEnumerator, number& output, const coeffs r);
84
85 EXTERN_VAR omBin rnumber_bin;
86
87 #define FREE_RNUMBER(x) omFreeBin((void *)x, rnumber_bin)
88 #define ALLOC_RNUMBER() (number)omAllocBin(rnumber_bin)
89 #define ALLOC0_RNUMBER() (number)omAlloc0Bin(rnumber_bin)
90
91
92 /// Creation data needed for finite fields
93 typedef struct
94 {
95 int GFChar;
96 int GFDegree;
97 const char* GFPar_name;
98 } GFInfo;
99
100 typedef struct
101 {
102 short float_len; /**< additional char-flags, rInit */
103 short float_len2; /**< additional char-flags, rInit */
104 const char* par_name; /**< parameter name */
105 } LongComplexInfo;
106
107
108 enum n_coeffRep
109 {
110 n_rep_unknown=0,
111 n_rep_int, /**< (int), see modulop.h */
112 n_rep_gap_rat, /**< (number), see longrat.h */
113 n_rep_gap_gmp, /**< (), see rinteger.h, new impl. */
114 n_rep_poly, /**< (poly), see algext.h */
115 n_rep_rat_fct, /**< (fraction), see transext.h */
116 n_rep_gmp, /**< (mpz_ptr), see rmodulon,h */
117 n_rep_float, /**< (float), see shortfl.h */
118 n_rep_gmp_float, /**< (gmp_float), see */
119 n_rep_gmp_complex,/**< (gmp_complex), see gnumpc.h */
120 n_rep_gf /**< (int), see ffields.h */
121 };
122
123 struct n_Procs_s
124 {
125 // administration of coeffs:
126 coeffs next;
127 int ref;
128 n_coeffRep rep;
129 n_coeffType type;
130 /// how many variables of factory are already used by this coeff
131 int factoryVarOffset;
132
133 // general properties:
134 /// TRUE, if nNew/nDelete/nCopy are dummies
135 BOOLEAN has_simple_Alloc;
136 /// TRUE, if std should make polynomials monic (if nInvers is cheap)
137 /// if false, then a gcd routine is used for a content computation
138 BOOLEAN has_simple_Inverse;
139
140 /// TRUE, if cf is a field
141 BOOLEAN is_field;
142 /// TRUE, if cf is a domain
143 BOOLEAN is_domain;
144
145 // tests for numbers.cc:
146 BOOLEAN (*nCoeffIsEqual)(const coeffs r, n_coeffType n, void * parameter);
147
148 /// output of coeff description via Print
149 void (*cfCoeffWrite)(const coeffs r, BOOLEAN details);
150
151 /// string output of coeff description
152 char* (*cfCoeffString)(const coeffs r);
153
154 /// default name of cf, should substitue cfCoeffWrite, cfCoeffString
155 char* (*cfCoeffName)(const coeffs r);
156
157 // ?
158 // initialisation:
159 //void (*cfInitChar)(coeffs r, int parameter); // do one-time initialisations
160 void (*cfKillChar)(coeffs r); // undo all initialisations
161 // or NULL
162 void (*cfSetChar)(const coeffs r); // initialisations after each ring change
163 // or NULL
164 // general stuff
165 // if the ring has a meaningful Euclidean structure, hopefully
166 // supported by cfQuotRem, then
167 // IntMod, Div should give the same result
168 // Div(a,b) = QuotRem(a,b, &IntMod(a,b))
169 // if the ring is not Euclidean or a field, then IntMod should return 0
170 // and Div the exact quotient. It is assumed that the function is
171 // ONLY called on Euclidean rings or in the case of an exact division.
172 //
173 // cfDiv does an exact division, but has to handle illegal input
174 // cfExactDiv does an exact division, but no error checking
175 // (I'm not sure I understant and even less that this makes sense)
176 numberfunc cfMult, cfSub ,cfAdd ,cfDiv, cfIntMod, cfExactDiv;
177
178 /// init with an integer
179 number (*cfInit)(long i,const coeffs r);
180
181 /// init with a GMP integer
182 number (*cfInitMPZ)(mpz_t i, const coeffs r);
183
184 /// how complicated, (0) => 0, or positive
185 int (*cfSize)(number n, const coeffs r);
186
187 /// convertion to long, 0 if impossible
188 long (*cfInt)(number &n, const coeffs r);
189
190 /// Converts a (integer) number n into a GMP number, 0 if impossible
191 void (*cfMPZ)(mpz_t result, number &n, const coeffs r);
192
193 /// changes argument inline: a:= -a
194 /// return -a! (no copy is returned)
195 /// the result should be assigned to the original argument: e.g. a = n_InpNeg(a,r)
196 number (*cfInpNeg)(number a, const coeffs r);
197 /// return 1/a
198 number (*cfInvers)(number a, const coeffs r);
199 /// return a copy of a
200 number (*cfCopy)(number a, const coeffs r);
201 number (*cfRePart)(number a, const coeffs r);
202 number (*cfImPart)(number a, const coeffs r);
203
204 /// print a given number (long format)
205 void (*cfWriteLong)(number a, const coeffs r);
206
207 /// print a given number in a shorter way, if possible
208 /// e.g. in K(a): a2 instead of a^2
209 void (*cfWriteShort)(number a, const coeffs r);
210
211 // it is legal, but not always useful to have cfRead(s, a, r)
212 // just return s again.
213 // Useful application (read constants which are not an projection
214 // from int/bigint:
215 // Let ring r = R,x,dp;
216 // where R is a coeffs having "special" "named" elements (ie.
217 // the primitive element in some algebraic extension).
218 // If there is no interpreter variable of the same name, it is
219 // difficult to create non-trivial elements in R.
220 // Hence one can use the string to allow creation of R-elts using the
221 // unbound name of the special element.
222 const char * (*cfRead)(const char * s, number * a, const coeffs r);
223
224 void (*cfNormalize)(number &a, const coeffs r);
225
226 BOOLEAN (*cfGreater)(number a,number b, const coeffs r),
227 /// tests
228 (*cfEqual)(number a,number b, const coeffs r),
229 (*cfIsZero)(number a, const coeffs r),
230 (*cfIsOne)(number a, const coeffs r),
231 // IsMOne is used for printing os polynomials:
232 // -1 is only printed for constant monomials
233 (*cfIsMOne)(number a, const coeffs r),
234 //GreaterZero is used for printing of polynomials:
235 // a "+" is only printed in front of a coefficient
236 // if the element is >0. It is assumed that any element
237 // failing this will start printing with a leading "-"
238 (*cfGreaterZero)(number a, const coeffs r);
239
240 void (*cfPower)(number a, int i, number * result, const coeffs r);
241 number (*cfGetDenom)(number &n, const coeffs r);
242 number (*cfGetNumerator)(number &n, const coeffs r);
243 //CF: a Euclidean ring is a commutative, unitary ring with an Euclidean
244 // function f s.th. for all a,b in R, b ne 0, we can find q, r s.th.
245 // a = qb+r and either r=0 or f(r) < f(b)
246 // Note that neither q nor r nor f(r) are unique.
247 number (*cfGcd)(number a, number b, const coeffs r);
248 number (*cfSubringGcd)(number a, number b, const coeffs r);
249 number (*cfExtGcd)(number a, number b, number *s, number *t,const coeffs r);
250 //given a and b in a Euclidean setting, return s,t,u,v sth.
251 // sa + tb = gcd
252 // ua + vb = 0
253 // sv + tu = 1
254 // ie. the 2x2 matrix (s t | u v) is unimodular and maps (a,b) to (g, 0)
255 //CF: note, in general, this cannot be derived from ExtGcd due to
256 // zero divisors
257 number (*cfXExtGcd)(number a, number b, number *s, number *t, number *u, number *v, const coeffs r);
258 //in a Euclidean ring, return the Euclidean norm as a bigint (of type number)
259 number (*cfEucNorm)(number a, const coeffs r);
260 //in a principal ideal ring (with zero divisors): the annihilator
261 // NULL otherwise
262 number (*cfAnn)(number a, const coeffs r);
263 //find a "canonical representative of a modulo the units of r
264 //return NULL if a is already normalized
265 //otherwise, the factor.
266 //(for Z: make positive, for z/nZ make the gcd with n
267 //aparently it is GetUnit!
268 //in a Euclidean ring, return the quotient and compute the remainder
269 //rem can be NULL
270 number (*cfQuotRem)(number a, number b, number *rem, const coeffs r);
271 number (*cfLcm)(number a, number b, const coeffs r);
272 number (*cfNormalizeHelper)(number a, number b, const coeffs r);
273 void (*cfDelete)(number * a, const coeffs r);
274
275 //CF: tries to find a canonical map from src -> dst
276 nMapFunc (*cfSetMap)(const coeffs src, const coeffs dst);
277
278 void (*cfWriteFd)(number a, const ssiInfo *f, const coeffs r);
279 number (*cfReadFd)( const ssiInfo *f, const coeffs r);
280
281 /// Inplace: a *= b
282 void (*cfInpMult)(number &a, number b, const coeffs r);
283
284 /// Inplace: a += b
285 void (*cfInpAdd)(number &a, number b, const coeffs r);
286
287 /// rational reconstruction: "best" rational a/b with a/b = p mod n
288 // or a = bp mod n
289 // CF: no idea what this would be in general
290 // it seems to be extended to operate coefficient wise in extensions.
291 // I presume then n in coeffs_BIGINT while p in coeffs
292 number (*cfFarey)(number p, number n, const coeffs);
293
294 /// chinese remainder
295 /// returns X with X mod q[i]=x[i], i=0..rl-1
296 //CF: by the looks of it: q[i] in Z (coeffs_BIGINT)
297 // strange things happen in naChineseRemainder for example.
298 number (*cfChineseRemainder)(number *x, number *q,int rl, BOOLEAN sym,CFArray &inv_cache,const coeffs);
299
300 /// degree for coeffcients: -1 for 0, 0 for "constants", ...
301 int (*cfParDeg)(number x,const coeffs r);
302
303 /// create i^th parameter or NULL if not possible
304 number (*cfParameter)(const int i, const coeffs r);
305
306 /// a function returning random elements
307 number (*cfRandom)(siRandProc p, number p1, number p2, const coeffs cf);
308
309 /// function pointer behind n_ClearContent
310 nCoeffsEnumeratorFunc cfClearContent;
311
312 /// function pointer behind n_ClearDenominators
313 nCoeffsEnumeratorFunc cfClearDenominators;
314
315 /// conversion to CanonicalForm(factory) to number
316 number (*convFactoryNSingN)( const CanonicalForm n, const coeffs r);
317 CanonicalForm (*convSingNFactoryN)( number n, BOOLEAN setChar, const coeffs r );
318
319 /// Number of Parameters in the coeffs (default 0)
320 int iNumberOfParameters;
321
322 /// array containing the names of Parameters (default NULL)
323 char const ** pParameterNames;
324 // NOTE that it replaces the following:
325 // char* complex_parameter; //< the name of sqrt(-1) in n_long_C , i.e. 'i' or 'j' etc...?
326 // char * m_nfParameter; //< the name of parameter in n_GF
327
328 /////////////////////////////////////////////
329 // the union stuff
330
331 //-------------------------------------------
332
333 /* for extension fields we need to be able to represent polynomials,
334 so here is the polynomial ring: */
335 ring extRing;
336
337 //number minpoly; //< no longer needed: replaced by
338 // //< extRing->qideal->[0]
339
340
341 int ch; /* characteristic, set by the local *InitChar methods;
342 In field extensions or extensions towers, the
343 characteristic can be accessed from any of the
344 intermediate extension fields, i.e., in this case
345 it is redundant along the chain of field extensions;
346 CONTRARY to SINGULAR as it was, we do NO LONGER use
347 negative values for ch;
348 for rings, ch will also be set and is - per def -
349 the smallest number of 1's that sum up to zero;
350 however, in this case ch may not fit in an int,
351 thus ch may contain a faulty value */
352
353 short float_len; /* additional char-flags, rInit */
354 short float_len2; /* additional char-flags, rInit */
355
356 // BOOLEAN CanShortOut; //< if the elements can be printed in short format
357 // // this is set to FALSE if a parameter name has >2 chars
358 // BOOLEAN ShortOut; //< if the elements should print in short format
359
360 // ---------------------------------------------------
361 // for n_GF
362
363 int m_nfCharQ; ///< the number of elements: q
364 int m_nfM1; ///< representation of -1
365 int m_nfCharP; ///< the characteristic: p
366 int m_nfCharQ1; ///< q-1
367 unsigned short *m_nfPlus1Table;
368 int *m_nfMinPoly;
369
370 // ---------------------------------------------------
371 // for Zp:
372 unsigned short *npInvTable;
373 unsigned short *npExpTable;
374 unsigned short *npLogTable;
375 // int npPrimeM; // NOTE: npPrimeM is deprecated, please use ch instead!
376 int npPminus1M; ///< characteristic - 1
377 //-------------------------------------------
378 int (*cfDivComp)(number a,number b,const coeffs r);
379 BOOLEAN (*cfIsUnit)(number a,const coeffs r);
380 number (*cfGetUnit)(number a,const coeffs r);
381 //CF: test if b divides a
382 BOOLEAN (*cfDivBy)(number a, number b, const coeffs r);
383 /* The following members are for representing the ring Z/n,
384 where n is not a prime. We distinguish four cases:
385 1.) n has at least two distinct prime factors. Then
386 modBase stores n, modExponent stores 1, modNumber
387 stores n, and mod2mMask is not used;
388 2.) n = p^k for some odd prime p and k > 1. Then
389 modBase stores p, modExponent stores k, modNumber
390 stores n, and mod2mMask is not used;
391 3.) n = 2^k for some k > 1; moreover, 2^k - 1 fits in
392 an unsigned long. Then modBase stores 2, modExponent
393 stores k, modNumber is not used, and mod2mMask stores
394 2^k - 1, i.e., the bit mask '111..1' of length k.
395 4.) n = 2^k for some k > 1; but 2^k - 1 does not fit in
396 an unsigned long. Then modBase stores 2, modExponent
397 stores k, modNumber stores n, and mod2mMask is not
398 used;
399 Cases 1.), 2.), and 4.) are covered by the implementation
400 in the files rmodulon.h and rmodulon.cc, whereas case 3.)
401 is implemented in the files rmodulo2m.h and rmodulo2m.cc. */
402 mpz_ptr modBase;
403 unsigned long modExponent;
404 mpz_ptr modNumber;
405 unsigned long mod2mMask;
406 //returns coeffs with updated ch, modNumber and modExp
407 coeffs (*cfQuot1)(number c, const coeffs r);
408
409 /*CF: for blackbox rings, contains data needed to define the ring.
410 * contents depends on the actual example.*/
411 void * data;
412 #ifdef LDEBUG
413 // must be last entry:
414 /// Test: is "a" a correct number?
415 // DB as in debug, not data base.
416 BOOLEAN (*cfDBTest)(number a, const char *f, const int l, const coeffs r);
417 #endif
418 };
419
420 // test properties and type
421 /// Returns the type of coeffs domain
getCoeffType(const coeffs r)422 static FORCE_INLINE n_coeffType getCoeffType(const coeffs r)
423 { assume(r != NULL); return r->type; }
424
425 /// one-time initialisations for new coeffs
426 /// in case of an error return NULL
427 coeffs nInitChar(n_coeffType t, void * parameter);
428
429 /// "copy" coeffs, i.e. increment ref
nCopyCoeff(const coeffs r)430 static FORCE_INLINE coeffs nCopyCoeff(const coeffs r)
431 { assume(r!=NULL); r->ref++; return r;}
432
433 /// undo all initialisations
434 void nKillChar(coeffs r);
435
436 /// initialisations after each ring change
nSetChar(const coeffs r)437 static FORCE_INLINE void nSetChar(const coeffs r)
438 { STATISTIC(nSetChar); assume(r!=NULL); assume(r->cfSetChar != NULL); r->cfSetChar(r); }
439
440 void nNew(number * a);
441 #define n_New(n, r) nNew(n)
442
443
444 /// Return the characteristic of the coeff. domain.
n_GetChar(const coeffs r)445 static FORCE_INLINE int n_GetChar(const coeffs r)
446 { STATISTIC(n_GetChar); assume(r != NULL); return r->ch; }
447
448
449 // the access methods (part 2):
450
451 /// return a copy of 'n'
n_Copy(number n,const coeffs r)452 static FORCE_INLINE number n_Copy(number n, const coeffs r)
453 { STATISTIC(n_Copy); assume(r != NULL); assume(r->cfCopy!=NULL); return r->cfCopy(n, r); }
454
455 /// delete 'p'
n_Delete(number * p,const coeffs r)456 static FORCE_INLINE void n_Delete(number* p, const coeffs r)
457 { STATISTIC(n_Delete); assume(r != NULL); assume(r->cfDelete!= NULL); r->cfDelete(p, r); }
458
459 /// TRUE iff 'a' and 'b' represent the same number;
460 /// they may have different representations
n_Equal(number a,number b,const coeffs r)461 static FORCE_INLINE BOOLEAN n_Equal(number a, number b, const coeffs r)
462 { STATISTIC(n_Equal); assume(r != NULL); assume(r->cfEqual!=NULL); return r->cfEqual(a, b, r); }
463
464 /// TRUE iff 'n' represents the zero element
n_IsZero(number n,const coeffs r)465 static FORCE_INLINE BOOLEAN n_IsZero(number n, const coeffs r)
466 { STATISTIC(n_IsZero); assume(r != NULL); assume(r->cfIsZero!=NULL); return r->cfIsZero(n,r); }
467
468 /// TRUE iff 'n' represents the one element
n_IsOne(number n,const coeffs r)469 static FORCE_INLINE BOOLEAN n_IsOne(number n, const coeffs r)
470 { STATISTIC(n_IsOne); assume(r != NULL); assume(r->cfIsOne!=NULL); return r->cfIsOne(n,r); }
471
472 /// TRUE iff 'n' represents the additive inverse of the one element, i.e. -1
n_IsMOne(number n,const coeffs r)473 static FORCE_INLINE BOOLEAN n_IsMOne(number n, const coeffs r)
474 { STATISTIC(n_IsMOne); assume(r != NULL); assume(r->cfIsMOne!=NULL); return r->cfIsMOne(n,r); }
475
476 /// ordered fields: TRUE iff 'n' is positive;
477 /// in Z/pZ: TRUE iff 0 < m <= roundedBelow(p/2), where m is the long
478 /// representing n
479 /// in C: TRUE iff (Im(n) != 0 and Im(n) >= 0) or
480 /// (Im(n) == 0 and Re(n) >= 0)
481 /// in K(a)/<p(a)>: TRUE iff (n != 0 and (LC(n) > 0 or deg(n) > 0))
482 /// in K(t_1, ..., t_n): TRUE iff (LC(numerator(n) is a constant and > 0)
483 /// or (LC(numerator(n) is not a constant)
484 /// in Z/2^kZ: TRUE iff 0 < n <= 2^(k-1)
485 /// in Z/mZ: TRUE iff the internal mpz is greater than zero
486 /// in Z: TRUE iff n > 0
487 ///
488 /// !!! Recommendation: remove implementations for unordered fields
489 /// !!! and raise errors instead, in these cases
490 /// !!! Do not follow this recommendation: while writing polys,
491 /// !!! between 2 monomials will be an additional + iff !n_GreaterZero(next coeff)
492 /// Then change definition to include n_GreaterZero => printing does NOT
493 /// start with -
494 ///
n_GreaterZero(number n,const coeffs r)495 static FORCE_INLINE BOOLEAN n_GreaterZero(number n, const coeffs r)
496 { STATISTIC(n_GreaterZero); assume(r != NULL); assume(r->cfGreaterZero!=NULL); return r->cfGreaterZero(n,r); }
497
498 /// ordered fields: TRUE iff 'a' is larger than 'b';
499 /// in Z/pZ: TRUE iff la > lb, where la and lb are the long's representing
500 // a and b, respectively
501 /// in C: TRUE iff (Im(a) > Im(b))
502 /// in K(a)/<p(a)>: TRUE iff (a != 0 and (b == 0 or deg(a) > deg(b))
503 /// in K(t_1, ..., t_n): TRUE only if one or both numerator polynomials are
504 /// zero or if their degrees are equal. In this case,
505 /// TRUE if LC(numerator(a)) > LC(numerator(b))
506 /// in Z/2^kZ: TRUE if n_DivBy(a, b)
507 /// in Z/mZ: TRUE iff the internal mpz's fulfill the relation '>'
508 /// in Z: TRUE iff a > b
509 ///
510 /// !!! Recommendation: remove implementations for unordered fields
511 /// !!! and raise errors instead, in these cases
n_Greater(number a,number b,const coeffs r)512 static FORCE_INLINE BOOLEAN n_Greater(number a, number b, const coeffs r)
513 { STATISTIC(n_Greater); assume(r != NULL); assume(r->cfGreater!=NULL); return r->cfGreater(a,b,r); }
514
515 /// TRUE iff n has a multiplicative inverse in the given coeff field/ring r
n_IsUnit(number n,const coeffs r)516 static FORCE_INLINE BOOLEAN n_IsUnit(number n, const coeffs r)
517 { STATISTIC(n_IsUnit); assume(r != NULL); assume(r->cfIsUnit!=NULL); return r->cfIsUnit(n,r); }
518
n_CoeffRingQuot1(number c,const coeffs r)519 static FORCE_INLINE coeffs n_CoeffRingQuot1(number c, const coeffs r)
520 { STATISTIC(n_CoeffRingQuot1); assume(r != NULL); assume(r->cfQuot1 != NULL); return r->cfQuot1(c, r); }
521
522 #ifdef HAVE_RINGS
n_DivComp(number a,number b,const coeffs r)523 static FORCE_INLINE int n_DivComp(number a, number b, const coeffs r)
524 { STATISTIC(n_DivComp); assume(r != NULL); assume(r->cfDivComp!=NULL); return r->cfDivComp (a,b,r); }
525
526 /// in Z: 1
527 /// in Z/kZ (where k is not a prime): largest divisor of n (taken in Z) that
528 /// is co-prime with k
529 /// in Z/2^kZ: largest odd divisor of n (taken in Z)
530 /// other cases: not implemented
531 // CF: shold imply that n/GetUnit(n) is normalized in Z/kZ
532 // it would make more sense to return the inverse...
n_GetUnit(number n,const coeffs r)533 static FORCE_INLINE number n_GetUnit(number n, const coeffs r)
534 { STATISTIC(n_GetUnit); assume(r != NULL); assume(r->cfGetUnit!=NULL); return r->cfGetUnit(n,r); }
535
536 #endif
537
538 /// a number representing i in the given coeff field/ring r
n_Init(long i,const coeffs r)539 static FORCE_INLINE number n_Init(long i, const coeffs r)
540 { STATISTIC(n_Init); assume(r != NULL); assume(r->cfInit!=NULL); return r->cfInit(i,r); }
541
542 /// conversion of a GMP integer to number
n_InitMPZ(mpz_t n,const coeffs r)543 static FORCE_INLINE number n_InitMPZ(mpz_t n, const coeffs r)
544 { STATISTIC(n_InitMPZ); assume(r != NULL); assume(r->cfInitMPZ != NULL); return r->cfInitMPZ(n,r); }
545
546 /// conversion of n to an int; 0 if not possible
547 /// in Z/pZ: the representing int lying in (-p/2 .. p/2]
n_Int(number & n,const coeffs r)548 static FORCE_INLINE long n_Int(number &n, const coeffs r)
549 { STATISTIC(n_Int); assume(r != NULL); assume(r->cfInt!=NULL); return r->cfInt(n,r); }
550
551 /// conversion of n to a GMP integer; 0 if not possible
n_MPZ(mpz_t result,number & n,const coeffs r)552 static FORCE_INLINE void n_MPZ(mpz_t result, number &n, const coeffs r)
553 { STATISTIC(n_MPZ); assume(r != NULL); assume(r->cfMPZ!=NULL); r->cfMPZ(result, n, r); }
554
555
556 /// in-place negation of n
557 /// MUST BE USED: n = n_InpNeg(n) (no copy is returned)
n_InpNeg(number n,const coeffs r)558 static FORCE_INLINE number n_InpNeg(number n, const coeffs r)
559 { STATISTIC(n_InpNeg); assume(r != NULL); assume(r->cfInpNeg!=NULL); return r->cfInpNeg(n,r); }
560
561 /// return the multiplicative inverse of 'a';
562 /// raise an error if 'a' is not invertible
563 ///
564 /// !!! Recommendation: rename to 'n_Inverse'
n_Invers(number a,const coeffs r)565 static FORCE_INLINE number n_Invers(number a, const coeffs r)
566 { STATISTIC(n_Invers); assume(r != NULL); assume(r->cfInvers!=NULL); return r->cfInvers(a,r); }
567
568 /// return a non-negative measure for the complexity of n;
569 /// return 0 only when n represents zero;
570 /// (used for pivot strategies in matrix computations with entries from r)
n_Size(number n,const coeffs r)571 static FORCE_INLINE int n_Size(number n, const coeffs r)
572 { STATISTIC(n_Size); assume(r != NULL); assume(r->cfSize!=NULL); return r->cfSize(n,r); }
573
574 /// inplace-normalization of n;
575 /// produces some canonical representation of n;
576 ///
577 /// !!! Recommendation: remove this method from the user-interface, i.e.,
578 /// !!! this should be hidden
n_Normalize(number & n,const coeffs r)579 static FORCE_INLINE void n_Normalize(number& n, const coeffs r)
580 { STATISTIC(n_Normalize); assume(r != NULL); assume(r->cfNormalize!=NULL); r->cfNormalize(n,r); }
581
582 /// write to the output buffer of the currently used reporter
583 //CF: the "&" should be removed, as one wants to write constants as well
n_WriteLong(number n,const coeffs r)584 static FORCE_INLINE void n_WriteLong(number n, const coeffs r)
585 { STATISTIC(n_WriteLong); assume(r != NULL); assume(r->cfWriteLong!=NULL); r->cfWriteLong(n,r); }
586
587 /// write to the output buffer of the currently used reporter
588 /// in a shortest possible way, e.g. in K(a): a2 instead of a^2
n_WriteShort(number n,const coeffs r)589 static FORCE_INLINE void n_WriteShort(number n, const coeffs r)
590 { STATISTIC(n_WriteShort); assume(r != NULL); assume(r->cfWriteShort!=NULL); r->cfWriteShort(n,r); }
591
592 static FORCE_INLINE void n_Write(number n, const coeffs r, const BOOLEAN bShortOut = TRUE)
593 { STATISTIC(n_Write); if (bShortOut) n_WriteShort(n, r); else n_WriteLong(n, r); }
594
595
596 /// !!! Recommendation: This method is too cryptic to be part of the user-
597 /// !!! interface. As defined here, it is merely a helper
598 /// !!! method for parsing number input strings.
n_Read(const char * s,number * a,const coeffs r)599 static FORCE_INLINE const char *n_Read(const char * s, number * a, const coeffs r)
600 { STATISTIC(n_Read); assume(r != NULL); assume(r->cfRead!=NULL); return r->cfRead(s, a, r); }
601
602 /// return the denominator of n
603 /// (if elements of r are by nature not fractional, result is 1)
n_GetDenom(number & n,const coeffs r)604 static FORCE_INLINE number n_GetDenom(number& n, const coeffs r)
605 { STATISTIC(n_GetDenom); assume(r != NULL); assume(r->cfGetDenom!=NULL); return r->cfGetDenom(n, r); }
606
607 /// return the numerator of n
608 /// (if elements of r are by nature not fractional, result is n)
n_GetNumerator(number & n,const coeffs r)609 static FORCE_INLINE number n_GetNumerator(number& n, const coeffs r)
610 { STATISTIC(n_GetNumerator); assume(r != NULL); assume(r->cfGetNumerator!=NULL); return r->cfGetNumerator(n, r); }
611
612 /// return the quotient of 'a' and 'b', i.e., a/b;
613 /// raises an error if 'b' is not invertible in r
614 /// exception in Z: raises an error if 'a' is not divisible by 'b'
615 /// always: n_Div(a,b,r)*b+n_IntMod(a,b,r)==a
n_Div(number a,number b,const coeffs r)616 static FORCE_INLINE number n_Div(number a, number b, const coeffs r)
617 { STATISTIC(n_Div); assume(r != NULL); assume(r->cfDiv!=NULL); return r->cfDiv(a,b,r); }
618
619 /// assume that there is a canonical subring in cf and we know
620 /// that division is possible for these a and b in the subring,
621 /// n_ExactDiv performs it, may skip additional tests.
622 /// Can always be substituted by n_Div at the cost of larger computing time.
n_ExactDiv(number a,number b,const coeffs r)623 static FORCE_INLINE number n_ExactDiv(number a, number b, const coeffs r)
624 { STATISTIC(n_ExactDiv); assume(r != NULL); assume(r->cfExactDiv!=NULL); return r->cfExactDiv(a,b,r); }
625
626 /// for r a field, return n_Init(0,r)
627 /// always: n_Div(a,b,r)*b+n_IntMod(a,b,r)==a
628 /// n_IntMod(a,b,r) >=0
n_IntMod(number a,number b,const coeffs r)629 static FORCE_INLINE number n_IntMod(number a, number b, const coeffs r)
630 { STATISTIC(n_IntMod); assume(r != NULL); return r->cfIntMod(a,b,r); }
631
632 /// fill res with the power a^b
n_Power(number a,int b,number * res,const coeffs r)633 static FORCE_INLINE void n_Power(number a, int b, number *res, const coeffs r)
634 { STATISTIC(n_Power); assume(r != NULL); assume(r->cfPower!=NULL); r->cfPower(a,b,res,r); }
635
636 /// return the product of 'a' and 'b', i.e., a*b
n_Mult(number a,number b,const coeffs r)637 static FORCE_INLINE number n_Mult(number a, number b, const coeffs r)
638 { STATISTIC(n_Mult); assume(r != NULL); assume(r->cfMult!=NULL); return r->cfMult(a, b, r); }
639
640 /// multiplication of 'a' and 'b';
641 /// replacement of 'a' by the product a*b
n_InpMult(number & a,number b,const coeffs r)642 static FORCE_INLINE void n_InpMult(number &a, number b, const coeffs r)
643 { STATISTIC(n_InpMult); assume(r != NULL); assume(r->cfInpMult!=NULL); r->cfInpMult(a,b,r); }
644
645 /// addition of 'a' and 'b';
646 /// replacement of 'a' by the sum a+b
n_InpAdd(number & a,number b,const coeffs r)647 static FORCE_INLINE void n_InpAdd(number &a, number b, const coeffs r)
648 { STATISTIC(n_InpAdd); assume(r != NULL); assume(r->cfInpAdd!=NULL); r->cfInpAdd(a,b,r);
649
650 #ifdef HAVE_NUMSTATS
651 // avoid double counting
652 if( r->cfIsZero(a,r) ) STATISTIC(n_CancelOut);
653 #endif
654 }
655
656 /// return the sum of 'a' and 'b', i.e., a+b
n_Add(number a,number b,const coeffs r)657 static FORCE_INLINE number n_Add(number a, number b, const coeffs r)
658 { STATISTIC(n_Add); assume(r != NULL); assume(r->cfAdd!=NULL); const number sum = r->cfAdd(a, b, r);
659
660 #ifdef HAVE_NUMSTATS
661 // avoid double counting
662 if( r->cfIsZero(sum,r) ) STATISTIC(n_CancelOut);
663 #endif
664
665 return sum;
666 }
667
668
669 /// return the difference of 'a' and 'b', i.e., a-b
n_Sub(number a,number b,const coeffs r)670 static FORCE_INLINE number n_Sub(number a, number b, const coeffs r)
671 { STATISTIC(n_Sub); assume(r != NULL); assume(r->cfSub!=NULL); const number d = r->cfSub(a, b, r);
672
673 #ifdef HAVE_NUMSTATS
674 // avoid double counting
675 if( r->cfIsZero(d,r) ) STATISTIC(n_CancelOut);
676 #endif
677
678 return d;
679 }
680
681 /// in Z: return the gcd of 'a' and 'b'
682 /// in Z/nZ, Z/2^kZ: computed as in the case Z
683 /// in Z/pZ, C, R: not implemented
684 /// in Q: return the gcd of the numerators of 'a' and 'b'
685 /// in K(a)/<p(a)>: not implemented
686 /// in K(t_1, ..., t_n): not implemented
n_Gcd(number a,number b,const coeffs r)687 static FORCE_INLINE number n_Gcd(number a, number b, const coeffs r)
688 { STATISTIC(n_Gcd); assume(r != NULL); assume(r->cfGcd!=NULL); return r->cfGcd(a,b,r); }
n_SubringGcd(number a,number b,const coeffs r)689 static FORCE_INLINE number n_SubringGcd(number a, number b, const coeffs r)
690 { STATISTIC(n_SubringGcd); assume(r != NULL); assume(r->cfSubringGcd!=NULL); return r->cfSubringGcd(a,b,r); }
691
692 /// beware that ExtGCD is only relevant for a few chosen coeff. domains
693 /// and may perform something unexpected in some cases...
n_ExtGcd(number a,number b,number * s,number * t,const coeffs r)694 static FORCE_INLINE number n_ExtGcd(number a, number b, number *s, number *t, const coeffs r)
695 { STATISTIC(n_ExtGcd); assume(r != NULL); assume(r->cfExtGcd!=NULL); return r->cfExtGcd (a,b,s,t,r); }
n_XExtGcd(number a,number b,number * s,number * t,number * u,number * v,const coeffs r)696 static FORCE_INLINE number n_XExtGcd(number a, number b, number *s, number *t, number *u, number *v, const coeffs r)
697 { STATISTIC(n_XExtGcd); assume(r != NULL); assume(r->cfXExtGcd!=NULL); return r->cfXExtGcd (a,b,s,t,u,v,r); }
n_EucNorm(number a,const coeffs r)698 static FORCE_INLINE number n_EucNorm(number a, const coeffs r)
699 { STATISTIC(n_EucNorm); assume(r != NULL); assume(r->cfEucNorm!=NULL); return r->cfEucNorm (a,r); }
700 /// if r is a ring with zero divisors, return an annihilator!=0 of b
701 /// otherwise return NULL
n_Ann(number a,const coeffs r)702 static FORCE_INLINE number n_Ann(number a, const coeffs r)
703 { STATISTIC(n_Ann); assume(r != NULL); return r->cfAnn (a,r); }
n_QuotRem(number a,number b,number * q,const coeffs r)704 static FORCE_INLINE number n_QuotRem(number a, number b, number *q, const coeffs r)
705 { STATISTIC(n_QuotRem); assume(r != NULL); assume(r->cfQuotRem!=NULL); return r->cfQuotRem (a,b,q,r); }
706
707
708 /// in Z: return the lcm of 'a' and 'b'
709 /// in Z/nZ, Z/2^kZ: computed as in the case Z
710 /// in Z/pZ, C, R: not implemented
711 /// in K(a)/<p(a)>: not implemented
712 /// in K(t_1, ..., t_n): not implemented
n_Lcm(number a,number b,const coeffs r)713 static FORCE_INLINE number n_Lcm(number a, number b, const coeffs r)
714 { STATISTIC(n_Lcm); assume(r != NULL); assume(r->cfLcm!=NULL); return r->cfLcm(a,b,r); }
715
716 /// assume that r is a quotient field (otherwise, return 1)
717 /// for arguments (a1/a2,b1/b2) return (lcm(a1,b2)/1)
n_NormalizeHelper(number a,number b,const coeffs r)718 static FORCE_INLINE number n_NormalizeHelper(number a, number b, const coeffs r)
719 { STATISTIC(n_NormalizeHelper); assume(r != NULL); assume(r->cfNormalizeHelper!=NULL); return r->cfNormalizeHelper(a,b,r); }
720
721 number ndCopyMap(number a, const coeffs src, const coeffs dst);
722 /// set the mapping function pointers for translating numbers from src to dst
n_SetMap(const coeffs src,const coeffs dst)723 static FORCE_INLINE nMapFunc n_SetMap(const coeffs src, const coeffs dst)
724 { STATISTIC(n_SetMap);
725 assume(src != NULL && dst != NULL); assume(dst->cfSetMap!=NULL);
726 if (src==dst) return ndCopyMap;
727 return dst->cfSetMap(src,dst);
728 }
729
730 #ifdef LDEBUG
731 /// test whether n is a correct number;
732 /// only used if LDEBUG is defined
n_DBTest(number n,const char * filename,const int linenumber,const coeffs r)733 static FORCE_INLINE BOOLEAN n_DBTest(number n, const char *filename, const int linenumber, const coeffs r)
734 { STATISTIC(n_Test); assume(r != NULL); assume(r->cfDBTest != NULL); return r->cfDBTest(n, filename, linenumber, r); }
735 /// BOOLEAN n_Test(number a, const coeffs r)
736 #define n_Test(a,r) n_DBTest(a, __FILE__, __LINE__, r)
737 #else
738 #define n_Test(a,r) 1
739 #endif
740
741
742 /// output the coeff description
743 static FORCE_INLINE void n_CoeffWrite(const coeffs r, BOOLEAN details = TRUE)
744 { STATISTIC(n_CoeffWrite); assume(r != NULL); assume(r->cfCoeffWrite != NULL); r->cfCoeffWrite(r, details); }
745
746 // Tests:
747 #ifdef HAVE_RINGS
nCoeff_is_Ring_2toM(const coeffs r)748 static FORCE_INLINE BOOLEAN nCoeff_is_Ring_2toM(const coeffs r)
749 { assume(r != NULL); return (getCoeffType(r)==n_Z2m); }
750
nCoeff_is_Ring_PtoM(const coeffs r)751 static FORCE_INLINE BOOLEAN nCoeff_is_Ring_PtoM(const coeffs r)
752 { assume(r != NULL); return (getCoeffType(r)==n_Znm); }
753
nCoeff_is_Ring(const coeffs r)754 static FORCE_INLINE BOOLEAN nCoeff_is_Ring(const coeffs r)
755 { assume(r != NULL); return (r->is_field==0); }
756 #else
757 #define nCoeff_is_Ring_2toM(A) 0
758 #define nCoeff_is_Ring_PtoM(A) 0
759 #define nCoeff_is_Ring(A) 0
760 #endif
761
762 /// returns TRUE, if r is a field or r has no zero divisors (i.e is a domain)
nCoeff_is_Domain(const coeffs r)763 static FORCE_INLINE BOOLEAN nCoeff_is_Domain(const coeffs r)
764 {
765 assume(r != NULL);
766 return (r->is_domain);
767 }
768
769 /// test whether 'a' is divisible 'b';
770 /// for r encoding a field: TRUE iff 'b' does not represent zero
771 /// in Z: TRUE iff 'b' divides 'a' (with remainder = zero)
772 /// in Z/nZ: TRUE iff (a = 0 and b divides n in Z) or
773 /// (a != 0 and b/gcd(a, b) is co-prime with n, i.e.
774 /// a unit in Z/nZ)
775 /// in Z/2^kZ: TRUE iff ((a = 0 mod 2^k) and (b = 0 or b is a power of 2))
776 /// or ((a, b <> 0) and (b/gcd(a, b) is odd))
n_DivBy(number a,number b,const coeffs r)777 static FORCE_INLINE BOOLEAN n_DivBy(number a, number b, const coeffs r)
778 { STATISTIC(n_DivBy); assume(r != NULL);
779 #ifdef HAVE_RINGS
780 if( nCoeff_is_Ring(r) )
781 {
782 assume(r->cfDivBy!=NULL); return r->cfDivBy(a,b,r);
783 }
784 #endif
785 return !n_IsZero(b, r);
786 }
787
n_ChineseRemainderSym(number * a,number * b,int rl,BOOLEAN sym,CFArray & inv_cache,const coeffs r)788 static FORCE_INLINE number n_ChineseRemainderSym(number *a, number *b, int rl, BOOLEAN sym,CFArray &inv_cache,const coeffs r)
789 { STATISTIC(n_ChineseRemainderSym); assume(r != NULL); assume(r->cfChineseRemainder != NULL); return r->cfChineseRemainder(a,b,rl,sym,inv_cache,r); }
790
n_Farey(number a,number b,const coeffs r)791 static FORCE_INLINE number n_Farey(number a, number b, const coeffs r)
792 { STATISTIC(n_Farey); assume(r != NULL); assume(r->cfFarey != NULL); return r->cfFarey(a,b,r); }
793
n_ParDeg(number n,const coeffs r)794 static FORCE_INLINE int n_ParDeg(number n, const coeffs r)
795 { STATISTIC(n_ParDeg); assume(r != NULL); assume(r->cfParDeg != NULL); return r->cfParDeg(n,r); }
796
797 /// Returns the number of parameters
n_NumberOfParameters(const coeffs r)798 static FORCE_INLINE int n_NumberOfParameters(const coeffs r)
799 { STATISTIC(n_NumberOfParameters); assume(r != NULL); return r->iNumberOfParameters; }
800
801 /// Returns a (const!) pointer to (const char*) names of parameters
n_ParameterNames(const coeffs r)802 static FORCE_INLINE char const * * n_ParameterNames(const coeffs r)
803 { STATISTIC(n_ParameterNames); assume(r != NULL); return r->pParameterNames; }
804
805 /// return the (iParameter^th) parameter as a NEW number
806 /// NOTE: parameter numbering: 1..n_NumberOfParameters(...)
n_Param(const int iParameter,const coeffs r)807 static FORCE_INLINE number n_Param(const int iParameter, const coeffs r)
808 { assume(r != NULL);
809 assume((iParameter >= 1) || (iParameter <= n_NumberOfParameters(r)));
810 assume(r->cfParameter != NULL);
811 STATISTIC(n_Param); return r->cfParameter(iParameter, r);
812 }
813
n_RePart(number i,const coeffs cf)814 static FORCE_INLINE number n_RePart(number i, const coeffs cf)
815 { STATISTIC(n_RePart); assume(cf != NULL); assume(cf->cfRePart!=NULL); return cf->cfRePart(i,cf); }
816
n_ImPart(number i,const coeffs cf)817 static FORCE_INLINE number n_ImPart(number i, const coeffs cf)
818 { STATISTIC(n_ImPart); assume(cf != NULL); assume(cf->cfImPart!=NULL); return cf->cfImPart(i,cf); }
819
820 /// returns TRUE, if r is not a field and r has non-trivial units
nCoeff_has_Units(const coeffs r)821 static FORCE_INLINE BOOLEAN nCoeff_has_Units(const coeffs r)
822 { assume(r != NULL); return ((getCoeffType(r)==n_Zn) || (getCoeffType(r)==n_Z2m) || (getCoeffType(r)==n_Znm)); }
823
nCoeff_is_Zp(const coeffs r)824 static FORCE_INLINE BOOLEAN nCoeff_is_Zp(const coeffs r)
825 { assume(r != NULL); return getCoeffType(r)==n_Zp; }
826
nCoeff_is_Zp(const coeffs r,int p)827 static FORCE_INLINE BOOLEAN nCoeff_is_Zp(const coeffs r, int p)
828 { assume(r != NULL); return ((getCoeffType(r)==n_Zp) && (r->ch == p)); }
829
nCoeff_is_Q(const coeffs r)830 static FORCE_INLINE BOOLEAN nCoeff_is_Q(const coeffs r)
831 {
832 assume(r != NULL);
833 #if SI_INTEGER_VARIANT==1
834 return getCoeffType(r)==n_Q && (r->is_field);
835 #else
836 return getCoeffType(r)==n_Q;
837 #endif
838 }
839
nCoeff_is_Z(const coeffs r)840 static FORCE_INLINE BOOLEAN nCoeff_is_Z(const coeffs r)
841 {
842 assume(r != NULL);
843 #if SI_INTEGER_VARIANT==1
844 return ((getCoeffType(r)==n_Q) && (!r->is_field));
845 #else
846 return getCoeffType(r)==n_Z;
847 #endif
848 }
849
nCoeff_is_Zn(const coeffs r)850 static FORCE_INLINE BOOLEAN nCoeff_is_Zn(const coeffs r)
851 { assume(r != NULL); return getCoeffType(r)==n_Zn; }
852
nCoeff_is_Q_or_BI(const coeffs r)853 static FORCE_INLINE BOOLEAN nCoeff_is_Q_or_BI(const coeffs r)
854 { assume(r != NULL); return getCoeffType(r)==n_Q; }
855
nCoeff_is_numeric(const coeffs r)856 static FORCE_INLINE BOOLEAN nCoeff_is_numeric(const coeffs r) /* R, long R, long C */
857 { assume(r != NULL); return (getCoeffType(r)==n_R) || (getCoeffType(r)==n_long_R) || (getCoeffType(r)==n_long_C); }
858 // (r->ringtype == 0) && (r->ch == -1); ??
859
nCoeff_is_R(const coeffs r)860 static FORCE_INLINE BOOLEAN nCoeff_is_R(const coeffs r)
861 { assume(r != NULL); return getCoeffType(r)==n_R; }
862
nCoeff_is_GF(const coeffs r)863 static FORCE_INLINE BOOLEAN nCoeff_is_GF(const coeffs r)
864 { assume(r != NULL); return getCoeffType(r)==n_GF; }
865
nCoeff_is_GF(const coeffs r,int q)866 static FORCE_INLINE BOOLEAN nCoeff_is_GF(const coeffs r, int q)
867 { assume(r != NULL); return (getCoeffType(r)==n_GF) && (r->ch == q); }
868
869 /* TRUE iff r represents an algebraic or transcendental extension field */
nCoeff_is_Extension(const coeffs r)870 static FORCE_INLINE BOOLEAN nCoeff_is_Extension(const coeffs r)
871 {
872 assume(r != NULL);
873 return (getCoeffType(r)==n_algExt) || (getCoeffType(r)==n_transExt);
874 }
875
876 /* DO NOT USE (only kept for compatibility reasons towards the SINGULAR
877 svn trunk);
878 intension: should be TRUE iff the given r is an extension field above
879 some Z/pZ;
880 actually: TRUE iff the given r is an extension tower of arbitrary
881 height above some field of characteristic p (may be Z/pZ or some
882 Galois field of characteristic p) */
nCoeff_is_Zp_a(const coeffs r)883 static FORCE_INLINE BOOLEAN nCoeff_is_Zp_a(const coeffs r)
884 {
885 assume(r != NULL);
886 return ((!nCoeff_is_Ring(r)) && (n_GetChar(r) != 0) && nCoeff_is_Extension(r));
887 }
888
889 /* DO NOT USE (only kept for compatibility reasons towards the SINGULAR
890 svn trunk);
891 intension: should be TRUE iff the given r is an extension field above
892 Z/pZ (with p as provided);
893 actually: TRUE iff the given r is an extension tower of arbitrary
894 height above some field of characteristic p (may be Z/pZ or some
895 Galois field of characteristic p) */
nCoeff_is_Zp_a(const coeffs r,int p)896 static FORCE_INLINE BOOLEAN nCoeff_is_Zp_a(const coeffs r, int p)
897 {
898 assume(r != NULL);
899 assume(p != 0);
900 return ((!nCoeff_is_Ring(r)) && (n_GetChar(r) == p) && nCoeff_is_Extension(r));
901 }
902
903 /* DO NOT USE (only kept for compatibility reasons towards the SINGULAR
904 svn trunk);
905 intension: should be TRUE iff the given r is an extension field
906 above Q;
907 actually: TRUE iff the given r is an extension tower of arbitrary
908 height above some field of characteristic 0 (may be Q, R, or C) */
nCoeff_is_Q_a(const coeffs r)909 static FORCE_INLINE BOOLEAN nCoeff_is_Q_a(const coeffs r)
910 {
911 assume(r != NULL);
912 return ((n_GetChar(r) == 0) && nCoeff_is_Extension(r));
913 }
914
nCoeff_is_long_R(const coeffs r)915 static FORCE_INLINE BOOLEAN nCoeff_is_long_R(const coeffs r)
916 { assume(r != NULL); return getCoeffType(r)==n_long_R; }
917
nCoeff_is_long_C(const coeffs r)918 static FORCE_INLINE BOOLEAN nCoeff_is_long_C(const coeffs r)
919 { assume(r != NULL); return getCoeffType(r)==n_long_C; }
920
nCoeff_is_CF(const coeffs r)921 static FORCE_INLINE BOOLEAN nCoeff_is_CF(const coeffs r)
922 { assume(r != NULL); return getCoeffType(r)==n_CF; }
923
924 /// TRUE, if the computation of the inverse is fast,
925 /// i.e. prefer leading coeff. 1 over content
nCoeff_has_simple_inverse(const coeffs r)926 static FORCE_INLINE BOOLEAN nCoeff_has_simple_inverse(const coeffs r)
927 { assume(r != NULL); return r->has_simple_Inverse; }
928
929 /// TRUE if n_Delete/n_New are empty operations
nCoeff_has_simple_Alloc(const coeffs r)930 static FORCE_INLINE BOOLEAN nCoeff_has_simple_Alloc(const coeffs r)
931 { assume(r != NULL); return r->has_simple_Alloc; }
932
933 /// TRUE iff r represents an algebraic extension field
nCoeff_is_algExt(const coeffs r)934 static FORCE_INLINE BOOLEAN nCoeff_is_algExt(const coeffs r)
935 { assume(r != NULL); return (getCoeffType(r)==n_algExt); }
936
937 /// is it an alg. ext. of Q?
nCoeff_is_Q_algext(const coeffs r)938 static FORCE_INLINE BOOLEAN nCoeff_is_Q_algext(const coeffs r)
939 { assume(r != NULL); return ((n_GetChar(r) == 0) && nCoeff_is_algExt(r)); }
940
941 /// TRUE iff r represents a transcendental extension field
nCoeff_is_transExt(const coeffs r)942 static FORCE_INLINE BOOLEAN nCoeff_is_transExt(const coeffs r)
943 { assume(r != NULL); return (getCoeffType(r)==n_transExt); }
944
945 /// Computes the content and (inplace) divides it out on a collection
946 /// of numbers
947 /// number @em c is the content (i.e. the GCD of all the coeffs, which
948 /// we divide out inplace)
949 /// NOTE: it assumes all coefficient numbers to be integer!!!
950 /// NOTE/TODO: see also the description by Hans
951 /// TODO: rename into n_ClearIntegerContent
n_ClearContent(ICoeffsEnumerator & numberCollectionEnumerator,number & c,const coeffs r)952 static FORCE_INLINE void n_ClearContent(ICoeffsEnumerator& numberCollectionEnumerator, number& c, const coeffs r)
953 { STATISTIC(n_ClearContent); assume(r != NULL); r->cfClearContent(numberCollectionEnumerator, c, r); }
954
955 /// (inplace) Clears denominators on a collection of numbers
956 /// number @em d is the LCM of all the coefficient denominators (i.e. the number
957 /// with which all the number coeffs. were multiplied)
958 /// NOTE/TODO: see also the description by Hans
n_ClearDenominators(ICoeffsEnumerator & numberCollectionEnumerator,number & d,const coeffs r)959 static FORCE_INLINE void n_ClearDenominators(ICoeffsEnumerator& numberCollectionEnumerator, number& d, const coeffs r)
960 { STATISTIC(n_ClearDenominators); assume(r != NULL); r->cfClearDenominators(numberCollectionEnumerator, d, r); }
961
962 // convenience helpers (no number returned - but the input enumeration
963 // is to be changed
964 // TODO: do we need separate hooks for these as our existing code does
965 // *different things* there: compare p_Cleardenom (which calls
966 // *p_Content) and p_Cleardenom_n (which doesn't)!!!
967
n_ClearContent(ICoeffsEnumerator & numberCollectionEnumerator,const coeffs r)968 static FORCE_INLINE void n_ClearContent(ICoeffsEnumerator& numberCollectionEnumerator, const coeffs r)
969 { STATISTIC(n_ClearContent); number c; n_ClearContent(numberCollectionEnumerator, c, r); n_Delete(&c, r); }
970
n_ClearDenominators(ICoeffsEnumerator & numberCollectionEnumerator,const coeffs r)971 static FORCE_INLINE void n_ClearDenominators(ICoeffsEnumerator& numberCollectionEnumerator, const coeffs r)
972 { STATISTIC(n_ClearDenominators); assume(r != NULL); number d; n_ClearDenominators(numberCollectionEnumerator, d, r); n_Delete(&d, r); }
973
974
975 /// print a number (BEWARE of string buffers!)
976 /// mostly for debugging
977 void n_Print(number& a, const coeffs r);
978
979
980
981 /// TODO: make it a virtual method of coeffs, together with:
982 /// Decompose & Compose, rParameter & rPar
nCoeffString(const coeffs cf)983 static FORCE_INLINE char * nCoeffString(const coeffs cf)
984 { STATISTIC(nCoeffString); assume( cf != NULL ); return cf->cfCoeffString(cf); }
985
986
nCoeffName(const coeffs cf)987 static FORCE_INLINE char * nCoeffName (const coeffs cf)
988 { STATISTIC(nCoeffName); assume( cf != NULL ); return cf->cfCoeffName(cf); }
989
n_Random(siRandProc p,number p1,number p2,const coeffs cf)990 static FORCE_INLINE number n_Random(siRandProc p, number p1, number p2, const coeffs cf)
991 { STATISTIC(n_Random); assume( cf != NULL ); assume( cf->cfRandom != NULL ); return cf->cfRandom(p, p1, p2, cf); }
992
993 /// io via ssi:
n_WriteFd(number a,const ssiInfo * f,const coeffs r)994 static FORCE_INLINE void n_WriteFd(number a, const ssiInfo *f, const coeffs r)
995 { STATISTIC(n_WriteFd); assume(r != NULL); assume(r->cfWriteFd != NULL); return r->cfWriteFd(a, f, r); }
996
997 /// io via ssi:
n_ReadFd(const ssiInfo * f,const coeffs r)998 static FORCE_INLINE number n_ReadFd( const ssiInfo *f, const coeffs r)
999 { STATISTIC(n_ReadFd); assume(r != NULL); assume(r->cfReadFd != NULL); return r->cfReadFd(f, r); }
1000
1001
1002 // the following wrappers went to numbers.cc since they needed factory
1003 // knowledge!
1004 number n_convFactoryNSingN( const CanonicalForm n, const coeffs r);
1005
1006 CanonicalForm n_convSingNFactoryN( number n, BOOLEAN setChar, const coeffs r );
1007
1008
1009 // TODO: remove the following functions...
1010 // the following 2 inline functions are just convenience shortcuts for Frank's code:
number2mpz(number n,coeffs c,mpz_t m)1011 static FORCE_INLINE void number2mpz(number n, coeffs c, mpz_t m){ n_MPZ(m, n, c); }
mpz2number(mpz_t m,coeffs c)1012 static FORCE_INLINE number mpz2number(mpz_t m, coeffs c){ return n_InitMPZ(m, c); }
1013
1014 #endif
1015
1016