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