//! this module implements parallelators to make matrices work with //! the rayon crate seamlessly use crate::{ iter::{ColumnIter, ColumnIterMut}, Dim, Matrix, MatrixSlice, MatrixSliceMut, RawStorage, RawStorageMut, U1, }; use core::fmt::Debug; use rayon::{iter::plumbing::bridge, prelude::*}; /// A rayon parallel iterator over the colums of a matrix pub struct ParColumnIter<'a, T, R: Dim, Cols: Dim, S: RawStorage> { mat: &'a Matrix, } impl<'a, T, R: Dim, Cols: Dim, S: RawStorage> ParColumnIter<'a, T, R, Cols, S> { /// create a new parallel iterator for the given matrix fn new(matrix: &'a Matrix) -> Self { Self { mat: matrix } } } impl<'a, T, R: Dim, Cols: Dim, S: RawStorage> ParallelIterator for ParColumnIter<'a, T, R, Cols, S> where T: Sync + Send + Clone + Debug + PartialEq + 'static, S: Sync, { type Item = MatrixSlice<'a, T, R, U1, S::RStride, S::CStride>; fn drive_unindexed(self, consumer: Consumer) -> Consumer::Result where Consumer: rayon::iter::plumbing::UnindexedConsumer, { bridge(self, consumer) } fn opt_len(&self) -> Option { Some(self.mat.ncols()) } } impl<'a, T, R: Dim, Cols: Dim, S: RawStorage> IndexedParallelIterator for ParColumnIter<'a, T, R, Cols, S> where T: Send + Sync + Clone + Debug + PartialEq + 'static, S: Sync, { fn len(&self) -> usize { self.mat.ncols() } fn drive>(self, consumer: C) -> C::Result { bridge(self, consumer) } fn with_producer>( self, callback: CB, ) -> CB::Output { let producer = ColumnIter::new(self.mat); callback.callback(producer) } } impl> Matrix where T: Send + Sync + Clone + Debug + PartialEq + 'static, S: Sync, { /// Iterate through the columns of the matrix in parallel using rayon. pub fn par_column_iter(&self) -> ParColumnIter<'_, T, R, Cols, S> { ParColumnIter::new(self) } } /// A rayon parallel iterator through the mutable columns of a matrix pub struct ParColumnIterMut< 'a, T, R: Dim, Cols: Dim, S: RawStorage + RawStorageMut, > { mat: &'a mut Matrix, } impl<'a, T, R, Cols, S> ParColumnIterMut<'a, T, R, Cols, S> where R: Dim, Cols: Dim, S: RawStorage + RawStorageMut, { /// create a new parallel iterator for the given matrix fn new(mat: &'a mut Matrix) -> Self { Self { mat } } } impl<'a, T, R, Cols, S> ParallelIterator for ParColumnIterMut<'a, T, R, Cols, S> where R: Dim, Cols: Dim, S: RawStorage + RawStorageMut, T: Send + Sync + Debug + PartialEq + Clone + 'static, S: Send + Sync, { type Item = MatrixSliceMut<'a, T, R, U1, S::RStride, S::CStride>; fn drive_unindexed(self, consumer: C) -> C::Result where C: rayon::iter::plumbing::UnindexedConsumer, { bridge(self, consumer) } fn opt_len(&self) -> Option { Some(self.mat.ncols()) } } impl<'a, T, R, Cols, S> IndexedParallelIterator for ParColumnIterMut<'a, T, R, Cols, S> where R: Dim, Cols: Dim, S: RawStorage + RawStorageMut, T: Send + Sync + Debug + PartialEq + Clone + 'static, S: Send + Sync, { fn drive>(self, consumer: C) -> C::Result { bridge(self, consumer) } fn len(&self) -> usize { self.mat.ncols() } fn with_producer>( self, callback: CB, ) -> CB::Output { let producer = ColumnIterMut::new(self.mat); callback.callback(producer) } } impl + RawStorageMut> Matrix where T: Send + Sync + Clone + Debug + PartialEq + 'static, S: Sync, { /// Mutably iterate through the columns of this matrix in parallel using rayon pub fn par_column_iter_mut(&mut self) -> ParColumnIterMut<'_, T, R, Cols, S> { ParColumnIterMut::new(self) } }