use crate::math::UnitValue;
pub trait Curve<I, V> {
fn eval(&self, u: I) -> V;
}
pub trait MonotonicCurve<I, V>: Curve<I, V> {
fn inv(&self, w: V) -> I;
}
#[derive(Copy, Clone, Debug)]
pub struct CurveLut<I: UnitValue, V: UnitValue, const N: usize, const M: usize = N> {
pub(crate) fwd: &'static [V; N],
pub(crate) inv: Option<&'static [I; M]>,
}
pub type CurveLut256 = CurveLut<u8, u8, 256>;
pub type CurveLut65536 = CurveLut<u16, u16, 65536>;
impl<I: UnitValue, V: UnitValue, const N: usize, const M: usize> CurveLut<I, V, N, M> {
pub const fn new(fwd: &'static [V; N], inv: Option<&'static [I; M]>) -> Self {
Self { fwd, inv }
}
#[inline(always)]
pub const fn fwd_lut(&self) -> &'static [V; N] {
self.fwd
}
#[inline(always)]
pub const fn inv_lut(&self) -> Option<&'static [I; M]> {
self.inv
}
#[inline(always)]
pub const fn monotonic(self) -> Option<MonotonicCurveLut<I, V, N, M>> {
match self.inv {
Some(inv) => Some(MonotonicCurveLut { fwd: self.fwd, inv }),
None => None,
}
}
}
impl<I: UnitValue, V: UnitValue, const N: usize, const M: usize> Curve<I, V>
for CurveLut<I, V, N, M>
{
#[inline(always)]
fn eval(&self, u: I) -> V {
self.fwd[u.to_index()]
}
}
#[derive(Copy, Clone, Debug)]
pub struct MonotonicCurveLut<I: UnitValue, V: UnitValue, const N: usize, const M: usize = N> {
fwd: &'static [V; N],
inv: &'static [I; M],
}
pub type MonotonicCurveLut256 = MonotonicCurveLut<u8, u8, 256>;
pub type MonotonicCurveLut65536 = MonotonicCurveLut<u16, u16, 65536>;
impl<I: UnitValue, V: UnitValue, const N: usize, const M: usize> MonotonicCurveLut<I, V, N, M> {
pub const fn new(fwd: &'static [V; N], inv: &'static [I; M]) -> Self {
Self { fwd, inv }
}
#[inline(always)]
pub const fn fwd_lut(&self) -> &'static [V; N] {
self.fwd
}
#[inline(always)]
pub const fn inv_lut(&self) -> &'static [I; M] {
self.inv
}
}
impl<I: UnitValue, V: UnitValue, const N: usize, const M: usize> Curve<I, V>
for MonotonicCurveLut<I, V, N, M>
{
#[inline(always)]
fn eval(&self, u: I) -> V {
self.fwd[u.to_index()]
}
}
impl<I: UnitValue, V: UnitValue, const N: usize, const M: usize> MonotonicCurve<I, V>
for MonotonicCurveLut<I, V, N, M>
{
#[inline(always)]
fn inv(&self, w: V) -> I {
self.inv[w.to_index()]
}
}