use core::ops::Add;
use core::ops::Mul;
use core::ops::RangeInclusive;
pub fn lerp<T>(range: RangeInclusive<T>, t: f32) -> T
where
f32: Mul<T, Output = T>,
T: Add<T, Output = T> + Copy,
{
(1.0 - t) * *range.start() + t * *range.end()
}
pub fn remap(x: f32, from: RangeInclusive<f32>, to: RangeInclusive<f32>) -> f32 {
let t = (x - from.start()) / (from.end() - from.start());
lerp(to, t)
}
pub fn remap_clamp(x: f32, from: RangeInclusive<f32>, to: RangeInclusive<f32>) -> f32 {
if x <= *from.start() {
*to.start()
} else if *from.end() <= x {
*to.end()
} else {
let t = (x - from.start()) / (from.end() - from.start());
if 1.0 <= t {
*to.end()
} else {
lerp(to, t)
}
}
}
#[allow(clippy::float_cmp)]
#[cfg(test)]
mod test {
use super::*;
#[test]
fn remapping() {
assert_eq!(remap(0.2, -1.0..=1.0, -2.0..=2.0), 0.4000001);
assert_eq!(remap_clamp(0.2, -1.0..=1.0, -2.0..=2.0), 0.4000001);
assert_eq!(remap(3.0, -1.0..=1.0, -2.0..=2.0), 6.0);
assert_eq!(remap_clamp(3.0, -1.0..=1.0, -2.0..=2.0), 2.0);
assert!(remap(0.0, 0.0..=0.0, -2.0..=2.0).is_nan());
assert_eq!(remap_clamp(0.0, 0.0..=0.0, -2.0..=2.0), -2.0);
}
}