use std::cmp::Ordering;
use std::convert::TryInto;
use std::mem;
#[cfg(test)]
mod tests {
use crate::*;
#[test]
fn test_increment_coordinates_beyond_bit_range() {
let mut loop_coords = vec![0, 0];
for _incr_count in 0..1024 {
coordinates_increment(4, &mut loop_coords);
assert!(loop_coords[0] < 16, "x = {} < 16", loop_coords[0]);
assert!(loop_coords[1] < 16, "y = {} < 16", loop_coords[1]);
}
}
#[test]
fn test_iterate_dimensions() {
for x in 0..1 << 4 {
for y in 0..1 << 4 {
let coords = vec![x, y];
let _index = coordinates_to_index(4, &coords);
}
}
}
}
pub type HilbertIndex = moore_hilbert_sys::BitmaskT;
pub type HilbertCoordinate = u64;
pub type BitsPerDimensionType = usize;
const BITS_PER_BYTE: usize = 8;
pub fn coordinates_to_index(
bits_per_dimension: BitsPerDimensionType,
coords: &[HilbertCoordinate],
) -> Result<HilbertIndex, ()> {
if bits_per_dimension * coords.len() > mem::size_of::<HilbertIndex>() * BITS_PER_BYTE {
panic!("number of coordinates * bits_per_dimension > sizeof(HilbertIndex) * BITS_PER_BYTE");
}
unsafe {
return Ok(moore_hilbert_sys::hilbert_c2i(
coords.len().try_into().unwrap(),
bits_per_dimension.try_into().unwrap(),
coords.as_ptr(),
));
}
}
pub fn index_to_coordinates(
bits_per_dimension: BitsPerDimensionType,
index: HilbertIndex,
coords: &mut [HilbertCoordinate],
) -> () {
if bits_per_dimension as usize * coords.len() > mem::size_of::<HilbertIndex>() * BITS_PER_BYTE {
panic!("number of coordinates * bits_per_dimension > mem::size_of(HilbertIndex) * BITS_PER_BYTE");
}
unsafe {
return moore_hilbert_sys::hilbert_i2c(
coords.len().try_into().unwrap(),
bits_per_dimension.try_into().unwrap(),
index,
coords.as_mut_ptr(),
);
}
}
pub fn coordinates_compare(
bits_per_dimension: BitsPerDimensionType,
coord1: &[HilbertCoordinate],
coord2: &[HilbertCoordinate],
) -> Ordering {
if bits_per_dimension as usize > mem::size_of::<HilbertIndex>() * BITS_PER_BYTE {
panic!("bits_per_dimension > mem::size_of::<HilbertIndex>() * BITS_PER_BYTE");
}
if coord1.len() != coord2.len() {
panic!("Coordinates supplied are not equal in length");
}
unsafe {
let r = moore_hilbert_sys::hilbert_cmp(
coord1.len().try_into().unwrap(),
mem::size_of::<HilbertCoordinate>().try_into().unwrap(),
bits_per_dimension.try_into().unwrap(),
coord1.as_ptr() as *const std::ffi::c_void,
coord2.as_ptr() as *const std::ffi::c_void,
);
if r == -1 {
return Ordering::Less;
}
if r == 0 {
return Ordering::Equal;
}
return Ordering::Greater;
}
}
pub fn coordinates_float_compare(coord1: &[f64], coord2: &[f64]) -> Ordering {
if coord1.len() != coord2.len() {
panic!("Coordinates supplied are not equal in length");
}
unsafe {
let r = moore_hilbert_sys::hilbert_ieee_cmp(
coord1.len().try_into().unwrap(),
coord1.as_ptr(),
coord2.as_ptr(),
);
if r == -1 {
return Ordering::Less;
}
if r == 0 {
return Ordering::Equal;
}
return Ordering::Greater;
}
}
pub fn coordinates_increment(
bits_per_dimension: BitsPerDimensionType,
coord: &mut [HilbertCoordinate],
) -> () {
if bits_per_dimension as usize > mem::size_of::<HilbertIndex>() * BITS_PER_BYTE {
panic!("bits_per_dimension > mem::size_of::<HilbertIndex>() * BITS_PER_BYTE");
}
unsafe {
moore_hilbert_sys::hilbert_incr(
coord.len().try_into().unwrap(),
bits_per_dimension.try_into().unwrap(),
coord.as_mut_ptr(),
);
}
}
pub fn box_vertex(
bits_per_dimension: BitsPerDimensionType,
find_min: bool,
coord1: &mut [HilbertCoordinate],
coord2: &mut [HilbertCoordinate],
) -> usize {
if coord1.len() != coord2.len() {
panic!("Coordinates supplied are not equal in length");
}
if bits_per_dimension as usize > mem::size_of::<HilbertIndex>() * BITS_PER_BYTE {
panic!("bits_per_dimension > mem::size_of::<HilbertIndex>() * BITS_PER_BYTE");
}
unsafe {
return moore_hilbert_sys::hilbert_box_vtx(
coord1.len().try_into().unwrap(),
mem::size_of::<HilbertCoordinate>().try_into().unwrap(),
bits_per_dimension.try_into().unwrap(),
if find_min { 1 } else { 0 },
coord1.as_ptr() as *mut std::ffi::c_void,
coord2.as_ptr() as *mut std::ffi::c_void,
) as usize;
}
}
pub fn box_float_vertex(find_min: bool, coord1: &mut [f64], coord2: &mut [f64]) -> usize {
if coord1.len() != coord2.len() {
panic!("Coordinates supplied are not equal in length");
}
unsafe {
return moore_hilbert_sys::hilbert_ieee_box_vtx(
coord1.len().try_into().unwrap(),
if find_min { 1 } else { 0 },
coord1.as_mut_ptr(),
coord2.as_mut_ptr(),
) as usize;
}
}
pub fn box_point(
bits_per_dimension: BitsPerDimensionType,
find_min: bool,
coord1: &mut [HilbertCoordinate],
coord2: &mut [HilbertCoordinate],
) -> usize {
if coord1.len() != coord2.len() {
panic!("Coordinates supplied are not equal in length");
}
unsafe {
return moore_hilbert_sys::hilbert_box_pt(
coord1.len().try_into().unwrap(),
mem::size_of::<HilbertCoordinate>().try_into().unwrap(),
bits_per_dimension.try_into().unwrap(),
if find_min { 1 } else { 0 },
coord1.as_mut_ptr() as *mut std::ffi::c_void,
coord2.as_mut_ptr() as *mut std::ffi::c_void,
) as usize;
}
}
pub fn box_point_float(find_min: bool, coord1: &mut [f64], coord2: &mut [f64]) -> usize {
if coord1.len() != coord2.len() {
panic!("Coordinates supplied are not equal in length");
}
unsafe {
return moore_hilbert_sys::hilbert_ieee_box_pt(
coord1.len().try_into().unwrap(),
if find_min { 1 } else { 0 },
coord1.as_mut_ptr(),
coord2.as_mut_ptr(),
) as usize;
}
}
pub fn box_next_point(
bits_per_dimension: BitsPerDimensionType,
find_prev: bool,
coord1: &mut [HilbertCoordinate],
coord2: &mut [HilbertCoordinate],
point: &[HilbertCoordinate],
) -> bool {
if coord1.len() != coord2.len() {
panic!("Coordinates supplied are not equal in length");
}
if point.len() != coord1.len() {
panic!("Coordinates supplied are not equal in length to the point supplied");
}
unsafe {
if moore_hilbert_sys::hilbert_nextinbox(
coord1.len().try_into().unwrap(),
mem::size_of::<HilbertCoordinate>().try_into().unwrap(),
bits_per_dimension.try_into().unwrap(),
if find_prev { 1 } else { 0 },
coord1.as_mut_ptr() as *mut std::ffi::c_void,
coord2.as_mut_ptr() as *mut std::ffi::c_void,
point.as_ptr() as *mut std::ffi::c_void,
) == 1
{
true
} else {
false
}
}
}