use crate::{
index_range::{CoveredRange, IndexRange, OverlappingRange},
zorder::z_range::ZRange,
};
use alloc::{boxed::Box, collections::VecDeque, vec, vec::Vec};
const DEFAULT_RECURSE: usize = 7;
const LEVEL_TERMINATOR: (Option<u64>, Option<u64>) = (None, None);
pub trait ZN {
const BITS_PER_DIMENSION: u32;
const DIMENSIONS: u64;
const MAX_MASK: u64;
const TOTAL_BITS: u64;
const QUADRANTS: u32 = 2_u32.pow(Self::DIMENSIONS as u32);
fn split(value: u32) -> u64;
fn combine(z: u64) -> u32;
fn contains(range: ZRange, value: u64) -> bool;
#[must_use]
fn contains_value(range: ZRange, value: ZRange) -> bool {
Self::contains(range, value.min) && Self::contains(range, value.max)
}
#[must_use]
fn overlaps(range: ZRange, value: ZRange) -> bool;
#[must_use]
fn zranges_default<Z: ZN>(zbounds: &[ZRange]) -> Vec<Box<dyn IndexRange>> {
Self::zranges::<Z>(zbounds, 64, Some(usize::MAX), Some(DEFAULT_RECURSE))
}
#[must_use]
fn zranges<Z: ZN>(
zbounds: &[ZRange],
precision: u64,
max_ranges: Option<usize>,
max_recurse: Option<usize>,
) -> Vec<Box<dyn IndexRange>> {
let mut ranges: Vec<Box<dyn IndexRange>> = Vec::with_capacity(100);
let mut remaining: VecDeque<(Option<u64>, Option<u64>)> = VecDeque::with_capacity(100);
let lcp = Self::longest_common_prefix(
zbounds
.iter()
.flat_map(|b| vec![b.min, b.max])
.collect::<Vec<u64>>()
.as_slice(),
);
let mut offset = 64 - lcp.precision;
check_value::<Z>(
lcp.prefix,
0,
offset,
zbounds,
precision,
&mut ranges,
&mut remaining,
);
remaining.push_back(LEVEL_TERMINATOR);
offset -= Self::DIMENSIONS;
let mut level = 0;
let max_recurse = max_recurse.unwrap_or(DEFAULT_RECURSE);
let max_ranges = max_ranges.unwrap_or(usize::MAX);
loop {
let next = remaining.pop_front();
match next {
Some(LEVEL_TERMINATOR) if !remaining.is_empty() => {
level += 1;
if offset == 0 || level >= max_recurse {
bottom_out(&mut ranges, &mut remaining);
} else {
remaining.push_back(LEVEL_TERMINATOR);
}
offset -= Self::DIMENSIONS;
}
Some((Some(min), _)) => {
let prefix = min;
let mut quadrant = 0_u64;
while quadrant < Self::QUADRANTS.into() {
check_value::<Z>(
prefix,
quadrant,
offset,
zbounds,
precision,
&mut ranges,
&mut remaining,
);
quadrant += 1;
}
if ranges.len() + remaining.len() > max_ranges {
bottom_out(&mut ranges, &mut remaining);
}
}
_ => (),
}
if remaining.is_empty() {
break;
}
}
ranges.sort();
let mut current: Option<Box<dyn IndexRange>> = None;
let mut results = Vec::new();
for range in ranges {
match current.take() {
Some(cur) => {
if range.lower() <= cur.upper().saturating_add(1) {
let max = cur.upper().max(range.upper());
let min = cur.lower();
if cur.contained() && range.contained() {
current = Some(Box::new(CoveredRange::new(min, max)));
} else {
current = Some(Box::new(OverlappingRange::new(min, max)));
}
} else {
results.push(cur);
current = Some(range);
}
}
_ => {
current = Some(range);
}
}
}
if let Some(cur) = current {
results.push(cur);
}
results
}
#[must_use]
fn longest_common_prefix(values: &[u64]) -> ZPrefix {
assert!(!values.is_empty());
let mut bit_shift = Self::TOTAL_BITS - Self::DIMENSIONS;
let mut head = values[0].wrapping_shr(bit_shift as u32);
while values[1..]
.iter()
.all(|v| v.wrapping_shr(bit_shift as u32) == head)
{
bit_shift -= Self::DIMENSIONS;
head = values[0].wrapping_shr(bit_shift as u32);
if bit_shift == 0 {
break;
}
}
bit_shift += Self::DIMENSIONS;
ZPrefix {
prefix: values[0] & (u64::MAX.wrapping_shl(bit_shift as u32)),
precision: 64 - bit_shift,
}
}
}
#[derive(Debug, PartialEq)]
pub struct ZPrefix {
pub prefix: u64,
pub precision: u64,
}
fn check_value<Z: ZN>(
prefix: u64,
quadrant: u64,
offset: u64,
zbounds: &[ZRange],
precision: u64,
ranges: &mut Vec<Box<dyn IndexRange>>,
remaining: &mut VecDeque<(Option<u64>, Option<u64>)>,
) {
let min = prefix | quadrant.wrapping_shl(offset as u32);
let max = min | (1_u64.wrapping_shl(offset as u32) - 1);
let quadrant_range = ZRange { min, max };
if is_contained::<Z>(quadrant_range, zbounds) || offset < 64 - precision {
ranges.push(Box::new(CoveredRange::new(min, max)));
} else if is_overlapped::<Z>(quadrant_range, zbounds) {
remaining.push_back((Some(min), Some(max)));
}
}
fn bottom_out(
ranges: &mut Vec<Box<dyn IndexRange>>,
remaining: &mut VecDeque<(Option<u64>, Option<u64>)>,
) {
while let Some((min, max)) = remaining.pop_front() {
if let (Some(min), Some(max)) = (min, max) {
ranges.push(Box::new(OverlappingRange::new(min, max)));
}
}
}
fn is_contained<Z: ZN>(range: ZRange, zbounds: &[ZRange]) -> bool {
for bound in zbounds {
if Z::contains_value(*bound, range) {
return true;
}
}
false
}
fn is_overlapped<Z: ZN>(range: ZRange, zbounds: &[ZRange]) -> bool {
for bound in zbounds {
if Z::overlaps(*bound, range) {
return true;
}
}
false
}