diff --git a/src/impl_views/constructors.rs b/src/impl_views/constructors.rs index a133ee1d1..fd9457fa1 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> @@ -29,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(); @@ -55,7 +57,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 +154,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 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();