summaryrefslogtreecommitdiff
path: root/src/mpfr-gmp.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/mpfr-gmp.h')
-rw-r--r--src/mpfr-gmp.h255
1 files changed, 142 insertions, 113 deletions
diff --git a/src/mpfr-gmp.h b/src/mpfr-gmp.h
index 946605f6e..8b111b822 100644
--- a/src/mpfr-gmp.h
+++ b/src/mpfr-gmp.h
@@ -1,4 +1,4 @@
-/* Interface to replace gmp-impl.h
+/* Uniform Interface to GMP.
Copyright 2004-2014 Free Software Foundation, Inc.
Contributed by the AriC and Caramel projects, INRIA.
@@ -27,8 +27,66 @@ http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
# error "mpfr-impl.h not included"
#endif
-#include <limits.h> /* For INT_MAX, ... */
-#include <string.h> /* For memcpy, memset and memmove */
+
+/******************************************************
+ ******************** C++ Compatibility ***************
+ ******************************************************/
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+
+/******************************************************
+ ******************** Identify GMP ********************
+ ******************************************************/
+
+/* Macro to detect the GMP version */
+#if defined(__GNU_MP_VERSION) && \
+ defined(__GNU_MP_VERSION_MINOR) && \
+ defined(__GNU_MP_VERSION_PATCHLEVEL)
+# define __MPFR_GMP(a,b,c) \
+ (MPFR_VERSION_NUM(__GNU_MP_VERSION,__GNU_MP_VERSION_MINOR,__GNU_MP_VERSION_PATCHLEVEL) >= MPFR_VERSION_NUM(a,b,c))
+#else
+# define __MPFR_GMP(a,b,c) 0
+#endif
+
+
+
+/******************************************************
+ ******************** Check GMP ***********************
+ ******************************************************/
+
+#if !__MPFR_GMP(4,2,0)
+# error "GMP 4.2.0 or newer needed"
+#endif
+
+#if GMP_NAIL_BITS != 0
+# error "MPFR doesn't support nonzero values of GMP_NAIL_BITS"
+#endif
+
+#if (GMP_NUMB_BITS<32) || (GMP_NUMB_BITS & (GMP_NUMB_BITS - 1))
+# error "GMP_NUMB_BITS must be a power of 2, and >= 32"
+#endif
+
+#if GMP_NUMB_BITS == 32
+# define MPFR_LOG2_GMP_NUMB_BITS 5
+#elif GMP_NUMB_BITS == 64
+# define MPFR_LOG2_GMP_NUMB_BITS 6
+#elif GMP_NUMB_BITS == 128
+# define MPFR_LOG2_GMP_NUMB_BITS 7
+#elif GMP_NUMB_BITS == 256
+# define MPFR_LOG2_GMP_NUMB_BITS 8
+#else
+# error "Can't compute log2(GMP_NUMB_BITS)"
+#endif
+
+
+
+/******************************************************
+ ************* Define GMP Internal Interface *********
+ ******************************************************/
+
+#ifndef MPFR_HAVE_GMP_IMPL /* Build with gmp internals */
/* The following tries to get a good version of alloca.
See gmp-impl.h for implementation details and original version */
@@ -51,26 +109,6 @@ void *alloca (size_t);
# endif
#endif
-#if defined (__cplusplus)
-extern "C" {
-#endif
-
-/* Define GMP_NUMB_BITS
- Can't use sizeof(mp_limb_t) since it should be a preprocessor constant */
-#if defined(GMP_NUMB_BITS) /* GMP 4.1.2 or above */
-#ifndef GMP_NUMB_BITS
-# define GMP_NUMB_BITS (GMP_NUMB_BITS+GMP_NAIL_BITS)
-#endif
-#elif defined (__GMP_GMP_NUMB_BITS) /* Older versions 4.x.x */
-# define GMP_NUMB_BITS __GMP_GMP_NUMB_BITS
-# define GMP_NUMB_BITS GMP_NUMB_BITS
-# ifndef GMP_NAIL_BITS
-# define GMP_NAIL_BITS 0
-# endif
-#else
-# error "Could not detect GMP_NUMB_BITS. Try with gmp internal files."
-#endif
-
/* Define some macros */
#define BYTES_PER_MP_LIMB (GMP_NUMB_BITS/CHAR_BIT)
@@ -221,47 +259,8 @@ __MPFR_DECLSPEC extern const struct bases mpfr_bases[257];
#define MAX(h,i) ((h) > (i) ? (h) : (i))
#define numberof(x) (sizeof (x) / sizeof ((x)[0]))
-/* Random */
-/* TODO: these variables and macros seem to be used only in the tests.
- Remove them from the MPFR source (src directory) so that the symbols
- mpfr_rands_initialized and mpfr_rands are not defined in the MPFR
- library? Moreover, whether the GMP build directory is used or not,
- we could use our own rand state, so that __gmp_rands_initialized and
- __gmp_rands would no longer be needed. */
-#undef __gmp_rands_initialized
-#undef __gmp_rands
-#define __gmp_rands_initialized mpfr_rands_initialized
-#define __gmp_rands mpfr_rands
-
-__MPFR_DECLSPEC extern char mpfr_rands_initialized;
-__MPFR_DECLSPEC extern gmp_randstate_t mpfr_rands;
-
-#undef RANDS
-#define RANDS \
- ((__gmp_rands_initialized ? 0 \
- : (__gmp_rands_initialized = 1, \
- gmp_randinit_default (__gmp_rands), 0)), \
- __gmp_rands)
-
-#undef RANDS_CLEAR
-#define RANDS_CLEAR() \
- do { \
- if (__gmp_rands_initialized) \
- { \
- __gmp_rands_initialized = 0; \
- gmp_randclear (__gmp_rands); \
- } \
- } while (0)
-
-typedef __gmp_randstate_struct *gmp_randstate_ptr;
-
/* Allocate func are defined in gmp-impl.h */
-/* In newer GMP, there aren't anymore __gmp_allocate_func,
- __gmp_reallocate_func & __gmp_free_func in gmp.h
- Just getting the correct value by calling mp_get_memory_functions */
-#ifdef mp_get_memory_functions
-
#undef __gmp_allocate_func
#undef __gmp_reallocate_func
#undef __gmp_free_func
@@ -275,19 +274,6 @@ __MPFR_DECLSPEC extern void * (*mpfr_reallocate_func) _MPFR_PROTO ((void *,
__MPFR_DECLSPEC extern void (*mpfr_free_func) _MPFR_PROTO ((void *,
size_t));
-#endif
-
-#undef __gmp_default_allocate
-#undef __gmp_default_reallocate
-#undef __gmp_default_free
-#define __gmp_default_allocate mpfr_default_allocate
-#define __gmp_default_reallocate mpfr_default_reallocate
-#define __gmp_default_free mpfr_default_free
-__MPFR_DECLSPEC void *__gmp_default_allocate _MPFR_PROTO ((size_t));
-__MPFR_DECLSPEC void *__gmp_default_reallocate _MPFR_PROTO ((void *, size_t,
- size_t));
-__MPFR_DECLSPEC void __gmp_default_free _MPFR_PROTO ((void *, size_t));
-
#if defined(WANT_GMP_INTERNALS) && defined(HAVE___GMPN_ROOTREM)
#ifndef __gmpn_rootrem
__MPFR_DECLSPEC mp_size_t __gmpn_rootrem _MPFR_PROTO ((mp_limb_t*,
@@ -302,8 +288,8 @@ __MPFR_DECLSPEC void __gmp_default_free _MPFR_PROTO ((void *, size_t));
#endif
#endif
-/* Temp memory allocate */
+/* Temp memory allocate */
struct tmp_marker
{
void *ptr;
@@ -322,51 +308,35 @@ __MPFR_DECLSPEC void mpfr_tmp_free _MPFR_PROTO ((struct tmp_marker *));
#define TMP_MARK(m) (tmp_marker = 0)
#define TMP_FREE(m) mpfr_tmp_free (tmp_marker)
+#endif /* GMP Internal replacement */
+
+
+
+/******************************************************
+ ****** GMP Interface which changes with versions *****
+ ****** to other versions of GMP. Add missing *****
+ ****** interfaces. *****
+ ******************************************************/
+
+/* If a mpn_sqr_n macro is not defined, use mpn_mul. GMP 4.x defines a
+ mpn_sqr_n macro in gmp-impl.h (and this macro disappeared in GMP 5),
+ so that GMP's macro can only be used when MPFR has been configured
+ with --with-gmp-build (and only with GMP 4.x). */
+#ifndef mpn_sqr_n
+# define mpn_sqr_n(dst,src,n) mpn_mul((dst),(src),(n),(src),(n))
+#endif
+
/* invert_limb macro, copied from GMP 5.0.2, file gmp-impl.h.
It returns invxl = floor((B^2-1)/xl)-B, where B=2^BITS_PER_LIMB,
assuming the most significant bit of xl is set. */
-#undef invert_limb
+#ifndef invert_limb
#define invert_limb(invxl,xl) \
do { \
mp_limb_t dummy MPFR_MAYBE_UNUSED; \
MPFR_ASSERTD ((xl) != 0); \
udiv_qrnnd (invxl, dummy, ~(xl), ~(mp_limb_t)0, xl); \
} while (0)
-
-typedef struct {mp_limb_t inv32;} mpfr_pi1_t; /* We changed gmp_pi1_t into
- mpfr_pi1_t to avoid using
- GMP's namespace. */
-/* invert_pi1 macro, adapted from GMP 5.0.2, file gmp-impl.h.
- It returns dinv = floor((B^3-1)/(d1*B+d0))-B, where B=2^BITS_PER_LIMB,
- assuming the most significant bit of d1 is set. */
-#undef invert_pi1
-#define invert_pi1(dinv, d1, d0) \
- do { \
- mp_limb_t _v, _p, _t1, _t0, _mask; \
- invert_limb (_v, d1); \
- _p = d1 * _v; \
- _p += d0; \
- if (_p < d0) \
- { \
- _v--; \
- _mask = -(_p >= d1); \
- _p -= d1; \
- _v += _mask; \
- _p -= _mask & d1; \
- } \
- umul_ppmm (_t1, _t0, d0, _v); \
- _p += _t1; \
- if (_p < _t1) \
- { \
- _v--; \
- if (MPFR_UNLIKELY (_p >= d1)) \
- { \
- if (_p > d1 || _t0 >= d0) \
- _v--; \
- } \
- } \
- (dinv).inv32 = _v; \
- } while (0)
+#endif
/* udiv_qr_3by2 macro, adapted from GMP 5.0.2, file gmp-impl.h.
Compute quotient the quotient and remainder for n / d. Requires d
@@ -377,7 +347,7 @@ typedef struct {mp_limb_t inv32;} mpfr_pi1_t; /* We changed gmp_pi1_t into
NOTE: Output variables are updated multiple times. Only some inputs
and outputs may overlap.
*/
-#undef udiv_qr_3by2
+#ifndef udiv_qr_3by2
#define udiv_qr_3by2(q, r1, r0, n2, n1, n0, d1, d0, dinv) \
do { \
mp_limb_t _q0, _t1, _t0, _mask; \
@@ -405,7 +375,66 @@ typedef struct {mp_limb_t inv32;} mpfr_pi1_t; /* We changed gmp_pi1_t into
} \
} \
} while (0)
+#endif
+
+/* invert_pi1 macro adapted from GMP 5 */
+typedef struct {mp_limb_t inv32;} mpfr_pi1_t;
+#ifndef invert_pi1
+#define invert_pi1(dinv, d1, d0) \
+ do { \
+ mp_limb_t _v, _p, _t1, _t0, _mask; \
+ invert_limb (_v, d1); \
+ _p = (d1) * _v; \
+ _p += (d0); \
+ if (_p < (d0)) \
+ { \
+ _v--; \
+ _mask = -(mp_limb_t) (_p >= (d1)); \
+ _p -= (d1); \
+ _v += _mask; \
+ _p -= _mask & (d1); \
+ } \
+ umul_ppmm (_t1, _t0, d0, _v); \
+ _p += _t1; \
+ if (_p < _t1) \
+ { \
+ _v--; \
+ if (MPFR_UNLIKELY (_p >= (d1))) \
+ { \
+ if (_p > (d1) || _t0 >= (d0)) \
+ _v--; \
+ } \
+ } \
+ (dinv).inv32 = _v; \
+ } while (0)
+#endif
+
+/* mpn_copyd is a new exported function in GMP 5.
+ It existed in GMP 4 in the internal header, but still may not be
+ defined if HAVE_NATIVE_mpn_copyd is not defined */
+#if !__MPFR_GMP(5,0,0)
+# undef mpn_copyd
+# define mpn_copyd MPN_COPY
+#endif
+
+
+
+/******************************************************
+ ************* GMP Basic Pointer Types ****************
+ ******************************************************/
+/* Compatibility with old GMP versions. */
+#if !__MPFR_GMP(5,0,0)
+typedef unsigned long mp_bitcnt_t;
+#endif
+
+typedef mp_limb_t *mpfr_limb_ptr;
+typedef __gmp_const mp_limb_t *mpfr_limb_srcptr;
+
+
+/******************************************************
+ ******************** C++ Compatibility ***************
+ ******************************************************/
#if defined (__cplusplus)
}
#endif