xref: /dragonfly/contrib/mpfr/src/mpfr-gmp.h (revision f2c43266)
1 /* Interface to replace gmp-impl.h
2 
3 Copyright 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc.
4 Contributed by the AriC and Caramel projects, INRIA.
5 
6 This file is part of the GNU MPFR Library.
7 
8 The GNU MPFR Library is free software; you can redistribute it and/or modify
9 it under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or (at your
11 option) any later version.
12 
13 The GNU MPFR Library is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
16 License for more details.
17 
18 You should have received a copy of the GNU Lesser General Public License
19 along with the GNU MPFR Library; see the file COPYING.LESSER.  If not, see
20 http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
21 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
22 
23 #ifndef __GMPFR_GMP_H__
24 #define __GMPFR_GMP_H__
25 
26 #ifndef __MPFR_IMPL_H__
27 # error  "mpfr-impl.h not included"
28 #endif
29 
30 #include <limits.h> /* For INT_MAX, ... */
31 #include <string.h> /* For memcpy, memset and memmove */
32 
33 /* The following tries to get a good version of alloca.
34    See gmp-impl.h for implementation details and original version */
35 /* FIXME: the autoconf manual gives a different piece of code under the
36    documentation of the AC_FUNC_ALLOCA macro. Should we switch to it? */
37 #ifndef alloca
38 # if defined ( __GNUC__ )
39 #  define alloca __builtin_alloca
40 # elif defined (__DECC)
41 #  define alloca(x) __ALLOCA(x)
42 # elif defined (_MSC_VER)
43 #  include <malloc.h>
44 #  define alloca _alloca
45 # elif defined (HAVE_ALLOCA_H)
46 #  include <alloca.h>
47 # elif defined (_AIX) || defined (_IBMR2)
48 #  pragma alloca
49 # else
50 void *alloca (size_t);
51 # endif
52 #endif
53 
54 #if defined (__cplusplus)
55 extern "C" {
56 #endif
57 
58 /* Define GMP_NUMB_BITS
59    Can't use sizeof(mp_limb_t) since it should be a preprocessor constant */
60 #if defined(GMP_NUMB_BITS) /* GMP 4.1.2 or above */
61 #ifndef GMP_NUMB_BITS
62 # define GMP_NUMB_BITS  (GMP_NUMB_BITS+GMP_NAIL_BITS)
63 #endif
64 #elif defined (__GMP_GMP_NUMB_BITS) /* Older versions 4.x.x */
65 # define GMP_NUMB_BITS  __GMP_GMP_NUMB_BITS
66 # define GMP_NUMB_BITS GMP_NUMB_BITS
67 # ifndef GMP_NAIL_BITS
68 #  define GMP_NAIL_BITS 0
69 # endif
70 #else
71 # error "Could not detect GMP_NUMB_BITS. Try with gmp internal files."
72 #endif
73 
74 /* Define some macros */
75 #define BYTES_PER_MP_LIMB (GMP_NUMB_BITS/CHAR_BIT)
76 
77 #define MP_LIMB_T_MAX (~(mp_limb_t)0)
78 
79 #define ULONG_HIGHBIT (ULONG_MAX ^ ((unsigned long) ULONG_MAX >> 1))
80 #define UINT_HIGHBIT  (UINT_MAX ^ ((unsigned) UINT_MAX >> 1))
81 #define USHRT_HIGHBIT ((unsigned short) (USHRT_MAX ^ ((unsigned short) USHRT_MAX >> 1)))
82 
83 #define GMP_LIMB_HIGHBIT (MP_LIMB_T_MAX ^ (MP_LIMB_T_MAX >> 1))
84 
85 
86 #if __GMP_MP_SIZE_T_INT
87 #define MP_SIZE_T_MAX      INT_MAX
88 #define MP_SIZE_T_MIN      INT_MIN
89 #else
90 #define MP_SIZE_T_MAX      LONG_MAX
91 #define MP_SIZE_T_MIN      LONG_MIN
92 #endif
93 
94 #define LONG_HIGHBIT       LONG_MIN
95 #define INT_HIGHBIT        INT_MIN
96 #define SHRT_HIGHBIT       SHRT_MIN
97 
98 /* MP_LIMB macros */
99 #define MPN_ZERO(dst, n) memset((dst), 0, (n)*BYTES_PER_MP_LIMB)
100 #define MPN_COPY_DECR(dst,src,n) memmove((dst),(src),(n)*BYTES_PER_MP_LIMB)
101 #define MPN_COPY_INCR(dst,src,n) memmove((dst),(src),(n)*BYTES_PER_MP_LIMB)
102 #define MPN_COPY(dst,src,n) \
103   do                                                                  \
104     {                                                                 \
105       if ((dst) != (src))                                             \
106         {                                                             \
107           MPFR_ASSERTD ((char *) (dst) >= (char *) (src) +            \
108                                           (n) * BYTES_PER_MP_LIMB ||  \
109                         (char *) (src) >= (char *) (dst) +            \
110                                           (n) * BYTES_PER_MP_LIMB);   \
111           memcpy ((dst), (src), (n) * BYTES_PER_MP_LIMB);             \
112         }                                                             \
113     }                                                                 \
114   while (0)
115 
116 /* MPN macros taken from gmp-impl.h */
117 #define MPN_NORMALIZE(DST, NLIMBS) \
118   do {                                        \
119     while (NLIMBS > 0)                        \
120       {                                       \
121         if ((DST)[(NLIMBS) - 1] != 0)         \
122           break;                              \
123         NLIMBS--;                             \
124       }                                       \
125   } while (0)
126 #define MPN_NORMALIZE_NOT_ZERO(DST, NLIMBS)     \
127   do {                                          \
128     MPFR_ASSERTD ((NLIMBS) >= 1);               \
129     while (1)                                   \
130       {                                         \
131         if ((DST)[(NLIMBS) - 1] != 0)           \
132           break;                                \
133         NLIMBS--;                               \
134       }                                         \
135   } while (0)
136 #define MPN_OVERLAP_P(xp, xsize, yp, ysize) \
137   ((xp) + (xsize) > (yp) && (yp) + (ysize) > (xp))
138 #define MPN_SAME_OR_INCR2_P(dst, dsize, src, ssize)             \
139   ((dst) <= (src) || ! MPN_OVERLAP_P (dst, dsize, src, ssize))
140 #define MPN_SAME_OR_INCR_P(dst, src, size)      \
141   MPN_SAME_OR_INCR2_P(dst, size, src, size)
142 #define MPN_SAME_OR_DECR2_P(dst, dsize, src, ssize)             \
143   ((dst) >= (src) || ! MPN_OVERLAP_P (dst, dsize, src, ssize))
144 #define MPN_SAME_OR_DECR_P(dst, src, size)      \
145   MPN_SAME_OR_DECR2_P(dst, size, src, size)
146 
147 /* If mul_basecase or mpn_sqr_basecase are not exported, used mpn_mul instead */
148 #ifndef mpn_mul_basecase
149 # define mpn_mul_basecase(dst,s1,n1,s2,n2) mpn_mul((dst),(s1),(n1),(s2),(n2))
150 #endif
151 #ifndef mpn_sqr_basecase
152 # define mpn_sqr_basecase(dst,src,n) mpn_mul((dst),(src),(n),(src),(n))
153 #endif
154 
155 /* ASSERT */
156 __MPFR_DECLSPEC void mpfr_assert_fail _MPFR_PROTO((const char *, int,
157                                                    const char *));
158 
159 #define ASSERT_FAIL(expr)  mpfr_assert_fail (__FILE__, __LINE__, #expr)
160 #define ASSERT(expr)       MPFR_ASSERTD(expr)
161 
162 /* Access fileds of GMP struct */
163 #define SIZ(x) ((x)->_mp_size)
164 #define ABSIZ(x) ABS (SIZ (x))
165 #define PTR(x) ((x)->_mp_d)
166 #define EXP(x) ((x)->_mp_exp)
167 #define PREC(x) ((x)->_mp_prec)
168 #define ALLOC(x) ((x)->_mp_alloc)
169 #define MPZ_REALLOC(z,n) ((n) > ALLOC(z) ? _mpz_realloc(z,n) : PTR(z))
170 
171 /* Non IEEE float supports -- needs to detect them with proper configure */
172 #undef  XDEBUG
173 #define XDEBUG
174 
175 /* For longlong.h */
176 #ifdef HAVE_ATTRIBUTE_MODE
177 typedef unsigned int UQItype    __attribute__ ((mode (QI)));
178 typedef          int SItype     __attribute__ ((mode (SI)));
179 typedef unsigned int USItype    __attribute__ ((mode (SI)));
180 typedef          int DItype     __attribute__ ((mode (DI)));
181 typedef unsigned int UDItype    __attribute__ ((mode (DI)));
182 #else
183 typedef unsigned char UQItype;
184 typedef          long SItype;
185 typedef unsigned long USItype;
186 #ifdef HAVE_LONG_LONG
187 typedef long long int DItype;
188 typedef unsigned long long int UDItype;
189 #else /* Assume `long' gives us a wide enough type.  Needed for hppa2.0w.  */
190 typedef long int DItype;
191 typedef unsigned long int UDItype;
192 #endif
193 #endif
194 typedef mp_limb_t UWtype;
195 typedef unsigned int UHWtype;
196 #define W_TYPE_SIZE GMP_NUMB_BITS
197 
198 /* Remap names of internal mpn functions (for longlong.h).  */
199 #undef  __clz_tab
200 #define __clz_tab               mpfr_clz_tab
201 
202 /* Use (4.0 * ...) instead of (2.0 * ...) to work around buggy compilers
203    that don't convert ulong->double correctly (eg. SunOS 4 native cc).  */
204 #undef MP_BASE_AS_DOUBLE
205 #define MP_BASE_AS_DOUBLE (4.0 * ((mp_limb_t) 1 << (GMP_NUMB_BITS - 2)))
206 
207 /* Structure for conversion between internal binary format and
208    strings in base 2..36.  */
209 struct bases
210 {
211   /* log(2)/log(conversion_base) */
212   double chars_per_bit_exactly;
213 };
214 #undef  __mp_bases
215 #define __mp_bases mpfr_bases
216 __MPFR_DECLSPEC extern const struct bases mpfr_bases[257];
217 
218 /* Standard macros */
219 #undef ABS
220 #undef MIN
221 #undef MAX
222 #undef numberof
223 #define ABS(x) ((x) >= 0 ? (x) : -(x))
224 #define MIN(l,o) ((l) < (o) ? (l) : (o))
225 #define MAX(h,i) ((h) > (i) ? (h) : (i))
226 #define numberof(x)  (sizeof (x) / sizeof ((x)[0]))
227 
228 /* Random */
229 #undef  __gmp_rands_initialized
230 #undef  __gmp_rands
231 #define __gmp_rands_initialized mpfr_rands_initialized
232 #define __gmp_rands             mpfr_rands
233 
234 __MPFR_DECLSPEC extern char             mpfr_rands_initialized;
235 __MPFR_DECLSPEC extern gmp_randstate_t  mpfr_rands;
236 
237 #undef RANDS
238 #define RANDS                                   \
239   ((__gmp_rands_initialized ? 0                 \
240     : (__gmp_rands_initialized = 1,             \
241        gmp_randinit_default (__gmp_rands), 0)), \
242    __gmp_rands)
243 
244 #undef RANDS_CLEAR
245 #define RANDS_CLEAR()                   \
246   do {                                  \
247     if (__gmp_rands_initialized)        \
248       {                                 \
249         __gmp_rands_initialized = 0;    \
250         gmp_randclear (__gmp_rands);    \
251       }                                 \
252   } while (0)
253 
254 typedef __gmp_randstate_struct *gmp_randstate_ptr;
255 
256 /* Allocate func are defined in gmp-impl.h */
257 
258 /* In newer GMP, there aren't anymore __gmp_allocate_func,
259    __gmp_reallocate_func & __gmp_free_func in gmp.h
260    Just getting the correct value by calling mp_get_memory_functions */
261 #ifdef mp_get_memory_functions
262 
263 #undef __gmp_allocate_func
264 #undef __gmp_reallocate_func
265 #undef __gmp_free_func
266 #define MPFR_GET_MEMFUNC mp_get_memory_functions(&mpfr_allocate_func, &mpfr_reallocate_func, &mpfr_free_func)
267 #define __gmp_allocate_func   (MPFR_GET_MEMFUNC, mpfr_allocate_func)
268 #define __gmp_reallocate_func (MPFR_GET_MEMFUNC, mpfr_reallocate_func)
269 #define __gmp_free_func       (MPFR_GET_MEMFUNC, mpfr_free_func)
270 __MPFR_DECLSPEC extern void * (*mpfr_allocate_func)   _MPFR_PROTO ((size_t));
271 __MPFR_DECLSPEC extern void * (*mpfr_reallocate_func) _MPFR_PROTO ((void *,
272                                                           size_t, size_t));
273 __MPFR_DECLSPEC extern void   (*mpfr_free_func)       _MPFR_PROTO ((void *,
274                                                                     size_t));
275 
276 #endif
277 
278 #undef __gmp_default_allocate
279 #undef __gmp_default_reallocate
280 #undef __gmp_default_free
281 #define __gmp_default_allocate   mpfr_default_allocate
282 #define __gmp_default_reallocate mpfr_default_reallocate
283 #define __gmp_default_free       mpfr_default_free
284 __MPFR_DECLSPEC void *__gmp_default_allocate _MPFR_PROTO ((size_t));
285 __MPFR_DECLSPEC void *__gmp_default_reallocate _MPFR_PROTO ((void *, size_t,
286                                                              size_t));
287 __MPFR_DECLSPEC void __gmp_default_free _MPFR_PROTO ((void *, size_t));
288 
289 #if defined(WANT_GMP_INTERNALS) && defined(HAVE___GMPN_ROOTREM)
290 #ifndef __gmpn_rootrem
291   __MPFR_DECLSPEC mp_size_t __gmpn_rootrem _MPFR_PROTO ((mp_limb_t*,
292                     mp_limb_t*, mp_limb_t*, mp_size_t, mp_limb_t));
293 #endif
294 #endif
295 
296 #if defined(WANT_GMP_INTERNALS) && defined(HAVE___GMPN_SBPI1_DIVAPPR_Q)
297 #ifndef __gmpn_sbpi1_divappr_q
298   __MPFR_DECLSPEC mp_limb_t __gmpn_sbpi1_divappr_q _MPFR_PROTO ((mp_limb_t*,
299                 mp_limb_t*, mp_size_t, mp_limb_t*, mp_size_t, mp_limb_t));
300 #endif
301 #endif
302 
303 /* Temp memory allocate */
304 
305 struct tmp_marker
306 {
307   void *ptr;
308   size_t size;
309   struct tmp_marker *next;
310 };
311 
312 __MPFR_DECLSPEC void *mpfr_tmp_allocate _MPFR_PROTO ((struct tmp_marker **,
313                                                       size_t));
314 __MPFR_DECLSPEC void mpfr_tmp_free _MPFR_PROTO ((struct tmp_marker *));
315 
316 /* Do not define TMP_SALLOC (see the test in mpfr-impl.h)! */
317 #define TMP_ALLOC(n) (MPFR_LIKELY ((n) < 16384) ?       \
318                       alloca (n) : mpfr_tmp_allocate (&tmp_marker, (n)))
319 #define TMP_DECL(m) struct tmp_marker *tmp_marker
320 #define TMP_MARK(m) (tmp_marker = 0)
321 #define TMP_FREE(m) mpfr_tmp_free (tmp_marker)
322 
323 /* invert_limb macro, copied from GMP 5.0.2, file gmp-impl.h.
324    It returns invxl = floor((B^2-1)/xl)-B, where B=2^BITS_PER_LIMB,
325    assuming the most significant bit of xl is set. */
326 #undef invert_limb
327 #define invert_limb(invxl,xl)                             \
328   do {                                                    \
329     mp_limb_t dummy;                                      \
330     MPFR_ASSERTD ((xl) != 0);                             \
331     udiv_qrnnd (invxl, dummy, ~(xl), ~(mp_limb_t)0, xl);  \
332   } while (0)
333 
334 typedef struct {mp_limb_t inv32;} mpfr_pi1_t; /* We changed gmp_pi1_t into
335                                                  mpfr_pi1_t to avoid using
336                                                  GMP's namespace. */
337 /* invert_pi1 macro, adapted from GMP 5.0.2, file gmp-impl.h.
338    It returns dinv = floor((B^3-1)/(d1*B+d0))-B, where B=2^BITS_PER_LIMB,
339    assuming the most significant bit of d1 is set. */
340 #undef invert_pi1
341 #define invert_pi1(dinv, d1, d0)                                \
342   do {                                                          \
343     mp_limb_t _v, _p, _t1, _t0, _mask;                          \
344     invert_limb (_v, d1);                                       \
345     _p = d1 * _v;                                               \
346     _p += d0;                                                   \
347     if (_p < d0)                                                \
348       {                                                         \
349         _v--;                                                   \
350         _mask = -(_p >= d1);                                    \
351         _p -= d1;                                               \
352         _v += _mask;                                            \
353         _p -= _mask & d1;                                       \
354       }                                                         \
355     umul_ppmm (_t1, _t0, d0, _v);                               \
356     _p += _t1;                                                  \
357     if (_p < _t1)                                               \
358       {                                                         \
359         _v--;                                                   \
360         if (MPFR_UNLIKELY (_p >= d1))                           \
361           {                                                     \
362             if (_p > d1 || _t0 >= d0)                           \
363               _v--;                                             \
364           }                                                     \
365       }                                                         \
366     (dinv).inv32 = _v;                                          \
367   } while (0)
368 
369 /* udiv_qr_3by2 macro, adapted from GMP 5.0.2, file gmp-impl.h.
370    Compute quotient the quotient and remainder for n / d. Requires d
371    >= B^2 / 2 and n < d B. dinv is the inverse
372 
373      floor ((B^3 - 1) / (d0 + d1 B)) - B.
374 
375    NOTE: Output variables are updated multiple times. Only some inputs
376    and outputs may overlap.
377 */
378 #undef udiv_qr_3by2
379 #define udiv_qr_3by2(q, r1, r0, n2, n1, n0, d1, d0, dinv)               \
380   do {                                                                  \
381     mp_limb_t _q0, _t1, _t0, _mask;                                     \
382     umul_ppmm ((q), _q0, (n2), (dinv));                                 \
383     add_ssaaaa ((q), _q0, (q), _q0, (n2), (n1));                        \
384                                                                         \
385     /* Compute the two most significant limbs of n - q'd */             \
386     (r1) = (n1) - (d1) * (q);                                           \
387     (r0) = (n0);                                                        \
388     sub_ddmmss ((r1), (r0), (r1), (r0), (d1), (d0));                    \
389     umul_ppmm (_t1, _t0, (d0), (q));                                    \
390     sub_ddmmss ((r1), (r0), (r1), (r0), _t1, _t0);                      \
391     (q)++;                                                              \
392                                                                         \
393     /* Conditionally adjust q and the remainders */                     \
394     _mask = - (mp_limb_t) ((r1) >= _q0);                                \
395     (q) += _mask;                                                       \
396     add_ssaaaa ((r1), (r0), (r1), (r0), _mask & (d1), _mask & (d0));    \
397     if (MPFR_UNLIKELY ((r1) >= (d1)))                                   \
398       {                                                                 \
399         if ((r1) > (d1) || (r0) >= (d0))                                \
400           {                                                             \
401             (q)++;                                                      \
402             sub_ddmmss ((r1), (r0), (r1), (r0), (d1), (d0));            \
403           }                                                             \
404       }                                                                 \
405   } while (0)
406 
407 #if defined (__cplusplus)
408 }
409 #endif
410 
411 #endif /* Gmp internal emulator */
412