yglnk/crates/yglnk-core/src/hilbert.rs
2023-01-08 06:57:37 +01:00

49 lines
992 B
Rust

/// rotate/flip a quadrant
fn rot(n: u32, x: &mut u32, y: &mut u32, rx: bool, ry: bool) {
if ry {
return;
}
if rx {
*x = n - 1 - *x;
*y = n - 1 - *y;
}
core::mem::swap(x, y);
}
fn bool2int(x: bool) -> u32 {
if x {
1
} else {
0
}
}
pub fn xy2d(nh: u8, mut x: u32, mut y: u32) -> u32 {
let n = 1 << nh;
(0..nh)
.rev()
.map(|sh| {
let s = 1u32 << sh;
let rx = (x & s) != 0;
let ry = (y & s) != 0;
rot(n, &mut x, &mut y, rx, ry);
s * s * ((3 * bool2int(rx)) ^ bool2int(ry))
})
.sum()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn simple() {
let exp: [u32; 16] = [0, 3, 4, 5, 1, 2, 7, 6, 14, 13, 8, 9, 15, 12, 11, 10];
for x in 0..4u16 {
for y in 0..4u16 {
assert_eq!(exp[usize::from(x * 4 + y)], xy2d(4, x.into(), y.into()));
}
}
}
}