Fix expt of floats by large positive bignums.

Brings behavior in line with Gambit.

Closes GH #1148.
This commit is contained in:
Vincent St-Amour 2015-11-25 17:30:26 -06:00
parent 8839f7b848
commit e9282d4f6e
2 changed files with 23 additions and 3 deletions

View File

@ -568,6 +568,11 @@
(test 0.0f0 expt -0.9999f0 (expt 2 5000))
(test -0.0f0 expt -0.9999f0 (add1 (expt 2 5000)))
(test +inf.0 expt -4.0 (expt 2 5000))
(test -inf.0 expt -4.0 (add1 (expt 2 5000)))
(test +inf.f expt -4.0f0 (expt 2 5000))
(test -inf.f expt -4.0f0 (add1 (expt 2 5000)))
(define (inf-non-real? x)
(and (not (real? x))
(= +inf.0 (abs (imag-part x)))

View File

@ -3617,18 +3617,33 @@ scheme_expt(int argc, Scheme_Object *argv[])
}
}
}
} else if ((d < 0.0) && (d > -1.0)) {
} else if (SCHEME_BIGNUMP(e) && SCHEME_BIGPOS(e)) {
/* If `e` is a positive bignum, then the result should be zero,
but we won't get that result if conversion produces infinity */
if (SCHEME_BIGNUMP(e) && SCHEME_BIGPOS(e)) {
double e_dbl;
#ifdef MZ_USE_SINGLE_FLOATS
int sgl = !SCHEME_DBLP(n);
int sgl = !SCHEME_DBLP(n);
#endif
if ((d < 0.0) && (d > -1.0)) {
if (SCHEME_FALSEP(scheme_odd_p(1, &e)))
return SELECT_EXPT_PRECISION(scheme_zerof, scheme_zerod);
else
return SELECT_EXPT_PRECISION(scheme_nzerof, scheme_nzerod);
}
/* If d is negative, and `e` is a large enough bignum which would
be converted to infinity, this would return a complex NaN.
Instead, we want to return (positive of negative) infinity.
See discussion in Github issue 1148. */
e_dbl = scheme_bignum_to_double(e);
if ((d < 0.0) && MZ_IS_POS_INFINITY(e_dbl)) {
if (SCHEME_TRUEP(scheme_odd_p(1, &e))) {
return SELECT_EXPT_PRECISION(scheme_single_minus_inf_object,
scheme_minus_inf_object);
} else {
return SELECT_EXPT_PRECISION(scheme_single_inf_object,
scheme_inf_object);
}
}
}
if ((d < 0.0) && SCHEME_RATIONALP(e)) {