80 lines
1.6 KiB
Rust
80 lines
1.6 KiB
Rust
#![allow(dead_code)]
|
|
|
|
const N: u32 = 1 << 16;
|
|
|
|
// Utility function used by the functions below.
|
|
fn hil_rot(n: u32, rx: u32, ry: u32, x: &mut u32, y: &mut u32) {
|
|
if ry == 0 {
|
|
if rx == 1 {
|
|
*x = (n - 1).wrapping_sub(*x);
|
|
*y = (n - 1).wrapping_sub(*y);
|
|
}
|
|
let t = *x;
|
|
*x = *y;
|
|
*y = t;
|
|
}
|
|
}
|
|
|
|
/// Convert (x,y) to hilbert curve index.
|
|
///
|
|
/// x: The x coordinate. Must be a positive integer no greater than 2^16-1.
|
|
/// y: The y coordinate. Must be a positive integer no greater than 2^16-1.
|
|
///
|
|
/// Returns the hilbert curve index corresponding to the (x,y) coordinates given.
|
|
pub fn xy2d(x: u32, y: u32) -> u32 {
|
|
assert!(x < N);
|
|
assert!(y < N);
|
|
|
|
let (mut x, mut y) = (x, y);
|
|
let mut d = 0;
|
|
let mut s = N >> 1;
|
|
while s > 0 {
|
|
let rx = if (x & s) > 0 { 1 } else { 0 };
|
|
let ry = if (y & s) > 0 { 1 } else { 0 };
|
|
d += s * s * ((3 * rx) ^ ry);
|
|
hil_rot(s, rx, ry, &mut x, &mut y);
|
|
|
|
s >>= 1
|
|
}
|
|
|
|
d
|
|
}
|
|
|
|
|
|
/// Convert hilbert curve index to (x,y).
|
|
///
|
|
/// d: The hilbert curve index.
|
|
///
|
|
/// Returns the (x, y) coords at the given index.
|
|
pub fn d2xy(d: u32) -> (u32, u32) {
|
|
let (mut x, mut y) = (0, 0);
|
|
let mut s = 1;
|
|
let mut t = d;
|
|
while s < N {
|
|
let rx = 1 & (t >> 1);
|
|
let ry = 1 & (t ^ rx);
|
|
hil_rot(s, rx, ry, &mut x, &mut y);
|
|
x += s * rx;
|
|
y += s * ry;
|
|
t >>= 2;
|
|
|
|
s <<= 1;
|
|
}
|
|
|
|
(x, y)
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn reversible() {
|
|
let d = 54;
|
|
let (x, y) = d2xy(d);
|
|
let d2 = xy2d(x, y);
|
|
|
|
assert_eq!(d, d2);
|
|
}
|
|
}
|