Skip to content

Commit fdbc884

Browse files
authored
Merge pull request #948 from rust-ndarray/neg-stride-constructors
Fix a few inconsistencies around negative strides in constructors
2 parents 67397ac + 7699e0c commit fdbc884

File tree

2 files changed

+65
-2
lines changed

2 files changed

+65
-2
lines changed

src/impl_views/constructors.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use crate::error::ShapeError;
1313
use crate::extension::nonnull::nonnull_debug_checked_from_ptr;
1414
use crate::imp_prelude::*;
1515
use crate::{is_aligned, StrideShape};
16+
use crate::dimension::offset_from_ptr_to_memory;
1617

1718
/// Methods for read-only array views.
1819
impl<'a, A, D> ArrayView<'a, A, D>
@@ -29,6 +30,7 @@ where
2930
/// use ndarray::arr3;
3031
/// use ndarray::ShapeBuilder;
3132
///
33+
/// // advanced example where we are even specifying exact strides to use (which is optional).
3234
/// let s = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
3335
/// let a = ArrayView::from_shape((2, 3, 2).strides((1, 4, 2)),
3436
/// &s).unwrap();
@@ -55,7 +57,7 @@ where
5557
let dim = shape.dim;
5658
dimension::can_index_slice_with_strides(xs, &dim, &shape.strides)?;
5759
let strides = shape.strides.strides_for_dim(&dim);
58-
unsafe { Ok(Self::new_(xs.as_ptr(), dim, strides)) }
60+
unsafe { Ok(Self::new_(xs.as_ptr().offset(-offset_from_ptr_to_memory(&dim, &strides)), dim, strides)) }
5961
}
6062

6163
/// Create an `ArrayView<A, D>` from shape information and a raw pointer to
@@ -152,7 +154,7 @@ where
152154
let dim = shape.dim;
153155
dimension::can_index_slice_with_strides(xs, &dim, &shape.strides)?;
154156
let strides = shape.strides.strides_for_dim(&dim);
155-
unsafe { Ok(Self::new_(xs.as_mut_ptr(), dim, strides)) }
157+
unsafe { Ok(Self::new_(xs.as_mut_ptr().offset(-offset_from_ptr_to_memory(&dim, &strides)), dim, strides)) }
156158
}
157159

158160
/// Create an `ArrayViewMut<A, D>` from shape information and a

tests/array.rs

+61
Original file line numberDiff line numberDiff line change
@@ -1827,6 +1827,27 @@ fn map_memory_order() {
18271827
assert_eq!(amap.strides(), v.strides());
18281828
}
18291829

1830+
#[test]
1831+
fn test_view_from_shape() {
1832+
let s = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];
1833+
let a = ArrayView::from_shape((2, 3, 2), &s).unwrap();
1834+
let mut answer = Array::from(s.to_vec()).into_shape((2, 3, 2)).unwrap();
1835+
assert_eq!(a, answer);
1836+
1837+
// custom strides (row major)
1838+
let a = ArrayView::from_shape((2, 3, 2).strides((6, 2, 1)), &s).unwrap();
1839+
assert_eq!(a, answer);
1840+
1841+
// custom strides (col major)
1842+
let a = ArrayView::from_shape((2, 3, 2).strides((1, 2, 6)), &s).unwrap();
1843+
assert_eq!(a, answer.t());
1844+
1845+
// negative strides
1846+
let a = ArrayView::from_shape((2, 3, 2).strides((6, (-2isize) as usize, 1)), &s).unwrap();
1847+
answer.invert_axis(Axis(1));
1848+
assert_eq!(a, answer);
1849+
}
1850+
18301851
#[test]
18311852
fn test_contiguous() {
18321853
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() {
19731994
assert_eq!(view, aview2(&[[0, 0, 2], [3, 4, 6]]));
19741995
}
19751996

1997+
#[should_panic(expected = "Unsupported")]
1998+
#[cfg(debug_assertions)]
1999+
#[test]
2000+
fn test_view_from_shape_ptr_deny_neg_strides() {
2001+
let data = [0, 1, 2, 3, 4, 5];
2002+
let _view = unsafe {
2003+
ArrayView::from_shape_ptr((2, 3).strides((-3isize as usize, 1)), data.as_ptr())
2004+
};
2005+
}
2006+
2007+
#[should_panic(expected = "Unsupported")]
2008+
#[cfg(debug_assertions)]
2009+
#[test]
2010+
fn test_view_mut_from_shape_ptr_deny_neg_strides() {
2011+
let mut data = [0, 1, 2, 3, 4, 5];
2012+
let _view = unsafe {
2013+
ArrayViewMut::from_shape_ptr((2, 3).strides((-3isize as usize, 1)), data.as_mut_ptr())
2014+
};
2015+
}
2016+
2017+
#[should_panic(expected = "Unsupported")]
2018+
#[cfg(debug_assertions)]
2019+
#[test]
2020+
fn test_raw_view_from_shape_ptr_deny_neg_strides() {
2021+
let data = [0, 1, 2, 3, 4, 5];
2022+
let _view = unsafe {
2023+
RawArrayView::from_shape_ptr((2, 3).strides((-3isize as usize, 1)), data.as_ptr())
2024+
};
2025+
}
2026+
2027+
#[should_panic(expected = "Unsupported")]
2028+
#[cfg(debug_assertions)]
2029+
#[test]
2030+
fn test_raw_view_mut_from_shape_ptr_deny_neg_strides() {
2031+
let mut data = [0, 1, 2, 3, 4, 5];
2032+
let _view = unsafe {
2033+
RawArrayViewMut::from_shape_ptr((2, 3).strides((-3isize as usize, 1)), data.as_mut_ptr())
2034+
};
2035+
}
2036+
19762037
#[test]
19772038
fn test_default() {
19782039
let a = <Array<f32, Ix2> as Default>::default();

0 commit comments

Comments
 (0)