1/* SPDX-License-Identifier: MIT OR Apache-2.0 */
2//! IEEE 754-2019 `minimum`.
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
12use super::super::Float;
13
14pub fn fminimum<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 || (x.to_bits() == F::NEG_ZERO.to_bits() && y.is_sign_positive()) {
20 x
21 } else {
22 y
23 };
24
25 // Canonicalize
26 res * F::ONE
27}
28
29#[cfg(test)]
30mod 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::ZERO),
39 (F::ONE, F::ZERO, F::ZERO),
40 (F::ZERO, F::NEG_ONE, F::NEG_ONE),
41 (F::NEG_ONE, F::ZERO, F::NEG_ONE),
42 (F::INFINITY, F::ZERO, F::ZERO),
43 (F::NEG_INFINITY, F::ZERO, F::NEG_INFINITY),
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::NEG_ZERO),
48 (F::NEG_ZERO, F::ZERO, F::NEG_ZERO),
49 ];
50
51 for (x, y, res) in cases {
52 let val = fminimum(x, y);
53 assert_biteq!(val, res, "fminimum({}, {})", 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