@@ -59,14 +59,89 @@ impl<A> Array<A, Ix0>
5959impl < A , D > Array < A , D >
6060where D : Dimension
6161{
62+ /// Returns the offset (in units of `A`) from the start of the allocation
63+ /// to the first element, or `None` if the array is empty.
64+ fn offset_from_alloc_to_logical_ptr ( & self ) -> Option < usize >
65+ {
66+ if self . is_empty ( ) {
67+ return None ;
68+ }
69+ if std:: mem:: size_of :: < A > ( ) == 0 {
70+ Some ( dimension:: offset_from_low_addr_ptr_to_logical_ptr ( & self . dim , & self . strides ) )
71+ } else {
72+ let offset = unsafe { self . as_ptr ( ) . offset_from ( self . data . as_ptr ( ) ) } ;
73+ debug_assert ! ( offset >= 0 ) ;
74+ Some ( offset as usize )
75+ }
76+ }
77+
6278 /// Return a vector of the elements in the array, in the way they are
63- /// stored internally.
79+ /// stored internally, and the index in the vector corresponding to the
80+ /// logically first element of the array (or `None` if the array is empty).
6481 ///
6582 /// If the array is in standard memory layout, the logical element order
6683 /// of the array (`.iter()` order) and of the returned vector will be the same.
67- pub fn into_raw_vec ( self ) -> Vec < A >
84+ ///
85+ /// ```
86+ /// use ndarray::{array, Array2, Axis};
87+ ///
88+ /// let mut arr: Array2<f64> = array![[1., 2.], [3., 4.], [5., 6.]];
89+ /// arr.slice_axis_inplace(Axis(0), (1..).into());
90+ /// assert_eq!(arr[[0, 0]], 3.);
91+ /// let copy = arr.clone();
92+ ///
93+ /// let shape = arr.shape().to_owned();
94+ /// let strides = arr.strides().to_owned();
95+ /// let (v, offset) = arr.into_raw_vec();
96+ ///
97+ /// assert_eq!(v, &[1., 2., 3., 4., 5., 6.]);
98+ /// assert_eq!(offset, Some(2));
99+ /// assert_eq!(v[offset.unwrap()], 3.);
100+ /// for row in 0..shape[0] {
101+ /// for col in 0..shape[1] {
102+ /// let index = (
103+ /// offset.unwrap() as isize
104+ /// + row as isize * strides[0]
105+ /// + col as isize * strides[1]
106+ /// ) as usize;
107+ /// assert_eq!(v[index], copy[[row, col]]);
108+ /// }
109+ /// }
110+ /// ```
111+ ///
112+ /// In the case of zero-sized elements, the offset to the logically first
113+ /// element is somewhat meaningless. For convenience, an offset will be
114+ /// returned such that all indices computed using the offset, shape, and
115+ /// strides will be in-bounds for the `Vec<A>`. Note that this offset won't
116+ /// necessarily be the same as the offset for an array of nonzero-sized
117+ /// elements sliced in the same way.
118+ ///
119+ /// ```
120+ /// use ndarray::{array, Array2, Axis};
121+ ///
122+ /// let mut arr: Array2<()> = array![[(), ()], [(), ()], [(), ()]];
123+ /// arr.slice_axis_inplace(Axis(0), (1..).into());
124+ ///
125+ /// let shape = arr.shape().to_owned();
126+ /// let strides = arr.strides().to_owned();
127+ /// let (v, offset) = arr.into_raw_vec();
128+ ///
129+ /// assert_eq!(v, &[(), (), (), (), (), ()]);
130+ /// for row in 0..shape[0] {
131+ /// for col in 0..shape[1] {
132+ /// let index = (
133+ /// offset.unwrap() as isize
134+ /// + row as isize * strides[0]
135+ /// + col as isize * strides[1]
136+ /// ) as usize;
137+ /// assert_eq!(v[index], ());
138+ /// }
139+ /// }
140+ /// ```
141+ pub fn into_raw_vec ( self ) -> ( Vec < A > , Option < usize > )
68142 {
69- self . data . into_vec ( )
143+ let offset = self . offset_from_alloc_to_logical_ptr ( ) ;
144+ ( self . data . into_vec ( ) , offset)
70145 }
71146}
72147
@@ -575,16 +650,11 @@ where D: Dimension
575650
576651 unsafe {
577652 // grow backing storage and update head ptr
578- let data_to_array_offset = if std:: mem:: size_of :: < A > ( ) != 0 {
579- self . as_ptr ( ) . offset_from ( self . data . as_ptr ( ) )
580- } else {
581- 0
582- } ;
583- debug_assert ! ( data_to_array_offset >= 0 ) ;
653+ let offset_from_alloc_to_logical = self . offset_from_alloc_to_logical_ptr ( ) . unwrap_or ( 0 ) ;
584654 self . ptr = self
585655 . data
586656 . reserve ( len_to_append)
587- . offset ( data_to_array_offset ) ;
657+ . add ( offset_from_alloc_to_logical ) ;
588658
589659 // clone elements from view to the array now
590660 //
0 commit comments