#![cfg_attr(not(feature = "std"), no_std)]
extern crate alloc;
#[allow(unused_imports)]
use alloc::{string::String, vec::Vec};
pub use layout_internal::soa_impl;
pub use layout_internal::SOA;
pub mod bitpack;
pub mod column;
pub mod compact;
#[doc(hidden)]
pub use alloc::vec::Drain;
#[doc(hidden)]
pub use branches;
pub use column::Column;
pub use compact::CompactRepr;
pub use compact::{
Compact, CompactBool, CompactChunks, CompactChunksExact,
CompactChunksExactMut, CompactChunksMut, CompactDrain, CompactIntoIter,
CompactIter, CompactIterMut, CompactPtr, CompactPtrMut, CompactRefMut,
CompactSlice, CompactSliceMut, CompactVec,
};
pub use layout_internal::CompactRepr;
#[doc(hidden)]
pub fn __invert_permutation(argsort: &[usize]) -> Vec<usize> {
let len = argsort.len();
let mut dest = alloc::vec![usize::MAX; len];
for (pos, &src) in argsort.iter().enumerate() {
assert!(src < len, "index {src} out of bounds for length {len}");
assert!(
dest[src] == usize::MAX,
"duplicate index {src}: indices must form a permutation"
);
dest[src] = pos;
}
dest
}
#[doc(hidden)]
pub struct VisitedBits {
words: Vec<usize>,
}
impl VisitedBits {
const W: usize = usize::BITS as usize;
#[inline]
pub fn new(len: usize) -> Self {
Self {
words: alloc::vec![0usize; (len + Self::W - 1) / Self::W],
}
}
#[inline]
pub fn test(&self, i: usize) -> bool {
(self.words[i / Self::W] >> (i % Self::W)) & 1 != 0
}
#[inline]
pub fn set(&mut self, i: usize) {
self.words[i / Self::W] |= 1 << (i % Self::W);
}
#[inline]
pub fn clear(&mut self) {
self.words.fill(0);
}
}
#[doc(hidden)]
pub fn __validate_permutation(dest: &[usize], len: usize) -> VisitedBits {
assert!(
dest.len() == len,
"permutation length {} does not match slice length {len}",
dest.len()
);
let mut visited = VisitedBits::new(len);
for &d in dest {
assert!(d < len, "index {d} out of bounds for length {len}");
assert!(
!visited.test(d),
"duplicate index {d}: indices must form a permutation"
);
visited.set(d);
}
visited
}
#[doc(hidden)]
pub fn __argsort_to_dest(argsort: &[usize]) -> Vec<usize> {
let mut dest = alloc::vec![0usize; argsort.len()];
for (pos, &src) in argsort.iter().enumerate() {
dest[src] = pos;
}
dest
}
#[doc(hidden)]
pub fn __keyed_to_dest<K>(keyed: &[(K, usize)]) -> Vec<usize> {
let mut dest = alloc::vec![0usize; keyed.len()];
for (pos, (_, src)) in keyed.iter().enumerate() {
dest[*src] = pos;
}
dest
}
#[doc(hidden)]
pub unsafe fn __apply_permutation_inplace_unchecked<T>(
slice: &mut [T],
dest: &[usize],
visited: &mut VisitedBits,
) {
let len = slice.len();
visited.clear();
let base = slice.as_mut_ptr();
for start in 0..len {
if visited.test(start) {
continue;
}
visited.set(start);
let mut current = start;
unsafe {
let mut temp = core::ptr::read(base.add(start));
loop {
let next = *dest.get_unchecked(current);
if next == start {
core::ptr::write(base.add(start), temp);
break;
}
temp = core::ptr::replace(base.add(next), temp);
visited.set(next);
current = next;
}
}
}
}
#[doc(hidden)]
pub trait SoACursor {
type Item;
unsafe fn cursor_next(&mut self) -> Self::Item;
unsafe fn cursor_next_back(&mut self) -> Self::Item;
}
impl<'a, T> SoACursor for core::slice::Iter<'a, T> {
type Item = &'a T;
#[inline(always)]
unsafe fn cursor_next(&mut self) -> &'a T {
unsafe { self.next().unwrap_unchecked() }
}
#[inline(always)]
unsafe fn cursor_next_back(&mut self) -> &'a T {
unsafe { self.next_back().unwrap_unchecked() }
}
}
impl<'a, T> SoACursor for core::slice::IterMut<'a, T> {
type Item = &'a mut T;
#[inline(always)]
unsafe fn cursor_next(&mut self) -> &'a mut T {
unsafe { self.next().unwrap_unchecked() }
}
#[inline(always)]
unsafe fn cursor_next_back(&mut self) -> &'a mut T {
unsafe { self.next_back().unwrap_unchecked() }
}
}
pub trait SOA {
type Type;
}
pub trait SoAIter<'a> {
type Ref;
type RefMut;
type Iter: 'a + Iterator<Item = Self::Ref>;
type IterMut: 'a + Iterator<Item = Self::RefMut>;
}
mod private_soa_indexes {
use ::core::ops;
pub trait Sealed {}
impl Sealed for usize {} impl Sealed for ops::Range<usize> {} impl Sealed for ops::RangeTo<usize> {} impl Sealed for ops::RangeFrom<usize> {} impl Sealed for ops::RangeFull {} impl Sealed for ops::RangeInclusive<usize> {} impl Sealed for ops::RangeToInclusive<usize> {} }
pub trait SoAIndex<T>: private_soa_indexes::Sealed {
type RefOutput;
fn get(self, soa: T) -> Option<Self::RefOutput>;
unsafe fn get_unchecked(self, soa: T) -> Self::RefOutput;
fn index(self, soa: T) -> Self::RefOutput;
}
pub trait SoAIndexMut<T>: private_soa_indexes::Sealed {
type MutOutput;
fn get_mut(self, soa: T) -> Option<Self::MutOutput>;
unsafe fn get_unchecked_mut(self, soa: T) -> Self::MutOutput;
fn index_mut(self, soa: T) -> Self::MutOutput;
}
#[macro_export]
macro_rules! soa_zip {
($self: expr, [$($fields: tt)*] $(, $external: expr)* $(,)*) => {{
let this = $self;
$crate::soa_zip_impl!(@munch this, {$($fields)*} -> [] $($external ,)*)
}};
}
pub trait SoAPointers {
type Ptr;
type MutPtr;
}
mod generics {
use super::*;
pub trait SoASlice<T: SOA> {
type Ref<'t>
where
Self: 't;
type Slice<'t>: SoASlice<T>
+ IntoSoAIter<'t, T, Ref<'t> = Self::Ref<'t>>
where
Self: 't;
type Iter<'t>: Iterator<Item = Self::Ref<'t>>
where
Self: 't;
type Ptr;
fn len(&self) -> usize;
fn is_empty(&self) -> bool;
fn as_slice(&self) -> Self::Slice<'_>;
fn slice<'c, 'a: 'c>(
&'c self,
index: impl core::ops::RangeBounds<usize>,
) -> Self::Slice<'c>
where
Self: 'a;
fn get(&self, index: usize) -> Option<Self::Ref<'_>>;
fn index(&self, index: usize) -> Self::Ref<'_>;
fn iter(&self) -> Self::Iter<'_>;
fn first(&self) -> Option<Self::Ref<'_>> {
self.get(0)
}
fn last(&self) -> Option<Self::Ref<'_>> {
self.get(self.len().saturating_sub(1))
}
fn as_ptr(&self) -> Self::Ptr;
}
pub trait SoASliceMut<T: SOA> {
type Ref<'t>
where
Self: 't;
type Slice<'t>: SoASlice<T>
+ IntoSoAIter<'t, T, Ref<'t> = Self::Ref<'t>>
where
Self: 't;
type Iter<'t>: Iterator<Item = Self::Ref<'t>>
where
Self: 't;
type Ptr;
type RefMut<'t>
where
Self: 't;
type SliceMut<'t>: SoASliceMut<T>
where
Self: 't;
type IterMut<'t>: Iterator<Item = Self::RefMut<'t>>
where
Self: 't;
type PtrMut;
fn len(&self) -> usize;
fn is_empty(&self) -> bool;
fn as_slice(&self) -> Self::Slice<'_>;
fn slice<'c, 'a: 'c>(
&'c self,
index: impl core::ops::RangeBounds<usize>,
) -> Self::Slice<'c>
where
Self: 'a;
fn get(&self, index: usize) -> Option<Self::Ref<'_>>;
fn index(&self, index: usize) -> Self::Ref<'_>;
fn iter(&self) -> Self::Iter<'_>;
fn first(&self) -> Option<Self::Ref<'_>> {
self.get(0)
}
fn last(&self) -> Option<Self::Ref<'_>> {
self.get(self.len().saturating_sub(1))
}
fn as_ptr(&self) -> Self::Ptr;
fn as_mut_slice<'c: 'b, 'b>(&'c mut self) -> Self::SliceMut<'c>
where
Self: 'b;
fn slice_mut(
&mut self,
index: impl core::ops::RangeBounds<usize>,
) -> Self::SliceMut<'_>;
fn get_mut(&mut self, index: usize) -> Option<Self::RefMut<'_>>;
fn index_mut(&mut self, index: usize) -> Self::RefMut<'_>;
fn iter_mut(&mut self) -> Self::IterMut<'_>;
fn apply_index(&mut self, indices: &[usize]);
fn sort_by<F>(&mut self, mut f: F)
where
F: FnMut(Self::Ref<'_>, Self::Ref<'_>) -> core::cmp::Ordering,
{
let mut permutation: Vec<usize> = (0..self.len()).collect();
permutation.sort_by(|j, k| f(self.index(*j), self.index(*k)));
self.apply_index(&permutation);
}
fn sort_by_key<F, K>(&mut self, mut f: F)
where
F: FnMut(Self::Ref<'_>) -> K,
K: Ord,
{
let mut permutation: Vec<usize> = (0..self.len()).collect();
permutation.sort_by_key(|j| f(self.index(*j)));
self.apply_index(&permutation);
}
fn first_mut(&mut self) -> Option<Self::RefMut<'_>> {
self.get_mut(0)
}
fn last_mut(&mut self) -> Option<Self::RefMut<'_>> {
self.get_mut(self.len().saturating_sub(1))
}
fn as_mut_ptr(&mut self) -> Self::PtrMut;
}
pub trait SoAVec<T: SOA> {
type Ref<'t>
where
Self: 't;
type Slice<'t>: SoASlice<T> + IntoSoAIter<'t, T>
where
Self: 't;
type Iter<'t>: Iterator<Item = Self::Ref<'t>>
where
Self: 't;
type Ptr;
type RefMut<'t>
where
Self: 't;
type SliceMut<'t>: SoASliceMut<T>
where
Self: 't;
type IterMut<'t>: Iterator<Item = Self::RefMut<'t>>
where
Self: 't;
type PtrMut;
fn len(&self) -> usize;
fn is_empty(&self) -> bool;
fn as_slice<'c, 'a: 'c>(&'c self) -> Self::Slice<'c>
where
Self: 'a;
fn slice<'c, 'a: 'c>(
&'c self,
index: impl core::ops::RangeBounds<usize>,
) -> Self::Slice<'c>
where
Self: 'a;
fn get(&self, index: usize) -> Option<Self::Ref<'_>>;
fn index(&self, index: usize) -> Self::Ref<'_>;
fn iter(&self) -> Self::Iter<'_>;
fn first(&self) -> Option<Self::Ref<'_>> {
self.get(0)
}
fn last(&self) -> Option<Self::Ref<'_>> {
self.get(self.len().saturating_sub(1))
}
fn as_ptr(&self) -> Self::Ptr;
fn as_mut_slice<'c, 'a: 'c>(&'c mut self) -> Self::SliceMut<'c>
where
Self: 'a;
fn slice_mut(
&mut self,
index: impl core::ops::RangeBounds<usize>,
) -> Self::SliceMut<'_>;
fn get_mut(&mut self, index: usize) -> Option<Self::RefMut<'_>>;
fn index_mut(&mut self, index: usize) -> Self::RefMut<'_>;
fn iter_mut(&mut self) -> Self::IterMut<'_>;
fn apply_index(&mut self, indices: &[usize]);
fn sort_by<F>(&mut self, mut f: F)
where
F: FnMut(Self::Ref<'_>, Self::Ref<'_>) -> core::cmp::Ordering,
{
let mut permutation: Vec<usize> = (0..self.len()).collect();
permutation.sort_by(|j, k| f(self.index(*j), self.index(*k)));
self.apply_index(&permutation);
}
fn sort_by_key<F, K>(&mut self, mut f: F)
where
F: FnMut(Self::Ref<'_>) -> K,
K: Ord,
{
let mut permutation: Vec<usize> = (0..self.len()).collect();
permutation.sort_by_key(|j| f(self.index(*j)));
self.apply_index(&permutation);
}
fn first_mut(&mut self) -> Option<Self::RefMut<'_>> {
self.get_mut(0)
}
fn last_mut(&mut self) -> Option<Self::RefMut<'_>> {
self.get_mut(self.len().saturating_sub(1))
}
fn as_mut_ptr(&mut self) -> Self::PtrMut;
fn new() -> Self;
fn with_capacity(capacity: usize) -> Self;
fn capacity(&self) -> usize;
fn reserve(&mut self, additional: usize);
fn reserve_exact(&mut self, additional: usize);
fn shrink_to_fit(&mut self);
fn truncate(&mut self, len: usize);
fn push(&mut self, value: T);
fn swap_remove(&mut self, index: usize) -> T;
fn insert(&mut self, index: usize, element: T);
fn replace(&mut self, index: usize, element: T) -> T;
fn remove(&mut self, index: usize) -> T;
fn pop(&mut self) -> Option<T>;
fn append(&mut self, other: &mut Self);
fn clear(&mut self);
fn split_off(&mut self, at: usize) -> Self;
}
pub trait ToSoAVec<T: SOA> {
type SoAVecType: SoAVec<T>;
fn to_vec(&self) -> Self::SoAVecType;
}
pub trait SoAAppendVec<T: SOA>: SoAVec<T> {
fn extend_from_slice(&mut self, other: Self::Slice<'_>);
}
pub trait IntoSoAIter<'a, T: SOA>:
SoASlice<T> + IntoIterator<Item = Self::Ref<'a>> + 'a
{
}
}
pub use generics::*;
#[macro_export]
#[doc(hidden)]
macro_rules! soa_zip_impl {
(@flatten $p:pat => $tup:expr ) => {
|$p| $tup
};
(@flatten $p:pat => ( $($tup:tt)* ) , $_iter:expr $( , $tail:expr )* ) => {
$crate::soa_zip_impl!(@flatten ($p, a) => ( $($tup)*, a ) $( , $tail )*)
};
(@last , $first: expr, $($tail: expr,)*) => {
::core::iter::IntoIterator::into_iter($first)
$(
.zip($tail)
)*
.map(
$crate::soa_zip_impl!(@flatten a => (a) $( , $tail )*)
)
};
(@munch $self: expr, {mut $field: ident} -> [$($output: tt)*] $($ext: expr ,)*) => {
$crate::soa_zip_impl!(@last $($output)*, $self.$field.iter_mut(), $($ext, )*)
};
(@munch $self: expr, {$field: ident} -> [$($output: tt)*] $($ext: expr ,)*) => {
$crate::soa_zip_impl!(@last $($output)*, $self.$field.iter(), $($ext, )*)
};
(@munch $self: expr, {mut $field: ident, $($tail: tt)*} -> [$($output: tt)*] $($ext: expr ,)*) => {
$crate::soa_zip_impl!(@munch $self, {$($tail)*} -> [$($output)*, $self.$field.iter_mut()] $($ext, )*)
};
(@munch $self: expr, {$field: ident, $($tail: tt)*} -> [$($output: tt)*] $($ext: expr ,)*) => {
$crate::soa_zip_impl!(@munch $self, {$($tail)*} -> [$($output)*, $self.$field.iter()] $($ext, )*)
};
}