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