diff --git a/src/lisp/k_cos.c b/src/lisp/k_cos.c index 2be76e07e279d79d332b0826135f04979a0b4346..e3af8aa3516e30de67b996156bd5da0f755e92e8 100644 --- a/src/lisp/k_cos.c +++ b/src/lisp/k_cos.c @@ -75,7 +75,12 @@ C6 = -1.13596475577881948265e-11; /* 0xBDA8FAE9, 0xBE8838D4 */ ux.d = x; ix = ux.i[HIWORD]&0x7fffffff; /* ix = |x|'s high word*/ if(ix<0x3e400000) { /* if x < 2**27 */ - if(((int)x)==0) return one; /* generate inexact */ + /* return 1 with inexact unless x == 0 */ + if (x != 0) { + fdlibm_setexception(x, FDLIBM_INEXACT); + } + + return one; } z = x*x; r = z*(C1+z*(C2+z*(C3+z*(C4+z*(C5+z*C6))))); diff --git a/tests/fdlibm.lisp b/tests/fdlibm.lisp index 9ca9d3001ecfa0183bba86e18fe5b0b67d31abbf..b99141e65d7fcedba56a5088ee2e58369b3903b1 100644 --- a/tests/fdlibm.lisp +++ b/tests/fdlibm.lisp @@ -608,3 +608,17 @@ (assert-error 'floating-point-inexact (kernel:%asin x))))) +(define-test %cos.exceptions + (:tag :fdlibm) + ;; cos(x) = 1 for |x| < 2^-27. Signal inexact unless x = 0 + (let ((x (scale-float 1d0 -28)) + (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 1d0 (kernel:%cos 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:%cos x)))))