Skip to content

Commit

Permalink
Add in/to_slice_memory_order for ArrayView/Mut
Browse files Browse the repository at this point in the history
  • Loading branch information
jturner314 committed May 29, 2021
1 parent e7600e8 commit 6cbac5c
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 0 deletions.
48 changes: 48 additions & 0 deletions src/impl_views/conversions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@
// except according to those terms.

use alloc::slice;
use rawpointer::PointerExt;
use std::mem::MaybeUninit;

use crate::imp_prelude::*;

use crate::{Baseiter, ElementsBase, ElementsBaseMut, Iter, IterMut};

use crate::dimension::offset_from_low_addr_ptr_to_logical_ptr;
use crate::iter::{self, AxisIter, AxisIterMut};
use crate::math_cell::MathCell;
use crate::IndexLonger;
Expand Down Expand Up @@ -44,6 +46,26 @@ where
}
}

/// Return the array’s data as a slice, if it is contiguous.
/// Return `None` otherwise.
///
/// Note that while the method is similar to
/// [`ArrayBase::as_slice_memory_order()`], this method tranfers the view's
/// lifetime to the slice, so it is a bit more powerful.
pub fn to_slice_memory_order(&self) -> Option<&'a [A]> {
if self.is_contiguous() {
let offset = offset_from_low_addr_ptr_to_logical_ptr(&self.dim, &self.strides);
unsafe {
Some(slice::from_raw_parts(
self.ptr.sub(offset).as_ptr(),
self.len(),
))
}
} else {
None
}
}

/// Converts to a raw array view.
pub(crate) fn into_raw_view(self) -> RawArrayView<A, D> {
unsafe { RawArrayView::new(self.ptr, self.dim, self.strides) }
Expand Down Expand Up @@ -120,6 +142,16 @@ where
self.try_into_slice().ok()
}

/// Return the array’s data as a slice, if it is contiguous.
/// Return `None` otherwise.
///
/// Note that while this is similar to
/// [`ArrayBase::as_slice_memory_order_mut()`], this method tranfers the
/// view's lifetime to the slice.
pub fn into_slice_memory_order(self) -> Option<&'a mut [A]> {
self.try_into_slice_memory_order().ok()
}

/// Return a shared view of the array with elements as if they were embedded in cells.
///
/// The cell view itself can be copied and accessed without exclusivity.
Expand Down Expand Up @@ -221,6 +253,22 @@ where
}
}

/// Return the array’s data as a slice, if it is contiguous.
/// Otherwise return self in the Err branch of the result.
fn try_into_slice_memory_order(self) -> Result<&'a mut [A], Self> {
if self.is_contiguous() {
let offset = offset_from_low_addr_ptr_to_logical_ptr(&self.dim, &self.strides);
unsafe {
Ok(slice::from_raw_parts_mut(
self.ptr.sub(offset).as_ptr(),
self.len(),
))
}
} else {
Err(self)
}
}

pub(crate) fn into_iter_(self) -> IterMut<'a, A, D> {
IterMut::new(self)
}
Expand Down
36 changes: 36 additions & 0 deletions tests/array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1000,6 +1000,42 @@ fn as_slice_memory_order() {
assert!(a != b, "{:?} != {:?}", a, b);
}

#[test]
fn to_slice_memory_order() {
for shape in vec![[2, 0, 3, 5], [2, 1, 3, 5], [2, 4, 3, 5]] {
let data: Vec<usize> = (0..shape.iter().product()).collect();
let mut orig = Array1::from(data.clone()).into_shape(shape).unwrap();
for perm in vec![[0, 1, 2, 3], [0, 2, 1, 3], [2, 0, 1, 3]] {
let mut a = orig.view_mut().permuted_axes(perm);
assert_eq!(a.as_slice_memory_order().unwrap(), &data);
assert_eq!(a.as_slice_memory_order_mut().unwrap(), &data);
assert_eq!(a.view().to_slice_memory_order().unwrap(), &data);
assert_eq!(a.view_mut().into_slice_memory_order().unwrap(), &data);
}
}
}

#[test]
fn to_slice_memory_order_discontiguous() {
let mut orig = Array3::<u8>::zeros([3, 2, 4]);
assert!(orig
.slice(s![.., 1.., ..])
.as_slice_memory_order()
.is_none());
assert!(orig
.slice_mut(s![.., 1.., ..])
.as_slice_memory_order_mut()
.is_none());
assert!(orig
.slice(s![.., 1.., ..])
.to_slice_memory_order()
.is_none());
assert!(orig
.slice_mut(s![.., 1.., ..])
.into_slice_memory_order()
.is_none());
}

#[test]
fn array0_into_scalar() {
// With this kind of setup, the `Array`'s pointer is not the same as the
Expand Down

0 comments on commit 6cbac5c

Please sign in to comment.