Thanks to visit codestin.com
Credit goes to docs.rs

ndarray/
impl_owned_array.rs

1#[cfg(not(feature = "std"))]
2use alloc::vec::Vec;
3use core::ptr::NonNull;
4use std::mem;
5use std::mem::MaybeUninit;
6
7#[allow(unused_imports)] // Needed for Rust 1.64
8use rawpointer::PointerExt;
9
10use crate::imp_prelude::*;
11
12use crate::dimension;
13use crate::error::{ErrorKind, ShapeError};
14use crate::iterators::Baseiter;
15use crate::low_level_util::AbortIfPanic;
16use crate::OwnedRepr;
17use crate::Zip;
18
19/// Methods specific to `Array0`.
20///
21/// ***See also all methods for [`ArrayBase`]***
22impl<A> Array<A, Ix0>
23{
24    /// Returns the single element in the array without cloning it.
25    ///
26    /// ```
27    /// use ndarray::{arr0, Array0};
28    ///
29    /// // `Foo` doesn't implement `Clone`.
30    /// #[derive(Debug, Eq, PartialEq)]
31    /// struct Foo;
32    ///
33    /// let array: Array0<Foo> = arr0(Foo);
34    /// let scalar: Foo = array.into_scalar();
35    /// assert_eq!(scalar, Foo);
36    /// ```
37    pub fn into_scalar(self) -> A
38    {
39        let size = mem::size_of::<A>();
40        if size == 0 {
41            // Any index in the `Vec` is fine since all elements are identical.
42            self.data.into_vec().remove(0)
43        } else {
44            // Find the index in the `Vec` corresponding to `self.ptr`.
45            // (This is necessary because the element in the array might not be
46            // the first element in the `Vec`, such as if the array was created
47            // by `array![1, 2, 3, 4].slice_move(s![2])`.)
48            let first = self.ptr.as_ptr() as usize;
49            let base = self.data.as_ptr() as usize;
50            let index = (first - base) / size;
51            debug_assert_eq!((first - base) % size, 0);
52            // Remove the element at the index and return it.
53            self.data.into_vec().remove(index)
54        }
55    }
56}
57
58/// Methods specific to `Array`.
59///
60/// ***See also all methods for [`ArrayBase`]***
61impl<A, D> Array<A, D>
62where D: Dimension
63{
64    /// Returns the offset (in units of `A`) from the start of the allocation
65    /// to the first element, or `None` if the array is empty.
66    fn offset_from_alloc_to_logical_ptr(&self) -> Option<usize>
67    {
68        if self.is_empty() {
69            return None;
70        }
71        if std::mem::size_of::<A>() == 0 {
72            Some(dimension::offset_from_low_addr_ptr_to_logical_ptr(&self.dim, &self.strides))
73        } else {
74            let offset = unsafe { self.as_ptr().offset_from(self.data.as_ptr()) };
75            debug_assert!(offset >= 0);
76            Some(offset as usize)
77        }
78    }
79
80    /// Return a vector of the elements in the array, in the way they are
81    /// stored internally, and the index in the vector corresponding to the
82    /// logically first element of the array (or 0 if the array is empty).
83    ///
84    /// If the array is in standard memory layout, the logical element order
85    /// of the array (`.iter()` order) and of the returned vector will be the same.
86    ///
87    /// ```
88    /// use ndarray::{array, Array2, Axis};
89    ///
90    /// let mut arr: Array2<f64> = array![[1., 2.], [3., 4.], [5., 6.]];
91    /// arr.slice_axis_inplace(Axis(0), (1..).into());
92    /// assert_eq!(arr[[0, 0]], 3.);
93    /// let copy = arr.clone();
94    ///
95    /// let shape = arr.shape().to_owned();
96    /// let strides = arr.strides().to_owned();
97    /// let (v, offset) = arr.into_raw_vec_and_offset();
98    ///
99    /// assert_eq!(v, &[1., 2., 3., 4., 5., 6.]);
100    /// assert_eq!(offset, Some(2));
101    /// assert_eq!(v[offset.unwrap()], 3.);
102    /// for row in 0..shape[0] {
103    ///     for col in 0..shape[1] {
104    ///         let index = (
105    ///             offset.unwrap() as isize
106    ///             + row as isize * strides[0]
107    ///             + col as isize * strides[1]
108    ///         ) as usize;
109    ///         assert_eq!(v[index], copy[[row, col]]);
110    ///     }
111    /// }
112    /// ```
113    ///
114    /// In the case of zero-sized elements, the offset to the logically first
115    /// element is somewhat meaningless. For convenience, an offset will be
116    /// returned such that all indices computed using the offset, shape, and
117    /// strides will be in-bounds for the `Vec<A>`. Note that this offset won't
118    /// necessarily be the same as the offset for an array of nonzero-sized
119    /// elements sliced in the same way.
120    ///
121    /// ```
122    /// use ndarray::{array, Array2, Axis};
123    ///
124    /// let mut arr: Array2<()> = array![[(), ()], [(), ()], [(), ()]];
125    /// arr.slice_axis_inplace(Axis(0), (1..).into());
126    ///
127    /// let shape = arr.shape().to_owned();
128    /// let strides = arr.strides().to_owned();
129    /// let (v, offset) = arr.into_raw_vec_and_offset();
130    ///
131    /// assert_eq!(v, &[(), (), (), (), (), ()]);
132    /// for row in 0..shape[0] {
133    ///     for col in 0..shape[1] {
134    ///         let index = (
135    ///             offset.unwrap() as isize
136    ///             + row as isize * strides[0]
137    ///             + col as isize * strides[1]
138    ///         ) as usize;
139    ///         assert_eq!(v[index], ());
140    ///     }
141    /// }
142    /// ```
143    pub fn into_raw_vec_and_offset(self) -> (Vec<A>, Option<usize>)
144    {
145        let offset = self.offset_from_alloc_to_logical_ptr();
146        (self.data.into_vec(), offset)
147    }
148
149    /// Return a vector of the elements in the array, in the way they are
150    /// stored internally.
151    ///
152    /// Depending on slicing and strides, the logically first element of the
153    /// array can be located at an offset. Because of this, prefer to use
154    /// `.into_raw_vec_and_offset()` instead.
155    #[deprecated(note = "Use .into_raw_vec_and_offset() instead", since = "0.16.0")]
156    pub fn into_raw_vec(self) -> Vec<A>
157    {
158        self.into_raw_vec_and_offset().0
159    }
160}
161
162/// Methods specific to `Array2`.
163///
164/// ***See also all methods for [`ArrayBase`]***
165impl<A> Array<A, Ix2>
166{
167    /// Append a row to an array
168    ///
169    /// The elements from `row` are cloned and added as a new row in the array.
170    ///
171    /// ***Errors*** with a shape error if the length of the row does not match the length of the
172    /// rows in the array.
173    ///
174    /// The memory layout of the `self` array matters for ensuring that the append is efficient.
175    /// Appending automatically changes memory layout of the array so that it is appended to
176    /// along the "growing axis". However, if the memory layout needs adjusting, the array must
177    /// reallocate and move memory.
178    ///
179    /// The operation leaves the existing data in place and is most efficent if one of these is
180    /// true:
181    ///
182    /// - The axis being appended to is the longest stride axis, i.e the array is in row major
183    ///   ("C") layout.
184    /// - The array has 0 or 1 rows (It is converted to row major)
185    ///
186    /// Ensure appending is efficient by, for example, appending to an empty array and then always
187    /// pushing/appending along the same axis. For pushing rows, ndarray's default layout (C order)
188    /// is efficient.
189    ///
190    /// When repeatedly appending to a single axis, the amortized average complexity of each
191    /// append is O(m), where *m* is the length of the row.
192    ///
193    /// ```rust
194    /// use ndarray::{Array, ArrayView, array};
195    ///
196    /// // create an empty array and append
197    /// let mut a = Array::zeros((0, 4));
198    /// a.push_row(ArrayView::from(&[ 1.,  2.,  3.,  4.])).unwrap();
199    /// a.push_row(ArrayView::from(&[-1., -2., -3., -4.])).unwrap();
200    ///
201    /// assert_eq!(
202    ///     a,
203    ///     array![[ 1.,  2.,  3.,  4.],
204    ///            [-1., -2., -3., -4.]]);
205    /// ```
206    pub fn push_row(&mut self, row: ArrayView<A, Ix1>) -> Result<(), ShapeError>
207    where A: Clone
208    {
209        self.append(Axis(0), row.insert_axis(Axis(0)))
210    }
211
212    /// Append a column to an array
213    ///
214    /// The elements from `column` are cloned and added as a new column in the array.
215    ///
216    /// ***Errors*** with a shape error if the length of the column does not match the length of
217    /// the columns in the array.
218    ///
219    /// The memory layout of the `self` array matters for ensuring that the append is efficient.
220    /// Appending automatically changes memory layout of the array so that it is appended to
221    /// along the "growing axis". However, if the memory layout needs adjusting, the array must
222    /// reallocate and move memory.
223    ///
224    /// The operation leaves the existing data in place and is most efficent if one of these is
225    /// true:
226    ///
227    /// - The axis being appended to is the longest stride axis, i.e the array is in column major
228    ///   ("F") layout.
229    /// - The array has 0 or 1 columns (It is converted to column major)
230    ///
231    /// Ensure appending is efficient by, for example, appending to an empty array and then always
232    /// pushing/appending along the same axis. For pushing columns, column major layout (F order)
233    /// is efficient.
234    ///
235    /// When repeatedly appending to a single axis, the amortized average complexity of each append
236    /// is O(m), where *m* is the length of the column.
237    ///
238    /// ```rust
239    /// use ndarray::{Array, ArrayView, array};
240    ///
241    /// // create an empty array and append
242    /// let mut a = Array::zeros((2, 0));
243    /// a.push_column(ArrayView::from(&[1., 2.])).unwrap();
244    /// a.push_column(ArrayView::from(&[-1., -2.])).unwrap();
245    ///
246    /// assert_eq!(
247    ///     a,
248    ///     array![[1., -1.],
249    ///            [2., -2.]]);
250    /// ```
251    pub fn push_column(&mut self, column: ArrayView<A, Ix1>) -> Result<(), ShapeError>
252    where A: Clone
253    {
254        self.append(Axis(1), column.insert_axis(Axis(1)))
255    }
256
257    /// Reserve capacity to grow array by at least `additional` rows.
258    ///
259    /// Existing elements of `array` are untouched and the backing storage is grown by
260    /// calling the underlying `reserve` method of the `OwnedRepr`.
261    ///
262    /// This is useful when pushing or appending repeatedly to an array to avoid multiple
263    /// allocations.
264    ///
265    /// ***Errors*** with a shape error if the resultant capacity is larger than the addressable
266    /// bounds; that is, the product of non-zero axis lengths once `axis` has been extended by
267    /// `additional` exceeds `isize::MAX`.
268    ///
269    /// ```rust
270    /// use ndarray::Array2;
271    /// let mut a = Array2::<i32>::zeros((2,4));
272    /// a.reserve_rows(1000).unwrap();
273    /// assert!(a.into_raw_vec().capacity() >= 4*1002);
274    /// ```
275    pub fn reserve_rows(&mut self, additional: usize) -> Result<(), ShapeError>
276    {
277        self.reserve(Axis(0), additional)
278    }
279
280    /// Reserve capacity to grow array by at least `additional` columns.
281    ///
282    /// Existing elements of `array` are untouched and the backing storage is grown by
283    /// calling the underlying `reserve` method of the `OwnedRepr`.
284    ///
285    /// This is useful when pushing or appending repeatedly to an array to avoid multiple
286    /// allocations.
287    ///
288    /// ***Errors*** with a shape error if the resultant capacity is larger than the addressable
289    /// bounds; that is, the product of non-zero axis lengths once `axis` has been extended by
290    /// `additional` exceeds `isize::MAX`.
291    ///
292    /// ```rust
293    /// use ndarray::Array2;
294    /// let mut a = Array2::<i32>::zeros((2,4));
295    /// a.reserve_columns(1000).unwrap();
296    /// assert!(a.into_raw_vec().capacity() >= 2*1002);
297    /// ```
298    pub fn reserve_columns(&mut self, additional: usize) -> Result<(), ShapeError>
299    {
300        self.reserve(Axis(1), additional)
301    }
302}
303
304impl<A, D> Array<A, D>
305where D: Dimension
306{
307    /// Move all elements from self into `new_array`, which must be of the same shape but
308    /// can have a different memory layout. The destination is overwritten completely.
309    ///
310    /// The destination should be a mut reference to an array or an `ArrayViewMut` with
311    /// `A` elements.
312    ///
313    /// ***Panics*** if the shapes don't agree.
314    ///
315    /// ## Example
316    ///
317    /// ```
318    /// use ndarray::Array;
319    ///
320    /// // Usage example of move_into in safe code
321    /// let mut a = Array::default((10, 10));
322    /// let b = Array::from_shape_fn((10, 10), |(i, j)| (i + j).to_string());
323    /// b.move_into(&mut a);
324    /// ```
325    pub fn move_into<'a, AM>(self, new_array: AM)
326    where
327        AM: Into<ArrayViewMut<'a, A, D>>,
328        A: 'a,
329    {
330        // Remove generic parameter P and call the implementation
331        let new_array = new_array.into();
332        if mem::needs_drop::<A>() {
333            self.move_into_needs_drop(new_array);
334        } else {
335            // If `A` doesn't need drop, we can overwrite the destination.
336            // Safe because: move_into_uninit only writes initialized values
337            unsafe { self.move_into_uninit(new_array.into_maybe_uninit()) }
338        }
339    }
340
341    fn move_into_needs_drop(mut self, new_array: ArrayViewMut<A, D>)
342    {
343        // Simple case where `A` has a destructor: just swap values between self and new_array.
344        // Afterwards, `self` drops full of initialized values and dropping works as usual.
345        // This avoids moving out of owned values in `self` while at the same time managing
346        // the dropping if the values being overwritten in `new_array`.
347        Zip::from(&mut self)
348            .and(new_array)
349            .for_each(|src, dst| mem::swap(src, dst));
350    }
351
352    /// Move all elements from self into `new_array`, which must be of the same shape but
353    /// can have a different memory layout. The destination is overwritten completely.
354    ///
355    /// The destination should be a mut reference to an array or an `ArrayViewMut` with
356    /// `MaybeUninit<A>` elements (which are overwritten without dropping any existing value).
357    ///
358    /// Minor implementation note: Owned arrays like `self` may be sliced in place and own elements
359    /// that are not part of their active view; these are dropped at the end of this function,
360    /// after all elements in the "active view" are moved into `new_array`. If there is a panic in
361    /// drop of any such element, other elements may be leaked.
362    ///
363    /// ***Panics*** if the shapes don't agree.
364    ///
365    /// ## Example
366    ///
367    /// ```
368    /// use ndarray::Array;
369    ///
370    /// let a = Array::from_iter(0..100).into_shape_with_order((10, 10)).unwrap();
371    /// let mut b = Array::uninit((10, 10));
372    /// a.move_into_uninit(&mut b);
373    /// unsafe {
374    ///     // we can now promise we have fully initialized `b`.
375    ///     let b = b.assume_init();
376    /// }
377    /// ```
378    pub fn move_into_uninit<'a, AM>(self, new_array: AM)
379    where
380        AM: Into<ArrayViewMut<'a, MaybeUninit<A>, D>>,
381        A: 'a,
382    {
383        // Remove generic parameter AM and call the implementation
384        self.move_into_impl(new_array.into())
385    }
386
387    fn move_into_impl(mut self, new_array: ArrayViewMut<MaybeUninit<A>, D>)
388    {
389        unsafe {
390            // Safety: copy_to_nonoverlapping cannot panic
391            let guard = AbortIfPanic(&"move_into: moving out of owned value");
392            // Move all reachable elements; we move elements out of `self`.
393            // and thus must not panic for the whole section until we call `self.data.set_len(0)`.
394            Zip::from(self.raw_view_mut())
395                .and(new_array)
396                .for_each(|src, dst| {
397                    src.copy_to_nonoverlapping(dst.as_mut_ptr(), 1);
398                });
399            guard.defuse();
400            // Drop all unreachable elements
401            self.drop_unreachable_elements();
402        }
403    }
404
405    /// This drops all "unreachable" elements in the data storage of self.
406    ///
407    /// That means those elements that are not visible in the slicing of the array.
408    /// *Reachable elements are assumed to already have been moved from.*
409    ///
410    /// # Safety
411    ///
412    /// This is a panic critical section since `self` is already moved-from.
413    fn drop_unreachable_elements(mut self) -> OwnedRepr<A>
414    {
415        let self_len = self.len();
416
417        // "deconstruct" self; the owned repr releases ownership of all elements and we
418        // and carry on with raw view methods
419        let data_len = self.data.len();
420
421        let has_unreachable_elements = self_len != data_len;
422        if !has_unreachable_elements || mem::size_of::<A>() == 0 || !mem::needs_drop::<A>() {
423            unsafe {
424                self.data.set_len(0);
425            }
426            self.data
427        } else {
428            self.drop_unreachable_elements_slow()
429        }
430    }
431
432    #[inline(never)]
433    #[cold]
434    fn drop_unreachable_elements_slow(mut self) -> OwnedRepr<A>
435    {
436        // "deconstruct" self; the owned repr releases ownership of all elements and we
437        // carry on with raw view methods
438        let data_len = self.data.len();
439        let data_ptr = self.data.as_nonnull_mut();
440
441        unsafe {
442            // Safety: self.data releases ownership of the elements. Any panics below this point
443            // will result in leaking elements instead of double drops.
444            let self_ = self.raw_view_mut();
445            self.data.set_len(0);
446
447            drop_unreachable_raw(self_, data_ptr, data_len);
448        }
449
450        self.data
451    }
452
453    /// Create an empty array with an all-zeros shape
454    ///
455    /// ***Panics*** if D is zero-dimensional, because it can't be empty
456    pub(crate) fn empty() -> Array<A, D>
457    {
458        assert_ne!(D::NDIM, Some(0));
459        let ndim = D::NDIM.unwrap_or(1);
460        Array::from_shape_simple_fn(D::zeros(ndim), || unreachable!())
461    }
462
463    /// Create new_array with the right layout for appending to `growing_axis`
464    #[cold]
465    fn change_to_contig_append_layout(&mut self, growing_axis: Axis)
466    {
467        let ndim = self.ndim();
468        let mut dim = self.raw_dim();
469
470        // The array will be created with 0 (C) or ndim-1 (F) as the biggest stride
471        // axis. Rearrange the shape so that `growing_axis` is the biggest stride axis
472        // afterwards.
473        let mut new_array;
474        if growing_axis == Axis(ndim - 1) {
475            new_array = Self::uninit(dim.f());
476        } else {
477            dim.slice_mut()[..=growing_axis.index()].rotate_right(1);
478            new_array = Self::uninit(dim);
479            new_array.dim.slice_mut()[..=growing_axis.index()].rotate_left(1);
480            new_array.strides.slice_mut()[..=growing_axis.index()].rotate_left(1);
481        }
482
483        // self -> old_self.
484        // dummy array -> self.
485        // old_self elements are moved -> new_array.
486        let old_self = std::mem::replace(self, Self::empty());
487        old_self.move_into_uninit(new_array.view_mut());
488
489        // new_array -> self.
490        unsafe {
491            *self = new_array.assume_init();
492        }
493    }
494
495    /// Append an array to the array along an axis.
496    ///
497    /// The elements of `array` are cloned and extend the axis `axis` in the present array;
498    /// `self` will grow in size by 1 along `axis`.
499    ///
500    /// Append to the array, where the array being pushed to the array has one dimension less than
501    /// the `self` array. This method is equivalent to [append](ArrayBase::append) in this way:
502    /// `self.append(axis, array.insert_axis(axis))`.
503    ///
504    /// ***Errors*** with a shape error if the shape of self does not match the array-to-append;
505    /// all axes *except* the axis along which it being appended matter for this check:
506    /// the shape of `self` with `axis` removed must be the same as the shape of `array`.
507    ///
508    /// The memory layout of the `self` array matters for ensuring that the append is efficient.
509    /// Appending automatically changes memory layout of the array so that it is appended to
510    /// along the "growing axis". However, if the memory layout needs adjusting, the array must
511    /// reallocate and move memory.
512    ///
513    /// The operation leaves the existing data in place and is most efficent if `axis` is a
514    /// "growing axis" for the array, i.e. one of these is true:
515    ///
516    /// - The axis is the longest stride axis, for example the 0th axis in a C-layout or the
517    ///   *n-1*th axis in an F-layout array.
518    /// - The axis has length 0 or 1 (It is converted to the new growing axis)
519    ///
520    /// Ensure appending is efficient by for example starting from an empty array and/or always
521    /// appending to an array along the same axis.
522    ///
523    /// The amortized average complexity of the append, when appending along its growing axis, is
524    /// O(*m*) where *m* is the number of individual elements to append.
525    ///
526    /// The memory layout of the argument `array` does not matter to the same extent.
527    ///
528    /// ```rust
529    /// use ndarray::{Array, ArrayView, array, Axis};
530    ///
531    /// // create an empty array and push rows to it
532    /// let mut a = Array::zeros((0, 4));
533    /// let ones  = ArrayView::from(&[1.; 4]);
534    /// let zeros = ArrayView::from(&[0.; 4]);
535    /// a.push(Axis(0), ones).unwrap();
536    /// a.push(Axis(0), zeros).unwrap();
537    /// a.push(Axis(0), ones).unwrap();
538    ///
539    /// assert_eq!(
540    ///     a,
541    ///     array![[1., 1., 1., 1.],
542    ///            [0., 0., 0., 0.],
543    ///            [1., 1., 1., 1.]]);
544    /// ```
545    pub fn push(&mut self, axis: Axis, array: ArrayView<A, D::Smaller>) -> Result<(), ShapeError>
546    where
547        A: Clone,
548        D: RemoveAxis,
549    {
550        // same-dimensionality conversion
551        self.append(axis, array.insert_axis(axis).into_dimensionality::<D>().unwrap())
552    }
553
554    /// Append an array to the array along an axis.
555    ///
556    /// The elements of `array` are cloned and extend the axis `axis` in the present array;
557    /// `self` will grow in size by `array.len_of(axis)` along `axis`.
558    ///
559    /// ***Errors*** with a shape error if the shape of self does not match the array-to-append;
560    /// all axes *except* the axis along which it being appended matter for this check:
561    /// the shape of `self` with `axis` removed must be the same as the shape of `array` with
562    /// `axis` removed.
563    ///
564    /// The memory layout of the `self` array matters for ensuring that the append is efficient.
565    /// Appending automatically changes memory layout of the array so that it is appended to
566    /// along the "growing axis". However, if the memory layout needs adjusting, the array must
567    /// reallocate and move memory.
568    ///
569    /// The operation leaves the existing data in place and is most efficent if `axis` is a
570    /// "growing axis" for the array, i.e. one of these is true:
571    ///
572    /// - The axis is the longest stride axis, for example the 0th axis in a C-layout or the
573    ///   *n-1*th axis in an F-layout array.
574    /// - The axis has length 0 or 1 (It is converted to the new growing axis)
575    ///
576    /// Ensure appending is efficient by for example starting from an empty array and/or always
577    /// appending to an array along the same axis.
578    ///
579    /// The amortized average complexity of the append, when appending along its growing axis, is
580    /// O(*m*) where *m* is the number of individual elements to append.
581    ///
582    /// The memory layout of the argument `array` does not matter to the same extent.
583    ///
584    /// ```rust
585    /// use ndarray::{Array, ArrayView, array, Axis};
586    ///
587    /// // create an empty array and append two rows at a time
588    /// let mut a = Array::zeros((0, 4));
589    /// let ones  = ArrayView::from(&[1.; 8]).into_shape_with_order((2, 4)).unwrap();
590    /// let zeros = ArrayView::from(&[0.; 8]).into_shape_with_order((2, 4)).unwrap();
591    /// a.append(Axis(0), ones).unwrap();
592    /// a.append(Axis(0), zeros).unwrap();
593    /// a.append(Axis(0), ones).unwrap();
594    ///
595    /// assert_eq!(
596    ///     a,
597    ///     array![[1., 1., 1., 1.],
598    ///            [1., 1., 1., 1.],
599    ///            [0., 0., 0., 0.],
600    ///            [0., 0., 0., 0.],
601    ///            [1., 1., 1., 1.],
602    ///            [1., 1., 1., 1.]]);
603    /// ```
604    pub fn append(&mut self, axis: Axis, mut array: ArrayView<A, D>) -> Result<(), ShapeError>
605    where
606        A: Clone,
607        D: RemoveAxis,
608    {
609        if self.ndim() == 0 {
610            return Err(ShapeError::from_kind(ErrorKind::IncompatibleShape));
611        }
612
613        let current_axis_len = self.len_of(axis);
614        let self_dim = self.raw_dim();
615        let array_dim = array.raw_dim();
616        let remaining_shape = self_dim.remove_axis(axis);
617        let array_rem_shape = array_dim.remove_axis(axis);
618
619        if remaining_shape != array_rem_shape {
620            return Err(ShapeError::from_kind(ErrorKind::IncompatibleShape));
621        }
622
623        let len_to_append = array.len();
624
625        let mut res_dim = self_dim;
626        res_dim[axis.index()] += array_dim[axis.index()];
627        let new_len = dimension::size_of_shape_checked(&res_dim)?;
628
629        if len_to_append == 0 {
630            // There are no elements to append and shapes are compatible:
631            // either the dimension increment is zero, or there is an existing
632            // zero in another axis in self.
633            debug_assert_eq!(self.len(), new_len);
634            self.dim = res_dim;
635            return Ok(());
636        }
637
638        let self_is_empty = self.is_empty();
639        let mut incompatible_layout = false;
640
641        // array must be empty or have `axis` as the outermost (longest stride) axis
642        if !self_is_empty && current_axis_len > 1 {
643            // `axis` must be max stride axis or equal to its stride
644            let axis_stride = self.stride_of(axis);
645            if axis_stride < 0 {
646                incompatible_layout = true;
647            } else {
648                for ax in self.axes() {
649                    if ax.axis == axis {
650                        continue;
651                    }
652                    if ax.len > 1 && ax.stride.abs() > axis_stride {
653                        incompatible_layout = true;
654                        break;
655                    }
656                }
657            }
658        }
659
660        // array must be be "full" (contiguous and have no exterior holes)
661        if self.len() != self.data.len() {
662            incompatible_layout = true;
663        }
664
665        if incompatible_layout {
666            self.change_to_contig_append_layout(axis);
667            // safety-check parameters after remodeling
668            debug_assert_eq!(self_is_empty, self.is_empty());
669            debug_assert_eq!(current_axis_len, self.len_of(axis));
670        }
671
672        let strides = if self_is_empty {
673            // recompute strides - if the array was previously empty, it could have zeros in
674            // strides.
675            // The new order is based on c/f-contig but must have `axis` as outermost axis.
676            if axis == Axis(self.ndim() - 1) {
677                // prefer f-contig when appending to the last axis
678                // Axis n - 1 is outermost axis
679                res_dim.fortran_strides()
680            } else {
681                // standard axis order except for the growing axis;
682                // anticipates that it's likely that `array` has standard order apart from the
683                // growing axis.
684                res_dim.slice_mut()[..=axis.index()].rotate_right(1);
685                let mut strides = res_dim.default_strides();
686                res_dim.slice_mut()[..=axis.index()].rotate_left(1);
687                strides.slice_mut()[..=axis.index()].rotate_left(1);
688                strides
689            }
690        } else if current_axis_len == 1 {
691            // This is the outermost/longest stride axis; so we find the max across the other axes
692            let new_stride = self.axes().fold(1, |acc, ax| {
693                if ax.axis == axis || ax.len <= 1 {
694                    acc
695                } else {
696                    let this_ax = ax.len as isize * ax.stride.abs();
697                    if this_ax > acc {
698                        this_ax
699                    } else {
700                        acc
701                    }
702                }
703            });
704            let mut strides = self.strides.clone();
705            strides[axis.index()] = new_stride as usize;
706            strides
707        } else {
708            self.strides.clone()
709        };
710
711        // grow backing storage and update head ptr
712        self.reserve(axis, array_dim[axis.index()])?;
713
714        unsafe {
715            // clone elements from view to the array now
716            //
717            // To be robust for panics and drop the right elements, we want
718            // to fill the tail in memory order, so that we can drop the right elements on panic.
719            //
720            // We have: Zip::from(tail_view).and(array)
721            // Transform tail_view into standard order by inverting and moving its axes.
722            // Keep the Zip traversal unchanged by applying the same axis transformations to
723            // `array`. This ensures the Zip traverses the underlying memory in order.
724            //
725            // XXX It would be possible to skip this transformation if the element
726            // doesn't have drop. However, in the interest of code coverage, all elements
727            // use this code initially.
728
729            // Invert axes in tail_view by inverting strides
730            let mut tail_strides = strides.clone();
731            if tail_strides.ndim() > 1 {
732                for i in 0..tail_strides.ndim() {
733                    let s = tail_strides[i] as isize;
734                    if s < 0 {
735                        tail_strides.set_axis(Axis(i), -s as usize);
736                        array.invert_axis(Axis(i));
737                    }
738                }
739            }
740
741            // With > 0 strides, the current end of data is the correct base pointer for tail_view
742            let tail_ptr = self.data.as_end_nonnull();
743            let mut tail_view = RawArrayViewMut::new(tail_ptr, array_dim, tail_strides);
744
745            if tail_view.ndim() > 1 {
746                sort_axes_in_default_order_tandem(&mut tail_view, &mut array);
747                debug_assert!(tail_view.is_standard_layout(),
748                              "not std layout dim: {:?}, strides: {:?}",
749                              tail_view.shape(), tail_view.strides());
750            }
751
752            // Keep track of currently filled length of `self.data` and update it
753            // on scope exit (panic or loop finish). This "indirect" way to
754            // write the length is used to help the compiler, the len store to self.data may
755            // otherwise be mistaken to alias with other stores in the loop.
756            struct SetLenOnDrop<'a, A: 'a>
757            {
758                len: usize,
759                data: &'a mut OwnedRepr<A>,
760            }
761
762            impl<A> Drop for SetLenOnDrop<'_, A>
763            {
764                fn drop(&mut self)
765                {
766                    unsafe {
767                        self.data.set_len(self.len);
768                    }
769                }
770            }
771
772            let mut data_length_guard = SetLenOnDrop {
773                len: self.data.len(),
774                data: &mut self.data,
775            };
776
777            // Safety: tail_view is constructed to have the same shape as array
778            Zip::from(tail_view)
779                .and_unchecked(array)
780                .debug_assert_c_order()
781                .for_each(|to, from| {
782                    to.write(from.clone());
783                    data_length_guard.len += 1;
784                });
785            drop(data_length_guard);
786
787            // update array dimension
788            self.strides = strides;
789            self.dim = res_dim;
790        }
791        // multiple assertions after pointer & dimension update
792        debug_assert_eq!(self.data.len(), self.len());
793        debug_assert_eq!(self.len(), new_len);
794        debug_assert!(self.pointer_is_inbounds());
795
796        Ok(())
797    }
798
799    /// Reserve capacity to grow array along `axis` by at least `additional` elements.
800    ///
801    /// The axis should be in the range `Axis(` 0 .. *n* `)` where *n* is the
802    /// number of dimensions (axes) of the array.
803    ///
804    /// Existing elements of `array` are untouched and the backing storage is grown by
805    /// calling the underlying `reserve` method of the `OwnedRepr`.
806    ///
807    /// This is useful when pushing or appending repeatedly to an array to avoid multiple
808    /// allocations.
809    ///
810    /// ***Panics*** if the axis is out of bounds.
811    ///
812    /// ***Errors*** with a shape error if the resultant capacity is larger than the addressable
813    /// bounds; that is, the product of non-zero axis lengths once `axis` has been extended by
814    /// `additional` exceeds `isize::MAX`.
815    ///
816    /// ```rust
817    /// use ndarray::{Array3, Axis};
818    /// let mut a = Array3::<i32>::zeros((0,2,4));
819    /// a.reserve(Axis(0), 1000).unwrap();
820    /// assert!(a.into_raw_vec().capacity() >= 2*4*1000);
821    /// ```
822    ///
823    pub fn reserve(&mut self, axis: Axis, additional: usize) -> Result<(), ShapeError>
824    where D: RemoveAxis
825    {
826        debug_assert!(axis.index() < self.ndim());
827        let self_dim = self.raw_dim();
828        let remaining_shape = self_dim.remove_axis(axis);
829
830        // Make sure added capacity doesn't overflow usize::MAX
831        let len_to_append = remaining_shape
832            .size()
833            .checked_mul(additional)
834            .ok_or(ShapeError::from_kind(ErrorKind::Overflow))?;
835
836        // Make sure new capacity is still in bounds
837        let mut res_dim = self_dim;
838        res_dim[axis.index()] += additional;
839        let new_len = dimension::size_of_shape_checked(&res_dim)?;
840
841        // Check whether len_to_append would cause an overflow
842        debug_assert_eq!(self.len().checked_add(len_to_append).unwrap(), new_len);
843
844        unsafe {
845            // grow backing storage and update head ptr
846            let data_to_array_offset = if std::mem::size_of::<A>() != 0 {
847                self.as_ptr().offset_from(self.data.as_ptr())
848            } else {
849                0
850            };
851            debug_assert!(data_to_array_offset >= 0);
852            self.ptr = self
853                .data
854                .reserve(len_to_append)
855                .offset(data_to_array_offset);
856        }
857
858        debug_assert!(self.pointer_is_inbounds());
859
860        Ok(())
861    }
862}
863
864/// This drops all "unreachable" elements in `self_` given the data pointer and data length.
865///
866/// # Safety
867///
868/// This is an internal function for use by move_into and IntoIter only, safety invariants may need
869/// to be upheld across the calls from those implementations.
870pub(crate) unsafe fn drop_unreachable_raw<A, D>(
871    mut self_: RawArrayViewMut<A, D>, data_ptr: NonNull<A>, data_len: usize,
872) where D: Dimension
873{
874    let self_len = self_.len();
875
876    for i in 0..self_.ndim() {
877        if self_.stride_of(Axis(i)) < 0 {
878            self_.invert_axis(Axis(i));
879        }
880    }
881    sort_axes_in_default_order(&mut self_);
882    // with uninverted axes this is now the element with lowest address
883    let array_memory_head_ptr = self_.ptr;
884    let data_end_ptr = data_ptr.add(data_len);
885    debug_assert!(data_ptr <= array_memory_head_ptr);
886    debug_assert!(array_memory_head_ptr <= data_end_ptr);
887
888    // The idea is simply this: the iterator will yield the elements of self_ in
889    // increasing address order.
890    //
891    // The pointers produced by the iterator are those that we *do not* touch.
892    // The pointers *not mentioned* by the iterator are those we have to drop.
893    //
894    // We have to drop elements in the range from `data_ptr` until (not including)
895    // `data_end_ptr`, except those that are produced by `iter`.
896
897    // As an optimization, the innermost axis is removed if it has stride 1, because
898    // we then have a long stretch of contiguous elements we can skip as one.
899    let inner_lane_len;
900    if self_.ndim() > 1 && self_.strides.last_elem() == 1 {
901        self_.dim.slice_mut().rotate_right(1);
902        self_.strides.slice_mut().rotate_right(1);
903        inner_lane_len = self_.dim[0];
904        self_.dim[0] = 1;
905        self_.strides[0] = 1;
906    } else {
907        inner_lane_len = 1;
908    }
909
910    // iter is a raw pointer iterator traversing the array in memory order now with the
911    // sorted axes.
912    let mut iter = Baseiter::new(self_.ptr, self_.dim, self_.strides);
913    let mut dropped_elements = 0;
914
915    let mut last_ptr = data_ptr;
916
917    while let Some(elem_ptr) = iter.next() {
918        // The interval from last_ptr up until (not including) elem_ptr
919        // should now be dropped. This interval may be empty, then we just skip this loop.
920        while last_ptr != elem_ptr {
921            debug_assert!(last_ptr < data_end_ptr);
922            std::ptr::drop_in_place(last_ptr.as_mut());
923            last_ptr = last_ptr.add(1);
924            dropped_elements += 1;
925        }
926        // Next interval will continue one past the current lane
927        last_ptr = elem_ptr.add(inner_lane_len);
928    }
929
930    while last_ptr < data_end_ptr {
931        std::ptr::drop_in_place(last_ptr.as_mut());
932        last_ptr = last_ptr.add(1);
933        dropped_elements += 1;
934    }
935
936    assert_eq!(data_len, dropped_elements + self_len,
937               "Internal error: inconsistency in move_into");
938}
939
940/// Sort axes to standard order, i.e Axis(0) has biggest stride and Axis(n - 1) least stride
941///
942/// The axes should have stride >= 0 before calling this method.
943fn sort_axes_in_default_order<S, D>(a: &mut ArrayBase<S, D>)
944where
945    S: RawData,
946    D: Dimension,
947{
948    if a.ndim() <= 1 {
949        return;
950    }
951    sort_axes1_impl(&mut a.dim, &mut a.strides);
952}
953
954fn sort_axes1_impl<D>(adim: &mut D, astrides: &mut D)
955where D: Dimension
956{
957    debug_assert!(adim.ndim() > 1);
958    debug_assert_eq!(adim.ndim(), astrides.ndim());
959    // bubble sort axes
960    let mut changed = true;
961    while changed {
962        changed = false;
963        for i in 0..adim.ndim() - 1 {
964            let axis_i = i;
965            let next_axis = i + 1;
966
967            // make sure higher stride axes sort before.
968            debug_assert!(astrides.slice()[axis_i] as isize >= 0);
969            if (astrides.slice()[axis_i] as isize) < astrides.slice()[next_axis] as isize {
970                changed = true;
971                adim.slice_mut().swap(axis_i, next_axis);
972                astrides.slice_mut().swap(axis_i, next_axis);
973            }
974        }
975    }
976}
977
978/// Sort axes to standard order, i.e Axis(0) has biggest stride and Axis(n - 1) least stride
979///
980/// Axes in a and b are sorted by the strides of `a`, and `a`'s axes should have stride >= 0 before
981/// calling this method.
982fn sort_axes_in_default_order_tandem<S, S2, D>(a: &mut ArrayBase<S, D>, b: &mut ArrayBase<S2, D>)
983where
984    S: RawData,
985    S2: RawData,
986    D: Dimension,
987{
988    if a.ndim() <= 1 {
989        return;
990    }
991    sort_axes2_impl(&mut a.dim, &mut a.strides, &mut b.dim, &mut b.strides);
992}
993
994fn sort_axes2_impl<D>(adim: &mut D, astrides: &mut D, bdim: &mut D, bstrides: &mut D)
995where D: Dimension
996{
997    debug_assert!(adim.ndim() > 1);
998    debug_assert_eq!(adim.ndim(), bdim.ndim());
999    // bubble sort axes
1000    let mut changed = true;
1001    while changed {
1002        changed = false;
1003        for i in 0..adim.ndim() - 1 {
1004            let axis_i = i;
1005            let next_axis = i + 1;
1006
1007            // make sure higher stride axes sort before.
1008            debug_assert!(astrides.slice()[axis_i] as isize >= 0);
1009            if (astrides.slice()[axis_i] as isize) < astrides.slice()[next_axis] as isize {
1010                changed = true;
1011                adim.slice_mut().swap(axis_i, next_axis);
1012                astrides.slice_mut().swap(axis_i, next_axis);
1013                bdim.slice_mut().swap(axis_i, next_axis);
1014                bstrides.slice_mut().swap(axis_i, next_axis);
1015            }
1016        }
1017    }
1018}