use std::simd::{LaneCount, Simd, StdFloat, SupportedLaneCount};
use crate::simd::{LANES, Vf32, Vusize};
#[inline(always)]
pub fn lerp(v0: f32, v1: f32, t: f32) -> f32 {
(1.0 - t) * v0 + t * v1
}
#[inline(always)]
pub fn lerp_simd<const N: usize>(
v0: Simd<f32, N>,
v1: Simd<f32, N>,
t: Simd<f32, N>,
) -> Simd<f32, N>
where
LaneCount<N>: SupportedLaneCount,
{
(Simd::<f32, N>::splat(1.0) - t) * v0 + t * v1
}
#[inline(always)]
pub fn cubic_hermite(xm1: f32, x0: f32, x1: f32, x2: f32, t: f32) -> f32 {
let c = (x1 - xm1) * 0.5;
let v = x0 - x1;
let w = c + v;
let a = w + v + (x2 - x0) * 0.5;
let b_neg = w + a;
(((a * t) - b_neg) * t + c) * t + x0
}
#[inline(always)]
pub fn cubic_hermite_simd<const N: usize>(
xm1: Simd<f32, N>,
x0: Simd<f32, N>,
x1: Simd<f32, N>,
x2: Simd<f32, N>,
t: Simd<f32, N>,
) -> Simd<f32, N>
where
LaneCount<N>: SupportedLaneCount,
{
let c = (x1 - xm1) * half_f32_simd();
let v = x0 - x1;
let w = c + v;
let a = w + v + (x2 - x0) * half_f32_simd();
let b_neg = w + a;
(((a * t) - b_neg) * t + c) * t + x0
}
#[inline(always)]
pub fn fast_tanh(x: f32) -> f32 {
let x2 = x * x;
let x3 = x2 * x;
let x5 = x3 * x2;
let a = x + (0.16489087 * x3) + (0.00985468 * x5);
a / (1.0 + (a * a)).sqrt()
}
#[inline(always)]
pub fn fast_tanh_vf32<const N: usize>(x: Simd<f32, N>) -> Simd<f32, N>
where
LaneCount<N>: SupportedLaneCount,
{
let x2 = x * x;
let x3 = x2 * x;
let x5 = x3 * x2;
let a = x + (Simd::<f32, N>::splat(0.16489087) * x3) + (Simd::<f32, N>::splat(0.00985468) * x5);
a / (one_f32_simd() + (a * a)).sqrt()
}
#[inline(always)]
pub const fn zero_f32_simd<const N: usize>() -> Simd<f32, N>
where
LaneCount<N>: SupportedLaneCount,
{
Simd::<f32, N>::splat(0.0)
}
#[inline(always)]
pub const fn one_f32_simd<const N: usize>() -> Simd<f32, N>
where
LaneCount<N>: SupportedLaneCount,
{
Simd::<f32, N>::splat(1.0)
}
#[inline(always)]
pub const fn half_f32_simd<const N: usize>() -> Simd<f32, N>
where
LaneCount<N>: SupportedLaneCount,
{
Simd::<f32, N>::splat(0.5)
}
#[inline(always)]
pub const fn zero_usize_simd<const N: usize>() -> Simd<usize, N>
where
LaneCount<N>: SupportedLaneCount,
{
Simd::<usize, N>::splat(0)
}
#[inline(always)]
pub const fn one_usize_simd<const N: usize>() -> Simd<usize, N>
where
LaneCount<N>: SupportedLaneCount,
{
Simd::<usize, N>::splat(1)
}
#[inline(always)]
pub const fn two_usize_simd<const N: usize>() -> Simd<usize, N>
where
LaneCount<N>: SupportedLaneCount,
{
Simd::<usize, N>::splat(2)
}
pub const ZERO_VF32: Vf32 = zero_f32_simd::<LANES>();
pub const HALF_VF32: Vf32 = half_f32_simd::<LANES>();
pub const ONE_VF32: Vf32 = one_f32_simd::<LANES>();
pub const ZERO_VUSIZE: Vusize = zero_usize_simd::<LANES>();
pub const ONE_VUSIZE: Vusize = one_usize_simd::<LANES>();
pub const TWO_VUSIZE: Vusize = two_usize_simd::<LANES>();