1 /* Interface to replace gmp-impl.h 2 3 Copyright 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. 4 Contributed by the Arenaire 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 LIMBS(x) ((x)->_mp_d) 167 #define EXP(x) ((x)->_mp_exp) 168 #define PREC(x) ((x)->_mp_prec) 169 #define ALLOC(x) ((x)->_mp_alloc) 170 #define MPZ_REALLOC(z,n) ((n) > ALLOC(z) ? _mpz_realloc(z,n) : PTR(z)) 171 172 /* Non IEEE float supports -- needs to detect them with proper configure */ 173 #undef XDEBUG 174 #define XDEBUG 175 176 /* For longlong.h */ 177 #ifdef HAVE_ATTRIBUTE_MODE 178 typedef unsigned int UQItype __attribute__ ((mode (QI))); 179 typedef int SItype __attribute__ ((mode (SI))); 180 typedef unsigned int USItype __attribute__ ((mode (SI))); 181 typedef int DItype __attribute__ ((mode (DI))); 182 typedef unsigned int UDItype __attribute__ ((mode (DI))); 183 #else 184 typedef unsigned char UQItype; 185 typedef long SItype; 186 typedef unsigned long USItype; 187 #ifdef HAVE_LONG_LONG 188 typedef long long int DItype; 189 typedef unsigned long long int UDItype; 190 #else /* Assume `long' gives us a wide enough type. Needed for hppa2.0w. */ 191 typedef long int DItype; 192 typedef unsigned long int UDItype; 193 #endif 194 #endif 195 typedef mp_limb_t UWtype; 196 typedef unsigned int UHWtype; 197 #define W_TYPE_SIZE GMP_NUMB_BITS 198 199 /* Remap names of internal mpn functions (for longlong.h). */ 200 #undef __clz_tab 201 #define __clz_tab mpfr_clz_tab 202 203 /* Use (4.0 * ...) instead of (2.0 * ...) to work around buggy compilers 204 that don't convert ulong->double correctly (eg. SunOS 4 native cc). */ 205 #undef MP_BASE_AS_DOUBLE 206 #define MP_BASE_AS_DOUBLE (4.0 * ((mp_limb_t) 1 << (GMP_NUMB_BITS - 2))) 207 208 /* Structure for conversion between internal binary format and 209 strings in base 2..36. */ 210 struct bases 211 { 212 /* log(2)/log(conversion_base) */ 213 double chars_per_bit_exactly; 214 }; 215 #undef __mp_bases 216 #define __mp_bases mpfr_bases 217 __MPFR_DECLSPEC extern const struct bases mpfr_bases[257]; 218 219 /* Standard macros */ 220 #undef ABS 221 #undef MIN 222 #undef MAX 223 #undef numberof 224 #define ABS(x) ((x) >= 0 ? (x) : -(x)) 225 #define MIN(l,o) ((l) < (o) ? (l) : (o)) 226 #define MAX(h,i) ((h) > (i) ? (h) : (i)) 227 #define numberof(x) (sizeof (x) / sizeof ((x)[0])) 228 229 /* Random */ 230 #undef __gmp_rands_initialized 231 #undef __gmp_rands 232 #define __gmp_rands_initialized mpfr_rands_initialized 233 #define __gmp_rands mpfr_rands 234 235 __MPFR_DECLSPEC extern char mpfr_rands_initialized; 236 __MPFR_DECLSPEC extern gmp_randstate_t mpfr_rands; 237 238 #undef RANDS 239 #define RANDS \ 240 ((__gmp_rands_initialized ? 0 \ 241 : (__gmp_rands_initialized = 1, \ 242 gmp_randinit_default (__gmp_rands), 0)), \ 243 __gmp_rands) 244 245 #undef RANDS_CLEAR 246 #define RANDS_CLEAR() \ 247 do { \ 248 if (__gmp_rands_initialized) \ 249 { \ 250 __gmp_rands_initialized = 0; \ 251 gmp_randclear (__gmp_rands); \ 252 } \ 253 } while (0) 254 255 typedef __gmp_randstate_struct *gmp_randstate_ptr; 256 257 /* Allocate func are defined in gmp-impl.h */ 258 259 /* In newer GMP, there aren't anymore __gmp_allocate_func, 260 __gmp_reallocate_func & __gmp_free_func in gmp.h 261 Just getting the correct value by calling mp_get_memory_functions */ 262 #ifdef mp_get_memory_functions 263 264 #undef __gmp_allocate_func 265 #undef __gmp_reallocate_func 266 #undef __gmp_free_func 267 #define MPFR_GET_MEMFUNC mp_get_memory_functions(&mpfr_allocate_func, &mpfr_reallocate_func, &mpfr_free_func) 268 #define __gmp_allocate_func (MPFR_GET_MEMFUNC, mpfr_allocate_func) 269 #define __gmp_reallocate_func (MPFR_GET_MEMFUNC, mpfr_reallocate_func) 270 #define __gmp_free_func (MPFR_GET_MEMFUNC, mpfr_free_func) 271 __MPFR_DECLSPEC extern void * (*mpfr_allocate_func) _MPFR_PROTO ((size_t)); 272 __MPFR_DECLSPEC extern void * (*mpfr_reallocate_func) _MPFR_PROTO ((void *, 273 size_t, size_t)); 274 __MPFR_DECLSPEC extern void (*mpfr_free_func) _MPFR_PROTO ((void *, 275 size_t)); 276 277 #endif 278 279 #undef __gmp_default_allocate 280 #undef __gmp_default_reallocate 281 #undef __gmp_default_free 282 #define __gmp_default_allocate mpfr_default_allocate 283 #define __gmp_default_reallocate mpfr_default_reallocate 284 #define __gmp_default_free mpfr_default_free 285 __MPFR_DECLSPEC void *__gmp_default_allocate _MPFR_PROTO ((size_t)); 286 __MPFR_DECLSPEC void *__gmp_default_reallocate _MPFR_PROTO ((void *, size_t, 287 size_t)); 288 __MPFR_DECLSPEC void __gmp_default_free _MPFR_PROTO ((void *, size_t)); 289 290 #if defined(WANT_GMP_INTERNALS) && defined(HAVE___GMPN_ROOTREM) 291 #ifndef __gmpn_rootrem 292 __MPFR_DECLSPEC mp_size_t __gmpn_rootrem _MPFR_PROTO ((mp_limb_t*, 293 mp_limb_t*, mp_limb_t*, mp_size_t, mp_limb_t)); 294 #endif 295 #endif 296 297 #if defined(WANT_GMP_INTERNALS) && defined(HAVE___GMPN_SBPI1_DIVAPPR_Q) 298 #ifndef __gmpn_sbpi1_divappr_q 299 __MPFR_DECLSPEC mp_limb_t __gmpn_sbpi1_divappr_q _MPFR_PROTO ((mp_limb_t*, 300 mp_limb_t*, mp_size_t, mp_limb_t*, mp_size_t, mp_limb_t)); 301 #endif 302 #endif 303 304 /* Temp memory allocate */ 305 306 struct tmp_marker 307 { 308 void *ptr; 309 size_t size; 310 struct tmp_marker *next; 311 }; 312 313 __MPFR_DECLSPEC void *mpfr_tmp_allocate _MPFR_PROTO ((struct tmp_marker **, 314 size_t)); 315 __MPFR_DECLSPEC void mpfr_tmp_free _MPFR_PROTO ((struct tmp_marker *)); 316 317 /* Do not define TMP_SALLOC (see the test in mpfr-impl.h)! */ 318 #define TMP_ALLOC(n) (MPFR_LIKELY ((n) < 16384) ? \ 319 alloca (n) : mpfr_tmp_allocate (&tmp_marker, (n))) 320 #define TMP_DECL(m) struct tmp_marker *tmp_marker 321 #define TMP_MARK(m) (tmp_marker = 0) 322 #define TMP_FREE(m) mpfr_tmp_free (tmp_marker) 323 324 /* invert_limb macro, copied from GMP 5.0.2, file gmp-impl.h. 325 It returns invxl = floor((B^2-1)/xl)-B, where B=2^BITS_PER_LIMB, 326 assuming the most significant bit of xl is set. */ 327 #undef invert_limb 328 #define invert_limb(invxl,xl) \ 329 do { \ 330 mp_limb_t dummy; \ 331 MPFR_ASSERTD ((xl) != 0); \ 332 udiv_qrnnd (invxl, dummy, ~(xl), ~(mp_limb_t)0, xl); \ 333 } while (0) 334 335 typedef struct {mp_limb_t inv32;} mpfr_pi1_t; /* We changed gmp_pi1_t into 336 mpfr_pi1_t to avoid using 337 GMP's namespace. */ 338 /* invert_pi1 macro, adapted from GMP 5.0.2, file gmp-impl.h. 339 It returns dinv = floor((B^3-1)/(d1*B+d0))-B, where B=2^BITS_PER_LIMB, 340 assuming the most significant bit of d1 is set. */ 341 #undef invert_pi1 342 #define invert_pi1(dinv, d1, d0) \ 343 do { \ 344 mp_limb_t _v, _p, _t1, _t0, _mask; \ 345 invert_limb (_v, d1); \ 346 _p = d1 * _v; \ 347 _p += d0; \ 348 if (_p < d0) \ 349 { \ 350 _v--; \ 351 _mask = -(_p >= d1); \ 352 _p -= d1; \ 353 _v += _mask; \ 354 _p -= _mask & d1; \ 355 } \ 356 umul_ppmm (_t1, _t0, d0, _v); \ 357 _p += _t1; \ 358 if (_p < _t1) \ 359 { \ 360 _v--; \ 361 if (MPFR_UNLIKELY (_p >= d1)) \ 362 { \ 363 if (_p > d1 || _t0 >= d0) \ 364 _v--; \ 365 } \ 366 } \ 367 (dinv).inv32 = _v; \ 368 } while (0) 369 370 /* udiv_qr_3by2 macro, adapted from GMP 5.0.2, file gmp-impl.h. 371 Compute quotient the quotient and remainder for n / d. Requires d 372 >= B^2 / 2 and n < d B. dinv is the inverse 373 374 floor ((B^3 - 1) / (d0 + d1 B)) - B. 375 376 NOTE: Output variables are updated multiple times. Only some inputs 377 and outputs may overlap. 378 */ 379 #undef udiv_qr_3by2 380 #define udiv_qr_3by2(q, r1, r0, n2, n1, n0, d1, d0, dinv) \ 381 do { \ 382 mp_limb_t _q0, _t1, _t0, _mask; \ 383 umul_ppmm ((q), _q0, (n2), (dinv)); \ 384 add_ssaaaa ((q), _q0, (q), _q0, (n2), (n1)); \ 385 \ 386 /* Compute the two most significant limbs of n - q'd */ \ 387 (r1) = (n1) - (d1) * (q); \ 388 (r0) = (n0); \ 389 sub_ddmmss ((r1), (r0), (r1), (r0), (d1), (d0)); \ 390 umul_ppmm (_t1, _t0, (d0), (q)); \ 391 sub_ddmmss ((r1), (r0), (r1), (r0), _t1, _t0); \ 392 (q)++; \ 393 \ 394 /* Conditionally adjust q and the remainders */ \ 395 _mask = - (mp_limb_t) ((r1) >= _q0); \ 396 (q) += _mask; \ 397 add_ssaaaa ((r1), (r0), (r1), (r0), _mask & (d1), _mask & (d0)); \ 398 if (MPFR_UNLIKELY ((r1) >= (d1))) \ 399 { \ 400 if ((r1) > (d1) || (r0) >= (d0)) \ 401 { \ 402 (q)++; \ 403 sub_ddmmss ((r1), (r0), (r1), (r0), (d1), (d0)); \ 404 } \ 405 } \ 406 } while (0) 407 408 #if defined (__cplusplus) 409 } 410 #endif 411 412 #endif /* Gmp internal emulator */ 413