1 #ifndef MPFQ_H_
2 #define MPFQ_H_
3
4 /* This header contains common declarations used by mpfq modules */
5
6 /* we always include stdio.h, otherwise our inclusion of gmp.h might
7 * prevent gmp's I/O functions to ever be exposed... */
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11
12 #ifndef GF2X_WORDSIZE
13 #error "This file has been modified for use within gf2x. Please arrange so that gf2x-small.h is included before this file"
14 #endif
15
16 #ifdef __cplusplus
17 extern "C" {
18 #endif
19
20
21
22 /*** Constants for field_specify ***/
23
24 #define MPFQ_DONE 0 /* At the end of the variadic option functions */
25 // #define MPFQ_PRIME_MPN 1 /* mp_limb_t *, size depending on implementation. Prefer MPFQ_PRIME_MPZ */
26 #define MPFQ_POLYNOMIAL 2 /* this expects an mpfq polynomial */
27 #define MPFQ_DEGREE 3 /* int */
28 #define MPFQ_IO_TYPE 4 /* for setopt */
29 #define MPFQ_SIMD_GROUPSIZE 5 /* int (SIMD group size) */
30 #define MPFQ_GROUPSIZE 5 /* (for compatibility, just in case) */
31 // #define MPFQ_PRIME_MPZ 6 /* mpz_t */
32 #define MPFQ_MANDATORY_TAG 7 /* force the tag to be this one ; this is
33 * of course pointless for the low-level
34 * implementation, but
35 * mpfq_vbase_oo_field_init_byfeatures
36 * uses it. */
37
38 #define LEXGE2(X,Y,A,B) (X>A || (X == A && Y >= B))
39 #define LEXGE3(X,Y,Z,A,B,C) (X>A || (X == A && LEXGE2(Y,Z,B,C)))
40 #define LEXLE2(X,Y,A,B) LEXGE2(A,B,X,Y)
41 #define LEXLE3(X,Y,Z,A,B,C) LEXGE3(A,B,C,X,Y,Z)
42
43 #ifndef GNUC_VERSION
44 #ifndef __GNUC__
45 #define GNUC_VERSION(X,Y,Z) 0
46 #else
47 #define GNUC_VERSION(X,Y,Z) \
48 (__GNUC__ == X && __GNUC_MINOR__ == Y && __GNUC_PATCHLEVEL__ == Z)
49 #endif
50 #endif
51
52 #ifndef GNUC_VERSION_ATLEAST
53 #ifndef __GNUC__
54 #define GNUC_VERSION_ATLEAST(X,Y,Z) 0
55 #else
56 #define GNUC_VERSION_ATLEAST(X,Y,Z) \
57 LEXGE3(__GNUC__,__GNUC_MINOR__,__GNUC_PATCHLEVEL__,X,Y,Z)
58 #endif
59 #endif
60
61 #ifndef GNUC_VERSION_ATMOST
62 #ifndef __GNUC__
63 #define GNUC_VERSION_ATMOST(X,Y,Z) 0
64 #else
65 #define GNUC_VERSION_ATMOST(X,Y,Z) \
66 LEXLE3(__GNUC__,__GNUC_MINOR__,__GNUC_PATCHLEVEL__,X,Y,Z)
67 #endif
68 #endif
69
70 /* typedef unsigned long ulong; */
71
72 #ifndef MAX
73 #define MAX(h,i) ((h) > (i) ? (h) : (i))
74 #endif
75
76 #ifndef MIN
77 #define MIN(l,o) ((l) < (o) ? (l) : (o))
78 #endif
79
80 #ifndef __cplusplus
81 #ifndef max
82 #define max(a,b) ((a) > (b) ? (a) : (b))
83 #endif
84
85 #ifndef min
86 #define min(a,b) ((a) < (b) ? (a) : (b))
87 #endif
88 #endif /* __cplusplus */
89
90
91 #ifndef ABS
92 #define ABS(x) ((x) >= 0 ? (x) : -(x))
93 #endif
94
95 #if GNUC_VERSION_ATLEAST(3,4,0)
96 /* according to
97 * http://gcc.gnu.org/onlinedocs/gcc-3.1.1/gcc/Variable-Attributes.html#Variable%20Attributes
98 * the 'unused' attribute already existed in 3.1.1 ; however the rules
99 * for its usage remained quirky until 3.4.0, so we prefer to stick to
100 * the more modern way of using the unused attribute, and recommend
101 * setting the -Wno-unused flag for pre-3.4 versions of gcc
102 */
103 #ifndef MAYBE_UNUSED
104 #define MAYBE_UNUSED __attribute__((unused))
105 #endif
106 #endif
107
108 #if GNUC_VERSION_ATLEAST(3,1,0) /* apparently */
109 #ifndef MPFQ_EXPECT
110 #define MPFQ_EXPECT(x,val) __builtin_expect(x,val)
111 #endif
112 #endif
113
114 #if GNUC_VERSION_ATLEAST(3,4,0)
115 #define mpfq_clzl(x) __builtin_clzl(x)
116 #define mpfq_ctzl(x) __builtin_ctzl(x)
117 #define mpfq_parityl(x) __builtin_parityl(x)
118 #else
119 /* provide slow fallbacks */
120 static inline int mpfq_clzl(unsigned long x)
121 {
122 static const int t[4] = { 2, 1, 0, 0 };
123 int a = 0;
124 int res;
125 #if (GF2X_WORDSIZE == 64)
126 if (x >> 32) { a += 32; x >>= 32; }
127 #endif
128 if (x >> 16) { a += 16; x >>= 16; }
129 if (x >> 8) { a += 8; x >>= 8; }
130 if (x >> 4) { a += 4; x >>= 4; }
131 if (x >> 2) { a += 2; x >>= 2; }
132 res = GF2X_WORDSIZE - 2 - a + t[x];
133 return res;
134 }
135 static inline int mpfq_ctzl(unsigned long x)
136 {
137 return GF2X_WORDSIZE - mpfq_clzl(x & - x);
138 }
139 static inline int mpfq_parityl(unsigned long x)
140 {
141 static const int t[4] = { 0, 1, 1, 0, };
142 #if (GF2X_WORDSIZE == 64)
143 x ^= (x >> 32);
144 #endif
145 x ^= (x >> 16);
146 x ^= (x >> 8);
147 x ^= (x >> 4);
148 x ^= (x >> 2);
149 return t[x & 3UL];
150 }
151 #endif
152
153 #ifndef MAYBE_UNUSED
154 #define MAYBE_UNUSED /**/
155 #endif
156
157 #ifndef MPFQ_EXPECT
158 #define MPFQ_EXPECT(x,val) (x)
159 #endif
160
161 #ifndef MPFQ_UNLIKELY
162 #define MPFQ_UNLIKELY(x) MPFQ_EXPECT(x, 0)
163 #endif
164 #ifndef MPFQ_LIKELY
165 #define MPFQ_LIKELY(x) MPFQ_EXPECT(x, 1)
166 #endif
167
168
169
mpfq_clzlx(unsigned long * x,int n)170 static inline int mpfq_clzlx(unsigned long * x, int n)
171 {
172 int r = 0;
173 for( ; n > 0 && MPFQ_UNLIKELY(!x[n-1]) ; --n) r+=GF2X_WORDSIZE;
174 if (n == 0) return r;
175 r += mpfq_clzl(x[n-1]);
176 return r;
177 }
178
mpfq_ctzlx(unsigned long * x,int n)179 static inline int mpfq_ctzlx(unsigned long * x, int n)
180 {
181 int r = 0;
182 for( ; n > 0 && MPFQ_UNLIKELY(!*x) ; --n,++x) r+=GF2X_WORDSIZE;
183 if (n == 0) return r;
184 r += mpfq_ctzl(*x);
185 return r;
186 }
187
188 /*** Some useful macros ***/
189
190 #if 0
191
192 /* Given the fact that copies are always very small, we're probably
193 * better off giving the compiler the opportunity to optimize all this
194 * away.
195 */
196
197 /* dst and src known to not overlap, except possibly if dst == src */
198 static inline void mpfq_copy(mp_limb_t * dst, const mp_limb_t * src, mp_size_t n) {
199 // if (dst != src) mpn_copyi(dst, src, n);
200 for( ; n-- ; ) *dst++ = *src++;
201 }
202
203 /* dst and src possibly overlap, copy increasingly so that src >= dst is ok */
204 static inline void mpfq_copyi(mp_limb_t * dst, const mp_limb_t * src, mp_size_t n) {
205 // mpn_copyi(dst, src, n);
206 for( ; n-- ; ) *dst++ = *src++;
207 }
208
209 /* dst and src possibly overlap, copy decreasingly so that src <= dst is ok */
210 static inline void mpfq_copyd(mp_limb_t * dst, const mp_limb_t * src, mp_size_t n) {
211 // mpn_copyd(dst, src, n);
212 for(dst += n, src += n ; n-- ; ) *--dst = *--src;
213 }
214
215 static inline void mpfq_zero(mp_limb_t * dst, mp_size_t n) {
216 // mpn_zero(dst, 0, n);
217 for( ; n-- ; ) *dst++ = 0;
218 }
219
220 #endif
221
222
223 #ifdef __cplusplus
224 }
225 #endif
226
227 #endif /* MPFQ_H_ */
228