compiler_builtins/libm/src/math/
fminimum_fmaximum.rs

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