49 lines
992 B
Rust
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()));
|
|
}
|
|
}
|
|
}
|
|
}
|