mod d2;
mod d3;
mod d4;
mod d5;
mod d6;
mod d7;
use num_traits::float::FloatCore;
pub trait MortonWord:
Send
+ Sync
+ Copy
+ Default
+ Ord
+ core::ops::BitXor<Output = Self>
+ core::ops::BitAnd<Output = Self>
+ core::ops::Shr<u32, Output = Self>
{
const BITS: u32;
fn msb_position(self) -> u32;
fn d_bit_mask(d: u32) -> Self;
}
impl MortonWord for u64 {
const BITS: u32 = 64;
#[inline]
fn d_bit_mask(d: u32) -> Self {
(1u64 << d) - 1
}
#[inline]
fn msb_position(self) -> u32 {
if self == 0 {
return Self::BITS - 1;
}
Self::BITS - 1 - self.leading_zeros()
}
}
impl MortonWord for u128 {
const BITS: u32 = 128;
#[inline]
fn d_bit_mask(d: u32) -> Self {
(1u128 << d) - 1
}
fn msb_position(self) -> u32 {
if self == 0 {
return Self::BITS - 1;
}
Self::BITS - 1 - self.leading_zeros()
}
}
pub trait Morton<const D: usize> {
const CHILDREN: usize;
const BITS: u32;
type Stack: AsMut<[u32]>;
type Word: MortonWord;
fn empty_stack() -> Self::Stack;
fn encode(coords: [u32; D]) -> Self::Word;
fn decode(code: Self::Word) -> [u32; D];
}
pub struct Dim<const D: usize>;
pub(crate) fn quantize<T: FloatCore, const D: usize>(
point: &[T; D],
min: &[T; D],
inv_scale: &[T; D],
max_bucket: u32,
) -> [u32; D] {
core::array::from_fn(|axis| {
let scaled = ((point[axis] - min[axis]) * inv_scale[axis]).floor();
if scaled > T::zero() {
scaled
.to_u64()
.map_or(max_bucket, |value| value.min(max_bucket as u64) as u32)
} else {
0
}
})
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn u64_msb_position() {
assert_eq!(0u64.msb_position(), 63);
assert_eq!(1u64.msb_position(), 0);
assert_eq!(2u64.msb_position(), 1);
assert_eq!(u64::MAX.msb_position(), 63);
assert_eq!((1u64 << 40).msb_position(), 40);
}
#[test]
fn u128_msb_position() {
assert_eq!(0u128.msb_position(), 127);
assert_eq!(1u128.msb_position(), 0);
assert_eq!(2u128.msb_position(), 1);
assert_eq!(u128::MAX.msb_position(), 127);
assert_eq!((1u128 << 80).msb_position(), 80);
}
#[test]
fn u64_d_bit_mask() {
assert_eq!(u64::d_bit_mask(0), 0);
assert_eq!(u64::d_bit_mask(1), 1);
assert_eq!(u64::d_bit_mask(2), 3);
assert_eq!(u64::d_bit_mask(4), 15);
assert_eq!(u64::d_bit_mask(32), (1u64 << 32) - 1);
}
#[test]
fn u128_d_bit_mask() {
assert_eq!(u128::d_bit_mask(0), 0);
assert_eq!(u128::d_bit_mask(1), 1);
assert_eq!(u128::d_bit_mask(64), (1u128 << 64) - 1);
}
}