Skip to content

Commit

Permalink
Merge pull request #948 from rust-ndarray/neg-stride-constructors
Browse files Browse the repository at this point in the history
Fix a few inconsistencies around negative strides in constructors
  • Loading branch information
bluss committed Mar 23, 2021
2 parents 67397ac + 7699e0c commit fdbc884
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 2 deletions.
6 changes: 4 additions & 2 deletions src/impl_views/constructors.rs
Expand Up @@ -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>
Expand All @@ -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();
Expand All @@ -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<A, D>` from shape information and a raw pointer to
Expand Down Expand Up @@ -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<A, D>` from shape information and a
Expand Down
61 changes: 61 additions & 0 deletions tests/array.rs
Expand Up @@ -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]]]);
Expand Down Expand Up @@ -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 = <Array<f32, Ix2> as Default>::default();
Expand Down

0 comments on commit fdbc884

Please sign in to comment.