use std::{
ops::IndexMut,
hash::Hash,
collections::HashSet,
slice::Iter,
iter::Copied,
};
use crate::{
indexed_type::Unindexed,
mutable::iter::{
SeqSelectIndicesMutIter, SeqSelectIndicesUncheckedMutIter,
},
};
pub unsafe trait OneToOne<Idx> : IndexMut<Idx> {}
unsafe impl<T> OneToOne<usize> for [T] {}
unsafe impl<T, const N: usize> OneToOne<usize> for [T; N] {}
unsafe impl<T> OneToOne<usize> for Vec<T> {}
#[cfg(feature = "ndarray")]
mod ndarray {
use super::OneToOne;
use ::ndarray::{
prelude::*,
Dimension, DataMut,
NdIndex
};
unsafe impl<S, D, I> OneToOne<I> for ArrayBase<S, D>
where
S: DataMut,
D: Dimension,
I: NdIndex<D>,
{}
}
pub trait SelectIndicesMut<'a>
{
unsafe fn select_with_iter_mut_unchecked<Indices>(&'a mut self, indices: Indices) -> SeqSelectIndicesUncheckedMutIter<Self, Indices::IntoIter, Unindexed>
where
Indices: IntoIterator,
Indices::Item: Copy,
Self: IndexMut<Indices::Item>,
{
SeqSelectIndicesUncheckedMutIter {
data: self,
indices: indices.into_iter(),
visited_refs: (),
_phantom: Default::default(),
}
}
unsafe fn select_indices_mut_unchecked<Idx>(&'a mut self, indices: &'a [Idx]) -> SeqSelectIndicesUncheckedMutIter<Self, Copied<Iter<'a, Idx>>, Unindexed>
where
Self:IndexMut<Idx>,
Idx: Copy,
{
self.select_with_iter_mut_unchecked(indices.iter().copied())
}
fn select_indices_mut<Idx>(&'a mut self, indices: &'a [Idx]) -> SeqSelectIndicesUncheckedMutIter<Self, Copied<Iter<'a, Idx>>, Unindexed>
where
Self: OneToOne<Idx>,
Idx: Sized + Eq + Hash + Copy,
{
{
let index_check: HashSet<Idx> = indices.iter().copied().collect();
assert!(
index_check.len() == indices.len(),
"par_select_indices_mut was passed duplicate indices!",
)
}
unsafe { self.select_with_iter_mut_unchecked(indices.iter().copied()) }
}
fn select_with_iter_mut<Indices>(&'a mut self, indices: Indices) -> SeqSelectIndicesMutIter<Self, Indices::IntoIter, Unindexed>
where
Indices: IntoIterator,
Indices::Item: Copy + Hash + Eq,
Self: OneToOne<Indices::Item>,
{
let index_iter = indices.into_iter();
let size = index_iter.size_hint();
let size = size.1.unwrap_or(size.0);
SeqSelectIndicesMutIter {
data: self,
indices: index_iter,
visited_refs: HashSet::with_capacity(size),
_phantom: Default::default(),
}
}
}
impl<D> SelectIndicesMut<'_> for D
where
D: ?Sized,
{}
#[cfg(feature = "rayon")]
mod parallel {
use std::{
ops::IndexMut,
hash::Hash,
collections::HashSet,
};
use crate::{
indexed_type::Unindexed,
mutable::iter::{ ParSelectIndicesMutIter, ParSelectIndicesUncheckedMutIter },
};
use super::OneToOne;
use ::rayon::{
prelude::*,
slice::Iter,
iter::Copied,
};
pub trait ParSelectIndicesMut<'a>
{
unsafe fn par_select_with_iter_mut_unchecked<Indices>(&'a mut self, indices: Indices) -> ParSelectIndicesUncheckedMutIter<Self, Indices::Iter, Unindexed>
where
Indices: IntoParallelIterator,
Indices::Item: Copy,
Self: IndexMut<Indices::Item>,
{
ParSelectIndicesUncheckedMutIter {
data: self,
indices: indices.into_par_iter(),
visited_refs: (),
_phantom: Default::default(),
}
}
unsafe fn par_select_indices_mut_unchecked<Idx>(&'a mut self, indices: &'a [Idx]) -> ParSelectIndicesUncheckedMutIter<Self, Copied<Iter<'a, Idx>>, Unindexed>
where
Self: OneToOne<Idx>,
Idx: Copy + Sync + Send,
{
self.par_select_with_iter_mut_unchecked(indices.into_par_iter().copied())
}
fn par_select_indices_mut<Idx>(&'a mut self, indices: &'a [Idx]) -> ParSelectIndicesUncheckedMutIter<Self, Copied<Iter<'a, Idx>>, Unindexed>
where
Self: OneToOne<Idx>,
Idx: Copy + Hash + Eq + Sync + Send,
{
{
let index_check: HashSet<Idx> = indices.iter().copied().collect();
assert!(
index_check.len() == indices.len(),
"par_select_indices_mut was passed duplicate indices!",
)
}
unsafe { self.par_select_with_iter_mut_unchecked(indices.into_par_iter().copied()) }
}
fn par_select_with_iter_mut<Indices>(&'a mut self, indices: Indices) -> ParSelectIndicesMutIter<Self, Indices::Iter, Unindexed>
where
Indices: IntoParallelIterator,
Indices::Item: Copy,
Self: IndexMut<Indices::Item>,
{
ParSelectIndicesMutIter {
data: self,
indices: indices.into_par_iter(),
visited_refs: Default::default(),
_phantom: Default::default(),
}
}
}
impl<D> ParSelectIndicesMut<'_> for D
where
D: ?Sized
{}
}
#[cfg(feature = "rayon")]
pub use self::parallel::ParSelectIndicesMut;