1pub use libm::{atan2, cos, exp, hypot, pow, sin, sqrt, tan};
4pub use libm::{cosf, expf, hypotf, sinf, sqrtf};
6
7pub fn lerp<Value: crate::Interpolate>(start: &Value, end: &Value, progress: f64) -> Value {
9 start.interpolate(end, progress)
10}
11
12pub fn clamp01(value: f64) -> f64 {
14 value.clamp(0.0, 1.0)
15}
16
17pub fn smoothstep(edge0: f64, edge1: f64, value: f64) -> f64 {
19 if value.is_nan() {
20 return value;
21 }
22 if edge0 == edge1 {
23 return f64::from(value >= edge1);
24 }
25 let progress = clamp01((value - edge0) / (edge1 - edge0));
26 progress * progress * (3.0 - 2.0 * progress)
27}
28
29#[cfg(test)]
30mod tests {
31 use super::*;
32
33 #[test]
34 fn deterministic_helpers_preserve_interpolation_and_interval_boundaries() {
35 assert_eq!(sin(0.25).to_bits(), libm::sin(0.25).to_bits());
36 assert_eq!(lerp(&2.0, &6.0, 1.5), 8.0);
37 assert_eq!(smoothstep(2.0, 4.0, 3.0), 0.5);
38 assert_eq!(smoothstep(2.0, 4.0, 0.0), 0.0);
39 assert_eq!(smoothstep(2.0, 4.0, 5.0), 1.0);
40 assert_eq!(smoothstep(1.0, 1.0, 1.0), 1.0);
41 assert!(clamp01(f64::NAN).is_nan());
42 }
43}