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:
parent
8f094b9720
commit
f8a8200bc0
1 changed files with 27 additions and 22 deletions
|
@ -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
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue