Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generalise functions for other uints #3

Merged
merged 2 commits into from
Mar 31, 2021
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
213 changes: 141 additions & 72 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,74 +37,104 @@
//! **512 Bytes of RAM** for the lookup tables (one for 2D->1D and another for 1D->2D).
//!

// Mapping from State and coordinates to hilbert states
// SXXXYYY => SHHH
// 8 bit => 8 bit
const LUT_3: [u8; 256] = [
64, 1, 206, 79, 16, 211, 84, 21, 131, 2, 205, 140, 81, 82, 151, 22, 4, 199, 8, 203, 158, 157,
88, 25, 69, 70, 73, 74, 31, 220, 155, 26, 186, 185, 182, 181, 32, 227, 100, 37, 59, 248, 55,
244, 97, 98, 167, 38, 124, 61, 242, 115, 174, 173, 104, 41, 191, 62, 241, 176, 47, 236, 171,
42, 0, 195, 68, 5, 250, 123, 60, 255, 65, 66, 135, 6, 249, 184, 125, 126, 142, 141, 72, 9, 246,
119, 178, 177, 15, 204, 139, 10, 245, 180, 51, 240, 80, 17, 222, 95, 96, 33, 238, 111, 147, 18,
221, 156, 163, 34, 237, 172, 20, 215, 24, 219, 36, 231, 40, 235, 85, 86, 89, 90, 101, 102, 105,
106, 170, 169, 166, 165, 154, 153, 150, 149, 43, 232, 39, 228, 27, 216, 23, 212, 108, 45, 226,
99, 92, 29, 210, 83, 175, 46, 225, 160, 159, 30, 209, 144, 48, 243, 116, 53, 202, 75, 12, 207,
113, 114, 183, 54, 201, 136, 77, 78, 190, 189, 120, 57, 198, 71, 130, 129, 63, 252, 187, 58,
197, 132, 3, 192, 234, 107, 44, 239, 112, 49, 254, 127, 233, 168, 109, 110, 179, 50, 253, 188,
230, 103, 162, 161, 52, 247, 56, 251, 229, 164, 35, 224, 117, 118, 121, 122, 218, 91, 28, 223,
138, 137, 134, 133, 217, 152, 93, 94, 11, 200, 7, 196, 214, 87, 146, 145, 76, 13, 194, 67, 213,
148, 19, 208, 143, 14, 193, 128,
];
#![cfg_attr(not(test), no_std)]

// Mapping from hilbert states to 2D coordinates
// SHHH => SXXXYYY
// 8 bit => 8 bit
const LUT_3_REV: [u8; 256] = [
64, 1, 9, 136, 16, 88, 89, 209, 18, 90, 91, 211, 139, 202, 194, 67, 4, 76, 77, 197, 70, 7, 15,
142, 86, 23, 31, 158, 221, 149, 148, 28, 36, 108, 109, 229, 102, 39, 47, 174, 118, 55, 63, 190,
253, 181, 180, 60, 187, 250, 242, 115, 235, 163, 162, 42, 233, 161, 160, 40, 112, 49, 57, 184,
0, 72, 73, 193, 66, 3, 11, 138, 82, 19, 27, 154, 217, 145, 144, 24, 96, 33, 41, 168, 48, 120,
121, 241, 50, 122, 123, 243, 171, 234, 226, 99, 100, 37, 45, 172, 52, 124, 125, 245, 54, 126,
127, 247, 175, 238, 230, 103, 223, 151, 150, 30, 157, 220, 212, 85, 141, 204, 196, 69, 6, 78,
79, 199, 255, 183, 182, 62, 189, 252, 244, 117, 173, 236, 228, 101, 38, 110, 111, 231, 159,
222, 214, 87, 207, 135, 134, 14, 205, 133, 132, 12, 84, 21, 29, 156, 155, 218, 210, 83, 203,
131, 130, 10, 201, 129, 128, 8, 80, 17, 25, 152, 32, 104, 105, 225, 98, 35, 43, 170, 114, 51,
59, 186, 249, 177, 176, 56, 191, 254, 246, 119, 239, 167, 166, 46, 237, 165, 164, 44, 116, 53,
61, 188, 251, 179, 178, 58, 185, 248, 240, 113, 169, 232, 224, 97, 34, 106, 107, 227, 219, 147,
146, 26, 153, 216, 208, 81, 137, 200, 192, 65, 2, 74, 75, 195, 68, 5, 13, 140, 20, 92, 93, 213,
22, 94, 95, 215, 143, 206, 198, 71,
];
extern crate num_traits;

use core::convert::{From, TryInto};
use core::ops::{BitOrAssign, ShlAssign, ShrAssign};
use num_traits::{PrimInt, Zero};

pub trait Double: num_traits::PrimInt + From<u8> + TryInto<usize> + BitOrAssign
where
Self::Key: PrimInt + ShrAssign + From<u8> + Zero + ShlAssign + BitOrAssign,
{
type Key;
const SEVEN: Self;
const SIXTY_THREE: Self::Key;
}

impl Double for u64 {
type Key = u128;
const SEVEN: Self = 7;
const SIXTY_THREE: Self::Key = 63;
}
impl Double for u16 {
type Key = u32;
const SEVEN: Self = 7;
const SIXTY_THREE: Self::Key = 63;
}
impl Double for u8 {
type Key = u16;
const SEVEN: Self = 7;
const SIXTY_THREE: Self::Key = 63;
}
impl Double for u32 {
type Key = u64;
const SEVEN: Self = 7;
const SIXTY_THREE: Self::Key = 63;
}

/// Convert form 2D to 1D hilbert space
/// # Arguments
/// * `x` - Coordinate in 2D space
/// * `y` - Coordinate in 2D space
pub fn xy2h(x: u32, y: u32) -> u64 {
let coor_bits = (core::mem::size_of::<u32>() * 8) as u32;
pub fn xy2h<T: Double>(x: T, y: T) -> <T as Double>::Key
where
<T as TryInto<usize>>::Error: core::fmt::Debug,
{
// Mapping from State and coordinates to hilbert states
// SXXXYYY => SHHH
// 8 bit => 8 bit
const LUT_3: [u8; 256] = [
64, 1, 206, 79, 16, 211, 84, 21, 131, 2, 205, 140, 81, 82, 151, 22, 4, 199, 8, 203, 158,
157, 88, 25, 69, 70, 73, 74, 31, 220, 155, 26, 186, 185, 182, 181, 32, 227, 100, 37, 59,
248, 55, 244, 97, 98, 167, 38, 124, 61, 242, 115, 174, 173, 104, 41, 191, 62, 241, 176, 47,
236, 171, 42, 0, 195, 68, 5, 250, 123, 60, 255, 65, 66, 135, 6, 249, 184, 125, 126, 142,
141, 72, 9, 246, 119, 178, 177, 15, 204, 139, 10, 245, 180, 51, 240, 80, 17, 222, 95, 96,
33, 238, 111, 147, 18, 221, 156, 163, 34, 237, 172, 20, 215, 24, 219, 36, 231, 40, 235, 85,
86, 89, 90, 101, 102, 105, 106, 170, 169, 166, 165, 154, 153, 150, 149, 43, 232, 39, 228,
27, 216, 23, 212, 108, 45, 226, 99, 92, 29, 210, 83, 175, 46, 225, 160, 159, 30, 209, 144,
48, 243, 116, 53, 202, 75, 12, 207, 113, 114, 183, 54, 201, 136, 77, 78, 190, 189, 120, 57,
198, 71, 130, 129, 63, 252, 187, 58, 197, 132, 3, 192, 234, 107, 44, 239, 112, 49, 254,
127, 233, 168, 109, 110, 179, 50, 253, 188, 230, 103, 162, 161, 52, 247, 56, 251, 229, 164,
35, 224, 117, 118, 121, 122, 218, 91, 28, 223, 138, 137, 134, 133, 217, 152, 93, 94, 11,
200, 7, 196, 214, 87, 146, 145, 76, 13, 194, 67, 213, 148, 19, 208, 143, 14, 193, 128,
];

let coor_bits = (core::mem::size_of::<T>() * 8) as u32;
let useless_bits = (x | y).leading_zeros() & !1;
let useful_bits = coor_bits - useless_bits;
let order = useful_bits;

let mut result: u64 = 0;
let mut state = 0;
let seven = T::SEVEN;
let sixty_three = T::SIXTY_THREE;

let mut result: <T as Double>::Key = <T as Double>::Key::zero();
let mut state = 0u8;
let mut shift_factor: i8 = order as i8 - 3;
loop {
if shift_factor > 0 {
let x_in = ((x >> shift_factor) & 0b111) << 3;
let y_in = (y >> shift_factor) & 0b111;
let r = LUT_3[state as usize | x_in as usize | y_in as usize];
let x_in = ((x >> shift_factor.try_into().unwrap()) & seven) << 3;
let y_in = (y >> shift_factor.try_into().unwrap()) & seven;
let index = x_in | y_in | state.into();
let index: usize = index.try_into().unwrap();
let r: u8 = LUT_3[index];
state = r & 0b11000000;
let mut hhh: u64 = (r & 0b00111111) as u64;
hhh <<= shift_factor << 1;
let r: <T as Double>::Key = r.into();
let mut hhh: <T as Double>::Key = r & sixty_three;
hhh <<= ((shift_factor as u8) << 1).into();
result = result | hhh;
shift_factor -= 3;
} else {
shift_factor *= -1;
let x_in = ((x << shift_factor) & 0b111) << 3;
let y_in = (y << shift_factor) & 0b111;
let r = LUT_3[state as usize | x_in as usize | y_in as usize];
let mut hhh: u64 = (r & 0b00111111) as u64;
hhh >>= shift_factor << 1;
let x_in = ((x << shift_factor.try_into().unwrap()) & seven) << 3;
let y_in = (y << shift_factor.try_into().unwrap()) & seven;
let index = x_in | y_in | state.into();
let r: u8 = LUT_3[index.try_into().unwrap()];
let r: <T as Double>::Key = r.into();
let mut hhh: <T as Double>::Key = r & sixty_three;
hhh >>= ((shift_factor as u8) << 1).into();
result = result | hhh;
return result;
}
Expand All @@ -114,35 +144,72 @@ pub fn xy2h(x: u32, y: u32) -> u64 {
/// Convert form 1D hilbert space to 2D coordinates
/// # Arguments
/// * `h` - Coordinate in 1D hilbert space
pub fn h2xy(h: u64) -> (u32, u32) {
let coor_bits = (core::mem::size_of::<u32>() * 8) as u32;
pub fn h2xy<T: Double>(h: <T as Double>::Key) -> (T, T)
where
<T as TryInto<usize>>::Error: core::fmt::Debug,
<<T as Double>::Key as TryInto<u8>>::Error: core::fmt::Debug,
<T as Double>::Key: TryInto<u8>,
{
// Mapping from hilbert states to 2D coordinates
// SHHH => SXXXYYY
// 8 bit => 8 bit
const LUT_3_REV: [u8; 256] = [
64, 1, 9, 136, 16, 88, 89, 209, 18, 90, 91, 211, 139, 202, 194, 67, 4, 76, 77, 197, 70, 7,
15, 142, 86, 23, 31, 158, 221, 149, 148, 28, 36, 108, 109, 229, 102, 39, 47, 174, 118, 55,
63, 190, 253, 181, 180, 60, 187, 250, 242, 115, 235, 163, 162, 42, 233, 161, 160, 40, 112,
49, 57, 184, 0, 72, 73, 193, 66, 3, 11, 138, 82, 19, 27, 154, 217, 145, 144, 24, 96, 33,
41, 168, 48, 120, 121, 241, 50, 122, 123, 243, 171, 234, 226, 99, 100, 37, 45, 172, 52,
124, 125, 245, 54, 126, 127, 247, 175, 238, 230, 103, 223, 151, 150, 30, 157, 220, 212, 85,
141, 204, 196, 69, 6, 78, 79, 199, 255, 183, 182, 62, 189, 252, 244, 117, 173, 236, 228,
101, 38, 110, 111, 231, 159, 222, 214, 87, 207, 135, 134, 14, 205, 133, 132, 12, 84, 21,
29, 156, 155, 218, 210, 83, 203, 131, 130, 10, 201, 129, 128, 8, 80, 17, 25, 152, 32, 104,
105, 225, 98, 35, 43, 170, 114, 51, 59, 186, 249, 177, 176, 56, 191, 254, 246, 119, 239,
167, 166, 46, 237, 165, 164, 44, 116, 53, 61, 188, 251, 179, 178, 58, 185, 248, 240, 113,
169, 232, 224, 97, 34, 106, 107, 227, 219, 147, 146, 26, 153, 216, 208, 81, 137, 200, 192,
65, 2, 74, 75, 195, 68, 5, 13, 140, 20, 92, 93, 213, 22, 94, 95, 215, 143, 206, 198, 71,
];

let coor_bits = (core::mem::size_of::<T>() * 8) as u32;
let useless_bits = (h.leading_zeros() >> 1) & !1;
let useful_bits = coor_bits - useless_bits;
let order = useful_bits;

let mut x_result: u32 = 0;
let mut y_result: u32 = 0;
let seven = T::SEVEN;
let sixty_three = T::SIXTY_THREE;

let mut x_result: T = T::zero();
let mut y_result: T = x_result;

let mut state = 0;
let mut state = 0u8;
let mut shift_factor: i8 = order as i8 - 3;
loop {
if shift_factor > 0 {
let h_in = (h >> (shift_factor << 1)) & 0b111111;
let r = LUT_3_REV[state as usize | h_in as usize];
let h_in: <T as Double>::Key = h >> ((shift_factor as usize) << 1);
let h_in: <T as Double>::Key = h_in & sixty_three;
let h_in: u8 = h_in.try_into().unwrap();
let r: u8 = LUT_3_REV[state as usize | h_in as usize];
state = r & 0b11000000;
let xxx: u32 = ((r & 0b00111000) >> 3) as u32;
let yyy: u32 = (r & 0b00000111) as u32;
x_result = (xxx << shift_factor) | x_result;
y_result = (yyy << shift_factor) | y_result;
let xxx: T = r.into();
let xxx: T = xxx >> 3;
let xxx: T = xxx & seven;
let yyy: T = r.into();
let yyy: T = yyy & seven;
x_result |= xxx << shift_factor.try_into().unwrap();
y_result |= yyy << shift_factor.try_into().unwrap();
shift_factor -= 3;
} else {
shift_factor *= -1;
let h_in = (h << (shift_factor << 1)) & 0b111111;
let r = LUT_3_REV[state as usize | h_in as usize];
let xxx: u32 = ((r & 0b00111000) >> 3) as u32;
let yyy: u32 = (r & 0b00000111) as u32;
x_result = (xxx >> shift_factor) | x_result;
y_result = (yyy >> shift_factor) | y_result;
let h_in: <T as Double>::Key = h << ((shift_factor as usize) << 1);
let h_in: <T as Double>::Key = h_in & sixty_three;
let h_in: u8 = h_in.try_into().unwrap();
let r: u8 = LUT_3_REV[state as usize | h_in as usize];
let xxx: T = r.into();
let xxx: T = xxx >> 3;
let xxx: T = xxx & seven;
let yyy: T = r.into();
let yyy: T = yyy & seven;
x_result = xxx >> shift_factor.try_into().unwrap() | x_result;
y_result = yyy >> shift_factor.try_into().unwrap() | y_result;
return (x_result, y_result);
}
}
Expand Down Expand Up @@ -223,14 +290,15 @@ mod tests {
fn hilbert_and_rev() {
let order = 16;
for h in 0..(2usize.pow(order) - 1) {
let (x, y) = h2xy(h as u64);
let (x, y): (u32, u32) = h2xy(h as u64);
let res_h = xy2h(x, y);
assert_eq!(h as u64, res_h);
}
}

#[test]
fn h2xy_one_bit() {
let h2xy = h2xy::<u8>;
let (x0, y0) = h2xy(0b00);
let (x1, y1) = h2xy(0b01);
let (x2, y2) = h2xy(0b11);
Expand All @@ -243,10 +311,10 @@ mod tests {

#[test]
fn xy2h_one_bit() {
let d0 = xy2h(0, 0);
let d1 = xy2h(0, 1);
let d2 = xy2h(1, 0);
let d3 = xy2h(1, 1);
let d0 = xy2h(0u64, 0);
let d1 = xy2h(0u64, 1);
let d2 = xy2h(1u64, 0);
let d3 = xy2h(1u64, 1);
assert_eq!(d0, 0b00);
assert_eq!(d1, 0b11);
assert_eq!(d2, 0b01);
Expand All @@ -255,6 +323,7 @@ mod tests {

#[test]
fn h2xy_two_bits() {
let h2xy = h2xy::<u32>;
for h in 0..8 {
let (rx, ry) = h2xy(h as u64);
let h_cmp = xy2h(rx as u32, ry as u32);
Expand Down