1 #ifndef LONGRAT_H
2 #define LONGRAT_H
3 /****************************************
4 *  Computer Algebra System SINGULAR     *
5 ****************************************/
6 /*
7 * ABSTRACT: computation with long rational numbers
8 */
9 #include "misc/auxiliary.h"
10 
11 #include "coeffs/si_gmp.h"
12 #include "coeffs/coeffs.h"
13 #include "factory/si_log2.h"
14 
15 number   nlGetDenom(number &n, const coeffs r); /*for SAGE,, better: n_GetDenom */
16 number   nlGetNumerator(number &n, const coeffs r); /*for SAGE, better: n_GetNumerator*/
17 
18 /*-----------------------------------------------------------------*/
19 /**
20 **  'SR_INT' is the type of those integers small enough to fit into  29  bits.
21 **  Therefor the value range of this small integers is: $-2^{28}...2^{28}-1$.
22 **
23 **  Small integers are represented by an immediate integer handle, containing
24 **  the value instead of pointing  to  it,  which  has  the  following  form:
25 **
26 **      +-------+-------+-------+-------+- - - -+-------+-------+-------+
27 **      | guard | sign  | bit   | bit   |       | bit   | tag   | tag   |
28 **      | bit   | bit   | 27    | 26    |       | 0     | 0     | 1     |
29 **      +-------+-------+-------+-------+- - - -+-------+-------+-------+
30 **
31 **  Immediate integers handles carry the tag 'SR_INT', i.e. the last bit is 1.
32 **  This distuingishes immediate integers from other handles which  point  to
33 **  structures aligned on 4 byte boundaries and therefor have last bit  zero.
34 **  (The second bit is reserved as tag to allow extensions of  this  scheme.)
35 **  Using immediates as pointers and dereferencing them gives address errors.
36 **
37 **  To aid overflow check the most significant two bits must always be equal,
38 **  that is to say that the sign bit of immediate integers has a  guard  bit.
39 **
40 **  The macros 'INT_TO_SR' and 'SR_TO_INT' should be used to convert  between
41 **  a small integer value and its representation as immediate integer handle.
42 **
43 **  Large integers and rationals are represented by z and n
44 **  where n may be undefined (if s==3)
45 **  NULL represents only deleted values
46 */
47 
48 struct snumber
49 {
50   mpz_t z; //< Zaehler
51   mpz_t n; //< Nenner
52 #if defined(LDEBUG)
53   int debug;
54 #endif
55 
56   /**
57    * parameter s in number:
58    * 0 (or FALSE): not normalised rational
59    * 1 (or TRUE):  normalised rational
60    * 3          :  integer with n==NULL
61    **/
62   BOOLEAN s; //< integer parameter
63 };
64 
65 #define SR_HDL(A) ((long)(A))
66 
67 #define SR_INT    1L
68 #define INT_TO_SR(INT)  ((number) (((long)INT << 2) + SR_INT))
69 #define SR_TO_INT(SR)   (((long)SR) >> 2)
70 
71 #define MP_SMALL 1
72 
73 BOOLEAN nlInitChar(coeffs, void*);
74 
75 /// only used by slimgb (tgb.cc)
nlQlogSize(number n,const coeffs r)76 static  FORCE_INLINE int nlQlogSize (number n, const coeffs r)
77 {
78   assume( nCoeff_is_Q (r) );
79 
80   if(SR_HDL(n)&SR_INT)
81   {
82     if (SR_HDL(n)==SR_INT) return 0;
83     long i = SR_TO_INT (n);
84     unsigned long v;
85     v = ABS(i);
86     return SI_LOG2_LONG(v) + 1;
87   }
88   //assume denominator is 0
89   number nn=(number) n;
90   return mpz_sizeinbase (nn->z, 2);
91 }
92 
93 
nlIsInteger(number q,const coeffs r)94 static FORCE_INLINE BOOLEAN nlIsInteger(number q, const coeffs r)
95 {
96   assume( nCoeff_is_Q (r) );
97   n_Test(q, r);
98 
99   if (SR_HDL(q) & SR_INT)
100     return TRUE; // immediate int
101 
102   return ( q->s == 3 );
103 }
104 
105 void nlMPZ(mpz_t m, number &n, const coeffs r);
106 number nlModP(number q, const coeffs Q, const coeffs Zp);
107 void   nlNormalize(number &x, const coeffs r);
108 void   nlInpGcd(number &a, number b, const coeffs r);
109 void   nlDelete(number *a, const coeffs r);  /*for SAGE,, better: n_Delete */
110 
111 
112 
113 /// create a rational i/j (implicitly) over Q
114 /// NOTE: make sure to use correct Q in debug mode
115 number   nlInit2 (int i, int j, const coeffs r);
116 
117 /// create a rational i/j (implicitly) over Q
118 /// NOTE: make sure to use correct Q in debug mode
119 number   nlInit2gmp (mpz_t i, mpz_t j, const coeffs r);
120 
121 #if 0 // substituted by nlMPZ
122 void   nlGMP(number &i, mpz_t n, const coeffs r);
123 #endif
124 // for ring similiar to Q/Z (char 0 required):
125 number   nlChineseRemainderSym(number *x, number *q,int rl, BOOLEAN sym, CFArray &inv_cache,const coeffs CF);
126 
127 
128 #endif
129 
130 
131