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
14use super::super::Float;
15
16pub 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)]
29mod 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