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();