Skip to content

Commit 245cfbb

Browse files
authored
Merge pull request #535 from jturner314/array0-into-scalar
Add into_scalar method for Array0
2 parents e63246c + 60d3b97 commit 245cfbb

File tree

3 files changed

+59
-4
lines changed

3 files changed

+59
-4
lines changed

src/impl_owned_array.rs

+39
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,44 @@
11
use imp_prelude::*;
22

3+
/// Methods specific to `Array0`.
4+
///
5+
/// ***See also all methods for [`ArrayBase`]***
6+
///
7+
/// [`ArrayBase`]: struct.ArrayBase.html
8+
impl<A> Array<A, Ix0> {
9+
/// Returns the single element in the array without cloning it.
10+
///
11+
/// ```
12+
/// use ndarray::{arr0, Array0};
13+
///
14+
/// // `Foo` doesn't implement `Clone`.
15+
/// #[derive(Debug, Eq, PartialEq)]
16+
/// struct Foo;
17+
///
18+
/// let array: Array0<Foo> = arr0(Foo);
19+
/// let scalar: Foo = array.into_scalar();
20+
/// assert_eq!(scalar, Foo);
21+
/// ```
22+
pub fn into_scalar(mut self) -> A {
23+
let size = ::std::mem::size_of::<A>();
24+
if size == 0 {
25+
// Any index in the `Vec` is fine since all elements are identical.
26+
self.data.0.remove(0)
27+
} else {
28+
// Find the index in the `Vec` corresponding to `self.ptr`.
29+
// (This is necessary because the element in the array might not be
30+
// the first element in the `Vec`, such as if the array was created
31+
// by `array![1, 2, 3, 4].slice_move(s![2])`.)
32+
let first = self.ptr as usize;
33+
let base = self.data.0.as_ptr() as usize;
34+
let index = (first - base) / size;
35+
debug_assert_eq!((first - base) % size, 0);
36+
// Remove the element at the index and return it.
37+
self.data.0.remove(index)
38+
}
39+
}
40+
}
41+
342
/// Methods specific to `Array`.
443
///
544
/// ***See also all methods for [`ArrayBase`]***

src/lib.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -855,11 +855,11 @@ pub type Ixs = isize;
855855
/// </tr>
856856
/// </table>
857857
///
858-
/// ### Conversions Between Arrays and `Vec`s/Slices
858+
/// ### Conversions Between Arrays and `Vec`s/Slices/Scalars
859859
///
860-
/// This is a table of the safe conversions between arrays and `Vec`s/slices.
861-
/// Note that some of the return values are actually `Result`/`Option` wrappers
862-
/// around the indicated output types.
860+
/// This is a table of the safe conversions between arrays and
861+
/// `Vec`s/slices/scalars. Note that some of the return values are actually
862+
/// `Result`/`Option` wrappers around the indicated output types.
863863
///
864864
/// Input | Output | Methods
865865
/// ------|--------|--------
@@ -875,6 +875,7 @@ pub type Ixs = isize;
875875
/// `&mut ArrayBase<S: DataMut, D>` | `&mut [A]` | [`.as_slice_mut()`](#method.as_slice_mut)<sup>[2](#req_contig_std)</sup>, [`.as_slice_memory_order_mut()`](#method.as_slice_memory_order_mut)<sup>[3](#req_contig)</sup>
876876
/// `ArrayView<A, D>` | `&[A]` | [`.into_slice()`](type.ArrayView.html#method.into_slice)
877877
/// `ArrayViewMut<A, D>` | `&mut [A]` | [`.into_slice()`](type.ArrayViewMut.html#method.into_slice)
878+
/// `Array0<A>` | `A` | [`.into_scalar()`](type.Array.html#method.into_scalar)
878879
///
879880
/// <sup><a name="into_raw_vec">1</a></sup>Returns the data in memory order.
880881
///

tests/array.rs

+15
Original file line numberDiff line numberDiff line change
@@ -928,6 +928,21 @@ fn as_slice_memory_order()
928928
assert!(a != b, "{:?} != {:?}", a, b);
929929
}
930930

931+
#[test]
932+
fn array0_into_scalar() {
933+
// With this kind of setup, the `Array`'s pointer is not the same as the
934+
// underlying `Vec`'s pointer.
935+
let a: Array0<i32> = array![4, 5, 6, 7].into_subview(Axis(0), 2);
936+
assert_ne!(a.as_ptr(), a.into_raw_vec().as_ptr());
937+
// `.into_scalar()` should still work correctly.
938+
let a: Array0<i32> = array![4, 5, 6, 7].into_subview(Axis(0), 2);
939+
assert_eq!(a.into_scalar(), 6);
940+
941+
// It should work for zero-size elements too.
942+
let a: Array0<()> = array![(), (), (), ()].into_subview(Axis(0), 2);
943+
assert_eq!(a.into_scalar(), ());
944+
}
945+
931946
#[test]
932947
fn owned_array1() {
933948
let mut a = Array::from_vec(vec![1, 2, 3, 4]);

0 commit comments

Comments
 (0)