From e9282d4f6e303438324cab6546f532cd287d1037 Mon Sep 17 00:00:00 2001 From: Vincent St-Amour Date: Wed, 25 Nov 2015 17:30:26 -0600 Subject: [PATCH] Fix `expt` of floats by large positive bignums. Brings behavior in line with Gambit. Closes GH #1148. --- .../racket-test-core/tests/racket/number.rktl | 5 +++++ racket/src/racket/src/number.c | 21 ++++++++++++++++--- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/pkgs/racket-test-core/tests/racket/number.rktl b/pkgs/racket-test-core/tests/racket/number.rktl index d601b473e1..0d0cb70062 100644 --- a/pkgs/racket-test-core/tests/racket/number.rktl +++ b/pkgs/racket-test-core/tests/racket/number.rktl @@ -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))) diff --git a/racket/src/racket/src/number.c b/racket/src/racket/src/number.c index bb20444a58..9feb28de65 100644 --- a/racket/src/racket/src/number.c +++ b/racket/src/racket/src/number.c @@ -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)) {