From 3005a8eba7a4c8da7dff9534ee8910c9c6f10f40 Mon Sep 17 00:00:00 2001 From: bluss Date: Thu, 30 Mar 2017 22:27:45 +0200 Subject: [PATCH 1/3] MAINT: Remove unused code lanes_along/lanes_along_mut are superseded by Inners/InnersMut --- src/impl_methods.rs | 35 ----------------------------------- 1 file changed, 35 deletions(-) diff --git a/src/impl_methods.rs b/src/impl_methods.rs index 5af1bfc61..e32bce212 100644 --- a/src/impl_methods.rs +++ b/src/impl_methods.rs @@ -1432,39 +1432,4 @@ impl ArrayBase where S: Data, D: Dimension } }) } - - #[cfg(lanes_along)] - fn lanes_along<'a, F>(&'a self, axis: Axis, mut visit: F) - where D: RemoveAxis, - F: FnMut(ArrayView1<'a, A>), - A: 'a, - { - let view_len = self.shape().axis(axis); - let view_stride = self.strides.axis(axis); - // use the 0th subview as a map to each 1d array view extended from - // the 0th element. - self.subview(axis, 0).visit(move |first_elt| { - unsafe { - visit(ArrayView::new_(first_elt, Ix1(view_len), Ix1(view_stride))) - } - }) - } - - #[cfg(lanes_along)] - fn lanes_along_mut<'a, F>(&'a mut self, axis: Axis, mut visit: F) - where D: RemoveAxis, - S: DataMut, - F: FnMut(ArrayViewMut1<'a, A>), - A: 'a, - { - let view_len = self.shape().axis(axis); - let view_stride = self.strides.axis(axis); - // use the 0th subview as a map to each 1d array view extended from - // the 0th element. - self.subview_mut(axis, 0).unordered_foreach_mut(move |first_elt| { - unsafe { - visit(ArrayViewMut::new_(first_elt, Ix1(view_len), Ix1(view_stride))) - } - }) - } } From 9e2cbf75128b68c44cdefc316bc993630a5398f2 Mon Sep 17 00:00:00 2001 From: bluss Date: Thu, 30 Mar 2017 22:27:45 +0200 Subject: [PATCH 2/3] ENH: Re-do zip by rows using inners producer and Zip --- src/impl_methods.rs | 38 +++++---------- src/iterators/inners.rs | 101 ++++++++++++++++++++++++++++++++++++++++ src/iterators/mod.rs | 5 ++ src/lib.rs | 16 +++++++ 4 files changed, 134 insertions(+), 26 deletions(-) create mode 100644 src/iterators/inners.rs diff --git a/src/impl_methods.rs b/src/impl_methods.rs index e32bce212..89eb2bef0 100644 --- a/src/impl_methods.rs +++ b/src/impl_methods.rs @@ -23,11 +23,12 @@ use super::ZipExt; use dimension::IntoDimension; use dimension::{axes_of, Axes, merge_axes, stride_offset}; use iterators::{ - new_inner_iter_smaller, - new_inner_iter_smaller_mut, + new_inners, + new_inners_mut, whole_chunks_of, whole_chunks_mut_of, }; +use zip::Zip; use { NdIndex, @@ -1184,33 +1185,18 @@ impl ArrayBase where S: Data, D: Dimension } return; } + // otherwise, break the arrays up into their inner rows - let mut try_slices = true; - let rows = new_inner_iter_smaller_mut(self.view_mut()).zip( - new_inner_iter_smaller(rhs.view())); - for (mut s_row, r_row) in rows { - if try_slices { - if let Some(self_s) = s_row.as_slice_mut() { - if let Some(rhs_s) = r_row.as_slice() { - let len = cmp::min(self_s.len(), rhs_s.len()); - let s = &mut self_s[..len]; - let r = &rhs_s[..len]; - for i in 0..len { - f(&mut s[i], &r[i]); - } - continue; - } - } - try_slices = false; - } - unsafe { - for i in 0..s_row.len() { - f(s_row.uget_mut(i), r_row.uget(i)) - } - } - } + let n = self.ndim(); + let dim = self.raw_dim(); + Zip::from(new_inners_mut(self.view_mut(), Axis(n - 1))) + .and(new_inners(rhs.broadcast_assume(dim), Axis(n - 1))) + .apply(move |s_row, r_row| { + Zip::from(s_row).and(r_row).apply(|a, b| f(a, b)) + }); } + fn zip_mut_with_elem(&mut self, rhs_elem: &B, mut f: F) where S: DataMut, F: FnMut(&mut A, &B) diff --git a/src/iterators/inners.rs b/src/iterators/inners.rs new file mode 100644 index 000000000..501c1b3e2 --- /dev/null +++ b/src/iterators/inners.rs @@ -0,0 +1,101 @@ + +use imp_prelude::*; +use {NdProducer, Layout}; + +impl_ndproducer! { + ['a, A, D: Dimension] + [Clone => 'a, A, D: Clone ] + Inners { + base, + inner_len, + inner_stride, + } + Inners<'a, A, D> { + type Dim = D; + type Item = ArrayView<'a, A, Ix1>; + + unsafe fn item(&self, ptr) { + ArrayView::new_(ptr, Ix1(self.inner_len), Ix1(self.inner_stride as Ix)) + } + } +} + +pub struct Inners<'a, A: 'a, D> { + base: ArrayView<'a, A, D>, + inner_len: Ix, + inner_stride: Ixs, +} + + +pub fn new_inners(v: ArrayView, axis: Axis) + -> Inners + where D: Dimension +{ + let ndim = v.ndim(); + let len; + let stride; + let iter_v; + if ndim == 0 { + len = 1; + stride = 0; + iter_v = v.try_remove_axis(Axis(0)) + } else { + len = v.dim.last_elem(); + stride = v.strides.last_elem() as isize; + iter_v = v.try_remove_axis(axis) + } + Inners { + inner_len: len, + inner_stride: stride, + base: iter_v, + } +} + +impl_ndproducer! { + ['a, A, D: Dimension] + [Clone =>] + InnersMut { + base, + inner_len, + inner_stride, + } + InnersMut<'a, A, D> { + type Dim = D; + type Item = ArrayViewMut<'a, A, Ix1>; + + unsafe fn item(&self, ptr) { + ArrayViewMut::new_(ptr, Ix1(self.inner_len), Ix1(self.inner_stride as Ix)) + } + } +} + +pub struct InnersMut<'a, A: 'a, D> { + base: ArrayViewMut<'a, A, D>, + inner_len: Ix, + inner_stride: Ixs, +} + + +pub fn new_inners_mut(v: ArrayViewMut, axis: Axis) + -> InnersMut + where D: Dimension +{ + let ndim = v.ndim(); + let len; + let stride; + let iter_v; + if ndim == 0 { + len = 1; + stride = 0; + iter_v = v.try_remove_axis(Axis(0)) + } else { + len = v.dim.last_elem(); + stride = v.strides.last_elem() as isize; + iter_v = v.try_remove_axis(axis) + } + InnersMut { + inner_len: len, + inner_stride: stride, + base: iter_v, + } +} diff --git a/src/iterators/mod.rs b/src/iterators/mod.rs index 9208f36b6..7ac87c5a1 100644 --- a/src/iterators/mod.rs +++ b/src/iterators/mod.rs @@ -9,6 +9,7 @@ #[macro_use] mod macros; mod chunks; +mod inners; use std::marker::PhantomData; use std::ptr; @@ -35,6 +36,10 @@ pub use self::chunks::{ WholeChunksIterMut, whole_chunks_mut_of, }; +pub use self::inners::{ + new_inners, + new_inners_mut, +}; /// Base for array iterators /// diff --git a/src/lib.rs b/src/lib.rs index 980c9a014..0782ab8da 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -590,6 +590,22 @@ impl ArrayBase } } + // Broadcast to dimension `E`, without checking that the dimensions match + // (Checked in debug assertions). + #[inline] + fn broadcast_assume(&self, dim: E) -> ArrayView + where E: Dimension, + { + let dim = dim.into_dimension(); + debug_assert_eq!(self.shape(), dim.slice()); + let ptr = self.ptr; + let mut strides = dim.clone(); + strides.slice_mut().copy_from_slice(self.strides.slice()); + unsafe { + ArrayView::new_(ptr, dim, strides) + } + } + fn raw_strides(&self) -> D { self.strides.clone() } From 916920e3d8afd7d6db0d3086b4edc5d6131b85ab Mon Sep 17 00:00:00 2001 From: bluss Date: Thu, 30 Mar 2017 22:27:45 +0200 Subject: [PATCH 3/3] MAINT: Cfg out unused function These functions will be used in the next version --- src/iterators/mod.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/iterators/mod.rs b/src/iterators/mod.rs index 7ac87c5a1..b3f4136a6 100644 --- a/src/iterators/mod.rs +++ b/src/iterators/mod.rs @@ -532,6 +532,7 @@ impl<'a, A, D> ExactSizeIterator for InnerIterMut<'a, A, D> } } +#[cfg(next_version)] /// Create an InnerIter one dimension smaller than D (if possible) pub fn new_inner_iter_smaller(v: ArrayView) -> InnerIter @@ -557,6 +558,7 @@ pub fn new_inner_iter_smaller(v: ArrayView) } } +#[cfg(next_version)] pub fn new_inner_iter_smaller_mut(v: ArrayViewMut) -> InnerIterMut where D: Dimension,