compiler_builtins\libm\src\math/
fmin_fmax.rs

1/// Return the lesser of two arguments or, if either argument is NaN, the other argument.
2///
3/// This coincides with IEEE 754-2011 `minNum`. The result disregards signed zero (meaning if
4/// the inputs are -0.0 and +0.0, either may be returned).
5#[cfg(f16_enabled)]
6#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
7pub fn fminf16(x: f16, y: f16) -> f16 {
8    super::generic::fmin(x, y)
9}
10
11/// Return the lesser of two arguments or, if either argument is NaN, the other argument.
12///
13/// This coincides with IEEE 754-2011 `minNum`. The result disregards signed zero (meaning if
14/// the inputs are -0.0 and +0.0, either may be returned).
15#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
16pub fn fminf(x: f32, y: f32) -> f32 {
17    super::generic::fmin(x, y)
18}
19
20/// Return the lesser of two arguments or, if either argument is NaN, the other argument.
21///
22/// This coincides with IEEE 754-2011 `minNum`. The result disregards signed zero (meaning if
23/// the inputs are -0.0 and +0.0, either may be returned).
24#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
25pub fn fmin(x: f64, y: f64) -> f64 {
26    super::generic::fmin(x, y)
27}
28
29/// Return the lesser of two arguments or, if either argument is NaN, the other argument.
30///
31/// This coincides with IEEE 754-2011 `minNum`. The result disregards signed zero (meaning if
32/// the inputs are -0.0 and +0.0, either may be returned).
33#[cfg(f128_enabled)]
34#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
35pub fn fminf128(x: f128, y: f128) -> f128 {
36    super::generic::fmin(x, y)
37}
38
39/// Return the greater of two arguments or, if either argument is NaN, the other argument.
40///
41/// This coincides with IEEE 754-2011 `maxNum`. The result disregards signed zero (meaning if
42/// the inputs are -0.0 and +0.0, either may be returned).
43#[cfg(f16_enabled)]
44#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
45pub fn fmaxf16(x: f16, y: f16) -> f16 {
46    super::generic::fmax(x, y)
47}
48
49/// Return the greater of two arguments or, if either argument is NaN, the other argument.
50///
51/// This coincides with IEEE 754-2011 `maxNum`. The result disregards signed zero (meaning if
52/// the inputs are -0.0 and +0.0, either may be returned).
53#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
54pub fn fmaxf(x: f32, y: f32) -> f32 {
55    super::generic::fmax(x, y)
56}
57
58/// Return the greater of two arguments or, if either argument is NaN, the other argument.
59///
60/// This coincides with IEEE 754-2011 `maxNum`. The result disregards signed zero (meaning if
61/// the inputs are -0.0 and +0.0, either may be returned).
62#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
63pub fn fmax(x: f64, y: f64) -> f64 {
64    super::generic::fmax(x, y)
65}
66
67/// Return the greater of two arguments or, if either argument is NaN, the other argument.
68///
69/// This coincides with IEEE 754-2011 `maxNum`. The result disregards signed zero (meaning if
70/// the inputs are -0.0 and +0.0, either may be returned).
71#[cfg(f128_enabled)]
72#[cfg_attr(all(test, assert_no_panic), no_panic::no_panic)]
73pub fn fmaxf128(x: f128, y: f128) -> f128 {
74    super::generic::fmax(x, y)
75}
76
77#[cfg(test)]
78mod tests {
79    use super::*;
80    use crate::support::{Float, Hexf};
81
82    fn fmin_spec_test<F: Float>(f: impl Fn(F, F) -> F) {
83        let cases = [
84            (F::ZERO, F::ZERO, F::ZERO),
85            (F::ZERO, F::ONE, F::ZERO),
86            (F::ZERO, F::NEG_ONE, F::NEG_ONE),
87            (F::ZERO, F::INFINITY, F::ZERO),
88            (F::ZERO, F::NEG_INFINITY, F::NEG_INFINITY),
89            (F::ZERO, F::NAN, F::ZERO),
90            (F::ZERO, F::NEG_NAN, F::ZERO),
91            (F::NEG_ZERO, F::NEG_ZERO, F::NEG_ZERO),
92            (F::NEG_ZERO, F::ONE, F::NEG_ZERO),
93            (F::NEG_ZERO, F::NEG_ONE, F::NEG_ONE),
94            (F::NEG_ZERO, F::INFINITY, F::NEG_ZERO),
95            (F::NEG_ZERO, F::NEG_INFINITY, F::NEG_INFINITY),
96            (F::NEG_ZERO, F::NAN, F::NEG_ZERO),
97            (F::NEG_ZERO, F::NEG_NAN, F::NEG_ZERO),
98            (F::ONE, F::ZERO, F::ZERO),
99            (F::ONE, F::NEG_ZERO, F::NEG_ZERO),
100            (F::ONE, F::ONE, F::ONE),
101            (F::ONE, F::NEG_ONE, F::NEG_ONE),
102            (F::ONE, F::INFINITY, F::ONE),
103            (F::ONE, F::NEG_INFINITY, F::NEG_INFINITY),
104            (F::ONE, F::NAN, F::ONE),
105            (F::ONE, F::NEG_NAN, F::ONE),
106            (F::NEG_ONE, F::ZERO, F::NEG_ONE),
107            (F::NEG_ONE, F::NEG_ZERO, F::NEG_ONE),
108            (F::NEG_ONE, F::ONE, F::NEG_ONE),
109            (F::NEG_ONE, F::NEG_ONE, F::NEG_ONE),
110            (F::NEG_ONE, F::INFINITY, F::NEG_ONE),
111            (F::NEG_ONE, F::NEG_INFINITY, F::NEG_INFINITY),
112            (F::NEG_ONE, F::NAN, F::NEG_ONE),
113            (F::NEG_ONE, F::NEG_NAN, F::NEG_ONE),
114            (F::INFINITY, F::ZERO, F::ZERO),
115            (F::INFINITY, F::NEG_ZERO, F::NEG_ZERO),
116            (F::INFINITY, F::ONE, F::ONE),
117            (F::INFINITY, F::NEG_ONE, F::NEG_ONE),
118            (F::INFINITY, F::INFINITY, F::INFINITY),
119            (F::INFINITY, F::NEG_INFINITY, F::NEG_INFINITY),
120            (F::INFINITY, F::NAN, F::INFINITY),
121            (F::INFINITY, F::NEG_NAN, F::INFINITY),
122            (F::NEG_INFINITY, F::ZERO, F::NEG_INFINITY),
123            (F::NEG_INFINITY, F::NEG_ZERO, F::NEG_INFINITY),
124            (F::NEG_INFINITY, F::ONE, F::NEG_INFINITY),
125            (F::NEG_INFINITY, F::NEG_ONE, F::NEG_INFINITY),
126            (F::NEG_INFINITY, F::INFINITY, F::NEG_INFINITY),
127            (F::NEG_INFINITY, F::NEG_INFINITY, F::NEG_INFINITY),
128            (F::NEG_INFINITY, F::NAN, F::NEG_INFINITY),
129            (F::NEG_INFINITY, F::NEG_NAN, F::NEG_INFINITY),
130            (F::NAN, F::ZERO, F::ZERO),
131            (F::NAN, F::NEG_ZERO, F::NEG_ZERO),
132            (F::NAN, F::ONE, F::ONE),
133            (F::NAN, F::NEG_ONE, F::NEG_ONE),
134            (F::NAN, F::INFINITY, F::INFINITY),
135            (F::NAN, F::NEG_INFINITY, F::NEG_INFINITY),
136            (F::NAN, F::NAN, F::NAN),
137            (F::NEG_NAN, F::ZERO, F::ZERO),
138            (F::NEG_NAN, F::NEG_ZERO, F::NEG_ZERO),
139            (F::NEG_NAN, F::ONE, F::ONE),
140            (F::NEG_NAN, F::NEG_ONE, F::NEG_ONE),
141            (F::NEG_NAN, F::INFINITY, F::INFINITY),
142            (F::NEG_NAN, F::NEG_INFINITY, F::NEG_INFINITY),
143        ];
144
145        for (x, y, res) in cases {
146            let val = f(x, y);
147            assert_biteq!(val, res, "fmin({}, {})", Hexf(x), Hexf(y));
148        }
149
150        // Ordering between zeros and NaNs does not matter
151        assert_eq!(f(F::ZERO, F::NEG_ZERO), F::ZERO);
152        assert_eq!(f(F::NEG_ZERO, F::ZERO), F::ZERO);
153        assert!(f(F::NAN, F::NEG_NAN).is_nan());
154        assert!(f(F::NEG_NAN, F::NAN).is_nan());
155        assert!(f(F::NEG_NAN, F::NEG_NAN).is_nan());
156    }
157
158    #[test]
159    #[cfg(f16_enabled)]
160    fn fmin_spec_tests_f16() {
161        fmin_spec_test::<f16>(fminf16);
162    }
163
164    #[test]
165    fn fmin_spec_tests_f32() {
166        fmin_spec_test::<f32>(fminf);
167    }
168
169    #[test]
170    fn fmin_spec_tests_f64() {
171        fmin_spec_test::<f64>(fmin);
172    }
173
174    #[test]
175    #[cfg(f128_enabled)]
176    fn fmin_spec_tests_f128() {
177        fmin_spec_test::<f128>(fminf128);
178    }
179
180    fn fmax_spec_test<F: Float>(f: impl Fn(F, F) -> F) {
181        let cases = [
182            (F::ZERO, F::ZERO, F::ZERO),
183            (F::ZERO, F::ONE, F::ONE),
184            (F::ZERO, F::NEG_ONE, F::ZERO),
185            (F::ZERO, F::INFINITY, F::INFINITY),
186            (F::ZERO, F::NEG_INFINITY, F::ZERO),
187            (F::ZERO, F::NAN, F::ZERO),
188            (F::ZERO, F::NEG_NAN, F::ZERO),
189            (F::NEG_ZERO, F::NEG_ZERO, F::NEG_ZERO),
190            (F::NEG_ZERO, F::ONE, F::ONE),
191            (F::NEG_ZERO, F::NEG_ONE, F::NEG_ZERO),
192            (F::NEG_ZERO, F::INFINITY, F::INFINITY),
193            (F::NEG_ZERO, F::NEG_INFINITY, F::NEG_ZERO),
194            (F::NEG_ZERO, F::NAN, F::NEG_ZERO),
195            (F::NEG_ZERO, F::NEG_NAN, F::NEG_ZERO),
196            (F::ONE, F::ZERO, F::ONE),
197            (F::ONE, F::NEG_ZERO, F::ONE),
198            (F::ONE, F::ONE, F::ONE),
199            (F::ONE, F::NEG_ONE, F::ONE),
200            (F::ONE, F::INFINITY, F::INFINITY),
201            (F::ONE, F::NEG_INFINITY, F::ONE),
202            (F::ONE, F::NAN, F::ONE),
203            (F::ONE, F::NEG_NAN, F::ONE),
204            (F::NEG_ONE, F::ZERO, F::ZERO),
205            (F::NEG_ONE, F::NEG_ZERO, F::NEG_ZERO),
206            (F::NEG_ONE, F::ONE, F::ONE),
207            (F::NEG_ONE, F::NEG_ONE, F::NEG_ONE),
208            (F::NEG_ONE, F::INFINITY, F::INFINITY),
209            (F::NEG_ONE, F::NEG_INFINITY, F::NEG_ONE),
210            (F::NEG_ONE, F::NAN, F::NEG_ONE),
211            (F::NEG_ONE, F::NEG_NAN, F::NEG_ONE),
212            (F::INFINITY, F::ZERO, F::INFINITY),
213            (F::INFINITY, F::NEG_ZERO, F::INFINITY),
214            (F::INFINITY, F::ONE, F::INFINITY),
215            (F::INFINITY, F::NEG_ONE, F::INFINITY),
216            (F::INFINITY, F::INFINITY, F::INFINITY),
217            (F::INFINITY, F::NEG_INFINITY, F::INFINITY),
218            (F::INFINITY, F::NAN, F::INFINITY),
219            (F::INFINITY, F::NEG_NAN, F::INFINITY),
220            (F::NEG_INFINITY, F::ZERO, F::ZERO),
221            (F::NEG_INFINITY, F::NEG_ZERO, F::NEG_ZERO),
222            (F::NEG_INFINITY, F::ONE, F::ONE),
223            (F::NEG_INFINITY, F::NEG_ONE, F::NEG_ONE),
224            (F::NEG_INFINITY, F::INFINITY, F::INFINITY),
225            (F::NEG_INFINITY, F::NEG_INFINITY, F::NEG_INFINITY),
226            (F::NEG_INFINITY, F::NAN, F::NEG_INFINITY),
227            (F::NEG_INFINITY, F::NEG_NAN, F::NEG_INFINITY),
228            (F::NAN, F::ZERO, F::ZERO),
229            (F::NAN, F::NEG_ZERO, F::NEG_ZERO),
230            (F::NAN, F::ONE, F::ONE),
231            (F::NAN, F::NEG_ONE, F::NEG_ONE),
232            (F::NAN, F::INFINITY, F::INFINITY),
233            (F::NAN, F::NEG_INFINITY, F::NEG_INFINITY),
234            (F::NAN, F::NAN, F::NAN),
235            (F::NEG_NAN, F::ZERO, F::ZERO),
236            (F::NEG_NAN, F::NEG_ZERO, F::NEG_ZERO),
237            (F::NEG_NAN, F::ONE, F::ONE),
238            (F::NEG_NAN, F::NEG_ONE, F::NEG_ONE),
239            (F::NEG_NAN, F::INFINITY, F::INFINITY),
240            (F::NEG_NAN, F::NEG_INFINITY, F::NEG_INFINITY),
241        ];
242
243        for (x, y, res) in cases {
244            let val = f(x, y);
245            assert_biteq!(val, res, "fmax({}, {})", Hexf(x), Hexf(y));
246        }
247
248        // Ordering between zeros and NaNs does not matter
249        assert_eq!(f(F::ZERO, F::NEG_ZERO), F::ZERO);
250        assert_eq!(f(F::NEG_ZERO, F::ZERO), F::ZERO);
251        assert!(f(F::NAN, F::NEG_NAN).is_nan());
252        assert!(f(F::NEG_NAN, F::NAN).is_nan());
253        assert!(f(F::NEG_NAN, F::NEG_NAN).is_nan());
254    }
255
256    #[test]
257    #[cfg(f16_enabled)]
258    fn fmax_spec_tests_f16() {
259        fmax_spec_test::<f16>(fmaxf16);
260    }
261
262    #[test]
263    fn fmax_spec_tests_f32() {
264        fmax_spec_test::<f32>(fmaxf);
265    }
266
267    #[test]
268    fn fmax_spec_tests_f64() {
269        fmax_spec_test::<f64>(fmax);
270    }
271
272    #[test]
273    #[cfg(f128_enabled)]
274    fn fmax_spec_tests_f128() {
275        fmax_spec_test::<f128>(fmaxf128);
276    }
277}