moonlander_gp/
num.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
//! Numeric helper functions

/// The general number type used by all simulations
pub type Number = f32;

/// A max() function that only requires a partial ordering.
pub fn partial_max<I: Iterator>(iter: I) -> Option<I::Item>
    where I::Item : PartialOrd {
    iter.fold(None, |ret, x| {
        match ret {
            None => Some(x),
            Some(ref y) if x > *y => Some(x),
            _ => ret
        }
    })
}

/// A min() function that only requires a partial ordering.
pub fn partial_min<I: Iterator>(iter: I) -> Option<I::Item>
    where I::Item : PartialOrd {
    iter.fold(None, |ret, x| {
        match ret {
            None => Some(x),
            Some(ref y) if x < *y => Some(x),
            _ => ret
        }
    })
}

/// A sum() function to use on an iterator, because Iterator.sum() is unstable.
pub fn sum<I: Iterator<Item=Number>>(iter: I) -> Number {
    let mut total = 0.0;
    for x in iter {
        total += x;
    }
    total
}

/// Crop a value to an N-sized torus
pub fn torus(x: i32, n: i32) -> i32 {
    let k = if x < 0 { -x / n + 1 } else { 0 };
    (x + k * n) % n
}

/// Square a number
pub fn square(x: Number) -> Number {
    x * x
}

#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn test_torus() {
        assert_eq!(1, torus(33, 32));
        assert_eq!(1, torus(-31, 32));
    }
}