#![deny(missing_docs)]
#![no_std]
#![cfg_attr(feature = "nightly", feature(concat_idents))]
#![cfg_attr(feature = "nightly", feature(core_intrinsics))]
extern crate alloc;
#[cfg(test)]
extern crate std;
use alloc::vec::Vec;
use core::{
borrow::Borrow,
mem::{self, MaybeUninit},
};
pub struct OrderedCollection<T> {
items: Vec<MaybeUninit<T>>,
}
impl<T: Ord> From<Vec<T>> for OrderedCollection<T> {
fn from(mut v: Vec<T>) -> OrderedCollection<T> {
v.sort_unstable();
Self::from_sorted_iter(v)
}
}
fn eytzinger_walk<I, T>(context: &mut (Vec<MaybeUninit<T>>, I), i: usize)
where
I: Iterator<Item = T>,
{
let (v, _) = context;
if i >= v.capacity() {
return;
}
eytzinger_walk(context, 2 * i);
let (v, iter) = context;
let value = iter.next().unwrap();
unsafe {
v.as_mut_ptr().add(i).write(MaybeUninit::new(value));
}
eytzinger_walk(context, 2 * i + 1);
}
impl<T: Ord> OrderedCollection<T> {
const MULTIPLIER: usize = 64 / mem::size_of::<T>();
const OFFSET: usize = Self::MULTIPLIER / 2;
pub fn from_sorted_iter<I>(iter: I) -> Self
where
I: IntoIterator<Item = T>,
I::IntoIter: ExactSizeIterator,
{
let iter = iter.into_iter();
let n = iter.len();
let mut context = (Vec::with_capacity(n + 1), iter);
eytzinger_walk(&mut context, 1);
let (mut items, _) = context;
unsafe { items.set_len(n + 1) };
OrderedCollection { items }
}
pub fn from_slice(v: &mut [T]) -> OrderedCollection<&T> {
v.sort_unstable();
OrderedCollection::from_sorted_iter(v.iter())
}
pub fn find_gte<X>(&self, x: X) -> Option<&T>
where
T: Borrow<X>,
X: Ord,
{
let x = x.borrow();
let mut i = 1;
let mask = prefetch_mask(self.items.len());
let prefetch_ptr = self.items.as_ptr().wrapping_add(Self::OFFSET);
while i < self.items.len() {
let offset = (Self::MULTIPLIER * i) & mask;
do_prefetch(prefetch_ptr.wrapping_add(offset));
let value = unsafe { self.items.get_unchecked(i).assume_init_ref() }.borrow();
i = 2 * i + usize::from(x > value);
}
i >>= i.trailing_ones() + 1;
(i > 0).then(|| unsafe { self.items.get_unchecked(i).assume_init_ref() })
}
pub fn iter(&self) -> Iter<'_, T> {
Iter { coll: self, idx: 0 }
}
}
impl<'a, T: Ord> IntoIterator for &'a OrderedCollection<T> {
type Item = &'a T;
type IntoIter = Iter<'a, T>;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
impl<T> IntoIterator for OrderedCollection<T> {
type Item = T;
type IntoIter = alloc::vec::IntoIter<T>;
fn into_iter(self) -> Self::IntoIter {
Vec::from(self).into_iter()
}
}
pub struct Iter<'a, T> {
coll: &'a OrderedCollection<T>,
idx: usize,
}
impl<'a, T> Iterator for Iter<'a, T> {
type Item = &'a T;
fn next(&mut self) -> Option<Self::Item> {
self.idx += 1;
if self.idx < self.coll.items.len() {
let value = &self.coll.items[self.idx];
Some(unsafe { value.assume_init_ref() })
} else {
None
}
}
}
impl<T> From<OrderedCollection<T>> for Vec<T> {
fn from(mut value: OrderedCollection<T>) -> Self {
assert!(!value.items.is_empty());
let mut items = mem::take(&mut value.items);
items.swap_remove(0);
unsafe { mem::transmute(items) }
}
}
impl<T> Drop for OrderedCollection<T> {
fn drop(&mut self) {
let items: &mut Vec<T> = unsafe { mem::transmute(&mut self.items) };
items.truncate(1);
}
}
#[cfg(feature = "nightly")]
#[inline(always)]
fn do_prefetch<T>(addr: *const T) {
unsafe {
core::intrinsics::prefetch_read_data(addr, 3);
}
}
#[cfg(not(feature = "nightly"))]
fn do_prefetch<T>(_addr: *const T) {}
fn prefetch_mask(n: usize) -> usize {
if n > 0 {
usize::max_value() >> n.leading_zeros()
} else {
0
}
}
#[cfg(test)]
mod tests {
use super::*;
use alloc::{boxed::Box, vec};
#[test]
fn complete_exact() {
let x = OrderedCollection::from(vec![1, 2, 4, 8, 16, 32, 64]);
assert_eq!(x.find_gte(1), Some(&1));
assert_eq!(x.find_gte(2), Some(&2));
assert_eq!(x.find_gte(4), Some(&4));
assert_eq!(x.find_gte(8), Some(&8));
assert_eq!(x.find_gte(16), Some(&16));
assert_eq!(x.find_gte(32), Some(&32));
assert_eq!(x.find_gte(64), Some(&64));
}
#[test]
fn complete_approximate() {
let x = OrderedCollection::from(vec![1, 2, 4, 8, 16, 32, 64]);
assert_eq!(x.find_gte(0), Some(&1));
assert_eq!(x.find_gte(3), Some(&4));
assert_eq!(x.find_gte(5), Some(&8));
assert_eq!(x.find_gte(6), Some(&8));
assert_eq!(x.find_gte(7), Some(&8));
for i in 9..16 {
assert_eq!(x.find_gte(i), Some(&16));
}
for i in 17..32 {
assert_eq!(x.find_gte(i), Some(&32));
}
for i in 33..64 {
assert_eq!(x.find_gte(i), Some(&64));
}
assert_eq!(x.find_gte(65), None);
}
#[test]
fn unbalanced_exact() {
let x = OrderedCollection::from(vec![1, 2, 4, 8, 16, 32, 64, 128, 256]);
assert_eq!(x.find_gte(1), Some(&1));
assert_eq!(x.find_gte(2), Some(&2));
assert_eq!(x.find_gte(4), Some(&4));
assert_eq!(x.find_gte(8), Some(&8));
assert_eq!(x.find_gte(16), Some(&16));
assert_eq!(x.find_gte(32), Some(&32));
assert_eq!(x.find_gte(64), Some(&64));
assert_eq!(x.find_gte(128), Some(&128));
assert_eq!(x.find_gte(256), Some(&256));
}
#[test]
fn unbalanced_approximate() {
let x = OrderedCollection::from(vec![1, 2, 4, 8, 16, 32, 64, 128, 256]);
assert_eq!(x.find_gte(0), Some(&1));
assert_eq!(x.find_gte(3), Some(&4));
assert_eq!(x.find_gte(5), Some(&8));
assert_eq!(x.find_gte(6), Some(&8));
assert_eq!(x.find_gte(7), Some(&8));
for i in 9..16 {
assert_eq!(x.find_gte(i), Some(&16));
}
for i in 17..32 {
assert_eq!(x.find_gte(i), Some(&32));
}
for i in 33..64 {
assert_eq!(x.find_gte(i), Some(&64));
}
for i in 65..128 {
assert_eq!(x.find_gte(i), Some(&128));
}
for i in 129..256 {
assert_eq!(x.find_gte(i), Some(&256));
}
assert_eq!(x.find_gte(257), None);
}
#[test]
fn check_into_iter() {
let expected = vec![1, 2, 4, 8, 16, 32, 64, 128, 256];
let mut values = OrderedCollection::from_sorted_iter(expected.clone())
.into_iter()
.collect::<Vec<_>>();
values.sort();
assert_eq!(values, expected);
}
#[test]
fn check_into_iter_empty() {
let values = OrderedCollection::<u32>::from(vec![]);
assert_eq!(Vec::from(values), vec![]);
}
#[test]
fn check_iter() {
let expected = vec![1, 2, 4, 8, 16, 32, 64, 128, 256];
let mut values = OrderedCollection::from_sorted_iter(expected.clone())
.iter()
.copied()
.collect::<Vec<_>>();
values.sort();
assert_eq!(values, expected);
}
#[test]
fn check_iter_empty() {
let values = OrderedCollection::<u32>::from(vec![]);
assert_eq!(values.iter().next(), None);
}
#[test]
fn check_mask() {
assert_eq!(prefetch_mask(0), 0b000);
assert_eq!(prefetch_mask(1), 0b001);
assert_eq!(prefetch_mask(2), 0b011);
assert_eq!(prefetch_mask(3), 0b011);
assert_eq!(prefetch_mask(4), 0b111);
assert_eq!(prefetch_mask(usize::max_value()), usize::max_value());
}
#[test]
fn check_drop_safety() {
drop(OrderedCollection::from(vec![
Box::new(1),
Box::new(2),
Box::new(3),
]));
}
}