Blame stdlib/gmp-impl.h

Packit 6c4009
/* Include file for internal GNU MP types and definitions.
Packit 6c4009
Packit 6c4009
Copyright (C) 1991-2018 Free Software Foundation, Inc.
Packit 6c4009
Packit 6c4009
This file is part of the GNU MP Library.
Packit 6c4009
Packit 6c4009
The GNU MP Library is free software; you can redistribute it and/or modify
Packit 6c4009
it under the terms of the GNU Lesser General Public License as published by
Packit 6c4009
the Free Software Foundation; either version 2.1 of the License, or (at your
Packit 6c4009
option) any later version.
Packit 6c4009
Packit 6c4009
The GNU MP Library is distributed in the hope that it will be useful, but
Packit 6c4009
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
Packit 6c4009
or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
Packit 6c4009
License for more details.
Packit 6c4009
Packit 6c4009
You should have received a copy of the GNU Lesser General Public License
Packit 6c4009
along with the GNU MP Library; see the file COPYING.LIB.  If not, see
Packit 6c4009
<http://www.gnu.org/licenses/>.  */
Packit 6c4009
Packit 6c4009
/* When using gcc, make sure to use its builtin alloca.  */
Packit 6c4009
#if ! defined (alloca) && defined (__GNUC__)
Packit 6c4009
#define alloca __builtin_alloca
Packit 6c4009
#define HAVE_ALLOCA
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
/* When using cc, do whatever necessary to allow use of alloca.  For many
Packit 6c4009
   machines, this means including alloca.h.  IBM's compilers need a #pragma
Packit 6c4009
   in "each module that needs to use alloca".  */
Packit 6c4009
#if ! defined (alloca)
Packit 6c4009
/* We need lots of variants for MIPS, to cover all versions and perversions
Packit 6c4009
   of OSes for MIPS.  */
Packit 6c4009
#if defined (__mips) || defined (MIPSEL) || defined (MIPSEB) \
Packit 6c4009
 || defined (_MIPSEL) || defined (_MIPSEB) || defined (__sgi) \
Packit 6c4009
 || defined (__alpha) || defined (__sparc) || defined (sparc) \
Packit 6c4009
 || defined (__ksr__)
Packit 6c4009
#include <alloca.h>
Packit 6c4009
#define HAVE_ALLOCA
Packit 6c4009
#endif
Packit 6c4009
#if defined (_IBMR2)
Packit 6c4009
#pragma alloca
Packit 6c4009
#define HAVE_ALLOCA
Packit 6c4009
#endif
Packit 6c4009
#if defined (__DECC)
Packit 6c4009
#define alloca(x) __ALLOCA(x)
Packit 6c4009
#define HAVE_ALLOCA
Packit 6c4009
#endif
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
#if (! defined (alloca) && ! defined (HAVE_ALLOCA)) \
Packit 6c4009
    || defined (USE_STACK_ALLOC)
Packit 6c4009
#include "stack-alloc.h"
Packit 6c4009
#else
Packit 6c4009
#define TMP_DECL(m)
Packit 6c4009
#define TMP_ALLOC(x) alloca(x)
Packit 6c4009
#define TMP_MARK(m)
Packit 6c4009
#define TMP_FREE(m)
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
#ifndef NULL
Packit 6c4009
#define NULL ((void *) 0)
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
#if ! defined (__GNUC__)
Packit 6c4009
#define inline			/* Empty */
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
/* Get MAX/MIN macros.  */
Packit 6c4009
#include <sys/param.h>
Packit 6c4009
Packit 6c4009
/* Field access macros.  */
Packit 6c4009
#define SIZ(x) ((x)->_mp_size)
Packit 6c4009
#define PTR(x) ((x)->_mp_d)
Packit 6c4009
#define EXP(x) ((x)->_mp_exp)
Packit 6c4009
#define PREC(x) ((x)->_mp_prec)
Packit 6c4009
#define ALLOC(x) ((x)->_mp_alloc)
Packit 6c4009
Packit 6c4009
#include "gmp-mparam.h"
Packit 6c4009
/* #include "longlong.h" */
Packit 6c4009
Packit 6c4009
#if defined (__STDC__)  || defined (__cplusplus)
Packit 6c4009
void *malloc (size_t);
Packit 6c4009
void *realloc (void *, size_t);
Packit 6c4009
void free (void *);
Packit 6c4009
Packit 6c4009
extern void *	(*_mp_allocate_func) (size_t);
Packit 6c4009
extern void *	(*_mp_reallocate_func) (void *, size_t, size_t);
Packit 6c4009
extern void	(*_mp_free_func) (void *, size_t);
Packit 6c4009
Packit 6c4009
void *_mp_default_allocate (size_t);
Packit 6c4009
void *_mp_default_reallocate (void *, size_t, size_t);
Packit 6c4009
void _mp_default_free (void *, size_t);
Packit 6c4009
Packit 6c4009
#else
Packit 6c4009
Packit 6c4009
#define const			/* Empty */
Packit 6c4009
#define signed			/* Empty */
Packit 6c4009
Packit 6c4009
void *malloc ();
Packit 6c4009
void *realloc ();
Packit 6c4009
void free ();
Packit 6c4009
Packit 6c4009
extern void *	(*_mp_allocate_func) ();
Packit 6c4009
extern void *	(*_mp_reallocate_func) ();
Packit 6c4009
extern void	(*_mp_free_func) ();
Packit 6c4009
Packit 6c4009
void *_mp_default_allocate ();
Packit 6c4009
void *_mp_default_reallocate ();
Packit 6c4009
void _mp_default_free ();
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
/* Copy NLIMBS *limbs* from SRC to DST.  */
Packit 6c4009
#define MPN_COPY_INCR(DST, SRC, NLIMBS) \
Packit 6c4009
  do {									\
Packit 6c4009
    mp_size_t __i;							\
Packit 6c4009
    for (__i = 0; __i < (NLIMBS); __i++)				\
Packit 6c4009
      (DST)[__i] = (SRC)[__i];						\
Packit 6c4009
  } while (0)
Packit 6c4009
#define MPN_COPY_DECR(DST, SRC, NLIMBS) \
Packit 6c4009
  do {									\
Packit 6c4009
    mp_size_t __i;							\
Packit 6c4009
    for (__i = (NLIMBS) - 1; __i >= 0; __i--)				\
Packit 6c4009
      (DST)[__i] = (SRC)[__i];						\
Packit 6c4009
  } while (0)
Packit 6c4009
#define MPN_COPY MPN_COPY_INCR
Packit 6c4009
Packit 6c4009
/* Zero NLIMBS *limbs* AT DST.  */
Packit 6c4009
#define MPN_ZERO(DST, NLIMBS) \
Packit 6c4009
  do {									\
Packit 6c4009
    mp_size_t __i;							\
Packit 6c4009
    for (__i = 0; __i < (NLIMBS); __i++)				\
Packit 6c4009
      (DST)[__i] = 0;							\
Packit 6c4009
  } while (0)
Packit 6c4009
Packit 6c4009
#define MPN_NORMALIZE(DST, NLIMBS) \
Packit 6c4009
  do {									\
Packit 6c4009
    while (NLIMBS > 0)							\
Packit 6c4009
      {									\
Packit 6c4009
	if ((DST)[(NLIMBS) - 1] != 0)					\
Packit 6c4009
	  break;							\
Packit 6c4009
	NLIMBS--;							\
Packit 6c4009
      }									\
Packit 6c4009
  } while (0)
Packit 6c4009
#define MPN_NORMALIZE_NOT_ZERO(DST, NLIMBS) \
Packit 6c4009
  do {									\
Packit 6c4009
    while (1)								\
Packit 6c4009
      {									\
Packit 6c4009
	if ((DST)[(NLIMBS) - 1] != 0)					\
Packit 6c4009
	  break;							\
Packit 6c4009
	NLIMBS--;							\
Packit 6c4009
      }									\
Packit 6c4009
  } while (0)
Packit 6c4009
Packit 6c4009
/* Initialize the MP_INT X with space for NLIMBS limbs.
Packit 6c4009
   X should be a temporary variable, and it will be automatically
Packit 6c4009
   cleared out when the running function returns.
Packit 6c4009
   We use __x here to make it possible to accept both mpz_ptr and mpz_t
Packit 6c4009
   arguments.  */
Packit 6c4009
#define MPZ_TMP_INIT(X, NLIMBS) \
Packit 6c4009
  do {									\
Packit 6c4009
    mpz_ptr __x = (X);							\
Packit 6c4009
    __x->_mp_alloc = (NLIMBS);						\
Packit 6c4009
    __x->_mp_d = (mp_ptr) TMP_ALLOC ((NLIMBS) * BYTES_PER_MP_LIMB);	\
Packit 6c4009
  } while (0)
Packit 6c4009
Packit 6c4009
#define MPN_MUL_N_RECURSE(prodp, up, vp, size, tspace) \
Packit 6c4009
  do {									\
Packit 6c4009
    if ((size) < KARATSUBA_THRESHOLD)					\
Packit 6c4009
      impn_mul_n_basecase (prodp, up, vp, size);			\
Packit 6c4009
    else								\
Packit 6c4009
      impn_mul_n (prodp, up, vp, size, tspace);			\
Packit 6c4009
  } while (0);
Packit 6c4009
#define MPN_SQR_N_RECURSE(prodp, up, size, tspace) \
Packit 6c4009
  do {									\
Packit 6c4009
    if ((size) < KARATSUBA_THRESHOLD)					\
Packit 6c4009
      impn_sqr_n_basecase (prodp, up, size);				\
Packit 6c4009
    else								\
Packit 6c4009
      impn_sqr_n (prodp, up, size, tspace);				\
Packit 6c4009
  } while (0);
Packit 6c4009
Packit 6c4009
/* Structure for conversion between internal binary format and
Packit 6c4009
   strings in base 2..36.  */
Packit 6c4009
struct bases
Packit 6c4009
{
Packit 6c4009
  /* Number of digits in the conversion base that always fits in an mp_limb_t.
Packit 6c4009
     For example, for base 10 on a machine where a mp_limb_t has 32 bits this
Packit 6c4009
     is 9, since 10**9 is the largest number that fits into a mp_limb_t.  */
Packit 6c4009
  int chars_per_limb;
Packit 6c4009
Packit 6c4009
  /* log(2)/log(conversion_base) */
Packit 6c4009
  float chars_per_bit_exactly;
Packit 6c4009
Packit 6c4009
  /* base**chars_per_limb, i.e. the biggest number that fits a word, built by
Packit 6c4009
     factors of base.  Exception: For 2, 4, 8, etc, big_base is log2(base),
Packit 6c4009
     i.e. the number of bits used to represent each digit in the base.  */
Packit 6c4009
  mp_limb_t big_base;
Packit 6c4009
Packit 6c4009
  /* A BITS_PER_MP_LIMB bit approximation to 1/big_base, represented as a
Packit 6c4009
     fixed-point number.  Instead of dividing by big_base an application can
Packit 6c4009
     choose to multiply by big_base_inverted.  */
Packit 6c4009
  mp_limb_t big_base_inverted;
Packit 6c4009
};
Packit 6c4009
Packit 6c4009
extern const struct bases __mp_bases[];
Packit 6c4009
extern mp_size_t __gmp_default_fp_limb_precision;
Packit 6c4009
Packit 6c4009
/* Divide the two-limb number in (NH,,NL) by D, with DI being the largest
Packit 6c4009
   limb not larger than (2**(2*BITS_PER_MP_LIMB))/D - (2**BITS_PER_MP_LIMB).
Packit 6c4009
   If this would yield overflow, DI should be the largest possible number
Packit 6c4009
   (i.e., only ones).  For correct operation, the most significant bit of D
Packit 6c4009
   has to be set.  Put the quotient in Q and the remainder in R.  */
Packit 6c4009
#define udiv_qrnnd_preinv(q, r, nh, nl, d, di) \
Packit 6c4009
  do {									\
Packit 6c4009
    mp_limb_t _ql __attribute__ ((unused));				\
Packit 6c4009
    mp_limb_t _q, _r;							\
Packit 6c4009
    mp_limb_t _xh, _xl;							\
Packit 6c4009
    umul_ppmm (_q, _ql, (nh), (di));					\
Packit 6c4009
    _q += (nh);			/* DI is 2**BITS_PER_MP_LIMB too small */\
Packit 6c4009
    umul_ppmm (_xh, _xl, _q, (d));					\
Packit 6c4009
    sub_ddmmss (_xh, _r, (nh), (nl), _xh, _xl);				\
Packit 6c4009
    if (_xh != 0)							\
Packit 6c4009
      {									\
Packit 6c4009
	sub_ddmmss (_xh, _r, _xh, _r, 0, (d));				\
Packit 6c4009
	_q += 1;							\
Packit 6c4009
	if (_xh != 0)							\
Packit 6c4009
	  {								\
Packit 6c4009
	    sub_ddmmss (_xh, _r, _xh, _r, 0, (d));			\
Packit 6c4009
	    _q += 1;							\
Packit 6c4009
	  }								\
Packit 6c4009
      }									\
Packit 6c4009
    if (_r >= (d))							\
Packit 6c4009
      {									\
Packit 6c4009
	_r -= (d);							\
Packit 6c4009
	_q += 1;							\
Packit 6c4009
      }									\
Packit 6c4009
    (r) = _r;								\
Packit 6c4009
    (q) = _q;								\
Packit 6c4009
  } while (0)
Packit 6c4009
/* Like udiv_qrnnd_preinv, but for any value D.  DNORM is D shifted left
Packit 6c4009
   so that its most significant bit is set.  LGUP is ceil(log2(D)).  */
Packit 6c4009
#define udiv_qrnnd_preinv2gen(q, r, nh, nl, d, di, dnorm, lgup) \
Packit 6c4009
  do {									\
Packit 6c4009
    mp_limb_t n2, n10, n1, nadj, q1;					\
Packit 6c4009
    mp_limb_t _xh, _xl;							\
Packit 6c4009
    n2 = ((nh) << (BITS_PER_MP_LIMB - (lgup))) + ((nl) >> 1 >> (l - 1));\
Packit 6c4009
    n10 = (nl) << (BITS_PER_MP_LIMB - (lgup));				\
Packit 6c4009
    n1 = ((mp_limb_signed_t) n10 >> (BITS_PER_MP_LIMB - 1));		\
Packit 6c4009
    nadj = n10 + (n1 & (dnorm));					\
Packit 6c4009
    umul_ppmm (_xh, _xl, di, n2 - n1);					\
Packit 6c4009
    add_ssaaaa (_xh, _xl, _xh, _xl, 0, nadj);				\
Packit 6c4009
    q1 = ~(n2 + _xh);							\
Packit 6c4009
    umul_ppmm (_xh, _xl, q1, d);					\
Packit 6c4009
    add_ssaaaa (_xh, _xl, _xh, _xl, nh, nl);				\
Packit 6c4009
    _xh -= (d);								\
Packit 6c4009
    (r) = _xl + ((d) & _xh);						\
Packit 6c4009
    (q) = _xh - q1;							\
Packit 6c4009
  } while (0)
Packit 6c4009
/* Exactly like udiv_qrnnd_preinv, but branch-free.  It is not clear which
Packit 6c4009
   version to use.  */
Packit 6c4009
#define udiv_qrnnd_preinv2norm(q, r, nh, nl, d, di) \
Packit 6c4009
  do {									\
Packit 6c4009
    mp_limb_t n2, n10, n1, nadj, q1;					\
Packit 6c4009
    mp_limb_t _xh, _xl;							\
Packit 6c4009
    n2 = (nh);								\
Packit 6c4009
    n10 = (nl);								\
Packit 6c4009
    n1 = ((mp_limb_signed_t) n10 >> (BITS_PER_MP_LIMB - 1));		\
Packit 6c4009
    nadj = n10 + (n1 & (d));						\
Packit 6c4009
    umul_ppmm (_xh, _xl, di, n2 - n1);					\
Packit 6c4009
    add_ssaaaa (_xh, _xl, _xh, _xl, 0, nadj);				\
Packit 6c4009
    q1 = ~(n2 + _xh);							\
Packit 6c4009
    umul_ppmm (_xh, _xl, q1, d);					\
Packit 6c4009
    add_ssaaaa (_xh, _xl, _xh, _xl, nh, nl);				\
Packit 6c4009
    _xh -= (d);								\
Packit 6c4009
    (r) = _xl + ((d) & _xh);						\
Packit 6c4009
    (q) = _xh - q1;							\
Packit 6c4009
  } while (0)
Packit 6c4009
Packit 6c4009
#if defined (__GNUC__)
Packit 6c4009
/* Define stuff for longlong.h.  */
Packit 6c4009
typedef unsigned int UQItype	__attribute__ ((mode (QI)));
Packit 6c4009
typedef 	 int SItype	__attribute__ ((mode (SI)));
Packit 6c4009
typedef unsigned int USItype	__attribute__ ((mode (SI)));
Packit 6c4009
typedef		 int DItype	__attribute__ ((mode (DI)));
Packit 6c4009
typedef unsigned int UDItype	__attribute__ ((mode (DI)));
Packit 6c4009
#else
Packit 6c4009
typedef unsigned char UQItype;
Packit 6c4009
typedef 	 long SItype;
Packit 6c4009
typedef unsigned long USItype;
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
typedef mp_limb_t UWtype;
Packit 6c4009
typedef unsigned int UHWtype;
Packit 6c4009
#define W_TYPE_SIZE BITS_PER_MP_LIMB
Packit 6c4009
Packit 6c4009
/* Internal mpn calls */
Packit 6c4009
#define impn_mul_n_basecase	__MPN(impn_mul_n_basecase)
Packit 6c4009
#define impn_mul_n		__MPN(impn_mul_n)
Packit 6c4009
#define impn_sqr_n_basecase	__MPN(impn_sqr_n_basecase)
Packit 6c4009
#define impn_sqr_n		__MPN(impn_sqr_n)
Packit 6c4009
Packit 6c4009
#ifndef _PROTO
Packit 6c4009
#if defined (__STDC__) || defined (__cplusplus)
Packit 6c4009
#define _PROTO(x) x
Packit 6c4009
#else
Packit 6c4009
#define _PROTO(x) ()
Packit 6c4009
#endif
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
/* Prototypes for internal mpn calls.  */
Packit 6c4009
extern void impn_mul_n_basecase _PROTO ((mp_ptr prodp, mp_srcptr up,
Packit 6c4009
					 mp_srcptr vp, mp_size_t size))
Packit 6c4009
     attribute_hidden;
Packit 6c4009
extern void impn_mul_n _PROTO ((mp_ptr prodp, mp_srcptr up, mp_srcptr vp,
Packit 6c4009
				mp_size_t size, mp_ptr tspace))
Packit 6c4009
     attribute_hidden;
Packit 6c4009
extern void impn_sqr_n_basecase _PROTO ((mp_ptr prodp, mp_srcptr up,
Packit 6c4009
					 mp_size_t size))
Packit 6c4009
     attribute_hidden;
Packit 6c4009
extern void impn_sqr_n _PROTO ((mp_ptr prodp, mp_srcptr up, mp_size_t size,
Packit 6c4009
				mp_ptr tspace))
Packit 6c4009
     attribute_hidden;
Packit 6c4009
Packit 6c4009
Packit 6c4009
Packit 6c4009
#ifndef IEEE_DOUBLE_BIG_ENDIAN
Packit 6c4009
#define IEEE_DOUBLE_BIG_ENDIAN 1
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
#ifndef IEEE_DOUBLE_MIXED_ENDIAN
Packit 6c4009
#define IEEE_DOUBLE_MIXED_ENDIAN 0
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
#if IEEE_DOUBLE_MIXED_ENDIAN
Packit 6c4009
union ieee_double_extract
Packit 6c4009
{
Packit 6c4009
  struct
Packit 6c4009
    {
Packit 6c4009
      unsigned int manh:20;
Packit 6c4009
      unsigned int exp:11;
Packit 6c4009
      unsigned int sig:1;
Packit 6c4009
      unsigned int manl:32;
Packit 6c4009
    } s;
Packit 6c4009
  double d;
Packit 6c4009
};
Packit 6c4009
#else
Packit 6c4009
#if IEEE_DOUBLE_BIG_ENDIAN
Packit 6c4009
union ieee_double_extract
Packit 6c4009
{
Packit 6c4009
  struct
Packit 6c4009
    {
Packit 6c4009
      unsigned int sig:1;
Packit 6c4009
      unsigned int exp:11;
Packit 6c4009
      unsigned int manh:20;
Packit 6c4009
      unsigned int manl:32;
Packit 6c4009
    } s;
Packit 6c4009
  double d;
Packit 6c4009
};
Packit 6c4009
#else
Packit 6c4009
union ieee_double_extract
Packit 6c4009
{
Packit 6c4009
  struct
Packit 6c4009
    {
Packit 6c4009
      unsigned int manl:32;
Packit 6c4009
      unsigned int manh:20;
Packit 6c4009
      unsigned int exp:11;
Packit 6c4009
      unsigned int sig:1;
Packit 6c4009
    } s;
Packit 6c4009
  double d;
Packit 6c4009
};
Packit 6c4009
#endif
Packit 6c4009
#endif