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