const fn generate_sqrt_lut() -> [u8; 256] {
let mut lut = [0u8; 256];
let mut i = 0;
while i < 256 {
let x = ((i as u32) << 8) | 0xFF;
let mut y = 1u32;
let mut y_squared = 1u32;
while y_squared <= x {
y += 1;
y_squared = y * y;
}
y -= 1;
lut[i] = y as u8;
i += 1;
}
lut
}
pub const SQRT_LUT: [u8; 256] = generate_sqrt_lut();
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_sqrt_lut_sanity() {
assert_eq!(SQRT_LUT[0], 15); assert_eq!(SQRT_LUT[1], 22); assert_eq!(SQRT_LUT[255], 255); }
#[test]
fn test_sqrt_lut_monotonic() {
for i in 0..255 {
assert!(
SQRT_LUT[i] <= SQRT_LUT[i + 1],
"LUT not monotonic at index {}: {} > {}",
i,
SQRT_LUT[i],
SQRT_LUT[i + 1]
);
}
}
#[test]
fn test_sqrt_lut_accuracy() {
for i in 0u8..=255 {
let x = ((i as u32) << 8) | 0xFF;
let lut_result = SQRT_LUT[i as usize] as u32;
let actual_sqrt = (x as f64).sqrt() as u32;
let diff = if lut_result > actual_sqrt {
lut_result - actual_sqrt
} else {
actual_sqrt - lut_result
};
assert!(
diff <= 1,
"LUT[{}] = {}, but sqrt({}) ≈ {}, diff = {}",
i,
lut_result,
x,
actual_sqrt,
diff
);
}
}
}