source: git/libpolys/coeffs/coeffs.h @ c4bb27c

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