1 | /* SPDX-License-Identifier: MIT OR Apache-2.0 */ |
2 | //! IEEE 754-2019 `maximumNumber`. |
3 | //! |
4 | //! Per the spec, returns: |
5 | //! - `x` if `x > y` |
6 | //! - `y` if `y > x` |
7 | //! - Non-NaN if one operand is NaN |
8 | //! - Logic following +0.0 > -0.0 |
9 | //! - Either `x` or `y` if `x == y` and the signs are the same |
10 | //! - qNaN if either operand is a NaN |
11 | //! |
12 | //! Excluded from our implementation is sNaN handling. |
13 | |
14 | use super::super::Float; |
15 | |
16 | pub fn fmaximum_num<F: Float>(x: F, y: F) -> F { |
17 | let res: F = |
18 | if x.is_nan() || x < y || (x.to_bits() == F::NEG_ZERO.to_bits() && y.is_sign_positive()) { |
19 | y |
20 | } else { |
21 | x |
22 | }; |
23 | |
24 | // Canonicalize |
25 | res * F::ONE |
26 | } |
27 | |
28 | #[cfg (test)] |
29 | mod tests { |
30 | use super::*; |
31 | use crate::support::{Hexf, Int}; |
32 | |
33 | fn spec_test<F: Float>() { |
34 | let cases = [ |
35 | (F::ZERO, F::ZERO, F::ZERO), |
36 | (F::ONE, F::ONE, F::ONE), |
37 | (F::ZERO, F::ONE, F::ONE), |
38 | (F::ONE, F::ZERO, F::ONE), |
39 | (F::ZERO, F::NEG_ONE, F::ZERO), |
40 | (F::NEG_ONE, F::ZERO, F::ZERO), |
41 | (F::INFINITY, F::ZERO, F::INFINITY), |
42 | (F::NEG_INFINITY, F::ZERO, F::ZERO), |
43 | (F::NAN, F::ZERO, F::ZERO), |
44 | (F::ZERO, F::NAN, F::ZERO), |
45 | (F::NAN, F::NAN, F::NAN), |
46 | (F::ZERO, F::NEG_ZERO, F::ZERO), |
47 | (F::NEG_ZERO, F::ZERO, F::ZERO), |
48 | ]; |
49 | |
50 | for (x, y, res) in cases { |
51 | let val = fmaximum_num(x, y); |
52 | assert_biteq!(val, res, "fmaximum_num({}, {})" , Hexf(x), Hexf(y)); |
53 | } |
54 | } |
55 | |
56 | #[test ] |
57 | #[cfg (f16_enabled)] |
58 | fn spec_tests_f16() { |
59 | spec_test::<f16>(); |
60 | } |
61 | |
62 | #[test ] |
63 | fn spec_tests_f32() { |
64 | spec_test::<f32>(); |
65 | } |
66 | |
67 | #[test ] |
68 | fn spec_tests_f64() { |
69 | spec_test::<f64>(); |
70 | } |
71 | |
72 | #[test ] |
73 | #[cfg (f128_enabled)] |
74 | fn spec_tests_f128() { |
75 | spec_test::<f128>(); |
76 | } |
77 | } |
78 | |