core: add 2D hilbert curve table support
This commit is contained in:
parent
b440739715
commit
607b87cb77
48
crates/yglnk-core/src/hilbert.rs
Normal file
48
crates/yglnk-core/src/hilbert.rs
Normal file
|
@ -0,0 +1,48 @@
|
|||
/// 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()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -3,6 +3,8 @@
|
|||
|
||||
use int_enum::IntEnum;
|
||||
|
||||
pub mod hilbert;
|
||||
|
||||
mod ht;
|
||||
pub use ht::*;
|
||||
|
||||
|
@ -69,3 +71,44 @@ pub fn linear_table_iter(
|
|||
rest: &i[16..],
|
||||
})
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct X2dhc<'a> {
|
||||
xybits: u8,
|
||||
data: &'a [u8],
|
||||
}
|
||||
|
||||
impl<'a> X2dhc<'a> {
|
||||
pub fn parse(data: &'a [u8], entsize: u16, entcount: u16) -> Option<Self> {
|
||||
if entsize != 1 {
|
||||
return None;
|
||||
}
|
||||
let data = data.get(..(16 * usize::from(entcount)))?;
|
||||
if data.len() < 32 {
|
||||
return None;
|
||||
}
|
||||
let xybits = data[0];
|
||||
if xybits >= 8 {
|
||||
return None;
|
||||
}
|
||||
let exp_len = 1usize.checked_shl(xybits.into())?.checked_mul(16)?;
|
||||
if (data.len() - 16) != exp_len {
|
||||
return None;
|
||||
}
|
||||
Some(Self {
|
||||
xybits,
|
||||
data: &data[16..],
|
||||
})
|
||||
}
|
||||
|
||||
pub fn x2dhc_lookup(&self, x: u8, y: u8) -> (u64, u64) {
|
||||
let xybr = 8 - self.xybits;
|
||||
let (x, y) = (x >> xybr, y >> xybr);
|
||||
let loc = 16 * usize::try_from(hilbert::xy2d(2 * self.xybits, x.into(), y.into())).unwrap();
|
||||
let dloc = &self.data[loc..loc + 16];
|
||||
(
|
||||
u64::from_be_bytes(dloc[0..8].try_into().unwrap()),
|
||||
u64::from_be_bytes(dloc[8..16].try_into().unwrap()),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue