max/min on nan arguments
Peter McGoron via Chicken-users <[email protected]> Sat, 1 Aug 2026 18:53:14 -0400
| Newsgroups | gmane.lisp.scheme.chicken |
|---|---|
| Message-ID | <[email protected]> |
This is on the latest master.
(max +nan.0 1.0 2.0) => +nan.0
(max 1.0 +nan.0 2.0) => 2.0
(max 1.0 2.0 +nan.0) => 2.0
This looks like these procedures are using `<` and `>` to compare
numbers, which fails on NaN.
There are two IEEE ways to handle NaNs in max and min:
1. Ignore them when possible, and only return a NaN when all arguments
are NaNs. So the above examples would be equivalent to `(max 1.0 2.0)`.
2. If any input arguments are NaN, then return a NaN. So each example
above would return NaN.
The R7RS doesn't specify any of these behaviors.
On the implementations I've tested the examples on that didn't have
inconsistent results, they all returned NaN when any input is a NaN. So
I recommend the second option because it will cause more portable
behavior across implementations.
My suggestion is to replace `(if (> h m) h m)` in the definition of
`max` with `(##max2 h m)`, where for the two options above:
(define (##max2-option1 h m)
(cond
((and (nan? h) (nan? m)) h)
((nan? h) m)
((nan? m) m)
((and (eqv? h -0.0) (eqv? m +0.0)) m)
((and (eqv? h +0.0) (eqv? m -0.0)) h)
((< h m) m)
(else h)))
(define (##max2-option2 h m)
(cond
((nan? h) h)
((nan? m) m)
((and (eqv? h -0.0) (eqv? m +0.0)) m)
((and (eqv? h +0.0) (eqv? m -0.0)) h)
((< h m) m)
(else h)))
IEEE 754-2019 mandates that, for the purposes of max and min, +0.0 is
greater than -0.0. Similar things apply to min.
I would add the following test cases:
(max +nan.0 1.0 2.0) => 2.0 (option 1) OR +nan.0 (option 2)
(max 1.0 +nan.0 2.0) => same
(max 1.0 2.0 +nan.0) => same
(max +nan.0) => +nan.0
(max +nan.0 +nan.0) => +nan.0
(max -0.0 +0.0) => +0.0
(max +0.0 -0.0) => +0.0
(min +nan.0 1.0 2.0) => 1.0 (option 1) OR +nan.0 (option 2)
(min 1.0 +nan.0 2.0) => same
(min 1.0 2.0 +nan.0) => same
(min +nan.0) => +nan.0
(min +nan.0 +nan.0) => +nan.0
(min -0.0 +0.0) => -0.0
(min +0.0 -0.0) => -0.0
-- Peter McGoron