Raymond Toy pushed to branch issue-425-correctly-rounded-math-functions-single-float at cmucl / cmucl Commits: b19caf9d by Raymond Toy at 2026-02-17T15:12:47-08:00 Add tests for %acoshf and %asinhf based on %acosh and %asinh Didn't need to do anything really special except the test for inexact can have a smaller value since we only have single-float precision. - - - - - b9039cc2 by Raymond Toy at 2026-02-17T15:15:52-08:00 Add tests for %atanhf based on %atanh Didn't need to do anything really special. - - - - - 2ab4931b by Raymond Toy at 2026-02-17T16:09:27-08:00 Add tests for %expm1f and %log1pf based on %expm1 and %log1p Straightforward update but noticed that expm1 and expm1f were not signaling overflow for +inf. Have the wrappers check for that. Add tests for this. Also, expm1 doesn't seem to signal inexact, but expm1f does. Not sure why. - - - - - 2 changed files: - src/lisp/irrat.c - tests/fdlibm.lisp Changes: ===================================== src/lisp/irrat.c ===================================== @@ -287,6 +287,10 @@ double lisp_expm1(double x) { #ifdef FEATURE_CORE_MATH + if (isinf(x) == 1) { + return fdlibm_setexception(x, FDLIBM_OVERFLOW); + } + return cr_expm1(x); #else return fdlibm_expm1(x); @@ -539,6 +543,10 @@ float lisp_expm1f(float x) { #ifdef FEATURE_CORE_MATH + if (isinf(x) == 1) { + return fdlibm_setexception(x, FDLIBM_OVERFLOW); + } + return cr_expm1f(x); #else return (float) fdlibm_expm1((double) x); ===================================== tests/fdlibm.lisp ===================================== @@ -198,6 +198,18 @@ (ext:with-float-traps-masked (:invalid) (assert-true (ext:float-nan-p (kernel:%acosh 0d0))))) +(define-test %acoshf.exceptions + (:tag :fdlibm) + (assert-error 'floating-point-overflow + (kernel:%acoshf ext:single-float-positive-infinity)) + (assert-error 'floating-point-invalid-operation + (kernel:%acoshf 0f0)) + (ext:with-float-traps-masked (:overflow) + (assert-equal ext:single-float-positive-infinity + (kernel:%acoshf ext:single-float-positive-infinity))) + (ext:with-float-traps-masked (:invalid) + (assert-true (ext:float-nan-p (kernel:%acoshf 0f0))))) + (define-test %asinh.exceptions (:tag :fdlibm) (assert-error 'floating-point-invalid-operation @@ -219,12 +231,43 @@ (ext:with-float-traps-enabled (:inexact) ;; This must not throw an inexact exception because the result ;; is exact when the arg is 0. - (assert-eql 0d0 (asinh x0))) + (assert-eql 0d0 (kernel:%asinh x0))) (ext:with-float-traps-enabled (:inexact) ;; This must throw an inexact exception for non-zero x even ;; though the result is exactly x. (assert-error 'floating-point-inexact - (asinh x))))) + (kernel:%asinh x))))) + +(define-test %asinh.exceptions + (:tag :fdlibm) + (assert-error 'floating-point-invalid-operation + (kernel:%asinhf *snan-single-float*)) + (assert-error 'floating-point-overflow + (kernel:%asinhf ext:single-float-positive-infinity)) + (assert-error 'floating-point-overflow + (kernel:%asinhf ext:single-float-negative-infinity)) + (assert-true (ext:float-nan-p (kernel:%asinhf *qnan-single-float*))) + (ext:with-float-traps-masked (:overflow) + (assert-equal ext:single-float-positive-infinity + (kernel:%asinhf ext:single-float-positive-infinity)) + (assert-error ext:single-float-negative-infinity + (kernel:%asinhf ext:single-float-negative-infinity))) + (ext:with-float-traps-masked (:invalid) + (assert-true (ext:float-nan-p (kernel:%asinhf *snan-single-float*)))) + ;; asinh(x) = x - x^3/6 + o(x^5). For small enough x, asinh(x) = x + ;; but we should signal inexact for those cases, except for when x = + ;; 0. The threshold is approximately 2^-17. + (let ((x (scale-float 1f0 -17)) + (x0 0f0)) + (ext:with-float-traps-enabled (:inexact) + ;; This must not throw an inexact exception because the result + ;; is exact when the arg is 0. + (assert-eql 0f0 (kernel:%asinhf x0))) + (ext:with-float-traps-enabled (:inexact) + ;; This must throw an inexact exception for non-zero x even + ;; though the result is exactly x. + (assert-error 'floating-point-inexact + (kernel:%asinhf x))))) (define-test %atanh.exceptions (:tag :fdlibm) @@ -245,11 +288,30 @@ (assert-equal ext:double-float-negative-infinity (kernel:%atanh -1d0)))) +(define-test %atanh.exceptions + (:tag :fdlibm) + (assert-error 'floating-point-invalid-operation + (kernel:%atanhf 2f0)) + (assert-error 'floating-point-invalid-operation + (kernel:%atanhf -2f0)) + (assert-error 'division-by-zero + (kernel:%atanhf 1f0)) + (assert-error 'division-by-zero + (kernel:%atanhf -1f0)) + (ext:with-float-traps-masked (:invalid) + (assert-true (ext:float-nan-p (kernel:%atanhf 2f0))) + (assert-true (ext:float-nan-p (kernel:%atanhf -2f0)))) + (ext:with-float-traps-masked (:divide-by-zero) + (assert-equal ext:single-float-positive-infinity + (kernel:%atanhf 1f0)) + (assert-equal ext:single-float-negative-infinity + (kernel:%atanhf -1f0)))) + (define-test %expm1.exceptions (:tag :fdlibm) (assert-error 'floating-point-overflow (kernel:%expm1 709.8d0)) - (assert-equal ext:double-float-positive-infinity + (assert-error 'floating-point-overflow (kernel:%expm1 ext:double-float-positive-infinity)) (assert-error 'floating-point-invalid-operation (kernel:%expm1 *snan*)) @@ -260,13 +322,36 @@ ) (ext:with-float-traps-masked (:invalid) (assert-true (ext::float-nan-p (kernel:%expm1 *snan*)))) - ;; expm1(x) = -1 for x < -56*log(2), signaling inexact + ;; expm1(x) = -1 for x < -56*log(2), signaling inexact. #-core-math (let ((x (* -57 (log 2d0)))) (ext:with-float-traps-enabled (:inexact) (assert-error 'floating-point-inexact (kernel:%expm1 x))))) +(define-test %expm1f.exceptions + (:tag :fdlibm) + (assert-error 'floating-point-overflow + (kernel:%expm1f 709.8f0)) + (assert-error 'floating-point-overflow + (kernel:%expm1f ext:single-float-positive-infinity)) + (assert-error 'floating-point-invalid-operation + (kernel:%expm1f *snan-single-float*)) + (assert-true (ext:float-nan-p (kernel:%expm1f *qnan-single-float*))) + (ext:with-float-traps-masked (:overflow) + (assert-equal ext:single-float-positive-infinity + (kernel:%expm1f 709.8f0)) + ) + (ext:with-float-traps-masked (:invalid) + (assert-true (ext::float-nan-p (kernel:%expm1f *snan-single-float*)))) + ;; expm1(x) = -1 for negative enough x. When x = -26*log(2), exp(x) + ;; is about 1.49e-8, which is smaller than single-float-epsilon so + ;; expm1(x) = -1. + (let ((x (log (scale-float 1f0 -26)))) + (ext:with-float-traps-enabled (:inexact) + (assert-error 'floating-point-inexact + (kernel:%expm1f x))))) + (define-test %log1p.exceptions (:tag :fdlibm) (assert-error 'floating-point-invalid-operation @@ -294,6 +379,33 @@ (assert-error 'floating-point-inexact (kernel:%log1p x))))) +(define-test %log1pf.exceptions + (:tag :fdlibm) + (assert-error 'floating-point-invalid-operation + (kernel:%log1pf -2f0)) + (assert-error #-core-math 'floating-point-overflow + #+core-math 'division-by-zero + (kernel:%log1pf -1f0)) + (assert-true (ext:float-nan-p (kernel:%log1pf *qnan-single-float*))) + (ext:with-float-traps-masked (#-core-math :overflow + #+core-math :divide-by-zero) + (assert-equal ext:single-float-negative-infinity + (kernel:%log1pf -1f0))) + (ext:with-float-traps-masked (:invalid) + (assert-true (ext:float-nan-p (kernel:%log1pf *snan-single-float*)))) + ;; log1p(x) = x for |x| < 2^-54, signaling inexact except for x = 0. + (let ((x (scale-float 1f0 -55)) + (x0 0f0)) + (ext:with-float-traps-enabled (:inexact) + ;; This must not throw an inexact exception because the result + ;; is exact when the arg is 0. + (assert-eql 0f0 (kernel:%log1pf x0))) + (ext:with-float-traps-enabled (:inexact) + ;; This must throw an inexact exception for non-zero x even + ;; though the result is exactly x. + (assert-error 'floating-point-inexact + (kernel:%log1pf x))))) + (define-test %exp.exceptions (:tag :fdlibm) (assert-error 'floating-point-overflow View it on GitLab: https://gitlab.common-lisp.net/cmucl/cmucl/-/compare/c916a9f722169965a54544c... -- View it on GitLab: https://gitlab.common-lisp.net/cmucl/cmucl/-/compare/c916a9f722169965a54544c... You're receiving this email because of your account on gitlab.common-lisp.net.
participants (1)
-
Raymond Toy (@rtoy)