pub fn lerp_u8(p: u8, q: u8, a: u8) -> u8 {
let base_shift = 8;
let base_msb = 1 << (base_shift - 1);
let v = if p > q { 1 } else { 0 };
let (q,p,a) = (i32::from(q), i32::from(p), i32::from(a));
let t0 : i32 = (q - p) * a + base_msb - v; let t1 : i32 = ((t0>>base_shift) + t0) >> base_shift;
(p + t1) as u8
}
pub fn prelerp_u8(p: u8, q: u8, a: u8) -> u8 {
p.wrapping_add(q).wrapping_sub(multiply_u8(p,a))
}
pub fn multiply_u8(a: u8, b: u8) -> u8 {
let base_shift = 8;
let base_msb = 1 << (base_shift - 1);
let (a,b) = (u32::from(a), u32::from(b));
let t : u32 = a * b + base_msb;
let tt : u32 = ((t >> base_shift) + t) >> base_shift;
tt as u8
}
#[cfg(test)]
mod tests {
use super::multiply_u8;
use super::lerp_u8;
use super::prelerp_u8;
fn mu864(i: u8, j: u8) -> u8 {
let i = i as f64 / 255.0;
let j = j as f64 / 255.0;
let c = i * j;
(c * 255.0).round() as u8
}
fn lerp_u8_f64(p: u8, q: u8, a: u8) -> u8 {
let p = p as f64 / 255.0;
let q = q as f64 / 255.0;
let a = a as f64 / 255.0;
let v = a * (q - p) + p;
(v * 255.0).round() as u8
}
fn prelerp_u8_f64(p: u8, q: u8, a: u8) -> u8 {
let p = p as f64 / 255.0;
let q = q as f64 / 255.0;
let a = a as f64 / 255.0;
let v = p + q - a * p;
(v * 255.0).round() as u8
}
#[test]
fn lerp_u8_test() {
for p in 0 ..= 255 {
for q in 0 ..= 255 {
for a in 0 ..= 255 {
let (p,q,a) = (p as u8, q as u8, a as u8);
let v = lerp_u8_f64(p,q,a);
assert_eq!(lerp_u8(p,q,a), v,
"lerp({},{},{}) = {}",p,q,a,v);
}
}
}
}
#[test]
fn perlerp_u8_test() {
for p in 0 ..= 255 {
for q in 0 ..= 255 {
for a in 0 ..= 255 {
let (p,q,a) = (p as u8, q as u8, a as u8);
let v = prelerp_u8_f64(p,q,a);
assert_eq!(prelerp_u8(p,q,a), v,
"prelerp({},{},{}) = {}",p,q,a,v);
}
}
}
}
#[test]
fn multiply_u8_test() {
for i in 0 ..= 255 {
for j in 0 ..= 255 {
let v = mu864(i,j);
assert_eq!(multiply_u8(i,j), v, "{} * {} = {}", i, j, v);
}
}
}
}