Skip to content

Commit 5e03afb

Browse files
committed
implement owning constructors taking dimensions and strides
1 parent a93923e commit 5e03afb

File tree

2 files changed

+67
-1
lines changed

2 files changed

+67
-1
lines changed

src/dimension.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,38 @@ pub fn stride_offset(n: Ix, stride: Ix) -> isize
1010
(n as isize) * ((stride as Ixs) as isize)
1111
}
1212

13+
/// Check whether `stride` is strictly positive
14+
#[inline]
15+
pub fn stride_is_positive(stride: Ix) -> bool
16+
{
17+
(stride as Ixs) > 0
18+
}
19+
20+
/// Check whether the given dimension and strides are memory safe
21+
/// to index the provided slice.
22+
///
23+
/// To be safe, no stride may be negative, and the
24+
pub fn can_index_slice<A, D: Dimension>(data: &[A],
25+
dim: &D,
26+
strides: &D
27+
) -> bool
28+
{
29+
if strides.slice().iter().cloned().all(stride_is_positive) {
30+
let mut last_index = dim.clone();
31+
for mut index in last_index.slice_mut().iter_mut() {
32+
*index -= 1;
33+
}
34+
if let Some(offset) = dim.stride_offset_checked(strides, &last_index) {
35+
// offset is guaranteed to be positive so no issue converting
36+
// to usize here
37+
if (offset as usize) < data.len() {
38+
return true;
39+
}
40+
}
41+
}
42+
false
43+
}
44+
1345
/// Trait for the shape and index types of arrays.
1446
///
1547
/// `unsafe` because of the assumptions in the default methods.

src/lib.rs

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ use std::marker::PhantomData;
7575

7676
use it::ZipSlices;
7777

78-
pub use dimension::{Dimension, RemoveAxis};
78+
pub use dimension::{Dimension, RemoveAxis, can_index_slice};
7979
pub use dimension::NdIndex;
8080
pub use indexes::Indexes;
8181
pub use shape_error::ShapeError;
@@ -634,6 +634,40 @@ impl<S, A, D> ArrayBase<S, D>
634634
dim: dim
635635
}
636636
}
637+
638+
/// Create an array from a vector and interpret it according to the
639+
/// provided dimensions and strides. No allocation needed.
640+
///
641+
/// Unsafe because dimension and strides are unchecked.
642+
pub unsafe fn from_vec_dim_stride_uchk(dim: D,
643+
strides: D,
644+
mut v: Vec<A>
645+
) -> ArrayBase<S, D>
646+
{
647+
ArrayBase {
648+
ptr: v.as_mut_ptr(),
649+
data: DataOwned::new(v),
650+
strides: strides,
651+
dim: dim
652+
}
653+
}
654+
655+
/// Create an array from a vector and interpret it according to the
656+
/// provided dimensions and strides. No allocation needed.
657+
///
658+
/// **Panics** if the stride and dimensions point outside the vector's
659+
/// memory.
660+
pub fn from_vec_dim_stride(dim: D,
661+
strides: D,
662+
v: Vec<A>
663+
) -> ArrayBase<S, D>
664+
{
665+
assert!(dimension::can_index_slice(&v, &dim, &strides),
666+
"dim and strides index out of the vector's memory");
667+
unsafe {
668+
Self::from_vec_dim_stride_uchk(dim, strides, v)
669+
}
670+
}
637671
}
638672

639673

0 commit comments

Comments
 (0)