#[inline(always)]
pub fn lerp<T: Lerp>(a: &T, b: &T, t: &T::Scalar) -> T {
a.lerp(b, t)
}
pub trait Lerp {
type Scalar;
fn lerp(&self, other: &Self, scalar: &Self::Scalar) -> Self;
}
macro_rules! impl_lerp_for_float {
($float: ident) => (
impl Lerp for $float {
type Scalar = $float;
#[inline(always)]
fn lerp(&self, other: &$float, scalar: &$float) -> $float {
self + (other - self) * scalar
}
}
)
}
impl_lerp_for_float!(f32);
impl_lerp_for_float!(f64);
macro_rules! impl_lerp_for_int {
($int: ident, $scalar: ident) => (
impl Lerp for $int {
type Scalar = $scalar;
#[inline(always)]
fn lerp(&self, other: &$int, scalar: &$scalar) -> $int {
self + ((other - self) as $scalar * scalar).round() as $int
}
}
)
}
impl_lerp_for_int!(i8, f32);
impl_lerp_for_int!(i16, f32);
impl_lerp_for_int!(i32, f32);
impl_lerp_for_int!(i64, f64);
macro_rules! impl_lerp_for_uint {
($uint: ident, $scalar: ident) => (
impl Lerp for $uint {
type Scalar = $scalar;
#[inline(always)]
fn lerp(&self, other: &$uint, scalar: &$scalar) -> $uint {
if self <= other {
self + ((other - self) as $scalar * scalar).round() as $uint
} else {
self - ((self - other) as $scalar * scalar).round() as $uint
}
}
}
)
}
impl_lerp_for_uint!(u8, f32);
impl_lerp_for_uint!(u16, f32);
impl_lerp_for_uint!(u32, f32);
impl_lerp_for_uint!(u64, f64);
macro_rules! impl_lerp_for_array {
($len:expr; $($i:expr),*) => {
impl<T> Lerp for [T; $len] where T: Lerp {
type Scalar = T::Scalar;
#[inline(always)]
fn lerp(&self, other: &Self, scalar: &Self::Scalar) -> Self {
[
$(self[$i].lerp(&other[$i], scalar)),*
]
}
}
}
}
impl_lerp_for_array!(1; 0);
impl_lerp_for_array!(2; 0, 1);
impl_lerp_for_array!(3; 0, 1, 2);
impl_lerp_for_array!(4; 0, 1, 2, 3);
impl_lerp_for_array!(5; 0, 1, 2, 3, 4);
#[test]
fn lerp_f32() {
for x in 0 ..= 10 {
let w = x as f32 / 10f32;
assert_eq!(lerp(&0f32, &10f32, &w), x as f32);
}
for x in (0 ..= 10).rev() {
let w = (10 - x) as f32 / 10f32;
assert_eq!(lerp(&10f32, &0f32, &w), x as f32);
}
for x in -10 .. 0 {
let w = (10 + x) as f32 / 10f32;
assert_eq!(lerp(&-10f32, &0f32, &w), x as f32);
}
for x in (-10 .. 0).rev() {
let w = (0 - x) as f32 / 10f32;
assert_eq!(lerp(&0f32, &-10f32, &w), x as f32);
}
}
#[test]
fn lerp_f64() {
for x in 0 ..= 10 {
let w = x as f64 / 10f64;
assert_eq!(lerp(&0f64, &10f64, &w), x as f64);
}
for x in (0 ..= 10).rev() {
let w = (10 - x) as f64 / 10f64;
assert_eq!(lerp(&10f64, &0f64, &w), x as f64);
}
for x in -10 .. 0 {
let w = (10 + x) as f64 / 10f64;
assert_eq!(lerp(&-10f64, &0f64, &w), x as f64);
}
for x in (-10 .. 0).rev() {
let w = (0 - x) as f64 / 10f64;
assert_eq!(lerp(&0f64, &-10f64, &w), x as f64);
}
}
#[test]
fn lerp_i8() {
for x in 0 ..= 10 {
let w = x as f32 / 10f32;
assert_eq!(lerp(&0i8, &10i8, &w), x);
}
for x in (0 ..= 10).rev() {
let w = (10 - x) as f32 / 10f32;
assert_eq!(lerp(&10i8, &0i8, &w), x);
}
for x in -10 .. 0 {
let w = (10 + x) as f32 / 10f32;
assert_eq!(lerp(&-10i8, &0i8, &w), x);
}
for x in (-10 .. 0).rev() {
let w = (0 - x) as f32 / 10f32;
assert_eq!(lerp(&0i8, &-10i8, &w), x);
}
}
#[test]
fn lerp_i16() {
for x in 0 ..= 10 {
let w = x as f32 / 10f32;
assert_eq!(lerp(&0i16, &10i16, &w), x);
}
for x in (0 ..= 10).rev() {
let w = (10 - x) as f32 / 10f32;
assert_eq!(lerp(&10i16, &0i16, &w), x);
}
for x in -10 .. 0 {
let w = (10 + x) as f32 / 10f32;
assert_eq!(lerp(&-10i16, &0i16, &w), x);
}
for x in (-10 .. 0).rev() {
let w = (0 - x) as f32 / 10f32;
assert_eq!(lerp(&0i16, &-10i16, &w), x);
}
}
#[test]
fn lerp_i32() {
for x in 0 ..= 10 {
let w = x as f32 / 10f32;
assert_eq!(lerp(&0i32, &10i32, &w), x);
}
for x in (0 ..= 10).rev() {
let w = (10 - x) as f32 / 10f32;
assert_eq!(lerp(&10i32, &0i32, &w), x);
}
for x in -10 .. 0 {
let w = (10 + x) as f32 / 10f32;
assert_eq!(lerp(&-10i32, &0i32, &w), x);
}
for x in (-10 .. 0).rev() {
let w = (0 - x) as f32 / 10f32;
assert_eq!(lerp(&0i32, &-10i32, &w), x);
}
}
#[test]
fn lerp_i64() {
for x in 0 ..= 10 {
let w = x as f64 / 10f64;
assert_eq!(lerp(&0i64, &10i64, &w), x);
}
for x in (0 ..= 10).rev() {
let w = (10 - x) as f64 / 10f64;
assert_eq!(lerp(&10i64, &0i64, &w), x);
}
for x in -10 .. 0 {
let w = (10 + x) as f64 / 10f64;
assert_eq!(lerp(&-10i64, &0i64, &w), x);
}
for x in (-10 .. 0).rev() {
let w = (0 - x) as f64 / 10f64;
assert_eq!(lerp(&0i64, &-10i64, &w), x);
}
}
#[test]
fn lerp_u8() {
for x in 0 ..= 10 {
let w = x as f32 / 10f32;
assert_eq!(lerp(&0u8, &10u8, &w), x);
}
for x in (0 ..= 10).rev() {
let w = (10 - x) as f32 / 10f32;
assert_eq!(lerp(&10u8, &0u8, &w), x);
}
}
#[test]
fn lerp_u16() {
for x in 0 ..= 10 {
let w = x as f32 / 10f32;
assert_eq!(lerp(&0u16, &10u16, &w), x);
}
for x in (0 ..= 10).rev() {
let w = (10 - x) as f32 / 10f32;
assert_eq!(lerp(&10u16, &0u16, &w), x);
}
}
#[test]
fn lerp_u32() {
for x in 0 ..= 10 {
let w = x as f32 / 10f32;
assert_eq!(lerp(&0u32, &10u32, &w), x);
}
for x in (0 ..= 10).rev() {
let w = (10 - x) as f32 / 10f32;
assert_eq!(lerp(&10u32, &0u32, &w), x);
}
}
#[test]
fn lerp_u64() {
for x in 0 ..= 10 {
let w = x as f64 / 10f64;
assert_eq!(lerp(&0u64, &10u64, &w), x);
}
for x in (0 ..= 10).rev() {
let w = (10 - x) as f64 / 10f64;
assert_eq!(lerp(&10u64, &0u64, &w), x);
}
}
#[test]
fn lerp_array_2() {
for x in 0 ..= 10 {
let w = x as f32 / 10f32;
let pt = lerp(&[0, 0], &[10, 10], &w);
assert_eq!(pt, [x, x]);
}
for x in (0 ..= 10).rev() {
let w = (10 - x) as f32 / 10f32;
let pt = lerp(&[10, 10], &[0, 0], &w);
assert_eq!(pt, [x, x]);
}
}
#[test]
fn lerp_array_3() {
for x in 0 ..= 10 {
let w = x as f32 / 10f32;
let pt = lerp(&[0, 0, 0], &[10, 10, 10], &w);
assert_eq!(pt, [x, x, x]);
}
for x in (0 ..= 10).rev() {
let w = (10 - x) as f32 / 10f32;
let pt = lerp(&[10, 10, 10], &[0, 0, 0], &w);
assert_eq!(pt, [x, x, x]);
}
}
#[test]
fn lerp_array_4() {
for x in 0 ..= 10 {
let w = x as f32 / 10f32;
let pt = lerp(&[0, 0, 0, 0], &[10, 10, 10, 10], &w);
assert_eq!(pt, [x, x, x, x]);
}
for x in (0 ..= 10).rev() {
let w = (10 - x) as f32 / 10f32;
let pt = lerp(&[10, 10, 10, 10], &[0, 0, 0, 0], &w);
assert_eq!(pt, [x, x, x, x]);
}
}
#[test]
fn lerp_array_5() {
for x in 0 ..= 10 {
let w = x as f32 / 10f32;
let pt = lerp(&[0, 0, 0, 0, 0], &[10, 10, 10, 10, 10], &w);
assert_eq!(pt, [x, x, x, x, x]);
}
for x in (0 ..= 10).rev() {
let w = (10 - x) as f32 / 10f32;
let pt = lerp(&[10, 10, 10, 10, 10], &[0, 0, 0, 0, 0], &w);
assert_eq!(pt, [x, x, x, x, x]);
}
}