use crate::{
Dim, Matrix, MatrixView, MatrixViewMut, RawStorage, RawStorageMut, Scalar, U1,
iter::{ColumnIter, ColumnIterMut},
};
use rayon::iter::plumbing::Producer;
use rayon::{iter::plumbing::bridge, prelude::*};
#[cfg_attr(docsrs, doc(cfg(feature = "rayon")))]
pub struct ParColumnIter<'a, T, R: Dim, Cols: Dim, S: RawStorage<T, R, Cols>> {
mat: &'a Matrix<T, R, Cols, S>,
}
impl<'a, T, R: Dim, Cols: Dim, S: RawStorage<T, R, Cols>> ParColumnIter<'a, T, R, Cols, S> {
fn new(matrix: &'a Matrix<T, R, Cols, S>) -> Self {
Self { mat: matrix }
}
}
#[cfg_attr(docsrs, doc(cfg(feature = "rayon")))]
impl<'a, T, R: Dim, Cols: Dim, S: RawStorage<T, R, Cols>> ParallelIterator
for ParColumnIter<'a, T, R, Cols, S>
where
T: Sync + Send + Scalar,
S: Sync,
{
type Item = MatrixView<'a, T, R, U1, S::RStride, S::CStride>;
fn drive_unindexed<Consumer>(self, consumer: Consumer) -> Consumer::Result
where
Consumer: rayon::iter::plumbing::UnindexedConsumer<Self::Item>,
{
bridge(self, consumer)
}
fn opt_len(&self) -> Option<usize> {
Some(self.mat.ncols())
}
}
#[cfg_attr(docsrs, doc(cfg(feature = "rayon")))]
impl<T, R: Dim, Cols: Dim, S: RawStorage<T, R, Cols>> IndexedParallelIterator
for ParColumnIter<'_, T, R, Cols, S>
where
T: Send + Sync + Scalar,
S: Sync,
{
fn len(&self) -> usize {
self.mat.ncols()
}
fn drive<C: rayon::iter::plumbing::Consumer<Self::Item>>(self, consumer: C) -> C::Result {
bridge(self, consumer)
}
fn with_producer<CB: rayon::iter::plumbing::ProducerCallback<Self::Item>>(
self,
callback: CB,
) -> CB::Output {
let producer = ColumnProducer(ColumnIter::new(self.mat));
callback.callback(producer)
}
}
#[cfg_attr(docsrs, doc(cfg(feature = "rayon")))]
pub struct ParColumnIterMut<
'a,
T,
R: Dim,
Cols: Dim,
S: RawStorage<T, R, Cols> + RawStorageMut<T, R, Cols>,
> {
mat: &'a mut Matrix<T, R, Cols, S>,
}
#[cfg_attr(docsrs, doc(cfg(feature = "rayon")))]
impl<'a, T, R, Cols, S> ParColumnIterMut<'a, T, R, Cols, S>
where
R: Dim,
Cols: Dim,
S: RawStorage<T, R, Cols> + RawStorageMut<T, R, Cols>,
{
fn new(mat: &'a mut Matrix<T, R, Cols, S>) -> Self {
Self { mat }
}
}
#[cfg_attr(docsrs, doc(cfg(feature = "rayon")))]
impl<'a, T, R, Cols, S> ParallelIterator for ParColumnIterMut<'a, T, R, Cols, S>
where
R: Dim,
Cols: Dim,
S: RawStorage<T, R, Cols> + RawStorageMut<T, R, Cols>,
T: Send + Sync + Scalar,
S: Send + Sync,
{
type Item = MatrixViewMut<'a, T, R, U1, S::RStride, S::CStride>;
fn drive_unindexed<C>(self, consumer: C) -> C::Result
where
C: rayon::iter::plumbing::UnindexedConsumer<Self::Item>,
{
bridge(self, consumer)
}
fn opt_len(&self) -> Option<usize> {
Some(self.mat.ncols())
}
}
#[cfg_attr(docsrs, doc(cfg(feature = "rayon")))]
impl<T, R, Cols, S> IndexedParallelIterator for ParColumnIterMut<'_, T, R, Cols, S>
where
R: Dim,
Cols: Dim,
S: RawStorage<T, R, Cols> + RawStorageMut<T, R, Cols>,
T: Send + Sync + Scalar,
S: Send + Sync,
{
fn drive<C: rayon::iter::plumbing::Consumer<Self::Item>>(self, consumer: C) -> C::Result {
bridge(self, consumer)
}
fn len(&self) -> usize {
self.mat.ncols()
}
fn with_producer<CB: rayon::iter::plumbing::ProducerCallback<Self::Item>>(
self,
callback: CB,
) -> CB::Output {
let producer = ColumnProducerMut(ColumnIterMut::new(self.mat));
callback.callback(producer)
}
}
#[cfg_attr(docsrs, doc(cfg(feature = "rayon")))]
impl<T, R: Dim, Cols: Dim, S: RawStorage<T, R, Cols>> Matrix<T, R, Cols, S>
where
T: Send + Sync + Scalar,
S: Sync,
{
pub fn par_column_iter(&self) -> ParColumnIter<'_, T, R, Cols, S> {
ParColumnIter::new(self)
}
pub fn par_column_iter_mut(&mut self) -> ParColumnIterMut<'_, T, R, Cols, S>
where
S: RawStorageMut<T, R, Cols>,
{
ParColumnIterMut::new(self)
}
}
struct ColumnProducer<'a, T, R: Dim, C: Dim, S: RawStorage<T, R, C>>(ColumnIter<'a, T, R, C, S>);
#[cfg_attr(docsrs, doc(cfg(feature = "rayon")))]
impl<'a, T, R: Dim, Cols: Dim, S: RawStorage<T, R, Cols>> Producer
for ColumnProducer<'a, T, R, Cols, S>
where
T: Send + Sync + Scalar,
S: Sync,
{
type Item = MatrixView<'a, T, R, U1, S::RStride, S::CStride>;
type IntoIter = ColumnIter<'a, T, R, Cols, S>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
self.0
}
#[inline]
fn split_at(self, index: usize) -> (Self, Self) {
let (left_iter, right_iter) = self.0.split_at(index);
(Self(left_iter), Self(right_iter))
}
}
struct ColumnProducerMut<'a, T, R: Dim, C: Dim, S: RawStorageMut<T, R, C>>(
ColumnIterMut<'a, T, R, C, S>,
);
impl<'a, T, R: Dim, C: Dim, S: 'a + RawStorageMut<T, R, C>> Producer
for ColumnProducerMut<'a, T, R, C, S>
where
T: Send + Sync + Scalar,
S: Send + Sync,
{
type Item = MatrixViewMut<'a, T, R, U1, S::RStride, S::CStride>;
type IntoIter = ColumnIterMut<'a, T, R, C, S>;
fn into_iter(self) -> Self::IntoIter {
self.0
}
fn split_at(self, index: usize) -> (Self, Self) {
let (left_iter, right_iter) = self.0.split_at(index);
(Self(left_iter), Self(right_iter))
}
}
unsafe impl<'a, T: Scalar, R: Dim, C: Dim, S: 'a + RawStorageMut<T, R, C>> Send
for ColumnIterMut<'a, T, R, C, S>
{
}