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