source: git/libpolys/coeffs/coeffs.h @ 353a42

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