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

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