1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-06-12 06:41:13 +02:00

Amend #if and comments for cmp_d and get_d about unreleased gmp, don't

know when or as what version number it will come out.
This commit is contained in:
Kevin Ryde 2004-08-06 01:26:26 +00:00
parent 8f094b9720
commit f8a8200bc0

View file

@ -116,10 +116,10 @@ isinf (double x)
#endif #endif
/* mpz_cmp_d only recognises infinities in gmp 4.2 and up. /* mpz_cmp_d in gmp 4.1.3 doesn't recognise infinities, so xmpz_cmp_d uses
For prior versions use an explicit check here. */ an explicit check. In some future gmp (don't know what version number),
#if __GNU_MP_VERSION < 4 \ mpz_cmp_d is supposed to do this itself. */
|| (__GNU_MP_VERSION == 4 && __GNU_MP_VERSION_MINOR < 2) #if 1
#define xmpz_cmp_d(z, d) \ #define xmpz_cmp_d(z, d) \
(xisinf (d) ? (d < 0.0 ? 1 : -1) : mpz_cmp_d (z, d)) (xisinf (d) ? (d < 0.0 ? 1 : -1) : mpz_cmp_d (z, d))
#else #else
@ -244,23 +244,29 @@ scm_i_dbl2num (double u)
with R5RS exact->inexact. with R5RS exact->inexact.
The approach is to use mpz_get_d to pick out the high DBL_MANT_DIG bits The approach is to use mpz_get_d to pick out the high DBL_MANT_DIG bits
(ie. it truncates towards zero), then adjust to get the closest double by (ie. truncate towards zero), then adjust to get the closest double by
examining the next lower bit and adding 1 if necessary. examining the next lower bit and adding 1 (to the absolute value) if
necessary.
Note that bignums exactly half way between representable doubles are Bignums exactly half way between representable doubles are rounded to the
rounded to the next higher absolute value (ie. away from zero). This next higher absolute value (ie. away from zero). This seems like an
seems like an adequate interpretation of R5RS "numerically closest", and adequate interpretation of R5RS "numerically closest", and it's easier
it's easier and faster than a full "nearest-even" style. and faster than a full "nearest-even" style.
The bit test is done on the absolute value of the mpz_t, which means we The bit test must be done on the absolute value of the mpz_t, which means
must use mpz_getlimbn. mpz_tstbit is not right, it treats negatives as we need to use mpz_getlimbn. mpz_tstbit is not right, it treats
twos complement. negatives as twos complement.
Prior to GMP 4.2, the rounding done by mpz_get_d was unspecified. It In current gmp 4.1.3, mpz_get_d rounding is unspecified. It ends up
happened to follow the hardware rounding mode, but on the absolute value following the hardware rounding mode, but applied to the absolute value
of its operand. This is not what we want, so we put the high of the mpz_t operand. This is not what we want so we put the high
DBL_MANT_DIG bits into a temporary. This extra init/clear is a slowdown, DBL_MANT_DIG bits into a temporary. In some future gmp, don't know when,
but doesn't matter too much since it's only for older GMP. */ mpz_get_d is supposed to always truncate towards zero.
ENHANCE-ME: The temporary init+clear to force the rounding in gmp 4.1.3
is a slowdown. It'd be faster to pick out the relevant high bits with
mpz_getlimbn if we could be bothered coding that, and if the new
truncating gmp doesn't come out. */
double double
scm_i_big2dbl (SCM b) scm_i_big2dbl (SCM b)
@ -270,10 +276,9 @@ scm_i_big2dbl (SCM b)
bits = mpz_sizeinbase (SCM_I_BIG_MPZ (b), 2); bits = mpz_sizeinbase (SCM_I_BIG_MPZ (b), 2);
#if __GNU_MP_VERSION < 4 \ #if 1
|| (__GNU_MP_VERSION == 4 && __GNU_MP_VERSION_MINOR < 2)
{ {
/* GMP prior to 4.2, force truncate towards zero */ /* Current GMP, eg. 4.1.3, force truncation towards zero */
mpz_t tmp; mpz_t tmp;
if (bits > DBL_MANT_DIG) if (bits > DBL_MANT_DIG)
{ {
@ -289,7 +294,7 @@ scm_i_big2dbl (SCM b)
} }
} }
#else #else
/* GMP 4.2 and up */ /* Future GMP */
result = mpz_get_d (SCM_I_BIG_MPZ (b)); result = mpz_get_d (SCM_I_BIG_MPZ (b));
#endif #endif