Skip to content

Commit

Permalink
Merge pull request #3 from DoubleHyphen/main
Browse files Browse the repository at this point in the history
Generalise functions for other uints
  • Loading branch information
becheran authored Mar 31, 2021
2 parents 4e065bc + 0fe5f18 commit 293aafb
Showing 1 changed file with 141 additions and 72 deletions.
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

0 comments on commit 293aafb

Please sign in to comment.