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

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