use semisafe::slice::get as semisafe_get;
pub(crate) const FRUIT_DITHER_8X8: [[u8; 8]; 8] = [
[1, 45, 10, 39, 2, 44, 32, 24],
[36, 30, 54, 17, 60, 21, 53, 11],
[58, 7, 27, 49, 13, 41, 6, 46],
[25, 33, 43, 3, 37, 19, 57, 31],
[0, 52, 20, 61, 23, 48, 14, 35],
[62, 15, 47, 12, 42, 4, 56, 8],
[29, 40, 5, 38, 16, 50, 34, 26],
[51, 18, 59, 22, 55, 28, 9, 63],
];
#[must_use]
pub(crate) fn fruit_offset(plane: usize, x: usize, y: usize) -> f32 {
let row = (y + plane * 3) & 7;
let column = (x + plane * 5) & 7;
let value = *semisafe_get(semisafe_get(&FRUIT_DITHER_8X8, row), column);
(f32::from(value) + 0.5) / 64.0 - 0.5
}
#[cfg(test)]
mod tests {
use super::{FRUIT_DITHER_8X8, fruit_offset};
#[test]
fn fruit_dither_matrix_is_stable() {
assert_eq!(FRUIT_DITHER_8X8[0], [1, 45, 10, 39, 2, 44, 32, 24]);
assert_eq!(FRUIT_DITHER_8X8[7], [51, 18, 59, 22, 55, 28, 9, 63]);
}
#[test]
fn fruit_dither_offsets_are_centered_in_one_code_unit() {
assert!((fruit_offset(0, 0, 0) - (-0.4765625)).abs() <= f32::EPSILON);
assert!((fruit_offset(0, 5, 0) - 0.1953125).abs() <= f32::EPSILON);
assert_ne!(fruit_offset(0, 0, 0), fruit_offset(1, 0, 0));
}
}