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

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