Raymond Toy pushed to branch issue-425-correctly-rounded-math-functions-single-float at cmucl / cmucl

Commits:

2 changed files:

Changes:

  • src/lisp/irrat.c
    ... ... @@ -287,6 +287,10 @@ double
    287 287
     lisp_expm1(double x)
    
    288 288
     {
    
    289 289
     #ifdef FEATURE_CORE_MATH
    
    290
    +    if (isinf(x) == 1) {
    
    291
    +	return fdlibm_setexception(x, FDLIBM_OVERFLOW);
    
    292
    +    }
    
    293
    +
    
    290 294
         return cr_expm1(x);
    
    291 295
     #else    
    
    292 296
         return fdlibm_expm1(x);
    
    ... ... @@ -539,6 +543,10 @@ float
    539 543
     lisp_expm1f(float x)
    
    540 544
     {
    
    541 545
     #ifdef FEATURE_CORE_MATH
    
    546
    +    if (isinf(x) == 1) {
    
    547
    +	return fdlibm_setexception(x, FDLIBM_OVERFLOW);
    
    548
    +    }
    
    549
    +
    
    542 550
         return cr_expm1f(x);
    
    543 551
     #else    
    
    544 552
         return (float) fdlibm_expm1((double) x);
    

  • tests/fdlibm.lisp
    ... ... @@ -198,6 +198,18 @@
    198 198
       (ext:with-float-traps-masked (:invalid)
    
    199 199
         (assert-true (ext:float-nan-p (kernel:%acosh 0d0)))))
    
    200 200
     
    
    201
    +(define-test %acoshf.exceptions
    
    202
    +  (:tag :fdlibm)
    
    203
    +  (assert-error 'floating-point-overflow
    
    204
    +		(kernel:%acoshf ext:single-float-positive-infinity))
    
    205
    +  (assert-error 'floating-point-invalid-operation
    
    206
    +		(kernel:%acoshf 0f0))
    
    207
    +  (ext:with-float-traps-masked (:overflow)
    
    208
    +    (assert-equal ext:single-float-positive-infinity
    
    209
    +		  (kernel:%acoshf ext:single-float-positive-infinity)))
    
    210
    +  (ext:with-float-traps-masked (:invalid)
    
    211
    +    (assert-true (ext:float-nan-p (kernel:%acoshf 0f0)))))
    
    212
    +
    
    201 213
     (define-test %asinh.exceptions
    
    202 214
       (:tag :fdlibm)
    
    203 215
       (assert-error 'floating-point-invalid-operation
    
    ... ... @@ -219,12 +231,43 @@
    219 231
         (ext:with-float-traps-enabled (:inexact)
    
    220 232
     	;; This must not throw an inexact exception because the result
    
    221 233
     	;; is exact when the arg is 0.
    
    222
    -	(assert-eql 0d0 (asinh x0)))
    
    234
    +	(assert-eql 0d0 (kernel:%asinh x0)))
    
    223 235
         (ext:with-float-traps-enabled (:inexact)
    
    224 236
     	;; This must throw an inexact exception for non-zero x even
    
    225 237
     	;; though the result is exactly x.
    
    226 238
     	(assert-error 'floating-point-inexact
    
    227
    -		      (asinh x)))))
    
    239
    +		      (kernel:%asinh x)))))
    
    240
    +
    
    241
    +(define-test %asinh.exceptions
    
    242
    +  (:tag :fdlibm)
    
    243
    +  (assert-error 'floating-point-invalid-operation
    
    244
    +		(kernel:%asinhf *snan-single-float*))
    
    245
    +  (assert-error 'floating-point-overflow
    
    246
    +		(kernel:%asinhf ext:single-float-positive-infinity))
    
    247
    +  (assert-error 'floating-point-overflow
    
    248
    +		(kernel:%asinhf ext:single-float-negative-infinity))
    
    249
    +  (assert-true (ext:float-nan-p (kernel:%asinhf *qnan-single-float*)))
    
    250
    +  (ext:with-float-traps-masked (:overflow)
    
    251
    +    (assert-equal ext:single-float-positive-infinity
    
    252
    +		  (kernel:%asinhf ext:single-float-positive-infinity))
    
    253
    +    (assert-error ext:single-float-negative-infinity
    
    254
    +		  (kernel:%asinhf ext:single-float-negative-infinity)))
    
    255
    +  (ext:with-float-traps-masked (:invalid)
    
    256
    +    (assert-true (ext:float-nan-p (kernel:%asinhf *snan-single-float*))))
    
    257
    +  ;; asinh(x) = x - x^3/6 + o(x^5).  For small enough x, asinh(x) = x
    
    258
    +  ;; but we should signal inexact for those cases, except for when x =
    
    259
    +  ;; 0.  The threshold is approximately 2^-17.
    
    260
    +  (let ((x (scale-float 1f0 -17))
    
    261
    +	(x0 0f0))
    
    262
    +    (ext:with-float-traps-enabled (:inexact)
    
    263
    +	;; This must not throw an inexact exception because the result
    
    264
    +	;; is exact when the arg is 0.
    
    265
    +	(assert-eql 0f0 (kernel:%asinhf x0)))
    
    266
    +    (ext:with-float-traps-enabled (:inexact)
    
    267
    +	;; This must throw an inexact exception for non-zero x even
    
    268
    +	;; though the result is exactly x.
    
    269
    +	(assert-error 'floating-point-inexact
    
    270
    +		      (kernel:%asinhf x)))))
    
    228 271
     
    
    229 272
     (define-test %atanh.exceptions
    
    230 273
       (:tag :fdlibm)
    
    ... ... @@ -245,11 +288,30 @@
    245 288
         (assert-equal ext:double-float-negative-infinity
    
    246 289
     		  (kernel:%atanh -1d0))))
    
    247 290
     
    
    291
    +(define-test %atanh.exceptions
    
    292
    +  (:tag :fdlibm)
    
    293
    +  (assert-error 'floating-point-invalid-operation
    
    294
    +		(kernel:%atanhf 2f0))
    
    295
    +  (assert-error 'floating-point-invalid-operation
    
    296
    +		(kernel:%atanhf -2f0))
    
    297
    +  (assert-error 'division-by-zero
    
    298
    +		(kernel:%atanhf 1f0))
    
    299
    +  (assert-error 'division-by-zero
    
    300
    +		(kernel:%atanhf -1f0))
    
    301
    +  (ext:with-float-traps-masked (:invalid)
    
    302
    +    (assert-true (ext:float-nan-p (kernel:%atanhf 2f0)))
    
    303
    +    (assert-true (ext:float-nan-p (kernel:%atanhf -2f0))))
    
    304
    +  (ext:with-float-traps-masked (:divide-by-zero)
    
    305
    +    (assert-equal ext:single-float-positive-infinity
    
    306
    +		  (kernel:%atanhf 1f0))
    
    307
    +    (assert-equal ext:single-float-negative-infinity
    
    308
    +		  (kernel:%atanhf -1f0))))
    
    309
    +
    
    248 310
     (define-test %expm1.exceptions
    
    249 311
       (:tag :fdlibm)
    
    250 312
       (assert-error 'floating-point-overflow
    
    251 313
     		(kernel:%expm1 709.8d0))
    
    252
    -  (assert-equal ext:double-float-positive-infinity
    
    314
    +  (assert-error 'floating-point-overflow
    
    253 315
     		(kernel:%expm1 ext:double-float-positive-infinity))
    
    254 316
       (assert-error 'floating-point-invalid-operation
    
    255 317
     		(kernel:%expm1 *snan*))
    
    ... ... @@ -260,13 +322,36 @@
    260 322
         )
    
    261 323
       (ext:with-float-traps-masked (:invalid)
    
    262 324
         (assert-true (ext::float-nan-p (kernel:%expm1 *snan*))))
    
    263
    -  ;; expm1(x) = -1 for x < -56*log(2), signaling inexact
    
    325
    +  ;; expm1(x) = -1 for x < -56*log(2), signaling inexact.
    
    264 326
       #-core-math
    
    265 327
       (let ((x (* -57 (log 2d0))))
    
    266 328
         (ext:with-float-traps-enabled (:inexact)
    
    267 329
     	(assert-error 'floating-point-inexact
    
    268 330
     		      (kernel:%expm1 x)))))
    
    269 331
     
    
    332
    +(define-test %expm1f.exceptions
    
    333
    +  (:tag :fdlibm)
    
    334
    +  (assert-error 'floating-point-overflow
    
    335
    +		(kernel:%expm1f 709.8f0))
    
    336
    +  (assert-error 'floating-point-overflow
    
    337
    +		(kernel:%expm1f ext:single-float-positive-infinity))
    
    338
    +  (assert-error 'floating-point-invalid-operation
    
    339
    +		(kernel:%expm1f *snan-single-float*))
    
    340
    +  (assert-true (ext:float-nan-p (kernel:%expm1f *qnan-single-float*)))
    
    341
    +  (ext:with-float-traps-masked (:overflow)
    
    342
    +    (assert-equal ext:single-float-positive-infinity
    
    343
    +		 (kernel:%expm1f 709.8f0))
    
    344
    +    )
    
    345
    +  (ext:with-float-traps-masked (:invalid)
    
    346
    +    (assert-true (ext::float-nan-p (kernel:%expm1f *snan-single-float*))))
    
    347
    +  ;; expm1(x) = -1 for negative enough x.  When x = -26*log(2), exp(x)
    
    348
    +  ;; is about 1.49e-8, which is smaller than single-float-epsilon so
    
    349
    +  ;; expm1(x) = -1.
    
    350
    +  (let ((x (log (scale-float 1f0 -26))))
    
    351
    +    (ext:with-float-traps-enabled (:inexact)
    
    352
    +	(assert-error 'floating-point-inexact
    
    353
    +		      (kernel:%expm1f x)))))
    
    354
    +
    
    270 355
     (define-test %log1p.exceptions
    
    271 356
       (:tag :fdlibm)
    
    272 357
       (assert-error 'floating-point-invalid-operation
    
    ... ... @@ -294,6 +379,33 @@
    294 379
     	(assert-error 'floating-point-inexact
    
    295 380
     		      (kernel:%log1p x)))))
    
    296 381
     
    
    382
    +(define-test %log1pf.exceptions
    
    383
    +  (:tag :fdlibm)
    
    384
    +  (assert-error 'floating-point-invalid-operation
    
    385
    +		(kernel:%log1pf -2f0))
    
    386
    +  (assert-error #-core-math 'floating-point-overflow
    
    387
    +		#+core-math 'division-by-zero
    
    388
    +		(kernel:%log1pf -1f0))
    
    389
    +  (assert-true (ext:float-nan-p (kernel:%log1pf *qnan-single-float*)))
    
    390
    +  (ext:with-float-traps-masked (#-core-math :overflow
    
    391
    +				#+core-math :divide-by-zero)
    
    392
    +    (assert-equal ext:single-float-negative-infinity
    
    393
    +		  (kernel:%log1pf -1f0)))
    
    394
    +  (ext:with-float-traps-masked (:invalid)
    
    395
    +    (assert-true (ext:float-nan-p (kernel:%log1pf *snan-single-float*))))
    
    396
    +  ;; log1p(x) = x for |x| < 2^-54, signaling inexact except for x = 0.
    
    397
    +  (let ((x (scale-float 1f0 -55))
    
    398
    +	(x0 0f0))
    
    399
    +    (ext:with-float-traps-enabled (:inexact)
    
    400
    +	;; This must not throw an inexact exception because the result
    
    401
    +	;; is exact when the arg is 0.
    
    402
    +	(assert-eql 0f0 (kernel:%log1pf x0)))
    
    403
    +    (ext:with-float-traps-enabled (:inexact)
    
    404
    +	;; This must throw an inexact exception for non-zero x even
    
    405
    +	;; though the result is exactly x.
    
    406
    +	(assert-error 'floating-point-inexact
    
    407
    +		      (kernel:%log1pf x)))))
    
    408
    +
    
    297 409
     (define-test %exp.exceptions
    
    298 410
       (:tag :fdlibm)
    
    299 411
       (assert-error 'floating-point-overflow