use super::*;
use std::convert::{AsMut, AsRef};
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct UniChunked<S, N> {
pub data: S,
pub chunk_size: N,
}
impl<T: bytemuck::Pod, N: Default + Array<T>> UniChunked<Vec<T>, U<N>> {
#[inline]
pub fn from_array_vec(data: Vec<N::Array>) -> UniChunked<Vec<T>, U<N>> {
UniChunked {
chunk_size: Default::default(),
data: unsafe { reinterpret::reinterpret_vec(data) },
}
}
}
impl<'a, T: bytemuck::Pod, N: Default + Array<T>> UniChunked<&'a [T], U<N>> {
#[inline]
pub fn from_array_slice(data: &[N::Array]) -> UniChunked<&[T], U<N>> {
UniChunked {
chunk_size: Default::default(),
data: bytemuck::cast_slice(data),
}
}
}
impl<'a, T: bytemuck::Pod, N: Default + Array<T>> UniChunked<&'a mut [T], U<N>> {
#[inline]
pub fn from_array_slice_mut(data: &'a mut [N::Array]) -> UniChunked<&'a mut [T], U<N>> {
UniChunked {
chunk_size: Default::default(),
data: bytemuck::cast_slice_mut(data),
}
}
}
impl<S, N: Copy> UniChunked<S, N> {
#[inline]
pub fn view<'a>(&'a self) -> UniChunked<S::Type, N>
where
S: View<'a>,
{
UniChunked {
data: self.data.view(),
chunk_size: self.chunk_size,
}
}
#[inline]
fn view_mut<'a>(&'a mut self) -> UniChunked<S::Type, N>
where
S: ViewMut<'a>,
{
UniChunked {
data: self.data.view_mut(),
chunk_size: self.chunk_size,
}
}
}
impl<S, N> UniChunked<S, U<N>>
where
S: Set,
N: Array<<S as Set>::Elem>,
<S as Set>::Elem: bytemuck::Pod,
{
#[inline]
pub fn into_arrays(self) -> S::Output
where
S: ReinterpretAsGrouped<N>,
{
ReinterpretAsGrouped::<N>::reinterpret_as_grouped(self.into_inner())
}
#[inline]
pub fn as_mut_arrays<'a>(&'a mut self) -> <&'a mut S as ReinterpretAsGrouped<N>>::Output
where
&'a mut S: ReinterpretAsGrouped<N>,
{
ReinterpretAsGrouped::<N>::reinterpret_as_grouped(self.data_mut())
}
#[inline]
pub fn as_arrays<'a>(&'a self) -> <&'a S as ReinterpretAsGrouped<N>>::Output
where
&'a S: ReinterpretAsGrouped<N>,
{
ReinterpretAsGrouped::<N>::reinterpret_as_grouped(self.data())
}
}
impl<T: Clone + bytemuck::Pod, N: Array<T> + Unsigned> From<UniChunked<Vec<T>, U<N>>>
for Vec<N::Array>
{
#[inline]
fn from(val: UniChunked<Vec<T>, U<N>>) -> Self {
val.into_arrays()
}
}
impl<'a, T: Clone + bytemuck::Pod, N: Array<T> + Unsigned> From<UniChunked<&'a [T], U<N>>>
for &'a [N::Array]
{
#[inline]
fn from(val: UniChunked<&'a [T], U<N>>) -> Self {
val.into_arrays()
}
}
impl<'a, T: Clone + bytemuck::Pod, N: Array<T> + Unsigned> From<UniChunked<&'a mut [T], U<N>>>
for &'a mut [N::Array]
{
#[inline]
fn from(val: UniChunked<&'a mut [T], U<N>>) -> Self {
val.into_arrays()
}
}
pub type ChunkedN<S> = UniChunked<S, usize>;
pub type Chunked9<S> = UniChunked<S, U9>;
pub type Chunked8<S> = UniChunked<S, U8>;
pub type Chunked7<S> = UniChunked<S, U7>;
pub type Chunked6<S> = UniChunked<S, U6>;
pub type Chunked5<S> = UniChunked<S, U5>;
pub type Chunked4<S> = UniChunked<S, U4>;
pub type Chunked3<S> = UniChunked<S, U3>;
pub type Chunked2<S> = UniChunked<S, U2>;
pub type Chunked1<S> = UniChunked<S, U1>;
pub trait Dimension: Copy {
fn value(self) -> usize;
}
impl<N: Unsigned + Copy> Dimension for U<N> {
#[inline]
fn value(self) -> usize {
N::to_usize()
}
}
impl Dimension for usize {
#[inline]
fn value(self) -> usize {
self
}
}
impl<S, N: Dimension> ChunkSize for UniChunked<S, N> {
#[inline]
fn chunk_size(&self) -> usize {
self.chunk_size.value()
}
}
impl<S: ChunkSize, N: Dimension> UniChunked<S, N> {
#[inline]
pub fn inner_chunk_size(&self) -> usize {
self.data.chunk_size()
}
}
impl<S, N> UniChunked<S, N> {
#[inline]
pub fn data(&self) -> &S {
&self.data
}
#[inline]
pub fn data_mut(&mut self) -> &mut S {
&mut self.data
}
}
impl<S: Default, N: Default> UniChunked<S, U<N>> {
#[inline]
pub fn new() -> Self {
UniChunked {
chunk_size: Default::default(), data: S::default(),
}
}
}
impl<S: Set, N: Unsigned + Default> UniChunked<S, U<N>> {
#[inline]
pub fn from_flat(data: S) -> Self {
assert_eq!(data.len() % N::to_usize(), 0);
UniChunked {
chunk_size: Default::default(), data,
}
}
}
impl<S, N> UniChunked<S, N> {
#[inline]
pub fn into_inner(self) -> S {
self.data
}
}
impl<S: Default> ChunkedN<S> {
#[inline]
pub fn with_stride(n: usize) -> Self {
UniChunked {
chunk_size: n,
data: S::default(),
}
}
}
impl<S: Set> ChunkedN<S> {
#[inline]
pub fn from_flat_with_stride(n: usize, data: S) -> Self {
assert_eq!(data.len() % n, 0);
UniChunked {
chunk_size: n,
data,
}
}
}
impl<S, N> UniChunked<S, N> {
pub fn copy_from_flat<T>(&mut self, src: &[T])
where
T: Copy,
S: AsMut<[T]>,
{
let data = self.data.as_mut();
assert_eq!(src.len(), data.len());
data.copy_from_slice(src);
}
pub fn clone_from_flat<T>(&mut self, src: &[T])
where
T: Clone,
S: AsMut<[T]>,
{
let data = self.data.as_mut();
assert_eq!(src.len(), data.len());
data.clone_from_slice(src);
}
}
impl<S, N> UniChunked<S, U<N>>
where
S: Set + UniChunkable<N>,
N: Unsigned,
{
pub fn copy_from_arrays(&mut self, src: &[N::Array])
where
N: Array<<S as Set>::Elem>,
<S as Set>::Elem: Copy + bytemuck::Pod,
S: AsMut<[<S as Set>::Elem]>,
{
assert_eq!(src.len(), self.len());
self.data
.as_mut()
.copy_from_slice(bytemuck::cast_slice(src));
}
pub fn clone_from_arrays(&mut self, src: &[N::Array])
where
N: Array<<S as Set>::Elem>,
<S as Set>::Elem: Clone + bytemuck::Pod,
S: AsMut<[<S as Set>::Elem]>,
{
assert_eq!(src.len(), self.len());
self.data
.as_mut()
.clone_from_slice(bytemuck::cast_slice(src));
}
}
impl<T, N: Unsigned + Array<T>> UniChunked<Vec<T>, U<N>> {
pub fn reserve(&mut self, new_length: usize) {
self.data.reserve(new_length * N::to_usize());
}
}
impl<T> ChunkedN<Vec<T>> {
pub fn reserve(&mut self, new_length: usize) {
self.data.reserve(new_length * self.chunk_size);
}
}
impl<T, N: Unsigned + Array<T>> UniChunked<Vec<T>, U<N>>
where
<N as Array<T>>::Array: Clone,
{
pub fn resize(&mut self, new_length: usize, default: N::Array)
where
T: PushArrayToVec<N> + Clone,
{
self.reserve(new_length);
for _ in 0..new_length {
PushArrayToVec::<N>::push_to_vec(default, &mut self.data);
}
}
}
impl<T> ChunkedN<Vec<T>> {
pub fn resize(&mut self, new_length: usize, default: &[T])
where
T: Clone,
{
self.reserve(new_length);
for _ in 0..new_length {
self.data.extend_from_slice(default);
}
}
}
impl<T, N> UniChunked<Vec<T>, U<N>>
where
N: Array<T>,
T: Clone + bytemuck::Pod,
{
pub fn extend_from_slice(&mut self, slice: &[N::Array]) {
self.data.extend_from_slice(bytemuck::cast_slice(slice));
}
}
impl<S: Set + UniChunkable<N>, N: Unsigned> Set for UniChunked<S, U<N>> {
type Elem = S::Chunk;
type Atom = S::Atom;
#[inline]
fn len(&self) -> usize {
self.data.len() / N::to_usize()
}
}
impl<S: Set> Set for ChunkedN<S> {
type Elem = Vec<S::Elem>;
type Atom = S::Atom;
#[inline]
fn len(&self) -> usize {
self.data.len() / self.chunk_size
}
}
impl<'a, S, N> Push<<S as UniChunkable<N>>::Chunk> for UniChunked<S, U<N>>
where
N: Unsigned,
S: Set + UniChunkable<N> + PushChunk<N>,
{
#[inline]
fn push(&mut self, element: S::Chunk) {
self.data.push_chunk(element);
}
}
impl<S> Push<&[<S as Set>::Elem]> for ChunkedN<S>
where
S: Set + Push<<S as Set>::Elem>,
<S as Set>::Elem: Clone,
{
#[inline]
fn push(&mut self, element: &[<S as Set>::Elem]) {
for e in element {
self.data.push(e.clone());
}
}
}
impl<S, N> ExtendFromSlice for UniChunked<S, U<N>>
where
S: Set + ExtendFromSlice<Item = <S as Set>::Elem>,
N: Unsigned + Array<<S as Set>::Elem>,
<S as Set>::Elem: bytemuck::Pod,
{
type Item = N::Array;
fn extend_from_slice(&mut self, other: &[Self::Item]) {
self.data.extend_from_slice(bytemuck::cast_slice(other));
}
}
impl<S, N> IntoIterator for UniChunked<S, U<N>>
where
S: Set + IntoStaticChunkIterator<N>,
N: Unsigned,
{
type Item = <S as IntoStaticChunkIterator<N>>::Item;
type IntoIter = <S as IntoStaticChunkIterator<N>>::IterType;
#[inline]
fn into_iter(self) -> Self::IntoIter {
self.data.into_static_chunk_iter()
}
}
impl<S> IntoIterator for ChunkedN<S>
where
S: Set + IntoChunkIterator,
{
type Item = <S as IntoChunkIterator>::Item;
type IntoIter = <S as IntoChunkIterator>::IterType;
#[inline]
fn into_iter(self) -> Self::IntoIter {
self.data.into_chunk_iter(self.chunk_size)
}
}
impl<S, N> std::iter::FromIterator<S::Chunk> for UniChunked<S, U<N>>
where
N: Unsigned + Default,
S: Set + UniChunkable<N> + PushChunk<N> + Default,
{
#[inline]
fn from_iter<T>(iter: T) -> Self
where
T: IntoIterator<Item = S::Chunk>,
{
let mut s: UniChunked<S, U<N>> = UniChunked::default();
for elem in iter {
s.data.push_chunk(elem);
}
s
}
}
impl<S, N> std::iter::Extend<<Self as Set>::Elem> for UniChunked<S, U<N>>
where
N: Unsigned,
S: Set + UniChunkable<N> + PushChunk<N>,
{
fn extend<T>(&mut self, iter: T)
where
T: IntoIterator<Item = <Self as Set>::Elem>,
{
for i in iter {
self.data.push_chunk(i);
}
}
}
impl<S: Set + Default, N: Unsigned + Default> Default for UniChunked<S, U<N>> {
#[inline]
fn default() -> Self {
Self::from_flat(S::default())
}
}
pub trait ReinterpretAsGrouped<N> {
type Output;
fn reinterpret_as_grouped(self) -> Self::Output;
}
impl<'a, S, N, M> ReinterpretAsGrouped<N> for UniChunked<S, U<M>>
where
S: ReinterpretAsGrouped<M>,
<S as ReinterpretAsGrouped<M>>::Output: ReinterpretAsGrouped<N>,
{
type Output = <<S as ReinterpretAsGrouped<M>>::Output as ReinterpretAsGrouped<N>>::Output;
#[inline]
fn reinterpret_as_grouped(self) -> Self::Output {
self.data.reinterpret_as_grouped().reinterpret_as_grouped()
}
}
pub trait PushChunk<N>: UniChunkable<N> {
fn push_chunk(&mut self, chunk: Self::Chunk);
}
pub trait PushArrayTo<S, N>
where
S: Set,
N: Array<<S as Set>::Elem>,
{
fn push_to(element: N::Array, set: &mut S);
}
pub trait PushArrayToVec<N>
where
N: Array<Self>,
Self: Sized,
{
fn push_to_vec(element: N::Array, set: &mut Vec<Self>);
}
impl<S: Set + Push<<S as Set>::Elem>, N: Array<<S as Set>::Elem>> PushArrayTo<S, N> for S::Elem
where
<S as Set>::Elem: Clone,
{
#[inline]
fn push_to(element: N::Array, set: &mut S) {
for i in N::iter(&element) {
set.push(i.clone());
}
}
}
impl<T: Clone, N: Array<T>> PushArrayToVec<N> for T {
#[inline]
fn push_to_vec(element: N::Array, set: &mut Vec<T>) {
set.extend_from_slice(N::as_slice(&element));
}
}
impl<S: Set + ReinterpretAsGrouped<N>, N: Array<<S as Set>::Elem> + Unsigned> AsRef<[N::Array]>
for UniChunked<S, U<N>>
where
<S as ReinterpretAsGrouped<N>>::Output: AsRef<[N::Array]>,
S: AsRef<[<S as Set>::Elem]>,
<S as Set>::Elem: bytemuck::Pod,
{
#[inline]
fn as_ref(&self) -> &[N::Array] {
ReinterpretAsGrouped::<N>::reinterpret_as_grouped(self.data.as_ref())
}
}
impl<S, N> IntoOwned for UniChunked<S, N>
where
S: IntoOwned,
N: Copy,
{
type Owned = UniChunked<<S as IntoOwned>::Owned, N>;
#[inline]
fn into_owned(self) -> Self::Owned {
UniChunked {
data: self.data.into_owned(),
chunk_size: self.chunk_size,
}
}
}
impl<S, N> IntoOwnedData for UniChunked<S, N>
where
S: IntoOwnedData,
N: Copy,
{
type OwnedData = UniChunked<S::OwnedData, N>;
#[inline]
fn into_owned_data(self) -> Self::OwnedData {
let UniChunked { chunk_size, data } = self;
UniChunked {
chunk_size,
data: data.into_owned_data(),
}
}
}
impl<'a, S, N> GetIndex<'a, UniChunked<S, U<N>>> for usize
where
S: Set + UniChunkable<N> + Get<'a, StaticRange<N>>,
N: Unsigned,
{
type Output = S::Output;
#[inline]
fn get(self, chunked: &UniChunked<S, U<N>>) -> Option<Self::Output> {
if self < chunked.len() {
chunked.data.get(StaticRange::new(self * N::to_usize()))
} else {
None
}
}
}
impl<'a, S, N> GetIndex<'a, UniChunked<S, U<N>>> for &usize
where
S: Set + UniChunkable<N> + Get<'a, StaticRange<N>>,
N: Unsigned,
{
type Output = S::Output;
#[inline]
fn get(self, chunked: &UniChunked<S, U<N>>) -> Option<Self::Output> {
GetIndex::get(*self, chunked)
}
}
impl<'a, S, N> GetIndex<'a, UniChunked<S, U<N>>> for std::ops::Range<usize>
where
S: Set + UniChunkable<N> + Get<'a, std::ops::Range<usize>>,
N: Unsigned + Default,
{
type Output = UniChunked<S::Output, U<N>>;
#[inline]
fn get(self, chunked: &UniChunked<S, U<N>>) -> Option<Self::Output> {
if self.start <= self.end && self.end <= chunked.len() {
chunked
.data
.get(N::to_usize() * self.start..N::to_usize() * self.end)
.map(|data| UniChunked {
data,
chunk_size: Default::default(),
})
} else {
None
}
}
}
impl<'a, S, N, M> GetIndex<'a, UniChunked<S, U<M>>> for StaticRange<N>
where
S: Set,
M: Unsigned,
N: Unsigned + std::ops::Mul<M>,
StaticRange<<N as std::ops::Mul<M>>::Output>: GetIndex<'a, S>,
{
type Output = UniChunked<<StaticRange<N::Output> as GetIndex<'a, S>>::Output, U<M>>;
#[inline]
fn get(self, chunked: &UniChunked<S, U<M>>) -> Option<Self::Output> {
let rng = StaticRange::<N::Output>::new(self.start * M::to_usize());
let UniChunked { data, chunk_size } = chunked;
GetIndex::get(rng, data).map(|data| UniChunked {
data,
chunk_size: *chunk_size,
})
}
}
impl<'a, S> GetIndex<'a, ChunkedN<S>> for usize
where
S: Set + Get<'a, std::ops::Range<usize>>,
{
type Output = S::Output;
#[inline]
fn get(self, chunked: &ChunkedN<S>) -> Option<Self::Output> {
if self < chunked.len() {
let stride = chunked.chunk_size;
chunked.data.get(std::ops::Range {
start: self * stride,
end: (self + 1) * stride,
})
} else {
None
}
}
}
impl<'a, S> GetIndex<'a, ChunkedN<S>> for std::ops::Range<usize>
where
S: Set + Get<'a, std::ops::Range<usize>>,
{
type Output = ChunkedN<S::Output>;
#[inline]
fn get(self, chunked: &ChunkedN<S>) -> Option<Self::Output> {
if self.start <= self.end && self.end <= chunked.len() {
let stride = chunked.chunk_size;
chunked
.data
.get(stride * self.start..stride * self.end)
.map(|data| UniChunked {
data,
chunk_size: stride,
})
} else {
None
}
}
}
impl<S, N> IsolateIndex<UniChunked<S, U<N>>> for usize
where
S: Set + Isolate<StaticRange<N>>,
N: Unsigned,
{
type Output = S::Output;
#[inline]
unsafe fn isolate_unchecked(self, chunked: UniChunked<S, U<N>>) -> Self::Output {
chunked
.data
.isolate_unchecked(StaticRange::new(self * N::to_usize()))
}
#[inline]
fn try_isolate(self, chunked: UniChunked<S, U<N>>) -> Option<Self::Output> {
if self * N::to_usize() < chunked.data.len() {
chunked
.data
.try_isolate(StaticRange::new(self * N::to_usize()))
} else {
None
}
}
}
impl<S, N> IsolateIndex<UniChunked<S, U<N>>> for std::ops::Range<usize>
where
S: Set + Isolate<std::ops::Range<usize>>,
N: Unsigned + Default,
{
type Output = UniChunked<S::Output, U<N>>;
#[inline]
unsafe fn isolate_unchecked(self, chunked: UniChunked<S, U<N>>) -> Self::Output {
UniChunked {
data: chunked
.data
.isolate_unchecked(N::to_usize() * self.start..self.end * N::to_usize()),
chunk_size: Default::default(),
}
}
#[inline]
fn try_isolate(self, chunked: UniChunked<S, U<N>>) -> Option<Self::Output> {
let data_end = self.end * N::to_usize();
if self.start <= self.end && data_end <= chunked.data.len() {
chunked
.data
.try_isolate(N::to_usize() * self.start..data_end)
.map(|data| UniChunked {
data,
chunk_size: Default::default(),
})
} else {
None
}
}
}
impl<S, N, M> IsolateIndex<UniChunked<S, U<M>>> for StaticRange<N>
where
S: Set,
M: Unsigned,
N: Unsigned + std::ops::Mul<M>,
StaticRange<<N as std::ops::Mul<M>>::Output>: IsolateIndex<S>,
{
type Output = UniChunked<<StaticRange<N::Output> as IsolateIndex<S>>::Output, U<M>>;
#[inline]
unsafe fn isolate_unchecked(self, set: UniChunked<S, U<M>>) -> Self::Output {
let rng = StaticRange::<N::Output>::new(self.start * M::to_usize());
let UniChunked { data, chunk_size } = set;
UniChunked {
data: IsolateIndex::isolate_unchecked(rng, data),
chunk_size,
}
}
#[inline]
fn try_isolate(self, set: UniChunked<S, U<M>>) -> Option<Self::Output> {
let rng = StaticRange::<N::Output>::new(self.start * M::to_usize());
let UniChunked { data, chunk_size } = set;
IsolateIndex::try_isolate(rng, data).map(|data| UniChunked { data, chunk_size })
}
}
impl<S> IsolateIndex<ChunkedN<S>> for usize
where
S: Set + Isolate<std::ops::Range<usize>>,
{
type Output = S::Output;
#[inline]
unsafe fn isolate_unchecked(self, chunked: ChunkedN<S>) -> Self::Output {
let stride = chunked.chunk_size;
chunked.data.isolate_unchecked(std::ops::Range {
start: self * stride,
end: (self + 1) * stride,
})
}
#[inline]
fn try_isolate(self, chunked: ChunkedN<S>) -> Option<Self::Output> {
if self < chunked.len() {
let stride = chunked.chunk_size;
chunked.data.try_isolate(std::ops::Range {
start: self * stride,
end: (self + 1) * stride,
})
} else {
None
}
}
}
impl<S> IsolateIndex<ChunkedN<S>> for std::ops::Range<usize>
where
S: Set + Isolate<std::ops::Range<usize>>,
{
type Output = ChunkedN<S::Output>;
#[inline]
unsafe fn isolate_unchecked(self, chunked: ChunkedN<S>) -> Self::Output {
let stride = chunked.chunk_size;
UniChunked {
data: chunked
.data
.isolate_unchecked(stride * self.start..stride * self.end),
chunk_size: stride,
}
}
#[inline]
fn try_isolate(self, chunked: ChunkedN<S>) -> Option<Self::Output> {
if self.start <= self.end && self.end <= chunked.len() {
let stride = chunked.chunk_size;
chunked
.data
.try_isolate(stride * self.start..stride * self.end)
.map(|data| UniChunked {
data,
chunk_size: stride,
})
} else {
None
}
}
}
impl<T, N> std::ops::Index<usize> for UniChunked<Vec<T>, U<N>>
where
N: Unsigned + Array<T>,
T: bytemuck::Pod,
{
type Output = N::Array;
#[inline]
fn index(&self, idx: usize) -> &Self::Output {
ReinterpretAsGrouped::<N>::reinterpret_as_grouped(&self.data).index(idx)
}
}
impl<T, N> std::ops::Index<usize> for UniChunked<&[T], U<N>>
where
N: Unsigned + Array<T>,
T: bytemuck::Pod,
{
type Output = N::Array;
#[inline]
fn index(&self, idx: usize) -> &Self::Output {
ReinterpretAsGrouped::<N>::reinterpret_as_grouped(self.data).index(idx)
}
}
impl<T, N> std::ops::Index<usize> for UniChunked<&mut [T], U<N>>
where
N: Unsigned + Array<T>,
T: bytemuck::Pod,
{
type Output = N::Array;
#[inline]
fn index(&self, idx: usize) -> &Self::Output {
ReinterpretAsGrouped::<N>::reinterpret_as_grouped(&*self.data).index(idx)
}
}
impl<T, N> std::ops::IndexMut<usize> for UniChunked<Vec<T>, U<N>>
where
N: Unsigned + Array<T>,
T: bytemuck::Pod,
{
#[inline]
fn index_mut(&mut self, idx: usize) -> &mut Self::Output {
ReinterpretAsGrouped::<N>::reinterpret_as_grouped(&mut self.data).index_mut(idx)
}
}
impl<T, N> std::ops::IndexMut<usize> for UniChunked<&mut [T], U<N>>
where
N: Unsigned + Array<T>,
T: bytemuck::Pod,
{
#[inline]
fn index_mut(&mut self, idx: usize) -> &mut Self::Output {
ReinterpretAsGrouped::<N>::reinterpret_as_grouped(&mut *self.data).index_mut(idx)
}
}
impl<T> std::ops::Index<usize> for ChunkedN<Vec<T>> {
type Output = [T];
#[inline]
fn index(&self, idx: usize) -> &Self::Output {
let begin = self.chunk_size * idx;
self.data.index(begin..begin + self.chunk_size)
}
}
impl<T> std::ops::Index<usize> for ChunkedN<&[T]> {
type Output = [T];
#[inline]
fn index(&self, idx: usize) -> &Self::Output {
let begin = self.chunk_size * idx;
self.data.index(begin..begin + self.chunk_size)
}
}
impl<T> std::ops::Index<usize> for ChunkedN<&mut [T]> {
type Output = [T];
#[inline]
fn index(&self, idx: usize) -> &Self::Output {
let begin = self.chunk_size * idx;
self.data.index(begin..begin + self.chunk_size)
}
}
impl<T> std::ops::IndexMut<usize> for ChunkedN<Vec<T>> {
#[inline]
fn index_mut(&mut self, idx: usize) -> &mut Self::Output {
let begin = self.chunk_size * idx;
self.data.index_mut(begin..begin + self.chunk_size)
}
}
impl<T> std::ops::IndexMut<usize> for ChunkedN<&mut [T]> {
#[inline]
fn index_mut(&mut self, idx: usize) -> &mut Self::Output {
let begin = self.chunk_size * idx;
self.data.index_mut(begin..begin + self.chunk_size)
}
}
impl<S, N> UniChunked<S, U<N>>
where
N: Unsigned,
{
#[inline]
pub fn iter<'a>(&'a self) -> <S::Type as IntoStaticChunkIterator<N>>::IterType
where
S: View<'a>,
<S as View<'a>>::Type: IntoStaticChunkIterator<N>,
{
self.data.view().into_static_chunk_iter()
}
#[inline]
pub fn iter_mut<'a>(&'a mut self) -> <S::Type as IntoStaticChunkIterator<N>>::IterType
where
S: ViewMut<'a>,
<S as ViewMut<'a>>::Type: IntoStaticChunkIterator<N>,
{
self.data.view_mut().into_static_chunk_iter()
}
}
impl<'a, S, N> ViewIterator<'a> for UniChunked<S, U<N>>
where
S: View<'a>,
<S as View<'a>>::Type: IntoStaticChunkIterator<N>,
N: Unsigned,
{
type Item = <S::Type as IntoStaticChunkIterator<N>>::Item;
type Iter = <S::Type as IntoStaticChunkIterator<N>>::IterType;
#[inline]
fn view_iter(&'a self) -> Self::Iter {
self.iter()
}
}
impl<'a, S, N> ViewMutIterator<'a> for UniChunked<S, U<N>>
where
S: ViewMut<'a>,
<S as ViewMut<'a>>::Type: IntoStaticChunkIterator<N>,
N: Unsigned,
{
type Item = <S::Type as IntoStaticChunkIterator<N>>::Item;
type Iter = <S::Type as IntoStaticChunkIterator<N>>::IterType;
#[inline]
fn view_mut_iter(&'a mut self) -> Self::Iter {
self.iter_mut()
}
}
impl_atom_iterators_recursive!(impl<S, N> for UniChunked<S, N> { data });
pub struct Chunks<S> {
chunk_size: usize,
data: S,
}
impl<S> Iterator for Chunks<S>
where
S: SplitAt + Set + Dummy,
{
type Item = S;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
let data_slice = std::mem::replace(&mut self.data, unsafe { Dummy::dummy() });
if data_slice.is_empty() {
None
} else {
let n = std::cmp::min(data_slice.len(), self.chunk_size);
let (l, r) = data_slice.split_at(n);
self.data = r;
Some(l)
}
}
}
impl<S> ChunkedN<S> {
#[inline]
pub fn iter<'a>(&'a self) -> Chunks<S::Type>
where
S: View<'a>,
{
let UniChunked { chunk_size, data } = self;
Chunks {
chunk_size: *chunk_size,
data: data.view(),
}
}
#[inline]
pub fn iter_mut<'a>(&'a mut self) -> Chunks<S::Type>
where
S: ViewMut<'a>,
{
let UniChunked { chunk_size, data } = self;
Chunks {
chunk_size: *chunk_size,
data: data.view_mut(),
}
}
}
impl<'a, S, N> View<'a> for UniChunked<S, N>
where
S: View<'a>,
N: Copy,
{
type Type = UniChunked<<S as View<'a>>::Type, N>;
#[inline]
fn view(&'a self) -> Self::Type {
UniChunked::view(self)
}
}
impl<'a, S, N> ViewMut<'a> for UniChunked<S, N>
where
S: ViewMut<'a>,
N: Copy,
{
type Type = UniChunked<<S as ViewMut<'a>>::Type, N>;
#[inline]
fn view_mut(&'a mut self) -> Self::Type {
UniChunked::view_mut(self)
}
}
impl<'a, S> ViewIterator<'a> for ChunkedN<S>
where
S: View<'a>,
<S as View<'a>>::Type: SplitAt + Set + Dummy,
{
type Item = S::Type;
type Iter = Chunks<S::Type>;
#[inline]
fn view_iter(&'a self) -> Self::Iter {
self.iter()
}
}
impl<'a, S> ViewMutIterator<'a> for ChunkedN<S>
where
S: ViewMut<'a>,
<S as ViewMut<'a>>::Type: SplitAt + Set + Dummy,
{
type Item = S::Type;
type Iter = Chunks<S::Type>;
#[inline]
fn view_mut_iter(&'a mut self) -> Self::Iter {
self.iter_mut()
}
}
impl<S: SplitAt + Set, N: Copy + Unsigned> SplitAt for UniChunked<S, U<N>> {
#[inline]
fn split_at(self, mid: usize) -> (Self, Self) {
let UniChunked { data, chunk_size } = self;
let (l, r) = data.split_at(mid * N::to_usize());
(
UniChunked {
data: l,
chunk_size,
},
UniChunked {
data: r,
chunk_size,
},
)
}
}
impl<S: SplitAt + Set> SplitAt for ChunkedN<S> {
#[inline]
fn split_at(self, mid: usize) -> (Self, Self) {
let UniChunked { data, chunk_size } = self;
let (l, r) = data.split_at(mid * chunk_size);
(
UniChunked {
data: l,
chunk_size,
},
UniChunked {
data: r,
chunk_size,
},
)
}
}
impl<S: SplitPrefix<N> + Set, N: Copy> SplitFirst for UniChunked<S, U<N>> {
type First = S::Prefix;
#[inline]
fn split_first(self) -> Option<(Self::First, Self)> {
let UniChunked { data, chunk_size } = self;
data.split_prefix().map(|(prefix, rest)| {
(
prefix,
UniChunked {
data: rest,
chunk_size,
},
)
})
}
}
impl<S, N, M> SplitPrefix<M> for UniChunked<S, U<N>>
where
S: SplitPrefix<<N as std::ops::Mul<M>>::Output> + Set,
N: Unsigned + std::ops::Mul<M> + Copy,
M: Unsigned,
{
type Prefix = UniChunked<S::Prefix, U<N>>;
#[inline]
fn split_prefix(self) -> Option<(Self::Prefix, Self)> {
let UniChunked { data, chunk_size } = self;
data.split_prefix().map(|(prefix, rest)| {
(
UniChunked {
data: prefix,
chunk_size,
},
UniChunked {
data: rest,
chunk_size,
},
)
})
}
}
impl<S, M: Unsigned> SplitPrefix<M> for ChunkedN<S>
where
S: SplitAt + Set,
{
type Prefix = ChunkedN<S>;
#[inline]
fn split_prefix(self) -> Option<(Self::Prefix, Self)> {
let mid = self.chunk_size * M::to_usize();
if mid < self.len() {
Some(self.split_at(mid))
} else {
None
}
}
}
impl<S, M> UniChunkable<M> for ChunkedN<S> {
type Chunk = ChunkedN<S>; }
impl<S, N, M> UniChunkable<M> for UniChunked<S, U<N>>
where
S: UniChunkable<<N as std::ops::Mul<M>>::Output>,
N: std::ops::Mul<M>,
{
type Chunk = UniChunked<S::Chunk, U<N>>;
}
impl<S, M, N> PushChunk<M> for UniChunked<S, U<N>>
where
S: Set
+ PushChunk<<N as std::ops::Mul<M>>::Output>
+ UniChunkable<<N as std::ops::Mul<M>>::Output>,
N: std::ops::Mul<M>,
{
#[inline]
fn push_chunk(&mut self, chunk: Self::Chunk) {
self.data.push_chunk(chunk.data);
}
}
impl<S, N, M> IntoStaticChunkIterator<N> for UniChunked<S, M>
where
Self: Set + SplitPrefix<N> + Dummy,
N: Unsigned,
{
type Item = <Self as SplitPrefix<N>>::Prefix;
type IterType = UniChunkedIter<Self, N>;
#[inline]
fn into_static_chunk_iter(self) -> Self::IterType {
self.into_generic_static_chunk_iter()
}
}
pub struct UniChunkedIter<S, N> {
pub(crate) chunk_size: std::marker::PhantomData<N>,
pub(crate) data: S,
}
impl<S, N> Iterator for UniChunkedIter<S, N>
where
S: Set + SplitPrefix<N> + Dummy,
N: Unsigned,
{
type Item = S::Prefix;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
let data_slice = std::mem::replace(&mut self.data, unsafe { Dummy::dummy() });
data_slice.split_prefix().map(|(prefix, rest)| {
self.data = rest;
prefix
})
}
}
pub struct ChunkedNIter<S> {
pub(crate) chunk_size: usize,
pub(crate) data: S,
}
impl<S> Iterator for ChunkedNIter<S>
where
S: Set + SplitAt + Dummy,
{
type Item = S;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
if self.data.is_empty() {
return None;
}
let data_slice = std::mem::replace(&mut self.data, unsafe { Dummy::dummy() });
let (l, r) = data_slice.split_at(self.chunk_size);
self.data = r;
Some(l)
}
}
impl<S: Dummy, N: Default> Dummy for UniChunked<S, N> {
#[inline]
unsafe fn dummy() -> Self {
UniChunked {
data: Dummy::dummy(),
chunk_size: N::default(),
}
}
}
impl<S: Truncate, N: Unsigned> Truncate for UniChunked<S, U<N>> {
#[inline]
fn truncate(&mut self, new_len: usize) {
self.data.truncate(new_len * N::to_usize());
}
}
impl<S: Truncate> Truncate for ChunkedN<S> {
#[inline]
fn truncate(&mut self, new_len: usize) {
self.data.truncate(new_len * self.chunk_size);
}
}
impl<S: IntoStorage, N> IntoStorage for UniChunked<S, N> {
type StorageType = <S as IntoStorage>::StorageType;
#[inline]
fn into_storage(self) -> Self::StorageType {
self.data.into_storage()
}
}
impl<T, S: CloneWithStorage<T>, N: Clone> CloneWithStorage<T> for UniChunked<S, N> {
type CloneType = UniChunked<S::CloneType, N>;
#[inline]
fn clone_with_storage(&self, storage: T) -> Self::CloneType {
UniChunked {
chunk_size: self.chunk_size.clone(),
data: self.data.clone_with_storage(storage),
}
}
}
impl<'a, S: StorageView<'a>, N> StorageView<'a> for UniChunked<S, N> {
type StorageView = S::StorageView;
#[inline]
fn storage_view(&'a self) -> Self::StorageView {
self.data.storage_view()
}
}
impl<S: Storage, N> Storage for UniChunked<S, N> {
type Storage = S::Storage;
#[inline]
fn storage(&self) -> &Self::Storage {
self.data.storage()
}
}
impl<S: StorageMut, N> StorageMut for UniChunked<S, N> {
#[inline]
fn storage_mut(&mut self) -> &mut Self::Storage {
self.data.storage_mut()
}
}
impl<S: RemovePrefix, N: Unsigned> RemovePrefix for UniChunked<S, U<N>> {
#[inline]
fn remove_prefix(&mut self, n: usize) {
self.data.remove_prefix(n * N::to_usize());
}
}
impl<S: RemovePrefix> RemovePrefix for ChunkedN<S> {
#[inline]
fn remove_prefix(&mut self, n: usize) {
self.data.remove_prefix(n * self.chunk_size);
}
}
impl<S: Clear, N> Clear for UniChunked<S, N> {
#[inline]
fn clear(&mut self) {
self.data.clear();
}
}
impl<S: StorageInto<T>, N, T> StorageInto<T> for UniChunked<S, N> {
type Output = UniChunked<S::Output, N>;
#[inline]
fn storage_into(self) -> Self::Output {
UniChunked {
data: self.data.storage_into(),
chunk_size: self.chunk_size,
}
}
}
impl<S: MapStorage<Out>, N, Out> MapStorage<Out> for UniChunked<S, N> {
type Input = S::Input;
type Output = UniChunked<S::Output, N>;
#[inline]
fn map_storage<F: FnOnce(Self::Input) -> Out>(self, f: F) -> Self::Output {
UniChunked {
data: self.data.map_storage(f),
chunk_size: self.chunk_size,
}
}
}
impl<S: SwapChunks> SwapChunks for ChunkedN<S> {
#[inline]
fn swap_chunks(&mut self, begin_a: usize, begin_b: usize, chunk_size: usize) {
assert!(begin_a + chunk_size <= begin_b || begin_b + chunk_size <= begin_a);
self.data.swap_chunks(
self.chunk_size * begin_a,
self.chunk_size * begin_b,
self.chunk_size * chunk_size,
);
}
}
impl<S: SwapChunks, N: Unsigned> SwapChunks for UniChunked<S, U<N>> {
#[inline]
fn swap_chunks(&mut self, begin_a: usize, begin_b: usize, chunk_size: usize) {
assert!(begin_a + chunk_size <= begin_b || begin_b + chunk_size <= begin_a);
self.data.swap_chunks(
N::to_usize() * begin_a,
N::to_usize() * begin_b,
N::to_usize() * chunk_size,
);
}
}
impl<S: Set + SwapChunks> PermuteInPlace for ChunkedN<S> {
fn permute_in_place(&mut self, permutation: &[usize], seen: &mut [bool]) {
debug_assert_eq!(permutation.len(), self.len());
debug_assert!(seen.len() >= self.len());
debug_assert!(seen.iter().all(|&s| !s));
seen.iter_mut()
.enumerate()
.zip(permutation.iter())
.filter_map(|((i, s), &p)| if p == i { Some(s) } else { None })
.for_each(|s| *s = true);
for unseen_i in 0..seen.len() {
if seen[unseen_i] {
continue;
}
let mut i = unseen_i;
loop {
let idx = permutation[i];
if seen[idx] {
break;
}
self.data
.swap_chunks(self.chunk_size * i, self.chunk_size * idx, self.chunk_size);
seen[i] = true;
i = idx;
}
}
}
}
impl<S: Dummy, N: Unsigned + Default> PermuteInPlace for UniChunked<S, U<N>>
where
ChunkedN<S>: PermuteInPlace,
{
#[inline]
fn permute_in_place(&mut self, permutation: &[usize], seen: &mut [bool]) {
let data = std::mem::replace(&mut self.data, unsafe { Dummy::dummy() });
let mut chunked = UniChunked {
chunk_size: N::to_usize(),
data,
};
chunked.permute_in_place(permutation, seen);
self.data = chunked.data;
}
}
impl<T, S: CloneIntoOther<T>, N> CloneIntoOther<UniChunked<T, N>> for UniChunked<S, N> {
#[inline]
fn clone_into_other(&self, other: &mut UniChunked<T, N>) {
self.data.clone_into_other(&mut other.data);
}
}
impl<S: Reserve, N: Dimension> Reserve for UniChunked<S, N> {
#[inline]
fn reserve_with_storage(&mut self, n: usize, storage_n: usize) {
self.data
.reserve_with_storage(n * self.chunk_size(), storage_n);
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn unichunked_viewable() {
let mut s = Chunked2::from_flat(vec![0, 1, 2, 3]);
let mut v = (&mut s).into_view();
{
v.iter_mut().next().unwrap()[0] = 100;
}
let mut view_iter = v.iter();
assert_eq!(Some(&[100, 1]), view_iter.next());
assert_eq!(Some(&[2, 3]), view_iter.next());
assert_eq!(None, view_iter.next());
}
#[test]
fn unichunked_index() {
let s = Chunked3::from_flat(vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]);
assert_eq!([7, 8, 9], s[2]);
let s = Chunked3::from_flat(vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]);
assert_eq!([7, 8, 9], s.view()[2]);
let mut s = Chunked3::from_flat(vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]);
assert_eq!([7, 8, 9], s.view_mut()[2]);
let v = vec![1, 2, 3, 4, 5, 6, 0, 0, 0, 10, 11, 12];
let mut s = Chunked3::from_flat(v);
s[2] = [7, 8, 9];
assert_eq!(
vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12],
s.into_storage().to_vec()
);
let mut v = vec![1, 2, 3, 4, 5, 6, 0, 0, 0, 10, 11, 12];
let mut s = Chunked3::from_flat(v.as_mut_slice());
s[2] = [7, 8, 9];
assert_eq!(vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], v);
let s = ChunkedN::from_flat_with_stride(
3,
vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15],
);
assert_eq!([7, 8, 9], s[2]);
let s = ChunkedN::from_flat_with_stride(
3,
vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15],
);
assert_eq!([7, 8, 9], s.view()[2]);
let mut s = ChunkedN::from_flat_with_stride(
3,
vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15],
);
assert_eq!([7, 8, 9], s.view_mut()[2]);
let v = vec![1, 2, 3, 4, 5, 6, 0, 0, 0, 10, 11, 12];
let mut s = ChunkedN::from_flat_with_stride(3, v);
s[2].copy_from_slice(&[7, 8, 9]);
assert_eq!(
vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12],
s.into_storage().to_vec()
);
let mut v = vec![1, 2, 3, 4, 5, 6, 0, 0, 0, 10, 11, 12];
let mut s = ChunkedN::from_flat_with_stride(3, v.as_mut_slice());
s[2].copy_from_slice(&[7, 8, 9]);
assert_eq!(vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], v);
}
}