use super::*;
use std::convert::AsRef;
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct Subset<S, I = Box<[usize]>> {
pub(crate) indices: Option<I>,
pub(crate) data: S,
}
pub type SubsetView<'a, S> = Subset<S, &'a [usize]>;
impl<S, I> Subset<S, I> {
#[inline]
pub fn into_raw(self) -> (Option<I>, S) {
(self.indices, self.data)
}
#[inline]
pub unsafe fn from_raw(indices: Option<I>, data: S) -> Subset<S, I> {
Subset { indices, data }
}
}
impl<S: Set + RemovePrefix> Subset<S, Vec<usize>> {
pub fn from_indices(mut indices: Vec<usize>, mut data: S) -> Self {
indices.sort_unstable();
indices.dedup();
if let Some(first) = indices.first() {
data.remove_prefix(*first);
}
Self::validate(Subset {
indices: Some(indices),
data,
})
}
}
impl<S: Set + RemovePrefix, I: AsRef<[usize]>> Subset<S, I> {
pub fn from_unique_ordered_indices(indices: I, mut data: S) -> Self {
assert!(Self::is_sorted(&indices));
assert!(!Self::has_duplicates(&indices));
if let Some(first) = indices.as_ref().first() {
data.remove_prefix(*first);
}
Self::validate(Subset {
indices: Some(indices),
data,
})
}
}
impl<S> Subset<S> {
#[inline]
pub fn all<I>(data: S) -> Subset<S, I> {
Subset {
indices: None,
data,
}
}
#[inline]
pub fn all_def(data: S) -> Subset<S> {
Self::all(data)
}
}
impl<S: Set, I: AsRef<[usize]>> Subset<S, I> {
pub fn find_by_index(&self, index: usize) -> Option<usize> {
match &self.indices {
Some(indices) => indices.as_ref().binary_search(&index).ok(),
None => {
Some(index)
}
}
}
}
impl<'a, S, I: AsRef<[usize]>> Subset<S, I> {
fn has_duplicates(indices: &I) -> bool {
let mut index_iter = indices.as_ref().iter().cloned();
if let Some(mut prev) = index_iter.next() {
for cur in index_iter {
if cur == prev {
return true;
} else {
prev = cur;
}
}
}
false
}
#[inline]
fn is_sorted(indices: &I) -> bool {
Self::is_sorted_by(indices, |a, b| a.partial_cmp(b))
}
#[allow(clippy::while_let_on_iterator)]
fn is_sorted_by<F>(indices: &I, mut compare: F) -> bool
where
F: FnMut(&usize, &usize) -> Option<std::cmp::Ordering>,
{
let mut iter = indices.as_ref().iter();
let mut last = match iter.next() {
Some(e) => e,
None => return true,
};
while let Some(curr) = iter.next() {
if compare(last, curr)
.map(|o| o == std::cmp::Ordering::Greater)
.unwrap_or(true)
{
return false;
}
last = curr;
}
true
}
}
impl<'a, S: Set, I> Subset<S, I> {
#[inline]
pub fn indices(&self) -> Option<&I> {
self.indices.as_ref()
}
#[inline]
pub fn into_super(self) -> S {
self.data
}
}
impl<'a, S: Set, I: AsRef<[usize]>> Subset<S, I> {
#[inline]
fn validate(self) -> Self {
if let Some(ref indices) = self.indices {
let indices = indices.as_ref();
if let Some(first) = indices.first() {
for &i in indices.iter() {
assert!(i - *first < self.data.len(), "Subset index out of bounds.");
}
}
}
self
}
}
impl<S: Set, I: AsRef<[usize]>> Set for Subset<S, I> {
type Elem = S::Elem;
type Atom = S::Atom;
#[inline]
fn len(&self) -> usize {
self.indices
.as_ref()
.map_or(self.data.len(), |indices| indices.as_ref().len())
}
}
impl<'a, S, I> View<'a> for Subset<S, I>
where
S: View<'a>,
I: AsRef<[usize]>,
{
type Type = Subset<S::Type, &'a [usize]>;
#[inline]
fn view(&'a self) -> Self::Type {
Subset {
indices: self.indices.as_ref().map(|indices| indices.as_ref()),
data: self.data.view(),
}
}
}
impl<'a, S, I> ViewMut<'a> for Subset<S, I>
where
S: ViewMut<'a>,
I: AsRef<[usize]>,
{
type Type = Subset<S::Type, &'a [usize]>;
#[inline]
fn view_mut(&'a mut self) -> Self::Type {
Subset {
indices: self.indices.as_ref().map(|indices| indices.as_ref()),
data: self.data.view_mut(),
}
}
}
impl<V> SplitAt for SubsetView<'_, V>
where
V: Set + SplitAt,
{
#[inline]
fn split_at(self, mid: usize) -> (Self, Self) {
if let Some(indices) = self.indices {
let (indices_l, indices_r) = indices.split_at(mid);
let n = self.data.len();
let offset = indices_r
.first()
.map(|first| *first - *indices_l.first().unwrap_or(first))
.unwrap_or(n);
let (data_l, data_r) = self.data.split_at(offset);
(
Subset {
indices: Some(indices_l),
data: data_l,
},
Subset {
indices: Some(indices_r),
data: data_r,
},
)
} else {
let (data_l, data_r) = self.data.split_at(mid);
(
Subset {
indices: None,
data: data_l,
},
Subset {
indices: None,
data: data_r,
},
)
}
}
}
impl<S, I> SplitFirst for Subset<S, I>
where
I: SplitFirst + AsRef<[usize]>,
<I as SplitFirst>::First: std::borrow::Borrow<usize>,
S: Set + SplitAt + SplitFirst,
{
type First = S::First;
#[inline]
fn split_first(self) -> Option<(Self::First, Self)> {
use std::borrow::Borrow;
let Subset { data, indices } = self;
if let Some(indices) = indices {
indices.split_first().map(|(first_index, rest_indices)| {
let n = data.len();
let offset = rest_indices
.as_ref()
.first()
.map(|next| *next - *first_index.borrow())
.unwrap_or(n);
let (data_l, data_r) = data.split_at(offset);
(
data_l.split_first().unwrap().0,
Subset {
indices: Some(rest_indices),
data: data_r,
},
)
})
} else {
data.split_first().map(|(first, rest)| {
(
first,
Subset {
indices: None,
data: rest,
},
)
})
}
}
}
impl<S: Set + RemovePrefix, I: RemovePrefix + AsRef<[usize]>> RemovePrefix for Subset<S, I> {
#[inline]
fn remove_prefix(&mut self, n: usize) {
if n == 0 {
return;
}
match self.indices {
Some(ref mut indices) => {
let first = indices.as_ref()[0]; indices.remove_prefix(n);
let data_len = self.data.len();
let next = indices.as_ref().get(0).unwrap_or(&data_len);
self.data.remove_prefix(*next - first);
}
None => {
self.data.remove_prefix(n);
}
}
}
}
impl<'a, S, I> Subset<S, I>
where
Self: Set + ViewIterator<'a>,
{
pub fn clone_into_other<V>(&'a self, other: &'a mut V)
where
V: Set + ViewMutIterator<'a> + ?Sized,
<Self as ViewIterator<'a>>::Item: CloneIntoOther<<V as ViewMutIterator<'a>>::Item>,
{
assert_eq!(other.len(), self.len());
for (mut theirs, mine) in other.view_mut_iter().zip(self.view_iter()) {
mine.clone_into_other(&mut theirs);
}
}
}
impl<'a, S, O> GetIndex<'a, Subset<S, O>> for usize
where
O: AsRef<[usize]>,
S: Get<'a, usize>,
{
type Output = <S as Get<'a, usize>>::Output;
#[inline]
fn get(self, subset: &Subset<S, O>) -> Option<Self::Output> {
if let Some(ref indices) = subset.indices {
indices.as_ref().get(0).and_then(|&first| {
indices
.as_ref()
.get(self)
.and_then(|&cur| Get::get(&subset.data, cur - first))
})
} else {
Get::get(&subset.data, self)
}
}
}
impl<'a, S, O> GetIndex<'a, Subset<S, O>> for &usize
where
O: AsRef<[usize]>,
S: Get<'a, usize>,
{
type Output = <S as Get<'a, usize>>::Output;
#[inline]
fn get(self, subset: &Subset<S, O>) -> Option<Self::Output> {
GetIndex::get(*self, subset)
}
}
impl<S, O> IsolateIndex<Subset<S, O>> for usize
where
O: AsRef<[usize]>,
S: Isolate<usize>,
{
type Output = <S as Isolate<usize>>::Output;
#[inline]
unsafe fn isolate_unchecked(self, subset: Subset<S, O>) -> Self::Output {
let Subset { indices, data } = subset;
Isolate::isolate_unchecked(
data,
if let Some(ref indices) = indices {
let cur = indices.as_ref().get_unchecked(self);
let first = indices.as_ref().get_unchecked(0);
cur - first
} else {
self
},
)
}
#[inline]
fn try_isolate(self, subset: Subset<S, O>) -> Option<Self::Output> {
let Subset { indices, data } = subset;
Isolate::try_isolate(
data,
if let Some(ref indices) = indices {
let cur = indices.as_ref().get(self)?;
let first = unsafe { indices.as_ref().get_unchecked(0) };
cur - first
} else {
self
},
)
}
}
impl_isolate_index_for_static_range!(impl<S, O> for Subset<S, O>);
macro_rules! impl_index_fn {
($self:ident, $idx:ident, $index_fn:ident) => {
$self
.data
.$index_fn($self.indices.as_ref().map_or($idx, |indices| {
let indices = indices.as_ref();
indices[$idx] - *indices.first().unwrap()
}))
};
}
impl<'a, S, I> std::ops::Index<usize> for Subset<S, I>
where
S: std::ops::Index<usize> + Set + ValueType,
I: AsRef<[usize]>,
{
type Output = S::Output;
#[inline]
fn index(&self, idx: usize) -> &Self::Output {
impl_index_fn!(self, idx, index)
}
}
impl<'a, S, I> std::ops::IndexMut<usize> for Subset<S, I>
where
S: std::ops::IndexMut<usize> + Set + ValueType,
I: AsRef<[usize]>,
{
#[inline]
fn index_mut(&mut self, idx: usize) -> &mut Self::Output {
impl_index_fn!(self, idx, index_mut)
}
}
impl<'a, T, I> std::ops::Index<usize> for Subset<&'a [T], I>
where
I: AsRef<[usize]>,
{
type Output = T;
#[inline]
fn index(&self, idx: usize) -> &Self::Output {
impl_index_fn!(self, idx, index)
}
}
impl<'a, T, I> std::ops::Index<usize> for Subset<&'a mut [T], I>
where
I: AsRef<[usize]>,
{
type Output = T;
#[inline]
fn index(&self, idx: usize) -> &Self::Output {
impl_index_fn!(self, idx, index)
}
}
impl<'a, T, I> std::ops::IndexMut<usize> for Subset<&'a mut [T], I>
where
I: AsRef<[usize]>,
{
#[inline]
fn index_mut(&mut self, idx: usize) -> &mut Self::Output {
impl_index_fn!(self, idx, index_mut)
}
}
impl<S, I> IntoIterator for Subset<S, I>
where
S: SplitAt + SplitFirst + Set + Dummy,
I: SplitFirst + Clone,
<I as SplitFirst>::First: std::borrow::Borrow<usize>,
{
type Item = S::First;
type IntoIter = SubsetIter<S, I>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
SubsetIter {
indices: self.indices,
data: self.data,
}
}
}
pub struct SubsetIter<S, I> {
indices: Option<I>,
data: S,
}
impl<S, I> Iterator for SubsetIter<S, I>
where
S: SplitAt + SplitFirst + Set + Dummy,
I: SplitFirst + Clone,
<I as SplitFirst>::First: std::borrow::Borrow<usize>,
{
type Item = S::First;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
use std::borrow::Borrow;
let SubsetIter { indices, data } = self;
let data_slice = std::mem::replace(data, unsafe { Dummy::dummy() });
match indices {
Some(ref mut indices) => indices.clone().split_first().map(|(first, rest)| {
let (item, right) = data_slice.split_first().expect("Corrupt subset");
if let Some((second, _)) = rest.clone().split_first() {
let (_, r) = right.split_at(*second.borrow() - *first.borrow() - 1);
*data = r;
} else {
let n = right.len();
let (_, r) = right.split_at(n);
*data = r;
}
*indices = rest;
item
}),
None => data_slice.split_first().map(|(item, rest)| {
*data = rest;
item
}),
}
}
}
pub enum SubsetIndexIter<'a> {
All(std::ops::Range<usize>),
Sub(&'a [usize]),
}
impl<'a> Iterator for SubsetIndexIter<'a> {
type Item = usize;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
match self {
SubsetIndexIter::Sub(ref mut indices) => indices.split_first().map(|(first, rest)| {
*indices = rest;
*first
}),
SubsetIndexIter::All(ref mut rng) => rng.next(),
}
}
#[inline]
fn nth(&mut self, n: usize) -> Option<Self::Item> {
match self {
SubsetIndexIter::Sub(ref mut indices) => {
if n >= indices.len() {
None
} else {
unsafe {
let item = *indices.get_unchecked(n);
*indices = indices.get_unchecked(n + 1..);
Some(item)
}
}
}
SubsetIndexIter::All(ref mut rng) => rng.nth(n),
}
}
}
impl<'a, S, I> Subset<S, I>
where
S: Set + View<'a>,
I: AsRef<[usize]>,
{
#[inline]
pub fn iter(&'a self) -> SubsetIter<S::Type, &'a [usize]> {
SubsetIter {
indices: self.indices.as_ref().map(|indices| indices.as_ref()),
data: self.data.view(),
}
}
#[inline]
pub fn index_iter(&'a self) -> SubsetIndexIter<'a> {
match self.indices {
Some(ref indices) => SubsetIndexIter::Sub(indices.as_ref()),
None => SubsetIndexIter::All(0..self.data.len()),
}
}
}
impl<'a, S, I> Subset<S, I>
where
S: Set + ViewMut<'a>,
I: AsRef<[usize]>,
{
#[inline]
pub fn iter_mut(&'a mut self) -> SubsetIter<<S as ViewMut<'a>>::Type, &'a [usize]> {
SubsetIter {
indices: self.indices.as_ref().map(|indices| indices.as_ref()),
data: self.data.view_mut(),
}
}
}
impl<'a, S, I> ViewIterator<'a> for Subset<S, I>
where
S: Set + View<'a>,
I: AsRef<[usize]>,
<S as View<'a>>::Type: SplitAt + SplitFirst + Set + Dummy,
{
type Item = <<S as View<'a>>::Type as SplitFirst>::First;
type Iter = SubsetIter<S::Type, &'a [usize]>;
#[inline]
fn view_iter(&'a self) -> Self::Iter {
self.iter()
}
}
impl<'a, S, I> ViewMutIterator<'a> for Subset<S, I>
where
S: Set + ViewMut<'a>,
I: AsRef<[usize]>,
<S as ViewMut<'a>>::Type: SplitAt + SplitFirst + Set + Dummy,
{
type Item = <<S as ViewMut<'a>>::Type as SplitFirst>::First;
type Iter = SubsetIter<S::Type, &'a [usize]>;
#[inline]
fn view_mut_iter(&'a mut self) -> Self::Iter {
self.iter_mut()
}
}
impl<S: Dummy, I> Dummy for Subset<S, I> {
#[inline]
unsafe fn dummy() -> Self {
Subset {
data: Dummy::dummy(),
indices: None,
}
}
}
impl<S: Truncate, I: Truncate> Truncate for Subset<S, I> {
#[inline]
fn truncate(&mut self, new_len: usize) {
match &mut self.indices {
Some(indices) => indices.truncate(new_len),
None => self.data.truncate(new_len),
}
}
}
impl<S: StorageInto<T>, I, T> StorageInto<T> for Subset<S, I> {
type Output = Subset<S::Output, I>;
#[inline]
fn storage_into(self) -> Self::Output {
Subset {
data: self.data.storage_into(),
indices: self.indices,
}
}
}
impl<S: MapStorage<Out>, I, Out> MapStorage<Out> for Subset<S, I> {
type Input = S::Input;
type Output = Subset<S::Output, I>;
#[inline]
fn map_storage<F: FnOnce(Self::Input) -> Out>(self, f: F) -> Self::Output {
Subset {
data: self.data.map_storage(f),
indices: self.indices,
}
}
}
impl<'a, S: StorageView<'a>, I> StorageView<'a> for Subset<S, I> {
type StorageView = S::StorageView;
#[inline]
fn storage_view(&'a self) -> Self::StorageView {
self.data.storage_view()
}
}
impl<S: Storage, I> Storage for Subset<S, I> {
type Storage = S::Storage;
#[inline]
fn storage(&self) -> &Self::Storage {
self.data.storage()
}
}
impl<S: StorageMut, I> StorageMut for Subset<S, I> {
#[inline]
fn storage_mut(&mut self) -> &mut Self::Storage {
self.data.storage_mut()
}
}
impl<S: ChunkSize, I> ChunkSize for Subset<S, I> {
#[inline]
fn chunk_size(&self) -> usize {
self.data.chunk_size()
}
}
impl<S: ChunkSize, I, N: Dimension> Subset<UniChunked<S, N>, I> {
#[inline]
pub fn inner_chunk_size(&self) -> usize {
self.data.inner_chunk_size()
}
}
impl<S: IntoOwned, I: IntoOwned> IntoOwned for Subset<S, I> {
type Owned = Subset<S::Owned, I::Owned>;
#[inline]
fn into_owned(self) -> Self::Owned {
Subset {
indices: self.indices.map(|x| x.into_owned()),
data: self.data.into_owned(),
}
}
}
impl<S, I> IntoOwnedData for Subset<S, I>
where
S: IntoOwnedData,
{
type OwnedData = Subset<S::OwnedData, I>;
#[inline]
fn into_owned_data(self) -> Self::OwnedData {
Subset {
indices: self.indices,
data: self.data.into_owned_data(),
}
}
}
impl<S, I, M> UniChunkable<M> for Subset<S, I> {
type Chunk = Subset<S, I>;
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn subset_of_subsets_iter() {
let set = vec![1, 2, 3, 4, 5, 6];
let subset = Subset::from_unique_ordered_indices(vec![1, 3, 5], set);
let subsubset = Subset::from_unique_ordered_indices(vec![0, 2], subset);
let mut iter = subsubset.iter();
assert_eq!(Some(&2), iter.next());
assert_eq!(Some(&6), iter.next());
assert_eq!(None, iter.next());
}
}