From 6017b2d745fdd8a85520cd52080ad423335ecacc Mon Sep 17 00:00:00 2001 From: SparrowLii Date: Wed, 27 Jan 2021 19:21:03 +0800 Subject: [PATCH 1/2] Fix constructors when strides are negative --- src/impl_views/constructors.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/impl_views/constructors.rs b/src/impl_views/constructors.rs index a133ee1d1..88a289ce7 100644 --- a/src/impl_views/constructors.rs +++ b/src/impl_views/constructors.rs @@ -13,6 +13,7 @@ use crate::error::ShapeError; use crate::extension::nonnull::nonnull_debug_checked_from_ptr; use crate::imp_prelude::*; use crate::{is_aligned, StrideShape}; +use crate::dimension::offset_from_ptr_to_memory; /// Methods for read-only array views. impl<'a, A, D> ArrayView<'a, A, D> @@ -55,7 +56,7 @@ where let dim = shape.dim; dimension::can_index_slice_with_strides(xs, &dim, &shape.strides)?; let strides = shape.strides.strides_for_dim(&dim); - unsafe { Ok(Self::new_(xs.as_ptr(), dim, strides)) } + unsafe { Ok(Self::new_(xs.as_ptr().offset(-offset_from_ptr_to_memory(&dim, &strides)), dim, strides)) } } /// Create an `ArrayView` from shape information and a raw pointer to @@ -152,7 +153,7 @@ where let dim = shape.dim; dimension::can_index_slice_with_strides(xs, &dim, &shape.strides)?; let strides = shape.strides.strides_for_dim(&dim); - unsafe { Ok(Self::new_(xs.as_mut_ptr(), dim, strides)) } + unsafe { Ok(Self::new_(xs.as_mut_ptr().offset(-offset_from_ptr_to_memory(&dim, &strides)), dim, strides)) } } /// Create an `ArrayViewMut` from shape information and a From 7699e0cdbf5208a610fb38bc4c7479b45a78fad3 Mon Sep 17 00:00:00 2001 From: bluss Date: Mon, 22 Mar 2021 19:03:49 +0100 Subject: [PATCH 2/2] TEST: Test for negative stride constructors for Raw/ArrayView --- src/impl_views/constructors.rs | 1 + tests/array.rs | 61 ++++++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+) diff --git a/src/impl_views/constructors.rs b/src/impl_views/constructors.rs index 88a289ce7..fd9457fa1 100644 --- a/src/impl_views/constructors.rs +++ b/src/impl_views/constructors.rs @@ -30,6 +30,7 @@ where /// use ndarray::arr3; /// use ndarray::ShapeBuilder; /// + /// // advanced example where we are even specifying exact strides to use (which is optional). /// let s = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; /// let a = ArrayView::from_shape((2, 3, 2).strides((1, 4, 2)), /// &s).unwrap(); diff --git a/tests/array.rs b/tests/array.rs index b1d37da70..8e084e49e 100644 --- a/tests/array.rs +++ b/tests/array.rs @@ -1827,6 +1827,27 @@ fn map_memory_order() { assert_eq!(amap.strides(), v.strides()); } +#[test] +fn test_view_from_shape() { + let s = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]; + let a = ArrayView::from_shape((2, 3, 2), &s).unwrap(); + let mut answer = Array::from(s.to_vec()).into_shape((2, 3, 2)).unwrap(); + assert_eq!(a, answer); + + // custom strides (row major) + let a = ArrayView::from_shape((2, 3, 2).strides((6, 2, 1)), &s).unwrap(); + assert_eq!(a, answer); + + // custom strides (col major) + let a = ArrayView::from_shape((2, 3, 2).strides((1, 2, 6)), &s).unwrap(); + assert_eq!(a, answer.t()); + + // negative strides + let a = ArrayView::from_shape((2, 3, 2).strides((6, (-2isize) as usize, 1)), &s).unwrap(); + answer.invert_axis(Axis(1)); + assert_eq!(a, answer); +} + #[test] fn test_contiguous() { let c = arr3(&[[[1, 2, 3], [4, 5, 6]], [[4, 5, 6], [7, 7, 7]]]); @@ -1973,6 +1994,46 @@ fn test_view_from_shape_ptr() { assert_eq!(view, aview2(&[[0, 0, 2], [3, 4, 6]])); } +#[should_panic(expected = "Unsupported")] +#[cfg(debug_assertions)] +#[test] +fn test_view_from_shape_ptr_deny_neg_strides() { + let data = [0, 1, 2, 3, 4, 5]; + let _view = unsafe { + ArrayView::from_shape_ptr((2, 3).strides((-3isize as usize, 1)), data.as_ptr()) + }; +} + +#[should_panic(expected = "Unsupported")] +#[cfg(debug_assertions)] +#[test] +fn test_view_mut_from_shape_ptr_deny_neg_strides() { + let mut data = [0, 1, 2, 3, 4, 5]; + let _view = unsafe { + ArrayViewMut::from_shape_ptr((2, 3).strides((-3isize as usize, 1)), data.as_mut_ptr()) + }; +} + +#[should_panic(expected = "Unsupported")] +#[cfg(debug_assertions)] +#[test] +fn test_raw_view_from_shape_ptr_deny_neg_strides() { + let data = [0, 1, 2, 3, 4, 5]; + let _view = unsafe { + RawArrayView::from_shape_ptr((2, 3).strides((-3isize as usize, 1)), data.as_ptr()) + }; +} + +#[should_panic(expected = "Unsupported")] +#[cfg(debug_assertions)] +#[test] +fn test_raw_view_mut_from_shape_ptr_deny_neg_strides() { + let mut data = [0, 1, 2, 3, 4, 5]; + let _view = unsafe { + RawArrayViewMut::from_shape_ptr((2, 3).strides((-3isize as usize, 1)), data.as_mut_ptr()) + }; +} + #[test] fn test_default() { let a = as Default>::default();