pub(crate) trait LutBarycentricReduction<T, U> {
#![allow(unused)]
fn reduce<const SRC_BP: usize, const BINS: usize>(v: T) -> U;
}
impl LutBarycentricReduction<u8, u8> for () {
#[inline(always)]
fn reduce<const SRC_BP: usize, const BINS: usize>(v: u8) -> u8 {
v
}
}
impl LutBarycentricReduction<u8, u16> for () {
#[inline(always)]
fn reduce<const SRC_BP: usize, const BINS: usize>(v: u8) -> u16 {
if BINS == 65536 {
return u16::from_ne_bytes([v, v]);
}
if BINS == 16384 {
return u16::from_ne_bytes([v, v]) >> 2;
}
unimplemented!()
}
}
impl LutBarycentricReduction<f32, u8> for () {
#[inline(always)]
fn reduce<const SRC_BP: usize, const BINS: usize>(v: f32) -> u8 {
(v * 255.).round().min(255.).max(0.) as u8
}
}
impl LutBarycentricReduction<f32, u16> for () {
#[inline(always)]
fn reduce<const SRC_BP: usize, const BINS: usize>(v: f32) -> u16 {
let scale = (BINS - 1) as f32;
(v * scale).round().min(scale).max(0.) as u16
}
}
impl LutBarycentricReduction<f64, u8> for () {
#[inline(always)]
fn reduce<const SRC_BP: usize, const BINS: usize>(v: f64) -> u8 {
(v * 255.).round().min(255.).max(0.) as u8
}
}
impl LutBarycentricReduction<f64, u16> for () {
#[inline(always)]
fn reduce<const SRC_BP: usize, const BINS: usize>(v: f64) -> u16 {
let scale = (BINS - 1) as f64;
(v * scale).round().min(scale).max(0.) as u16
}
}
impl LutBarycentricReduction<u16, u16> for () {
#[inline(always)]
fn reduce<const SRC_BP: usize, const BINS: usize>(v: u16) -> u16 {
let src_scale = 1. / ((1 << SRC_BP) - 1) as f32;
let scale = src_scale * (BINS - 1) as f32;
(v as f32 * scale).round().min(scale).max(0.) as u16
}
}
impl LutBarycentricReduction<u16, u8> for () {
#[inline(always)]
fn reduce<const SRC_BP: usize, const BINS: usize>(v: u16) -> u8 {
let shift = SRC_BP as u16 - 8;
if SRC_BP == 16 {
(v >> 8) as u8
} else {
(v >> shift).min(255) as u8
}
}
}