From 61abece7af1cd02fabd40258e3347d54a80ab29c Mon Sep 17 00:00:00 2001 From: geo-ant <54497890+geo-ant@users.noreply.github.com> Date: Sun, 27 Nov 2022 16:51:25 +0100 Subject: [PATCH] create separate newtype for producer trait --- src/base/iter.rs | 88 +++----------------------------------------- src/base/par_iter.rs | 86 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 89 insertions(+), 85 deletions(-) diff --git a/src/base/iter.rs b/src/base/iter.rs index 90a1607f..fc6bd664 100644 --- a/src/base/iter.rs +++ b/src/base/iter.rs @@ -301,8 +301,8 @@ impl<'a, T: Scalar, R: Dim, C: Dim, S: 'a + RawStorageMut> ExactSizeIte #[derive(Clone, Debug)] /// An iterator through the columns of a matrix. pub struct ColumnIter<'a, T, R: Dim, C: Dim, S: RawStorage> { - mat: &'a Matrix, - range: Range, + pub(crate) mat: &'a Matrix, + pub(crate) range: Range, } impl<'a, T, R: Dim, C: Dim, S: 'a + RawStorage> ColumnIter<'a, T, R, C, S> { @@ -370,9 +370,9 @@ impl<'a, T: Scalar, R: Dim, C: Dim, S: 'a + RawStorage> ExactSizeIterat /// An iterator through the mutable columns of a matrix. #[derive(Debug)] pub struct ColumnIterMut<'a, T, R: Dim, C: Dim, S: RawStorageMut> { - mat: *mut Matrix, - phantom: PhantomData<&'a mut Matrix>, - range: Range, + pub(crate) mat: *mut Matrix, + pub(crate) range: Range, + pub(crate) phantom: PhantomData<&'a mut Matrix>, } impl<'a, T, R: Dim, C: Dim, S: 'a + RawStorageMut> ColumnIterMut<'a, T, R, C, S> { @@ -443,81 +443,3 @@ impl<'a, T: Scalar, R: Dim, C: Dim, S: 'a + RawStorageMut> DoubleEndedI } } } - -/// implementations for parallel iteration with rayon -#[cfg(feature = "par-iter")] -mod parallel { - use super::*; - use rayon::iter::plumbing::Producer; - - #[cfg_attr(doc_cfg, doc(cfg(feature = "par-iter")))] - /// *only available if compiled with the feature `par-iter`* - impl<'a, T, R: Dim, Cols: Dim, S: RawStorage> Producer for ColumnIter<'a, T, R, Cols, S> - where - T: Send + Sync + Scalar, - S: Sync, - { - type Item = MatrixSlice<'a, T, R, U1, S::RStride, S::CStride>; - type IntoIter = ColumnIter<'a, T, R, Cols, S>; - - fn split_at(self, index: usize) -> (Self, Self) { - // the index is relative to the size of this current iterator - // it will always start at zero so it serves as an offset - let left = Self { - mat: self.mat, - range: self.range.start..(self.range.start + index), - }; - - let right = Self { - mat: self.mat, - range: (self.range.start + index)..self.range.end, - }; - (left, right) - } - - fn into_iter(self) -> Self::IntoIter { - self - } - } - - #[cfg_attr(doc_cfg, doc(cfg(feature = "par-iter")))] - /// *only available if compiled with the feature `par-iter`* - impl<'a, T, R: Dim, C: Dim, S: 'a + RawStorageMut> Producer - for ColumnIterMut<'a, T, R, C, S> - where - T: Send + Sync + Scalar, - S: Send + Sync, - { - type Item = MatrixSliceMut<'a, T, R, U1, S::RStride, S::CStride>; - type IntoIter = ColumnIterMut<'a, T, R, C, S>; - - fn into_iter(self) -> Self::IntoIter { - self - } - - fn split_at(self, index: usize) -> (Self, Self) { - // the index is relative to the size of this current iterator - // it will always start at zero so it serves as an offset - - let left = Self { - mat: self.mat, - range: self.range.start..(self.range.start + index), - phantom: Default::default(), - }; - - let right = Self { - mat: self.mat, - range: (self.range.start + index)..self.range.end, - phantom: Default::default(), - }; - (left, right) - } - } - - /// this implementation is safe because we are enforcing exclusive access - /// to the columns through the active range of the iterator - unsafe impl<'a, T: Scalar, R: Dim, C: Dim, S: 'a + RawStorageMut> Send - for ColumnIterMut<'a, T, R, C, S> - { - } -} diff --git a/src/base/par_iter.rs b/src/base/par_iter.rs index 7d943e40..46e3c607 100644 --- a/src/base/par_iter.rs +++ b/src/base/par_iter.rs @@ -9,6 +9,7 @@ use crate::{ Dim, Matrix, MatrixSlice, MatrixSliceMut, RawStorage, RawStorageMut, Scalar, U1, }; use rayon::{iter::plumbing::bridge, prelude::*}; +use rayon::iter::plumbing::Producer; /// A rayon parallel iterator over the colums of a matrix. It is created /// using the [`par_column_iter`] method of [`Matrix`]. @@ -69,7 +70,7 @@ where self, callback: CB, ) -> CB::Output { - let producer = ColumnIter::new(self.mat); + let producer = ColumnProducer(ColumnIter::new(self.mat)); callback.callback(producer) } } @@ -146,7 +147,7 @@ where self, callback: CB, ) -> CB::Output { - let producer = ColumnIterMut::new(self.mat); + let producer = ColumnProducerMut(ColumnIterMut::new(self.mat)); callback.callback(producer) } } @@ -219,3 +220,84 @@ where ParColumnIterMut::new(self) } } + +/// a private helper newtype that wraps the `ColumnIter` and implements +/// the rayon `Producer` trait. It's just here so we don't have to make the +/// rayon trait part of the public interface of the `ColumnIter` +struct ColumnProducer<'a,T,R:Dim,C:Dim,S:RawStorage>(ColumnIter<'a,T,R,C,S>); + +#[cfg_attr(doc_cfg, doc(cfg(feature = "par-iter")))] +/// *only available if compiled with the feature `par-iter`* +impl<'a, T, R: Dim, Cols: Dim, S: RawStorage> Producer for ColumnProducer<'a, T, R, Cols, S> +where +T: Send + Sync + Scalar, +S: Sync, +{ + type Item = MatrixSlice<'a, T, R, U1, S::RStride, S::CStride>; + type IntoIter = ColumnIter<'a, T, R, Cols, S>; + + #[inline] + fn split_at(self, index: usize) -> (Self, Self) { + // the index is relative to the size of this current iterator + // it will always start at zero so it serves as an offset + let left_iter = ColumnIter { + mat: self.0.mat, + range: self.0.range.start..(self.0.range.start + index), + }; + + let right_iter = ColumnIter { + mat: self.0.mat, + range: (self.0.range.start + index)..self.0.range.end, + }; + (Self(left_iter), Self(right_iter)) + } + + #[inline] + fn into_iter(self) -> Self::IntoIter { + self.0 + } +} + +/// See `ColumnProducer`. A private wrapper newtype that keeps the Producer +/// implementation private +struct ColumnProducerMut<'a, T, R: Dim, C: Dim, S: RawStorageMut>(ColumnIterMut<'a,T,R,C,S>); + +impl<'a, T, R: Dim, C: Dim, S: 'a + RawStorageMut> Producer +for ColumnProducerMut<'a, T, R, C, S> +where +T: Send + Sync + Scalar, +S: Send + Sync, +{ + type Item = MatrixSliceMut<'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) { + // the index is relative to the size of this current iterator + // it will always start at zero so it serves as an offset + + let left_iter = ColumnIterMut { + mat: self.0.mat, + range: self.0.range.start..(self.0.range.start + index), + phantom: Default::default(), + }; + + let right_iter = ColumnIterMut { + mat: self.0.mat, + range: (self.0.range.start + index)..self.0.range.end, + phantom: Default::default(), + }; + (Self(left_iter), Self(right_iter)) + } +} + + +/// this implementation is safe because we are enforcing exclusive access +/// to the columns through the active range of the iterator +unsafe impl<'a, T: Scalar, R: Dim, C: Dim, S: 'a + RawStorageMut> Send +for ColumnIterMut<'a, T, R, C, S> +{ +}