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

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