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

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