eazy_core/easing/oscillatory/
elastic.rs

1//! # The Elastic Curve.
2//!
3//! Use exp2f instead of powf(2.0, x) - exp2f is optimized for base 2.
4
5use crate::easing::Curve;
6
7use libm::{exp2f, sinf};
8
9/// ### The [`InElastic`] Easing Function.
10///
11/// #### examples.
12///
13/// ```
14/// use eazy::Curve;
15/// use eazy::standard::elastic::InElastic;
16///
17/// let p = InElastic.y(0.2222);
18/// ```
19#[derive(Debug)]
20pub struct InElastic;
21
22impl Curve for InElastic {
23  #[inline(always)]
24  fn y(&self, p: f32) -> f32 {
25    let m = p - 1.0;
26
27    -exp2f(10.0 * m) * sinf((m * 40.0 - 3.0) * core::f32::consts::PI / 6.0)
28  }
29}
30
31#[test]
32fn test_in_elastic() {
33  let p = InElastic.y(0.2222);
34
35  assert_eq!(p, -0.0038053591);
36}
37
38/// ### The [`OutElastic`] Easing Function.
39///
40/// #### examples.
41///
42/// ```
43/// use eazy::Curve;
44/// use eazy::standard::elastic::OutElastic;
45///
46/// let p = OutElastic.y(1.0);
47///
48/// assert_eq!(p, 1.0004883);
49/// ```
50#[derive(Debug)]
51pub struct OutElastic;
52
53impl Curve for OutElastic {
54  #[inline(always)]
55  fn y(&self, p: f32) -> f32 {
56    1.0
57      + (exp2f(-10.0 * p)
58        * sinf((-p * 40.0 - 3.0) * core::f32::consts::PI / 6.0))
59  }
60}
61
62#[test]
63fn test_out_elastic() {
64  let p = OutElastic.y(0.5345);
65
66  assert_eq!(p, 0.9951369);
67}
68
69/// ### The [`InOutElastic`] Easing Function.
70///
71/// #### examples.
72///
73/// ```
74/// use eazy::Curve;
75/// use eazy::standard::elastic::InOutElastic;
76///
77/// let p = InOutElastic.y(0.5345);
78/// ```
79#[derive(Debug)]
80pub struct InOutElastic;
81
82impl Curve for InOutElastic {
83  #[inline(always)]
84  fn y(&self, p: f32) -> f32 {
85    let s = 2.0 * p - 1.0; // remap: [0,0.5] -> [-1,0]
86    let k = (80.0 * s - 9.0) * core::f32::consts::PI / 18.0; // and [0.5,1] -> [0,+1]
87
88    if s < 0.0 {
89      return -0.5 * exp2f(10.0 * s) * sinf(k);
90    }
91
92    1.0 + 0.5 * exp2f(-10.0 * s) * sinf(k)
93  }
94}
95
96#[test]
97fn test_in_out_elastic() {
98  let p = InOutElastic.y(0.5345);
99
100  assert_eq!(p, 0.82312053);
101}