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

spielwiese
Last change on this file since 240295 was 240295, checked in by Hans Schoenemann <hannes@…>, 11 years ago
add: n_InpAdd from master
  • 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
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   /// changes argument  inline: a:= -a
142   /// return -a! (no copy is returned)
143   /// the result should be assigned to the original argument: e.g. a = n_Neg(a,r)
144   number  (*cfNeg)(number a, const coeffs r);
145   /// return 1/a
146   number  (*cfInvers)(number a, const coeffs r);
147   /// return a copy of a
148   number  (*cfCopy)(number a, const coeffs r);
149   number  (*cfRePart)(number a, const coeffs r);
150   number  (*cfImPart)(number a, const coeffs r);
151
152   /// print a given number (long format)
153   void    (*cfWriteLong)(number &a, const coeffs r);
154   
155   /// print a given number in a shorter way, if possible
156   /// e.g. in K(a): a2 instead of a^2
157   void    (*cfWriteShort)(number &a, const coeffs r);
158   
159   const char *  (*cfRead)(const char * s, number * a, const coeffs r);
160   void    (*cfNormalize)(number &a, const coeffs r);
161   
162#ifdef HAVE_RINGS
163   int     (*cfDivComp)(number a,number b,const coeffs r);
164   BOOLEAN (*cfIsUnit)(number a,const coeffs r);
165   number  (*cfGetUnit)(number a,const coeffs r);
166   BOOLEAN (*cfDivBy)(number a, number b, const coeffs r);
167#endif
168
169   
170   BOOLEAN (*cfGreater)(number a,number b, const coeffs r),
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   /// 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#ifdef HAVE_FACTORY
221   number (*convFactoryNSingN)( const CanonicalForm n, const coeffs r);
222   CanonicalForm (*convSingNFactoryN)( number n, BOOLEAN setChar, const coeffs r );
223#endif
224
225
226#ifdef LDEBUG
227   /// Test: is "a" a correct number?
228   BOOLEAN (*cfDBTest)(number a, const char *f, const int l, const coeffs r);
229#endif
230
231   /// the 0 as constant, NULL by default
232   number nNULL; 
233   int     char_flag;
234   int     ref;
235   /// how many variables of factort are already used by this coeff
236   int     factoryVarOffset;
237   n_coeffType type;
238
239
240   /// Number of Parameters in the coeffs (default 0)
241   int iNumberOfParameters;
242
243   /// array containing the names of Parameters (default NULL)
244   char const * const * pParameterNames;
245   // NOTE that it replaces the following:
246// char* complex_parameter; //< the name of sqrt(-1) in n_long_C , i.e. 'i' or 'j' etc...?
247// char * m_nfParameter; //< the name of parameter in n_GF
248
249   /////////////////////////////////////////////
250   // the union stuff
251
252   //-------------------------------------------
253
254  /* for extension fields we need to be able to represent polynomials,
255     so here is the polynomial ring: */
256  ring          extRing;
257
258  //number     minpoly;  //< no longer needed: replaced by
259  //                     //< extRing->qideal->[0]
260
261
262//-------------------------------------------
263#ifdef HAVE_RINGS
264  /* The following members are for representing the ring Z/n,
265     where n is not a prime. We distinguish four cases:
266     1.) n has at least two distinct prime factors. Then
267         modBase stores n, modExponent stores 1, modNumber
268         stores n, and mod2mMask is not used;
269     2.) n = p^k for some odd prime p and k > 1. Then
270         modBase stores p, modExponent stores k, modNumber
271         stores n, and mod2mMask is not used;
272     3.) n = 2^k for some k > 1; moreover, 2^k - 1 fits in
273         an unsigned long. Then modBase stores 2, modExponent
274         stores k, modNumber is not used, and mod2mMask stores
275         2^k - 1, i.e., the bit mask '111..1' of length k.
276     4.) n = 2^k for some k > 1; but 2^k - 1 does not fit in
277         an unsigned long. Then modBase stores 2, modExponent
278         stores k, modNumber stores n, and mod2mMask is not
279         used;
280     Cases 1.), 2.), and 4.) are covered by the implementation
281     in the files rmodulon.h and rmodulon.cc, whereas case 3.)
282     is implemented in the files rmodulo2m.h and rmodulo2m.cc. */
283  int_number    modBase;
284  unsigned long modExponent;
285  int_number    modNumber;
286  unsigned long mod2mMask;
287#endif
288  int        ch;  /* characteristic, set by the local *InitChar methods;
289                     In field extensions or extensions towers, the
290                     characteristic can be accessed from any of the
291                     intermediate extension fields, i.e., in this case
292                     it is redundant along the chain of field extensions;
293                     CONTRARY to SINGULAR as it was, we do NO LONGER use
294                     negative values for ch;
295                     for rings, ch will also be set and is - per def -
296                     the smallest number of 1's that sum up to zero;
297                     however, in this case ch may not fit in an int,
298                     thus ch may contain a faulty value */
299
300  short      float_len; /* additional char-flags, rInit */
301  short      float_len2; /* additional char-flags, rInit */
302
303//  BOOLEAN   CanShortOut; //< if the elements can be printed in short format
304//                     // this is set to FALSE if a parameter name has >2 chars
305//  BOOLEAN   ShortOut; //< if the elements should print in short format
306
307// ---------------------------------------------------
308  // for n_GF
309
310  int m_nfCharQ;  ///< the number of elements: q
311  int m_nfM1;       ///< representation of -1
312  int m_nfCharP;  ///< the characteristic: p
313  int m_nfCharQ1; ///< q-1
314  unsigned short *m_nfPlus1Table;
315  int *m_nfMinPoly;
316 
317// ---------------------------------------------------
318// for Zp:
319#ifdef HAVE_DIV_MOD
320  unsigned short *npInvTable;
321#endif
322#if !defined(HAVE_DIV_MOD) || !defined(HAVE_MULT_MOD)
323  unsigned short *npExpTable;
324  unsigned short *npLogTable;
325#endif
326   //   int npPrimeM; // NOTE: npPrimeM is deprecated, please use ch instead!
327  int npPminus1M; ///< characteristic - 1
328};
329//
330// test properties and type
331/// Returns the type of coeffs domain
332static inline n_coeffType getCoeffType(const coeffs r)
333{
334  assume(r != NULL);
335  return r->type;
336}
337
338/// one-time initialisations for new coeffs
339/// in case of an error return NULL
340coeffs nInitChar(n_coeffType t, void * parameter);
341
342/// undo all initialisations
343void nKillChar(coeffs r);
344
345/// initialisations after each ring change
346static inline void nSetChar(const coeffs r)
347{
348  assume(r!=NULL); // r==NULL is an error
349  assume(r->cfSetChar != NULL);
350  r->cfSetChar(r);
351}
352
353void           nNew(number * a);
354#define n_New(n, r)           nNew(n)
355
356
357/// Return the characteristic of the coeff. domain.
358static inline int n_GetChar(const coeffs r)
359{
360  assume(r != NULL);
361  return r->ch;
362}
363
364
365// the access methods (part 2):
366
367/// return a copy of 'n'
368static inline number n_Copy(number n,    const coeffs r)
369{   assume(r != NULL); assume(r->cfCopy!=NULL); return r->cfCopy(n, r); }
370
371/// delete 'p'
372static inline void   n_Delete(number* p, const coeffs r)
373{   assume(r != NULL); assume(r->cfDelete!= NULL); r->cfDelete(p, r); }
374
375/// TRUE iff 'a' and 'b' represent the same number;
376/// they may have different representations
377static inline BOOLEAN n_Equal(number a, number b, const coeffs r)
378{ assume(r != NULL); assume(r->cfEqual!=NULL); return r->cfEqual(a, b, r); }
379
380/// TRUE iff 'n' represents the zero element
381static inline BOOLEAN n_IsZero(number n, const coeffs r)
382{ assume(r != NULL); assume(r->cfIsZero!=NULL); return r->cfIsZero(n,r); }
383
384/// TRUE iff 'n' represents the one element
385static inline BOOLEAN n_IsOne(number n,  const coeffs r)
386{ assume(r != NULL); assume(r->cfIsOne!=NULL); return r->cfIsOne(n,r); }
387
388/// TRUE iff 'n' represents the additive inverse of the one element, i.e. -1
389static inline BOOLEAN n_IsMOne(number n, const coeffs r)
390{ assume(r != NULL); assume(r->cfIsMOne!=NULL); return r->cfIsMOne(n,r); }
391
392/// ordered fields: TRUE iff 'n' is positive;
393/// in Z/pZ: TRUE iff 0 < m <= roundedBelow(p/2), where m is the long
394///          representing n
395/// in C:    TRUE iff (Im(n) != 0 and Im(n) >= 0) or
396///                   (Im(n) == 0 and Re(n) >= 0)
397/// in K(a)/<p(a)>: TRUE iff (n != 0 and (LC(n) > 0 or deg(n) > 0))
398/// in K(t_1, ..., t_n): TRUE iff (LC(numerator(n) is a constant and > 0)
399///                            or (LC(numerator(n) is not a constant)
400/// in Z/2^kZ: TRUE iff 0 < n <= 2^(k-1)
401/// in Z/mZ: TRUE iff the internal mpz is greater than zero
402/// in Z: TRUE iff n > 0
403///
404/// !!! Recommendation: remove implementations for unordered fields
405/// !!!                 and raise errors instead, in these cases
406/// !!! Do not follow this recommendation: while writing polys,
407/// !!! between 2 monomials will be an additional + iff !n_GreaterZero(next coeff)
408///
409static inline BOOLEAN n_GreaterZero(number n, const coeffs r)
410{
411  assume(r != NULL); assume(r->cfGreaterZero!=NULL);
412  return r->cfGreaterZero(n,r);
413}
414
415/// ordered fields: TRUE iff 'a' is larger than 'b';
416/// in Z/pZ: TRUE iff la > lb, where la and lb are the long's representing
417//                             a and b, respectively
418/// in C:    TRUE iff (Im(a) > Im(b))
419/// in K(a)/<p(a)>: TRUE iff (a != 0 and (b == 0 or deg(a) > deg(b))
420/// in K(t_1, ..., t_n): TRUE only if one or both numerator polynomials are
421///                      zero or if their degrees are equal. In this case,
422///                      TRUE if LC(numerator(a)) > LC(numerator(b))
423/// in Z/2^kZ: TRUE if n_DivBy(a, b)
424/// in Z/mZ: TRUE iff the internal mpz's fulfill the relation '>'
425/// in Z: TRUE iff a > b
426///
427/// !!! Recommendation: remove implementations for unordered fields
428/// !!!                 and raise errors instead, in these cases
429static inline BOOLEAN n_Greater(number a, number b, const coeffs r)
430{ assume(r != NULL); assume(r->cfGreater!=NULL); return r->cfGreater(a,b,r); }
431
432#ifdef HAVE_RINGS
433static inline int n_DivComp(number a, number b, const coeffs r)
434{ assume(r != NULL); assume(r->cfDivComp!=NULL); return r->cfDivComp (a,b,r); }
435
436/// TRUE iff n has a multiplicative inverse in the given coeff field/ring r
437static inline BOOLEAN n_IsUnit(number n, const coeffs r)
438{ assume(r != NULL); assume(r->cfIsUnit!=NULL); return r->cfIsUnit(n,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/// addition of 'a' and 'b';
538/// replacement of 'a' by the sum a+b
539static inline void n_InpAdd(number &a, number b, const coeffs r)
540{ assume(r != NULL); assume(r->cfInpAdd!=NULL); r->cfInpAdd(a,b,r); }
541
542/// return the difference of 'a' and 'b', i.e., a-b
543static inline number n_Sub(number a, number b, const coeffs r)
544{ assume(r != NULL); assume(r->cfSub!=NULL); return r->cfSub(a, b, r); }
545
546/// return the sum of 'a' and 'b', i.e., a+b
547static inline number n_Add(number a, number b, const coeffs r)
548{ assume(r != NULL); assume(r->cfAdd!=NULL); return r->cfAdd(a, b, r); }
549
550/// return the quotient of 'a' and 'b', i.e., a/b;
551/// raise an error if 'b' is not invertible in r
552static inline number n_Div(number a, number b, const coeffs r)
553{ assume(r != NULL); assume(r->cfDiv!=NULL); return r->cfDiv(a,b,r); }
554
555/// in Z: largest c such that c*b <= a
556/// in Z/nZ, Z/2^kZ: computed as in the case Z (from integers representing
557///                  'a' and 'b')
558/// in Z/pZ: return a/b
559/// in K(a)/<p(a)>: return a/b
560/// in K(t_1, ..., t_n): return a/b
561/// other fields: not implemented
562static inline number n_IntDiv(number a, number b, const coeffs r)
563{ assume(r != NULL); assume(r->cfIntDiv!=NULL); return r->cfIntDiv(a,b,r); }
564
565static inline number n_IntMod(number a, number b, const coeffs r)
566{ assume(r != NULL); assume(r->cfIntMod!=NULL); return r->cfIntMod(a,b,r); }
567/// @todo: Describe me!!!
568///
569/// What is the purpose of this method, especially in comparison with
570/// n_Div?
571/// !!! Recommendation: remove this method from the user-interface.
572static inline number n_ExactDiv(number a, number b, const coeffs r)
573{ assume(r != NULL); assume(r->cfExactDiv!=NULL); return r->cfExactDiv(a,b,r); }
574
575/// in Z: return the gcd of 'a' and 'b'
576/// in Z/nZ, Z/2^kZ: computed as in the case Z
577/// in Z/pZ, C, R: not implemented
578/// in Q: return the gcd of the numerators of 'a' and 'b'
579/// in K(a)/<p(a)>: not implemented
580/// in K(t_1, ..., t_n): not implemented
581static inline number n_Gcd(number a, number b, const coeffs r)
582{ assume(r != NULL); assume(r->cfGcd!=NULL); return r->cfGcd(a,b,r); }
583
584/// beware that ExtGCD is only relevant for a few chosen coeff. domains
585/// and may perform something unexpected in some cases...
586static inline number n_ExtGcd(number a, number b, number *s, number *t, const coeffs r)
587{ assume(r != NULL); assume(r->cfExtGcd!=NULL); return r->cfExtGcd (a,b,s,t,r); }
588
589/// in Z: return the lcm of 'a' and 'b'
590/// in Z/nZ, Z/2^kZ: computed as in the case Z
591/// in Z/pZ, C, R: not implemented
592/// in Q: return the lcm of the numerators of 'a' and the denominator of 'b'
593/// in K(a)/<p(a)>: not implemented
594/// in K(t_1, ..., t_n): not implemented
595static inline number n_Lcm(number a, number b, const coeffs r)
596{ assume(r != NULL); assume(r->cfLcm!=NULL); return r->cfLcm(a,b,r); }
597
598/// set the mapping function pointers for translating numbers from src to dst
599static inline nMapFunc n_SetMap(const coeffs src, const coeffs dst)
600{ assume(src != NULL && dst != NULL); assume(dst->cfSetMap!=NULL); return dst->cfSetMap(src,dst); }
601
602/// test whether n is a correct number;
603/// only used if LDEBUG is defined
604#ifdef LDEBUG
605static inline BOOLEAN n_DBTest(number n, const char *filename, const int linenumber, const coeffs r)
606#else
607static inline BOOLEAN n_DBTest(number, const char*, const int, const coeffs)
608#endif
609{
610  assume(r != NULL); 
611#ifdef LDEBUG
612  assume(r->cfDBTest != NULL); 
613  return r->cfDBTest(n, filename, linenumber, r);
614#else
615  return TRUE;
616#endif
617}
618
619/// output the coeff description
620static inline void   n_CoeffWrite(const coeffs r, BOOLEAN details = TRUE)
621{ assume(r != NULL); assume(r->cfCoeffWrite != NULL); r->cfCoeffWrite(r, details); }
622
623// Tests:
624static inline BOOLEAN nCoeff_is_Ring_2toM(const coeffs r)
625{ assume(r != NULL); return (getCoeffType(r)==n_Z2m); }
626
627static inline BOOLEAN nCoeff_is_Ring_ModN(const coeffs r)
628{ assume(r != NULL); return (getCoeffType(r)==n_Zn); }
629
630static inline BOOLEAN nCoeff_is_Ring_PtoM(const coeffs r)
631{ assume(r != NULL); return (getCoeffType(r)==n_Znm); }
632
633static inline BOOLEAN nCoeff_is_Ring_Z(const coeffs r)
634{ assume(r != NULL); return (getCoeffType(r)==n_Z); }
635
636static inline BOOLEAN nCoeff_is_Ring(const coeffs r)
637{ assume(r != NULL); return ((getCoeffType(r)==n_Z) || (getCoeffType(r)==n_Z2m) || (getCoeffType(r)==n_Zn) || (getCoeffType(r)==n_Znm)); }
638
639/// returns TRUE, if r is not a field and r has no zero divisors (i.e is a domain)
640static inline BOOLEAN nCoeff_is_Domain(const coeffs r)
641{
642  assume(r != NULL); 
643#ifdef HAVE_RINGS
644  return (getCoeffType(r)==n_Z || ((getCoeffType(r)!=n_Z2m) && (getCoeffType(r)!=n_Zn) && (getCoeffType(r)!=n_Znm)));
645#else
646  return TRUE;
647#endif
648}
649
650/// test whether 'a' is divisible 'b';
651/// for r encoding a field: TRUE iff 'b' does not represent zero
652/// in Z: TRUE iff 'b' divides 'a' (with remainder = zero)
653/// in Z/nZ: TRUE iff (a = 0 and b divides n in Z) or
654///                   (a != 0 and b/gcd(a, b) is co-prime with n, i.e.
655///                                              a unit in Z/nZ)
656/// in Z/2^kZ: TRUE iff ((a = 0 mod 2^k) and (b = 0 or b is a power of 2))
657///                  or ((a, b <> 0) and (b/gcd(a, b) is odd))
658static inline BOOLEAN n_DivBy(number a, number b, const coeffs r)
659{
660  assume(r != NULL);
661#ifdef HAVE_RINGS
662  if( nCoeff_is_Ring(r) )
663  {
664    assume(r->cfDivBy!=NULL); return r->cfDivBy(a,b,r);
665  }
666#endif
667  return !n_IsZero(b, r);
668}
669
670static inline number n_ChineseRemainderSym(number *a, number *b, int rl, BOOLEAN sym,const coeffs r)
671{
672  assume(r != NULL); assume(r->cfChineseRemainder != NULL); return r->cfChineseRemainder(a,b,rl,sym,r);
673}
674
675static inline number n_Farey(number a, number b, const coeffs r)
676{
677  assume(r != NULL); assume(r->cfFarey != NULL); return r->cfFarey(a,b,r);
678}
679
680static inline int n_ParDeg(number n, const coeffs r)
681{ 
682  assume(r != NULL); assume(r->cfParDeg != NULL); return r->cfParDeg(n,r); 
683}
684
685/// Returns the number of parameters
686static inline int n_NumberOfParameters(const coeffs r){ return r->iNumberOfParameters; }
687
688/// Returns a (const!) pointer to (const char*) names of parameters
689static inline char const * const * n_ParameterNames(const coeffs r){ return r->pParameterNames; }
690
691
692/// return the (iParameter^th) parameter as a NEW number
693/// NOTE: parameter numbering: 1..n_NumberOfParameters(...)
694static inline number n_Param(const int iParameter, const coeffs r)
695{
696  assume(r != NULL);
697  assume((iParameter >= 1) || (iParameter <= n_NumberOfParameters(r)));
698  assume(r->cfParameter != NULL);
699  return r->cfParameter(iParameter, r); 
700}
701
702
703static inline number  n_Init_bigint(number i, const coeffs dummy,
704                const coeffs dst)
705{
706  assume(dummy != NULL && dst != NULL); assume(dst->cfInit_bigint!=NULL); 
707  return dst->cfInit_bigint(i, dummy, dst);
708}
709
710static inline number  n_RePart(number i, const coeffs cf)
711{
712  assume(cf != NULL); assume(cf->cfRePart!=NULL); 
713  return cf->cfRePart(i,cf);
714}
715static inline number  n_ImPart(number i, const coeffs cf)
716{
717  assume(cf != NULL); assume(cf->cfImPart!=NULL); 
718  return cf->cfImPart(i,cf);
719}
720
721/// returns TRUE, if r is not a field and r has non-trivial units
722static inline BOOLEAN nCoeff_has_Units(const coeffs r)
723{ assume(r != NULL); return ((getCoeffType(r)==n_Zn) || (getCoeffType(r)==n_Z2m) || (getCoeffType(r)==n_Znm)); }
724
725static inline BOOLEAN nCoeff_is_Zp(const coeffs r)
726{ assume(r != NULL); return getCoeffType(r)==n_Zp; }
727
728static inline BOOLEAN nCoeff_is_Zp(const coeffs r, int p)
729{ assume(r != NULL); return ((getCoeffType(r)==n_Zp) && (r->ch == p)); }
730
731static inline BOOLEAN nCoeff_is_Q(const coeffs r)
732{ assume(r != NULL); return getCoeffType(r)==n_Q; }
733
734static inline BOOLEAN nCoeff_is_numeric(const coeffs r) /* R, long R, long C */
735{ assume(r != NULL);  return (getCoeffType(r)==n_R) || (getCoeffType(r)==n_long_R) || (getCoeffType(r)==n_long_C); }
736// (r->ringtype == 0) && (r->ch ==  -1); ??
737
738static inline BOOLEAN nCoeff_is_R(const coeffs r)
739{ assume(r != NULL); return getCoeffType(r)==n_R; }
740
741static inline BOOLEAN nCoeff_is_GF(const coeffs r)
742{ assume(r != NULL); return getCoeffType(r)==n_GF; }
743
744static inline BOOLEAN nCoeff_is_GF(const coeffs r, int q)
745{ assume(r != NULL); return (getCoeffType(r)==n_GF) && (r->ch == q); }
746
747/* TRUE iff r represents an algebraic or transcendental extension field */
748static inline BOOLEAN nCoeff_is_Extension(const coeffs r)
749{
750  assume(r != NULL);
751  return (getCoeffType(r)==n_algExt) || (getCoeffType(r)==n_transExt);
752}
753
754/* DO NOT USE (only kept for compatibility reasons towards the SINGULAR
755   svn trunk);
756   intension: should be TRUE iff the given r is an extension field above
757   some Z/pZ;
758   actually: TRUE iff the given r is an extension tower of arbitrary
759   height above some field of characteristic p (may be Z/pZ or some
760   Galois field of characteristic p) */
761static inline BOOLEAN nCoeff_is_Zp_a(const coeffs r)
762{
763  assume(r != NULL);
764  return ((!nCoeff_is_Ring(r)) && (n_GetChar(r) != 0) && nCoeff_is_Extension(r));
765}
766
767/* DO NOT USE (only kept for compatibility reasons towards the SINGULAR
768   svn trunk);
769   intension: should be TRUE iff the given r is an extension field above
770   Z/pZ (with p as provided);
771   actually: TRUE iff the given r is an extension tower of arbitrary
772   height above some field of characteristic p (may be Z/pZ or some
773   Galois field of characteristic p) */
774static inline BOOLEAN nCoeff_is_Zp_a(const coeffs r, int p)
775{
776  assume(r != NULL);
777  assume(p != 0);
778  return ((!nCoeff_is_Ring(r)) && (n_GetChar(r) == p) && nCoeff_is_Extension(r));
779}
780
781/* DO NOT USE (only kept for compatibility reasons towards the SINGULAR
782   svn trunk);
783   intension: should be TRUE iff the given r is an extension field
784   above Q;
785   actually: TRUE iff the given r is an extension tower of arbitrary
786   height above some field of characteristic 0 (may be Q, R, or C) */
787static inline BOOLEAN nCoeff_is_Q_a(const coeffs r)
788{
789  assume(r != NULL);
790  return ((n_GetChar(r) == 0) && nCoeff_is_Extension(r));
791}
792
793
794
795
796static inline BOOLEAN nCoeff_is_long_R(const coeffs r)
797{ assume(r != NULL); return getCoeffType(r)==n_long_R; }
798
799static inline BOOLEAN nCoeff_is_long_C(const coeffs r)
800{ assume(r != NULL); return getCoeffType(r)==n_long_C; }
801
802static inline BOOLEAN nCoeff_is_CF(const coeffs r)
803{ assume(r != NULL); return getCoeffType(r)==n_CF; }
804
805/// TRUE, if the computation of the inverse is fast,
806/// i.e. prefer leading coeff. 1 over content
807static inline BOOLEAN nCoeff_has_simple_inverse(const coeffs r)
808{ assume(r != NULL); return r->has_simple_Inverse; }
809
810/// TRUE if n_Delete/n_New are empty operations
811static inline BOOLEAN nCoeff_has_simple_Alloc(const coeffs r)
812{ assume(r != NULL); return r->has_simple_Alloc; }
813
814/// TRUE iff r represents an algebraic extension field
815static inline BOOLEAN nCoeff_is_algExt(const coeffs r)
816{ assume(r != NULL); return (getCoeffType(r)==n_algExt); }
817
818/// is it an alg. ext. of Q?
819static inline BOOLEAN nCoeff_is_Q_algext(const coeffs r)
820{ assume(r != NULL); return ((n_GetChar(r) == 0) && nCoeff_is_algExt(r)); }
821
822/// TRUE iff r represents a transcendental extension field
823static inline BOOLEAN nCoeff_is_transExt(const coeffs r)
824{ assume(r != NULL); return (getCoeffType(r)==n_transExt); }
825
826/// BOOLEAN n_Test(number a, const coeffs r)
827#define n_Test(a,r)  n_DBTest(a, __FILE__, __LINE__, r)
828
829// Missing wrappers for: (TODO: review this?)
830// cfIntMod, cfRead, cfName, cfInit_bigint
831
832// HAVE_RINGS: cfDivComp, cfIsUnit, cfGetUnit, cfDivBy
833// BUT NOT cfExtGcd...!
834
835
836/// Computes the content and (inplace) divides it out on a collection
837/// of numbers
838/// number @em c is the content (i.e. the GCD of all the coeffs, which
839/// we divide out inplace)
840/// NOTE: it assumes all coefficient numbers to be integer!!!
841/// NOTE/TODO: see also the description by Hans
842/// TODO: rename into n_ClearIntegerContent
843static inline void n_ClearContent(ICoeffsEnumerator& numberCollectionEnumerator, number& c, const coeffs r)
844{
845  assume(r != NULL);
846  r->cfClearContent(numberCollectionEnumerator, c, r);
847}
848
849/// (inplace) Clears denominators on a collection of numbers
850/// number @em d is the LCM of all the coefficient denominators (i.e. the number
851/// with which all the number coeffs. were multiplied)
852/// NOTE/TODO: see also the description by Hans
853static inline void n_ClearDenominators(ICoeffsEnumerator& numberCollectionEnumerator, number& d, const coeffs r)
854{
855  assume(r != NULL);
856  r->cfClearDenominators(numberCollectionEnumerator, d, r);
857}
858
859// convenience helpers (no number returned - but the input enumeration
860// is to be changed
861// TODO: do we need separate hooks for these as our existing code does
862// *different things* there: compare p_Cleardenom (which calls
863// *p_Content) and p_Cleardenom_n (which doesn't)!!!
864
865static inline void n_ClearContent(ICoeffsEnumerator& numberCollectionEnumerator, const coeffs r)
866{
867  number c;
868  n_ClearContent(numberCollectionEnumerator, c, r);
869  n_Delete(&c, r);
870}
871
872static inline void n_ClearDenominators(ICoeffsEnumerator& numberCollectionEnumerator, const coeffs r)
873{
874  assume(r != NULL);
875  number d;
876  n_ClearDenominators(numberCollectionEnumerator, d, r);
877  n_Delete(&d, r);
878}
879
880/// print a number (BEWARE of string buffers!)
881/// mostly for debugging
882void   n_Print(number& a,  const coeffs r);
883
884#endif
885
Note: See TracBrowser for help on using the repository browser.