diff --git a/src/lisp/s_atan.c b/src/lisp/s_atan.c index f16c4b5ec4886c238dd3435c90bf1f6e4c0dce25..fa376499df428617c07e1b5c696904a9f63c93de 100644 --- a/src/lisp/s_atan.c +++ b/src/lisp/s_atan.c @@ -104,7 +104,12 @@ huge = 1.0e300; else return -atanhi[3]-atanlo[3]; } if (ix < 0x3fdc0000) { /* |x| < 0.4375 */ if (ix < 0x3e200000) { /* |x| < 2^-29 */ - if(huge+x>one) return x; /* raise inexact */ + /* return x inexact except 0 */ + if (x != 0) { + fdlibm_setexception(x, FDLIBM_INEXACT); + } + + return x; } id = -1; } else { diff --git a/tests/fdlibm.lisp b/tests/fdlibm.lisp index 5fb22a4a70e774a004c70f92cf877d9504bfb46a..16c3be43da5a545e479b90cbc08541632252dff1 100644 --- a/tests/fdlibm.lisp +++ b/tests/fdlibm.lisp @@ -258,7 +258,19 @@ (kernel:%atan *snan*)) (assert-true (ext:float-nan-p (kernel:%atan *qnan*))) (kernel::with-float-traps-masked (:invalid) - (assert-true (ext:float-nan-p (kernel:%atan *snan*))))) + (assert-true (ext:float-nan-p (kernel:%atan *snan*)))) + ;; atan(x) = x for |x| < 2^-29, signaling inexact. + (let ((x (scale-float 1d0 -30)) + (x0 0d0)) + (with-inexact-exception-enabled + ;; This must not throw an inexact exception because the result + ;; is exact when the arg is 0. + (assert-eql 0d0 (kernel:%atan x0))) + (with-inexact-exception-enabled + ;; This must throw an inexact exception for non-zero x even + ;; though the result is exactly x. + (assert-error 'floating-point-inexact + (kernel:%atan x))))) (define-test %log10.exceptions (:tag :fdlibm)