easer/functions/
bounce.rs

1use super::ease::Easing;
2use functions::util::*;
3
4/// This struct captures Bounce easing functions
5#[derive(Debug)]
6pub struct Bounce;
7
8impl<F: Float> Easing<F> for Bounce {
9    fn ease_in(t: F, b: F, c: F, d: F) -> F {
10        c - Bounce::ease_out(d - t, f(0.0), c, d) + b
11    }
12
13    fn ease_out(t: F, b: F, c: F, d: F) -> F {
14        cast_constants!(F; _1=1, _1_5=1.5, _2=2, _2_25=2.25, _2_5=2.5,
15            _2_625=2.625, _7_5625=7.5625);
16
17        let t = t / d;
18        if t < _1 / f(2.75) {
19            c * (_7_5625 * t * t) + b
20        } else if t < _2 / f(2.75) {
21            let t = t - _1_5 / f(2.75);
22            c * (_7_5625 * t * t + f(0.75)) + b
23        } else if t < _2_5 / f(2.75) {
24            let t = t - _2_25 / f(2.75);
25            c * (_7_5625 * t * t + f(0.9375)) + b
26        } else {
27            let t = t - _2_625 / f(2.75);
28            c * (_7_5625 * t * t + f(0.984375)) + b
29        }
30    }
31
32    fn ease_in_out(t: F, b: F, c: F, d: F) -> F {
33        if t < (d / f(2.0)) {
34            Bounce::ease_in(t * f(2.0), f(0.0), c, d) * f(0.5) + b
35        } else {
36            Bounce::ease_out(t * f(2.0) - d, f(0.0), c, d) * f(0.5) + c * f(0.5) + b
37        }
38
39    }
40}
41
42#[cfg(test)]
43mod test {
44    use super::*;
45
46    #[test]
47    fn ease_out() {
48        assert_relative_eq!(Bounce::ease_out(1.0_f32, 2.0, 3.0, 4.0), 3.4179688);
49        assert_relative_eq!(Bounce::ease_out(1.0_f32, 2.0, 3.0, 2.0), 4.296875);
50        assert_relative_eq!(Bounce::ease_out(100.0_f32, 1.0, 100.0, 100.0), 101.000000);
51    }
52
53    #[test]
54    fn ease_in() {
55        assert_relative_eq!(Bounce::ease_in(1.0_f32, 2.0, 3.0, 4.0), 2.082031);
56    }
57
58    #[test]
59    fn ease_in_out() {
60        assert_relative_eq!(Bounce::ease_in_out(1.0_f32, 2.0, 3.0, 4.0), 2.3515625);
61        assert_relative_eq!(Bounce::ease_in_out(51.0_f32, 1.0, 100.0, 100.0), 51.151250);
62    }
63
64    const PRECISE_RESULT: f64 = 2.3159476740972824;
65
66    #[test]
67    fn f32_precision() {
68        let ease32 = Bounce::ease_in(10_f32.sqrt(), 2.0, 3.0, 10.0);
69        assert_relative_ne!(ease32 as f64, PRECISE_RESULT); // f32 maths is actually happening
70        assert_relative_eq!(ease32, PRECISE_RESULT as f32);
71    }
72
73    #[test]
74    fn f64_precision() {
75        let ease64 = Bounce::ease_in(10_f64.sqrt(), 2.0, 3.0, 10.0);
76        assert_relative_eq!(ease64, PRECISE_RESULT);
77    }
78}