From edda93a29014a1a6726ce87c930634f4372e96dc Mon Sep 17 00:00:00 2001 From: DoubleHyphen <36716576+DoubleHyphen@users.noreply.github.com> Date: Mon, 29 Mar 2021 14:53:03 +0300 Subject: [PATCH] Generalise functions for other uints --- src/lib.rs | 217 ++++++++++++++++++++++++++++++++++------------------- 1 file changed, 141 insertions(+), 76 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index fdc0701..c5e878b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -37,75 +37,94 @@ //! **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, -]; - -// 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, -]; +#![cfg_attr(not(test), no_std)] + +use core::ops::{ShrAssign, ShlAssign, BitOrAssign}; +use core::convert::{TryInto, From}; +use num_traits::{Zero, PrimInt}; + +pub trait Double: num_traits::PrimInt + From + TryInto + BitOrAssign + where Self::Key: PrimInt + ShrAssign + From + 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. Must be < 2^`order` /// * `y` - Coordinate in 2D space. Must be < 2^`order` /// * `order` - Hilbert space order. Max order is 32, since 32 bit coordinates are used. -pub fn xy2h(x: u32, y: u32) -> u64 { - let coor_bits = (core::mem::size_of::() * 8) as u32; +pub fn xy2h(x: T, y: T) -> ::Key +where >::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::() * 8) as u32; let useless_bits = (x|y).leading_zeros() & !1; let useful_bits = coor_bits - useless_bits; let order = useful_bits; + + let seven = T::SEVEN; + let sixty_three = T::SIXTY_THREE; - let mut result: u64 = 0; - let mut state = 0; + let mut result: ::Key = ::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: ::Key = r.into(); + let mut hhh: ::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: ::Key = r.into(); + let mut hhh: ::Key = r & sixty_three; + hhh >>= ((shift_factor as u8) << 1).into(); result = result | hhh; return result; } @@ -116,35 +135,81 @@ pub fn xy2h(x: u32, y: u32) -> u64 { /// # Arguments /// * `h` - Coordinate in 1D hilbert space. Must be < (2^`order`) * 2. /// * `order` - Hilbert space order. Max order is 32, since 32 bit coordinates are used. -pub fn h2xy(h: u64) -> (u32, u32) { - let coor_bits = (core::mem::size_of::() * 8) as u32; +pub fn h2xy(h: ::Key) -> (T, T) +where >::Error: core::fmt::Debug, +<::Key as TryInto>::Error: core::fmt::Debug, +::Key: TryInto +{ + + + + + + // 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::() * 8) as u32; let useless_bits = (h.leading_zeros()>>1) & !1; let useful_bits = coor_bits - useless_bits; let order = useful_bits; + + let seven = T::SEVEN; + let sixty_three = T::SIXTY_THREE; - let mut x_result: u32 = 0; - let mut y_result: u32 = 0; + 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: ::Key = h >> ((shift_factor as usize) << 1); + let h_in: ::Key = h_in & sixty_three; + let h_in: u8 = h_in.try_into().unwrap(); + //let index: usize = (state as usize) | h_in.try_into().unwrap(); + //let index: usize = index.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: ::Key = h << ((shift_factor as usize) << 1); + let h_in: ::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); } } @@ -225,7 +290,7 @@ 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); } @@ -233,6 +298,7 @@ mod tests { #[test] fn h2xy_one_bit() { + let h2xy = h2xy::; let (x0, y0) = h2xy(0b00); let (x1, y1) = h2xy(0b01); let (x2, y2) = h2xy(0b11); @@ -245,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); @@ -257,6 +323,7 @@ mod tests { #[test] fn h2xy_two_bits() { + let h2xy = h2xy::; for h in 0..8 { let (rx, ry) = h2xy(h as u64); let h_cmp = xy2h(rx as u32, ry as u32); @@ -289,9 +356,7 @@ mod tests { // Only for rendering images //#[test] - fn write_image() { - let order: u8 = 3; - + fn _write_image() { let bits: usize = 8; let numbers: usize = 2usize.pow(bits as u32);