From: Taylor R Campbell Date: Sat, 27 Oct 2018 00:23:12 +0000 (+0000) Subject: Simple-minded criterion to compute x^-y by 1/x^y was too simple. X-Git-Tag: mit-scheme-pucked-10.1.2~16^2~150 X-Git-Url: https://birchwood-abbey.net/git?a=commitdiff_plain;h=ecf3e6cb79574d90c0c4a89fd398e513bed9e943;p=mit-scheme.git Simple-minded criterion to compute x^-y by 1/x^y was too simple. For any |x| > 1, we can't do this without comparing the size of log(x) and y well enough to discern what might yield subnormal, so might as well just compute the general case then. --- diff --git a/src/runtime/arith.scm b/src/runtime/arith.scm index 134e99908..71c66b399 100644 --- a/src/runtime/arith.scm +++ b/src/runtime/arith.scm @@ -1265,12 +1265,15 @@ USA. (loop x y answer))))))))) (cond ((int:positive? y) (exact-method y)) ((int:negative? y) - (if (int:< y microcode-id/floating-exponent-min) - ;; The exact method cannot generate - ;; subnormals because the negated exponent - ;; overflows, so use the general case. - (general-case x (int:->flonum y)) - (flo:/ flo:1 (exact-method (int:negate y))))) + (if (flo:< (flo:abs x) flo:1) + (flo:/ flo:1 (exact-method (int:negate y))) + ;; For any base above 1 and sufficiently large + ;; exponents, or for any negative exponent and + ;; sufficiently large base, the division above + ;; would overflow into infinite and then yield + ;; 0 when it should yield a subnormal. So use + ;; the general case. + (general-case x (int:->flonum y)))) (else flo:1)))) (else (general-case x (rat:->inexact y)))) diff --git a/tests/runtime/test-arith.scm b/tests/runtime/test-arith.scm index 7017c7e0e..9384402e9 100644 --- a/tests/runtime/test-arith.scm +++ b/tests/runtime/test-arith.scm @@ -245,4 +245,8 @@ USA. (let ((x (vector-ref v 0)) (y (vector-ref v 1)) (x^y (string->number (vector-ref v 2)))) - (assert-eqv (expt x y) x^y)))))) \ No newline at end of file + (assert-eqv (expt x y) x^y) + ;; For all the inputs, reciprocal is exact. + (assert-eqv (expt (/ 1 x) (- y)) x^y) + (assert-eqv (expt (* 2 x) (/ y 2)) x^y) + (assert-eqv (expt (/ 1 (* 2 x)) (- (/ y 2))) x^y)))))) \ No newline at end of file