numeric_statistics/f32/
max.rs

1/// Calculate statistical max for values.
2///
3/// # Nan
4/// 
5/// Return NaN if the values are empty.
6///
7/// From <https://doc.rust-lang.org/std/primitive.f32.html#method.max>:
8///
9/// If one of the arguments is NaN, then the other argument is returned. This
10/// follows the IEEE 754-2008 semantics for maxNum, except for handling of
11/// signaling NaNs; this function handles all NaNs the same way and avoids
12/// maxNum’s problems with associativity. This also matches the behavior of
13/// libm’s fmax. In particular, if the inputs compare equal (such as for the case
14/// of +0.0 and -0.0), either input may be returned non-deterministically.
15///
16pub fn max<T: AsRef<[f32]>>(values: T) -> f32 {
17    let values = values.as_ref();
18    if values.is_empty() { return f32::NAN; }
19    values.iter().fold(f32::NAN, |a, x| f32::max(a, *x))
20}
21
22#[cfg(test)]
23mod test {
24    use super::*;
25
26    #[test]
27    fn test_empty() {
28        let x: &[f32] = &[];
29        assert!(max(x).is_nan());
30    }
31
32    #[test]
33    fn test_nan() {
34        let x: &[f32] = &[f32::NAN];
35        assert!(max(x).is_nan());
36    }
37
38    #[test]
39    fn test_value() {
40        let x: &[f32] = &[1.0];
41        assert_eq!(max(x), 1.0);
42    }
43
44    #[test]
45    fn test_values_ascending() {
46        let x = &[1.0, 2.0, 3.0];
47        assert_eq!(max(x), 3.0);
48    }
49
50    #[test]
51    fn test_values_ascending_and_nans() {
52        let x = &[1.0, f32::NAN, 2.0, f32::NAN, 3.0];
53        assert_eq!(max(x), 3.0);
54    }
55
56    #[test]
57    fn test_values_descending() {
58        let x = &[3.0, 2.0, 1.0];
59        assert_eq!(max(x), 3.0);
60    }
61
62    #[test]
63    fn test_values_descending_and_nans() {
64        let x = &[3.0, f32::NAN, 2.0, f32::NAN, 1.0];
65        assert_eq!(max(x), 3.0);
66    }
67
68}