1/* Interface to replace gmp-impl.h 2 3Copyright 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc. 4Contributed by the AriC and Caramel projects, INRIA. 5 6This file is part of the GNU MPFR Library. 7 8The GNU MPFR Library is free software; you can redistribute it and/or modify 9it under the terms of the GNU Lesser General Public License as published by 10the Free Software Foundation; either version 3 of the License, or (at your 11option) any later version. 12 13The GNU MPFR Library is distributed in the hope that it will be useful, but 14WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 15or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 16License for more details. 17 18You should have received a copy of the GNU Lesser General Public License 19along with the GNU MPFR Library; see the file COPYING.LESSER. If not, see 20http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc., 2151 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 50void *alloca (size_t); 51# endif 52#endif 53 54#if defined (__cplusplus) 55extern "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 177typedef unsigned int UQItype __attribute__ ((mode (QI))); 178typedef int SItype __attribute__ ((mode (SI))); 179typedef unsigned int USItype __attribute__ ((mode (SI))); 180typedef int DItype __attribute__ ((mode (DI))); 181typedef unsigned int UDItype __attribute__ ((mode (DI))); 182#else 183typedef unsigned char UQItype; 184typedef long SItype; 185typedef unsigned long USItype; 186#ifdef HAVE_LONG_LONG 187typedef long long int DItype; 188typedef unsigned long long int UDItype; 189#else /* Assume `long' gives us a wide enough type. Needed for hppa2.0w. */ 190typedef long int DItype; 191typedef unsigned long int UDItype; 192#endif 193#endif 194typedef mp_limb_t UWtype; 195typedef 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. */ 209struct 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 254typedef __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 305struct 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 334typedef 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