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