use core::fmt::Debug;
use core::hash::Hash;
use core::ops::RangeBounds;
use crate::dilated::{Morton2, Morton3};
use crate::hilbert::Hilbert2;
use crate::hilbert3::Hilbert3;
use crate::word::Word;
pub trait Curve2: Copy + Ord + Hash + Debug {
type Word: Word;
const LEVELS: u32;
#[must_use]
fn encode(x: Self::Word, y: Self::Word) -> Self;
#[must_use]
fn decode(self) -> (Self::Word, Self::Word);
#[must_use]
fn key(self) -> Self::Word;
#[must_use]
fn from_key(key: Self::Word) -> Self;
fn cover(
x: impl RangeBounds<Self::Word>,
y: impl RangeBounds<Self::Word>,
out: &mut [(Self::Word, Self::Word)],
) -> &[(Self::Word, Self::Word)];
#[must_use]
fn intersects(
keys: impl RangeBounds<Self::Word>,
x: impl RangeBounds<Self::Word>,
y: impl RangeBounds<Self::Word>,
) -> bool;
}
pub trait Curve3: Copy + Ord + Hash + Debug {
type Word: Word;
const LEVELS: u32;
#[must_use]
fn encode(x: Self::Word, y: Self::Word, z: Self::Word) -> Self;
#[must_use]
fn decode(self) -> (Self::Word, Self::Word, Self::Word);
#[must_use]
fn key(self) -> Self::Word;
#[must_use]
fn from_key(key: Self::Word) -> Self;
}
macro_rules! curve2 {
($($curve:ident . $key:ident . $from:ident);*) => {$(
impl<W: Word> Curve2 for $curve<W> {
type Word = W;
const LEVELS: u32 = $curve::<W>::LEVELS;
#[inline]
fn encode(x: W, y: W) -> Self {
$curve::encode(x, y)
}
#[inline]
fn decode(self) -> (W, W) {
$curve::decode(self)
}
#[inline]
fn key(self) -> W {
self.$key()
}
#[inline]
fn from_key(key: W) -> Self {
$curve::$from(key)
}
#[inline]
fn cover(x: impl RangeBounds<W>, y: impl RangeBounds<W>, out: &mut [(W, W)]) -> &[(W, W)] {
$curve::cover(x, y, out)
}
#[inline]
fn intersects(keys: impl RangeBounds<W>, x: impl RangeBounds<W>, y: impl RangeBounds<W>) -> bool {
$curve::intersects(keys, x, y)
}
}
)*};
}
macro_rules! curve3 {
($($curve:ident . $key:ident . $from:ident);*) => {$(
impl<W: Word> Curve3 for $curve<W> {
type Word = W;
const LEVELS: u32 = $curve::<W>::LEVELS;
#[inline]
fn encode(x: W, y: W, z: W) -> Self {
$curve::encode(x, y, z)
}
#[inline]
fn decode(self) -> (W, W, W) {
$curve::decode(self)
}
#[inline]
fn key(self) -> W {
self.$key()
}
#[inline]
fn from_key(key: W) -> Self {
$curve::$from(key)
}
}
)*};
}
curve2!(Morton2.code.from_code; Hilbert2.index.from_index);
curve3!(Morton3.code.from_code; Hilbert3.index.from_index);
macro_rules! same_cell {
($($hilbert:ident <-> $morton:ident);*) => {$(
impl<W: Word> From<$morton<W>> for $hilbert<W> {
#[inline]
fn from(m: $morton<W>) -> Self {
Self::from_morton(m)
}
}
impl<W: Word> From<$hilbert<W>> for $morton<W> {
#[inline]
fn from(h: $hilbert<W>) -> Self {
h.to_morton()
}
}
)*};
}
same_cell!(Hilbert2 <-> Morton2; Hilbert3 <-> Morton3);
macro_rules! key_traits {
($($curve:ident . $key:ident . $from:ident);*) => {$(
impl<W: Word> Default for $curve<W> {
#[inline]
fn default() -> Self {
Self::$from(W::ZERO)
}
}
impl<W: Word> core::fmt::Binary for $curve<W> {
#[allow(clippy::missing_inline_in_public_items)]
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
core::fmt::Binary::fmt(&self.$key(), f)
}
}
impl<W: Word> core::fmt::LowerHex for $curve<W> {
#[allow(clippy::missing_inline_in_public_items)]
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
core::fmt::LowerHex::fmt(&self.$key(), f)
}
}
impl<W: Word> core::fmt::UpperHex for $curve<W> {
#[allow(clippy::missing_inline_in_public_items)]
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
core::fmt::UpperHex::fmt(&self.$key(), f)
}
}
)*};
}
key_traits!(
Morton2.code.from_code;
Morton3.code.from_code;
Hilbert2.index.from_index;
Hilbert3.index.from_index
);