kn0sys_ndarray/
impl_methods.rs

1// Copyright 2014-2016 bluss and ndarray developers.
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6// option. This file may not be copied, modified, or distributed
7// except according to those terms.
8
9use alloc::slice;
10use alloc::vec;
11#[cfg(not(feature = "std"))]
12use alloc::vec::Vec;
13#[allow(unused_imports)]
14use rawpointer::PointerExt;
15use std::mem::{size_of, ManuallyDrop};
16
17use crate::imp_prelude::*;
18
19use crate::argument_traits::AssignElem;
20use crate::dimension;
21use crate::dimension::broadcast::co_broadcast;
22use crate::dimension::reshape_dim;
23use crate::dimension::IntoDimension;
24use crate::dimension::{
25    abs_index,
26    axes_of,
27    do_slice,
28    merge_axes,
29    move_min_stride_axis_to_last,
30    offset_from_low_addr_ptr_to_logical_ptr,
31    size_of_shape_checked,
32    stride_offset,
33    Axes,
34};
35use crate::error::{self, from_kind, ErrorKind, ShapeError};
36use crate::itertools::zip;
37use crate::math_cell::MathCell;
38use crate::order::Order;
39use crate::shape_builder::ShapeArg;
40use crate::zip::{IntoNdProducer, Zip};
41use crate::AxisDescription;
42use crate::{arraytraits, DimMax};
43
44use crate::iter::{
45    AxisChunksIter,
46    AxisChunksIterMut,
47    AxisIter,
48    AxisIterMut,
49    AxisWindows,
50    ExactChunks,
51    ExactChunksMut,
52    IndexedIter,
53    IndexedIterMut,
54    Iter,
55    IterMut,
56    Lanes,
57    LanesMut,
58    Windows,
59};
60use crate::slice::{MultiSliceArg, SliceArg};
61use crate::stacking::concatenate;
62use crate::{NdIndex, Slice, SliceInfoElem};
63
64/// # Methods For All Array Types
65impl<A, S, D> ArrayBase<S, D>
66where
67    S: RawData<Elem = A>,
68    D: Dimension,
69{
70    /// Return the total number of elements in the array.
71    pub fn len(&self) -> usize
72    {
73        self.dim.size()
74    }
75
76    /// Return the length of `axis`.
77    ///
78    /// The axis should be in the range `Axis(` 0 .. *n* `)` where *n* is the
79    /// number of dimensions (axes) of the array.
80    ///
81    /// ***Panics*** if the axis is out of bounds.
82    #[track_caller]
83    pub fn len_of(&self, axis: Axis) -> usize
84    {
85        self.dim[axis.index()]
86    }
87
88    /// Return whether the array has any elements
89    pub fn is_empty(&self) -> bool
90    {
91        self.len() == 0
92    }
93
94    /// Return the number of dimensions (axes) in the array
95    pub fn ndim(&self) -> usize
96    {
97        self.dim.ndim()
98    }
99
100    /// Return the shape of the array in its “pattern” form,
101    /// an integer in the one-dimensional case, tuple in the n-dimensional cases
102    /// and so on.
103    pub fn dim(&self) -> D::Pattern
104    {
105        self.dim.clone().into_pattern()
106    }
107
108    /// Return the shape of the array as it's stored in the array.
109    ///
110    /// This is primarily useful for passing to other `ArrayBase`
111    /// functions, such as when creating another array of the same
112    /// shape and dimensionality.
113    ///
114    /// ```
115    /// use kn0sys_ndarray::Array;
116    ///
117    /// let a = Array::from_elem((2, 3), 5.);
118    ///
119    /// // Create an array of zeros that's the same shape and dimensionality as `a`.
120    /// let b = Array::<f64, _>::zeros(a.raw_dim());
121    /// ```
122    pub fn raw_dim(&self) -> D
123    {
124        self.dim.clone()
125    }
126
127    /// Return the shape of the array as a slice.
128    ///
129    /// Note that you probably don't want to use this to create an array of the
130    /// same shape as another array because creating an array with e.g.
131    /// [`Array::zeros()`](ArrayBase::zeros) using a shape of type `&[usize]`
132    /// results in a dynamic-dimensional array. If you want to create an array
133    /// that has the same shape and dimensionality as another array, use
134    /// [`.raw_dim()`](ArrayBase::raw_dim) instead:
135    ///
136    /// ```rust
137    /// use kn0sys_ndarray::{Array, Array2};
138    ///
139    /// let a = Array2::<i32>::zeros((3, 4));
140    /// let shape = a.shape();
141    /// assert_eq!(shape, &[3, 4]);
142    ///
143    /// // Since `a.shape()` returned `&[usize]`, we get an `ArrayD` instance:
144    /// let b = Array::zeros(shape);
145    /// assert_eq!(a.clone().into_dyn(), b);
146    ///
147    /// // To get the same dimension type, use `.raw_dim()` instead:
148    /// let c = Array::zeros(a.raw_dim());
149    /// assert_eq!(a, c);
150    /// ```
151    pub fn shape(&self) -> &[usize]
152    {
153        self.dim.slice()
154    }
155
156    /// Return the strides of the array as a slice.
157    pub fn strides(&self) -> &[isize]
158    {
159        let s = self.strides.slice();
160        // reinterpret unsigned integer as signed
161        unsafe { slice::from_raw_parts(s.as_ptr() as *const _, s.len()) }
162    }
163
164    /// Return the stride of `axis`.
165    ///
166    /// The axis should be in the range `Axis(` 0 .. *n* `)` where *n* is the
167    /// number of dimensions (axes) of the array.
168    ///
169    /// ***Panics*** if the axis is out of bounds.
170    #[track_caller]
171    pub fn stride_of(&self, axis: Axis) -> isize
172    {
173        // strides are reinterpreted as isize
174        self.strides[axis.index()] as isize
175    }
176
177    /// Return a read-only view of the array
178    pub fn view(&self) -> ArrayView<'_, A, D>
179    where S: Data
180    {
181        debug_assert!(self.pointer_is_inbounds());
182        unsafe { ArrayView::new(self.ptr, self.dim.clone(), self.strides.clone()) }
183    }
184
185    /// Return a read-write view of the array
186    pub fn view_mut(&mut self) -> ArrayViewMut<'_, A, D>
187    where S: DataMut
188    {
189        self.ensure_unique();
190        unsafe { ArrayViewMut::new(self.ptr, self.dim.clone(), self.strides.clone()) }
191    }
192
193    /// Return a shared view of the array with elements as if they were embedded in cells.
194    ///
195    /// The cell view requires a mutable borrow of the array. Once borrowed the
196    /// cell view itself can be copied and accessed without exclusivity.
197    ///
198    /// The view acts "as if" the elements are temporarily in cells, and elements
199    /// can be changed through shared references using the regular cell methods.
200    pub fn cell_view(&mut self) -> ArrayView<'_, MathCell<A>, D>
201    where S: DataMut
202    {
203        self.view_mut().into_cell_view()
204    }
205
206    /// Return an uniquely owned copy of the array.
207    ///
208    /// If the input array is contiguous, then the output array will have the same
209    /// memory layout. Otherwise, the layout of the output array is unspecified.
210    /// If you need a particular layout, you can allocate a new array with the
211    /// desired memory layout and [`.assign()`](Self::assign) the data.
212    /// Alternatively, you can collectan iterator, like this for a result in
213    /// standard layout:
214    ///
215    /// ```
216    /// # use kn0sys_ndarray::prelude::*;
217    /// # let arr = Array::from_shape_vec((2, 2).f(), vec![1, 2, 3, 4]).unwrap();
218    /// # let owned = {
219    /// Array::from_shape_vec(arr.raw_dim(), arr.iter().cloned().collect()).unwrap()
220    /// # };
221    /// # assert!(owned.is_standard_layout());
222    /// # assert_eq!(arr, owned);
223    /// ```
224    ///
225    /// or this for a result in column-major (Fortran) layout:
226    ///
227    /// ```
228    /// # use kn0sys_ndarray::prelude::*;
229    /// # let arr = Array::from_shape_vec((2, 2), vec![1, 2, 3, 4]).unwrap();
230    /// # let owned = {
231    /// Array::from_shape_vec(arr.raw_dim().f(), arr.t().iter().cloned().collect()).unwrap()
232    /// # };
233    /// # assert!(owned.t().is_standard_layout());
234    /// # assert_eq!(arr, owned);
235    /// ```
236    pub fn to_owned(&self) -> Array<A, D>
237    where
238        A: Clone,
239        S: Data,
240    {
241        if let Some(slc) = self.as_slice_memory_order() {
242            unsafe { Array::from_shape_vec_unchecked(self.dim.clone().strides(self.strides.clone()), slc.to_vec()) }
243        } else {
244            self.map(A::clone)
245        }
246    }
247
248    /// Return a shared ownership (copy on write) array, cloning the array
249    /// elements if necessary.
250    pub fn to_shared(&self) -> ArcArray<A, D>
251    where
252        A: Clone,
253        S: Data,
254    {
255        S::to_shared(self)
256    }
257
258    /// Turn the array into a uniquely owned array, cloning the array elements
259    /// if necessary.
260    pub fn into_owned(self) -> Array<A, D>
261    where
262        A: Clone,
263        S: Data,
264    {
265        S::into_owned(self)
266    }
267
268    /// Converts the array into `Array<A, D>` if this is possible without
269    /// cloning the array elements. Otherwise, returns `self` unchanged.
270    ///
271    /// ```
272    /// use kn0sys_ndarray::{array, rcarr2, ArcArray2, Array2};
273    ///
274    /// // Reference-counted, clone-on-write `ArcArray`.
275    /// let a: ArcArray2<_> = rcarr2(&[[1., 2.], [3., 4.]]);
276    /// {
277    ///     // Another reference to the same data.
278    ///     let b: ArcArray2<_> = a.clone();
279    ///     // Since there are two references to the same data, `.into_owned()`
280    ///     // would require cloning the data, so `.try_into_owned_nocopy()`
281    ///     // returns `Err`.
282    ///     assert!(b.try_into_owned_nocopy().is_err());
283    /// }
284    /// // Here, since the second reference has been dropped, the `ArcArray`
285    /// // can be converted into an `Array` without cloning the data.
286    /// let unique: Array2<_> = a.try_into_owned_nocopy().unwrap();
287    /// assert_eq!(unique, array![[1., 2.], [3., 4.]]);
288    /// ```
289    pub fn try_into_owned_nocopy(self) -> Result<Array<A, D>, Self>
290    where S: Data
291    {
292        S::try_into_owned_nocopy(self)
293    }
294
295    /// Turn the array into a shared ownership (copy on write) array,
296    /// cloning the array elements if necessary.
297    ///
298    /// If you want to generalize over `Array` and `ArcArray` inputs but avoid
299    /// an `A: Clone` bound, use `Into::<ArcArray<A, D>>::into` instead of this
300    /// method.
301    pub fn into_shared(self) -> ArcArray<A, D>
302    where
303        A: Clone,
304        S: DataOwned,
305    {
306        S::into_shared(self)
307    }
308
309    /// Returns a reference to the first element of the array, or `None` if it
310    /// is empty.
311    ///
312    /// # Example
313    ///
314    /// ```rust
315    /// use kn0sys_ndarray::Array3;
316    ///
317    /// let mut a = Array3::<f64>::zeros([3, 4, 2]);
318    /// a[[0, 0, 0]] = 42.;
319    /// assert_eq!(a.first(), Some(&42.));
320    ///
321    /// let b = Array3::<f64>::zeros([3, 0, 5]);
322    /// assert_eq!(b.first(), None);
323    /// ```
324    pub fn first(&self) -> Option<&A>
325    where S: Data
326    {
327        if self.is_empty() {
328            None
329        } else {
330            Some(unsafe { &*self.as_ptr() })
331        }
332    }
333
334    /// Returns a mutable reference to the first element of the array, or
335    /// `None` if it is empty.
336    ///
337    /// # Example
338    ///
339    /// ```rust
340    /// use kn0sys_ndarray::Array3;
341    ///
342    /// let mut a = Array3::<f64>::zeros([3, 4, 2]);
343    /// *a.first_mut().unwrap() = 42.;
344    /// assert_eq!(a[[0, 0, 0]], 42.);
345    ///
346    /// let mut b = Array3::<f64>::zeros([3, 0, 5]);
347    /// assert_eq!(b.first_mut(), None);
348    /// ```
349    pub fn first_mut(&mut self) -> Option<&mut A>
350    where S: DataMut
351    {
352        if self.is_empty() {
353            None
354        } else {
355            Some(unsafe { &mut *self.as_mut_ptr() })
356        }
357    }
358
359    /// Returns a reference to the last element of the array, or `None` if it
360    /// is empty.
361    ///
362    /// # Example
363    ///
364    /// ```rust
365    /// use kn0sys_ndarray::Array3;
366    ///
367    /// let mut a = Array3::<f64>::zeros([3, 4, 2]);
368    /// a[[2, 3, 1]] = 42.;
369    /// assert_eq!(a.last(), Some(&42.));
370    ///
371    /// let b = Array3::<f64>::zeros([3, 0, 5]);
372    /// assert_eq!(b.last(), None);
373    /// ```
374    pub fn last(&self) -> Option<&A>
375    where S: Data
376    {
377        if self.is_empty() {
378            None
379        } else {
380            let mut index = self.raw_dim();
381            for ax in 0..index.ndim() {
382                index[ax] -= 1;
383            }
384            Some(unsafe { self.uget(index) })
385        }
386    }
387
388    /// Returns a mutable reference to the last element of the array, or `None`
389    /// if it is empty.
390    ///
391    /// # Example
392    ///
393    /// ```rust
394    /// use kn0sys_ndarray::Array3;
395    ///
396    /// let mut a = Array3::<f64>::zeros([3, 4, 2]);
397    /// *a.last_mut().unwrap() = 42.;
398    /// assert_eq!(a[[2, 3, 1]], 42.);
399    ///
400    /// let mut b = Array3::<f64>::zeros([3, 0, 5]);
401    /// assert_eq!(b.last_mut(), None);
402    /// ```
403    pub fn last_mut(&mut self) -> Option<&mut A>
404    where S: DataMut
405    {
406        if self.is_empty() {
407            None
408        } else {
409            self.ensure_unique();
410            let mut index = self.raw_dim();
411            for ax in 0..index.ndim() {
412                index[ax] -= 1;
413            }
414            Some(unsafe { self.uget_mut(index) })
415        }
416    }
417
418    /// Return an iterator of references to the elements of the array.
419    ///
420    /// Elements are visited in the *logical order* of the array, which
421    /// is where the rightmost index is varying the fastest.
422    ///
423    /// Iterator element type is `&A`.
424    pub fn iter(&self) -> Iter<'_, A, D>
425    where S: Data
426    {
427        debug_assert!(self.pointer_is_inbounds());
428        self.view().into_iter_()
429    }
430
431    /// Return an iterator of mutable references to the elements of the array.
432    ///
433    /// Elements are visited in the *logical order* of the array, which
434    /// is where the rightmost index is varying the fastest.
435    ///
436    /// Iterator element type is `&mut A`.
437    pub fn iter_mut(&mut self) -> IterMut<'_, A, D>
438    where S: DataMut
439    {
440        self.view_mut().into_iter_()
441    }
442
443    /// Return an iterator of indexes and references to the elements of the array.
444    ///
445    /// Elements are visited in the *logical order* of the array, which
446    /// is where the rightmost index is varying the fastest.
447    ///
448    /// Iterator element type is `(D::Pattern, &A)`.
449    ///
450    /// See also [`Zip::indexed`]
451    pub fn indexed_iter(&self) -> IndexedIter<'_, A, D>
452    where S: Data
453    {
454        IndexedIter::new(self.view().into_elements_base())
455    }
456
457    /// Return an iterator of indexes and mutable references to the elements of the array.
458    ///
459    /// Elements are visited in the *logical order* of the array, which
460    /// is where the rightmost index is varying the fastest.
461    ///
462    /// Iterator element type is `(D::Pattern, &mut A)`.
463    pub fn indexed_iter_mut(&mut self) -> IndexedIterMut<'_, A, D>
464    where S: DataMut
465    {
466        IndexedIterMut::new(self.view_mut().into_elements_base())
467    }
468
469    /// Return a sliced view of the array.
470    ///
471    /// See [*Slicing*](#slicing) for full documentation.
472    /// See also [`s!`], [`SliceArg`], and [`SliceInfo`](crate::SliceInfo).
473    ///
474    /// **Panics** if an index is out of bounds or step size is zero.<br>
475    /// (**Panics** if `D` is `IxDyn` and `info` does not match the number of array axes.)
476    #[track_caller]
477    pub fn slice<I>(&self, info: I) -> ArrayView<'_, A, I::OutDim>
478    where
479        I: SliceArg<D>,
480        S: Data,
481    {
482        self.view().slice_move(info)
483    }
484
485    /// Return a sliced read-write view of the array.
486    ///
487    /// See [*Slicing*](#slicing) for full documentation.
488    /// See also [`s!`], [`SliceArg`], and [`SliceInfo`](crate::SliceInfo).
489    ///
490    /// **Panics** if an index is out of bounds or step size is zero.<br>
491    /// (**Panics** if `D` is `IxDyn` and `info` does not match the number of array axes.)
492    #[track_caller]
493    pub fn slice_mut<I>(&mut self, info: I) -> ArrayViewMut<'_, A, I::OutDim>
494    where
495        I: SliceArg<D>,
496        S: DataMut,
497    {
498        self.view_mut().slice_move(info)
499    }
500
501    /// Return multiple disjoint, sliced, mutable views of the array.
502    ///
503    /// See [*Slicing*](#slicing) for full documentation. See also
504    /// [`MultiSliceArg`], [`s!`], [`SliceArg`], and
505    /// [`SliceInfo`](crate::SliceInfo).
506    ///
507    /// **Panics** if any of the following occur:
508    ///
509    /// * if any of the views would intersect (i.e. if any element would appear in multiple slices)
510    /// * if an index is out of bounds or step size is zero
511    /// * if `D` is `IxDyn` and `info` does not match the number of array axes
512    ///
513    /// # Example
514    ///
515    /// ```
516    /// use kn0sys_ndarray::{arr2, s};
517    ///
518    /// let mut a = arr2(&[[1, 2, 3], [4, 5, 6]]);
519    /// let (mut edges, mut middle) = a.multi_slice_mut((s![.., ..;2], s![.., 1]));
520    /// edges.fill(1);
521    /// middle.fill(0);
522    /// assert_eq!(a, arr2(&[[1, 0, 1], [1, 0, 1]]));
523    /// ```
524    #[track_caller]
525    pub fn multi_slice_mut<'a, M>(&'a mut self, info: M) -> M::Output
526    where
527        M: MultiSliceArg<'a, A, D>,
528        S: DataMut,
529    {
530        info.multi_slice_move(self.view_mut())
531    }
532
533    /// Slice the array, possibly changing the number of dimensions.
534    ///
535    /// See [*Slicing*](#slicing) for full documentation.
536    /// See also [`s!`], [`SliceArg`], and [`SliceInfo`](crate::SliceInfo).
537    ///
538    /// **Panics** if an index is out of bounds or step size is zero.<br>
539    /// (**Panics** if `D` is `IxDyn` and `info` does not match the number of array axes.)
540    #[track_caller]
541    pub fn slice_move<I>(mut self, info: I) -> ArrayBase<S, I::OutDim>
542    where I: SliceArg<D>
543    {
544        assert_eq!(
545            info.in_ndim(),
546            self.ndim(),
547            "The input dimension of `info` must match the array to be sliced.",
548        );
549        let out_ndim = info.out_ndim();
550        let mut new_dim = I::OutDim::zeros(out_ndim);
551        let mut new_strides = I::OutDim::zeros(out_ndim);
552
553        let mut old_axis = 0;
554        let mut new_axis = 0;
555        info.as_ref().iter().for_each(|&ax_info| match ax_info {
556            SliceInfoElem::Slice { start, end, step } => {
557                // Slice the axis in-place to update the `dim`, `strides`, and `ptr`.
558                self.slice_axis_inplace(Axis(old_axis), Slice { start, end, step });
559                // Copy the sliced dim and stride to corresponding axis.
560                new_dim[new_axis] = self.dim[old_axis];
561                new_strides[new_axis] = self.strides[old_axis];
562                old_axis += 1;
563                new_axis += 1;
564            }
565            SliceInfoElem::Index(index) => {
566                // Collapse the axis in-place to update the `ptr`.
567                let i_usize = abs_index(self.len_of(Axis(old_axis)), index);
568                self.collapse_axis(Axis(old_axis), i_usize);
569                // Skip copying the axis since it should be removed. Note that
570                // removing this axis is safe because `.collapse_axis()` panics
571                // if the index is out-of-bounds, so it will panic if the axis
572                // is zero length.
573                old_axis += 1;
574            }
575            SliceInfoElem::NewAxis => {
576                // Set the dim and stride of the new axis.
577                new_dim[new_axis] = 1;
578                new_strides[new_axis] = 0;
579                new_axis += 1;
580            }
581        });
582        debug_assert_eq!(old_axis, self.ndim());
583        debug_assert_eq!(new_axis, out_ndim);
584
585        // safe because new dimension, strides allow access to a subset of old data
586        unsafe { self.with_strides_dim(new_strides, new_dim) }
587    }
588
589    /// Slice the array in place without changing the number of dimensions.
590    ///
591    /// In particular, if an axis is sliced with an index, the axis is
592    /// collapsed, as in [`.collapse_axis()`], rather than removed, as in
593    /// [`.slice_move()`] or [`.index_axis_move()`].
594    ///
595    /// [`.collapse_axis()`]: Self::collapse_axis
596    /// [`.slice_move()`]: Self::slice_move
597    /// [`.index_axis_move()`]: Self::index_axis_move
598    ///
599    /// See [*Slicing*](#slicing) for full documentation.
600    /// See also [`s!`], [`SliceArg`], and [`SliceInfo`](crate::SliceInfo).
601    ///
602    /// **Panics** in the following cases:
603    ///
604    /// - if an index is out of bounds
605    /// - if a step size is zero
606    /// - if [`SliceInfoElem::NewAxis`] is in `info`, e.g. if [`NewAxis`] was
607    ///   used in the [`s!`] macro
608    /// - if `D` is `IxDyn` and `info` does not match the number of array axes
609    #[track_caller]
610    pub fn slice_collapse<I>(&mut self, info: I)
611    where I: SliceArg<D>
612    {
613        assert_eq!(
614            info.in_ndim(),
615            self.ndim(),
616            "The input dimension of `info` must match the array to be sliced.",
617        );
618        let mut axis = 0;
619        info.as_ref().iter().for_each(|&ax_info| match ax_info {
620            SliceInfoElem::Slice { start, end, step } => {
621                self.slice_axis_inplace(Axis(axis), Slice { start, end, step });
622                axis += 1;
623            }
624            SliceInfoElem::Index(index) => {
625                let i_usize = abs_index(self.len_of(Axis(axis)), index);
626                self.collapse_axis(Axis(axis), i_usize);
627                axis += 1;
628            }
629            SliceInfoElem::NewAxis => panic!("`slice_collapse` does not support `NewAxis`."),
630        });
631        debug_assert_eq!(axis, self.ndim());
632    }
633
634    /// Return a view of the array, sliced along the specified axis.
635    ///
636    /// **Panics** if an index is out of bounds or step size is zero.<br>
637    /// **Panics** if `axis` is out of bounds.
638    #[track_caller]
639    #[must_use = "slice_axis returns an array view with the sliced result"]
640    pub fn slice_axis(&self, axis: Axis, indices: Slice) -> ArrayView<'_, A, D>
641    where S: Data
642    {
643        let mut view = self.view();
644        view.slice_axis_inplace(axis, indices);
645        view
646    }
647
648    /// Return a mutable view of the array, sliced along the specified axis.
649    ///
650    /// **Panics** if an index is out of bounds or step size is zero.<br>
651    /// **Panics** if `axis` is out of bounds.
652    #[track_caller]
653    #[must_use = "slice_axis_mut returns an array view with the sliced result"]
654    pub fn slice_axis_mut(&mut self, axis: Axis, indices: Slice) -> ArrayViewMut<'_, A, D>
655    where S: DataMut
656    {
657        let mut view_mut = self.view_mut();
658        view_mut.slice_axis_inplace(axis, indices);
659        view_mut
660    }
661
662    /// Slice the array in place along the specified axis.
663    ///
664    /// **Panics** if an index is out of bounds or step size is zero.<br>
665    /// **Panics** if `axis` is out of bounds.
666    #[track_caller]
667    pub fn slice_axis_inplace(&mut self, axis: Axis, indices: Slice)
668    {
669        let offset =
670            do_slice(&mut self.dim.slice_mut()[axis.index()], &mut self.strides.slice_mut()[axis.index()], indices);
671        unsafe {
672            self.ptr = self.ptr.offset(offset);
673        }
674        debug_assert!(self.pointer_is_inbounds());
675    }
676
677    /// Slice the array in place along the specified axis, then return the sliced array.
678    ///
679    /// **Panics** if an index is out of bounds or step size is zero.<br>
680    /// **Panics** if `axis` is out of bounds.
681    #[must_use = "slice_axis_move returns an array with the sliced result"]
682    pub fn slice_axis_move(mut self, axis: Axis, indices: Slice) -> Self
683    {
684        self.slice_axis_inplace(axis, indices);
685        self
686    }
687
688    /// Return a view of a slice of the array, with a closure specifying the
689    /// slice for each axis.
690    ///
691    /// This is especially useful for code which is generic over the
692    /// dimensionality of the array.
693    ///
694    /// **Panics** if an index is out of bounds or step size is zero.
695    #[track_caller]
696    pub fn slice_each_axis<F>(&self, f: F) -> ArrayView<'_, A, D>
697    where
698        F: FnMut(AxisDescription) -> Slice,
699        S: Data,
700    {
701        let mut view = self.view();
702        view.slice_each_axis_inplace(f);
703        view
704    }
705
706    /// Return a mutable view of a slice of the array, with a closure
707    /// specifying the slice for each axis.
708    ///
709    /// This is especially useful for code which is generic over the
710    /// dimensionality of the array.
711    ///
712    /// **Panics** if an index is out of bounds or step size is zero.
713    #[track_caller]
714    pub fn slice_each_axis_mut<F>(&mut self, f: F) -> ArrayViewMut<'_, A, D>
715    where
716        F: FnMut(AxisDescription) -> Slice,
717        S: DataMut,
718    {
719        let mut view = self.view_mut();
720        view.slice_each_axis_inplace(f);
721        view
722    }
723
724    /// Slice the array in place, with a closure specifying the slice for each
725    /// axis.
726    ///
727    /// This is especially useful for code which is generic over the
728    /// dimensionality of the array.
729    ///
730    /// **Panics** if an index is out of bounds or step size is zero.
731    #[track_caller]
732    pub fn slice_each_axis_inplace<F>(&mut self, mut f: F)
733    where F: FnMut(AxisDescription) -> Slice
734    {
735        for ax in 0..self.ndim() {
736            self.slice_axis_inplace(
737                Axis(ax),
738                f(AxisDescription {
739                    axis: Axis(ax),
740                    len: self.dim[ax],
741                    stride: self.strides[ax] as isize,
742                }),
743            )
744        }
745    }
746
747    /// Return a reference to the element at `index`, or return `None`
748    /// if the index is out of bounds.
749    ///
750    /// Arrays also support indexing syntax: `array[index]`.
751    ///
752    /// ```
753    /// use kn0sys_ndarray::arr2;
754    ///
755    /// let a = arr2(&[[1., 2.],
756    ///                [3., 4.]]);
757    ///
758    /// assert!(
759    ///     a.get((0, 1)) == Some(&2.) &&
760    ///     a.get((0, 2)) == None &&
761    ///     a[(0, 1)] == 2. &&
762    ///     a[[0, 1]] == 2.
763    /// );
764    /// ```
765    pub fn get<I>(&self, index: I) -> Option<&A>
766    where
767        S: Data,
768        I: NdIndex<D>,
769    {
770        unsafe { self.get_ptr(index).map(|ptr| &*ptr) }
771    }
772
773    /// Return a raw pointer to the element at `index`, or return `None`
774    /// if the index is out of bounds.
775    ///
776    /// ```
777    /// use kn0sys_ndarray::arr2;
778    ///
779    /// let a = arr2(&[[1., 2.], [3., 4.]]);
780    ///
781    /// let v = a.raw_view();
782    /// let p = a.get_ptr((0, 1)).unwrap();
783    ///
784    /// assert_eq!(unsafe { *p }, 2.);
785    /// ```
786    pub fn get_ptr<I>(&self, index: I) -> Option<*const A>
787    where I: NdIndex<D>
788    {
789        let ptr = self.ptr;
790        index
791            .index_checked(&self.dim, &self.strides)
792            .map(move |offset| unsafe { ptr.as_ptr().offset(offset) as *const _ })
793    }
794
795    /// Return a mutable reference to the element at `index`, or return `None`
796    /// if the index is out of bounds.
797    pub fn get_mut<I>(&mut self, index: I) -> Option<&mut A>
798    where
799        S: DataMut,
800        I: NdIndex<D>,
801    {
802        unsafe { self.get_mut_ptr(index).map(|ptr| &mut *ptr) }
803    }
804
805    /// Return a raw pointer to the element at `index`, or return `None`
806    /// if the index is out of bounds.
807    ///
808    /// ```
809    /// use kn0sys_ndarray::arr2;
810    ///
811    /// let mut a = arr2(&[[1., 2.], [3., 4.]]);
812    ///
813    /// let v = a.raw_view_mut();
814    /// let p = a.get_mut_ptr((0, 1)).unwrap();
815    ///
816    /// unsafe {
817    ///     *p = 5.;
818    /// }
819    ///
820    /// assert_eq!(a.get((0, 1)), Some(&5.));
821    /// ```
822    pub fn get_mut_ptr<I>(&mut self, index: I) -> Option<*mut A>
823    where
824        S: RawDataMut,
825        I: NdIndex<D>,
826    {
827        // const and mut are separate to enforce &mutness as well as the
828        // extra code in as_mut_ptr
829        let ptr = self.as_mut_ptr();
830        index
831            .index_checked(&self.dim, &self.strides)
832            .map(move |offset| unsafe { ptr.offset(offset) })
833    }
834
835    /// Perform *unchecked* array indexing.
836    ///
837    /// Return a reference to the element at `index`.
838    ///
839    /// **Note:** only unchecked for non-debug builds of ndarray.
840    ///
841    /// # Safety
842    ///
843    /// The caller must ensure that the index is in-bounds.
844    #[inline]
845    pub unsafe fn uget<I>(&self, index: I) -> &A
846    where
847        S: Data,
848        I: NdIndex<D>,
849    {
850        arraytraits::debug_bounds_check(self, &index);
851        let off = index.index_unchecked(&self.strides);
852        &*self.ptr.as_ptr().offset(off)
853    }
854
855    /// Perform *unchecked* array indexing.
856    ///
857    /// Return a mutable reference to the element at `index`.
858    ///
859    /// **Note:** Only unchecked for non-debug builds of ndarray.
860    ///
861    /// # Safety
862    ///
863    /// The caller must ensure that:
864    ///
865    /// 1. the index is in-bounds and
866    ///
867    /// 2. the data is uniquely held by the array. (This property is guaranteed
868    ///    for `Array` and `ArrayViewMut`, but not for `ArcArray` or `CowArray`.)
869    #[inline]
870    pub unsafe fn uget_mut<I>(&mut self, index: I) -> &mut A
871    where
872        S: DataMut,
873        I: NdIndex<D>,
874    {
875        debug_assert!(self.data.is_unique());
876        arraytraits::debug_bounds_check(self, &index);
877        let off = index.index_unchecked(&self.strides);
878        &mut *self.ptr.as_ptr().offset(off)
879    }
880
881    /// Swap elements at indices `index1` and `index2`.
882    ///
883    /// Indices may be equal.
884    ///
885    /// ***Panics*** if an index is out of bounds.
886    #[track_caller]
887    pub fn swap<I>(&mut self, index1: I, index2: I)
888    where
889        S: DataMut,
890        I: NdIndex<D>,
891    {
892        let ptr = self.as_mut_ptr();
893        let offset1 = index1.index_checked(&self.dim, &self.strides);
894        let offset2 = index2.index_checked(&self.dim, &self.strides);
895        if let Some(offset1) = offset1 {
896            if let Some(offset2) = offset2 {
897                unsafe {
898                    std::ptr::swap(ptr.offset(offset1), ptr.offset(offset2));
899                }
900                return;
901            }
902        }
903        panic!("swap: index out of bounds for indices {:?} {:?}", index1, index2);
904    }
905
906    /// Swap elements *unchecked* at indices `index1` and `index2`.
907    ///
908    /// Indices may be equal.
909    ///
910    /// **Note:** only unchecked for non-debug builds of ndarray.
911    ///
912    /// # Safety
913    ///
914    /// The caller must ensure that:
915    ///
916    /// 1. both `index1` and `index2` are in-bounds and
917    ///
918    /// 2. the data is uniquely held by the array. (This property is guaranteed
919    ///    for `Array` and `ArrayViewMut`, but not for `ArcArray` or `CowArray`.)
920    pub unsafe fn uswap<I>(&mut self, index1: I, index2: I)
921    where
922        S: DataMut,
923        I: NdIndex<D>,
924    {
925        debug_assert!(self.data.is_unique());
926        arraytraits::debug_bounds_check(self, &index1);
927        arraytraits::debug_bounds_check(self, &index2);
928        let off1 = index1.index_unchecked(&self.strides);
929        let off2 = index2.index_unchecked(&self.strides);
930        std::ptr::swap(self.ptr.as_ptr().offset(off1), self.ptr.as_ptr().offset(off2));
931    }
932
933    // `get` for zero-dimensional arrays
934    // panics if dimension is not zero. otherwise an element is always present.
935    fn get_0d(&self) -> &A
936    where S: Data
937    {
938        assert!(self.ndim() == 0);
939        unsafe { &*self.as_ptr() }
940    }
941
942    /// Returns a view restricted to `index` along the axis, with the axis
943    /// removed.
944    ///
945    /// See [*Subviews*](#subviews) for full documentation.
946    ///
947    /// **Panics** if `axis` or `index` is out of bounds.
948    ///
949    /// ```
950    /// use kn0sys_ndarray::{arr2, ArrayView, Axis};
951    ///
952    /// let a = arr2(&[[1., 2. ],    // ... axis 0, row 0
953    ///                [3., 4. ],    // --- axis 0, row 1
954    ///                [5., 6. ]]);  // ... axis 0, row 2
955    /// //               .   \
956    /// //                .   axis 1, column 1
957    /// //                 axis 1, column 0
958    /// assert!(
959    ///     a.index_axis(Axis(0), 1) == ArrayView::from(&[3., 4.]) &&
960    ///     a.index_axis(Axis(1), 1) == ArrayView::from(&[2., 4., 6.])
961    /// );
962    /// ```
963    #[track_caller]
964    pub fn index_axis(&self, axis: Axis, index: usize) -> ArrayView<'_, A, D::Smaller>
965    where
966        S: Data,
967        D: RemoveAxis,
968    {
969        self.view().index_axis_move(axis, index)
970    }
971
972    /// Returns a mutable view restricted to `index` along the axis, with the
973    /// axis removed.
974    ///
975    /// **Panics** if `axis` or `index` is out of bounds.
976    ///
977    /// ```
978    /// use kn0sys_ndarray::{arr2, aview2, Axis};
979    ///
980    /// let mut a = arr2(&[[1., 2. ],
981    ///                    [3., 4. ]]);
982    /// //                   .   \
983    /// //                    .   axis 1, column 1
984    /// //                     axis 1, column 0
985    ///
986    /// {
987    ///     let mut column1 = a.index_axis_mut(Axis(1), 1);
988    ///     column1 += 10.;
989    /// }
990    ///
991    /// assert!(
992    ///     a == aview2(&[[1., 12.],
993    ///                   [3., 14.]])
994    /// );
995    /// ```
996    #[track_caller]
997    pub fn index_axis_mut(&mut self, axis: Axis, index: usize) -> ArrayViewMut<'_, A, D::Smaller>
998    where
999        S: DataMut,
1000        D: RemoveAxis,
1001    {
1002        self.view_mut().index_axis_move(axis, index)
1003    }
1004
1005    /// Collapses the array to `index` along the axis and removes the axis.
1006    ///
1007    /// See [`.index_axis()`](Self::index_axis) and [*Subviews*](#subviews) for full documentation.
1008    ///
1009    /// **Panics** if `axis` or `index` is out of bounds.
1010    #[track_caller]
1011    pub fn index_axis_move(mut self, axis: Axis, index: usize) -> ArrayBase<S, D::Smaller>
1012    where D: RemoveAxis
1013    {
1014        self.collapse_axis(axis, index);
1015        let dim = self.dim.remove_axis(axis);
1016        let strides = self.strides.remove_axis(axis);
1017        // safe because new dimension, strides allow access to a subset of old data
1018        unsafe { self.with_strides_dim(strides, dim) }
1019    }
1020
1021    /// Selects `index` along the axis, collapsing the axis into length one.
1022    ///
1023    /// **Panics** if `axis` or `index` is out of bounds.
1024    #[track_caller]
1025    pub fn collapse_axis(&mut self, axis: Axis, index: usize)
1026    {
1027        let offset = dimension::do_collapse_axis(&mut self.dim, &self.strides, axis.index(), index);
1028        self.ptr = unsafe { self.ptr.offset(offset) };
1029        debug_assert!(self.pointer_is_inbounds());
1030    }
1031
1032    /// Along `axis`, select arbitrary subviews corresponding to `indices`
1033    /// and copy them into a new array.
1034    ///
1035    /// **Panics** if `axis` or an element of `indices` is out of bounds.
1036    ///
1037    /// ```
1038    /// use kn0sys_ndarray::{arr2, Axis};
1039    ///
1040    /// let x = arr2(&[[0., 1.],
1041    ///                [2., 3.],
1042    ///                [4., 5.],
1043    ///                [6., 7.],
1044    ///                [8., 9.]]);
1045    ///
1046    /// let r = x.select(Axis(0), &[0, 4, 3]);
1047    /// assert!(
1048    ///         r == arr2(&[[0., 1.],
1049    ///                     [8., 9.],
1050    ///                     [6., 7.]])
1051    ///);
1052    /// ```
1053    #[track_caller]
1054    pub fn select(&self, axis: Axis, indices: &[Ix]) -> Array<A, D>
1055    where
1056        A: Clone,
1057        S: Data,
1058        D: RemoveAxis,
1059    {
1060        if self.ndim() == 1 {
1061            // using .len_of(axis) means that we check if `axis` is in bounds too.
1062            let axis_len = self.len_of(axis);
1063            // bounds check the indices first
1064            if let Some(max_index) = indices.iter().cloned().max() {
1065                if max_index >= axis_len {
1066                    panic!("ndarray: index {} is out of bounds in array of len {}",
1067                           max_index, self.len_of(axis));
1068                }
1069            } // else: indices empty is ok
1070            let view = self.view().into_dimensionality::<Ix1>().unwrap();
1071            Array::from_iter(indices.iter().map(move |&index| {
1072                // Safety: bounds checked indexes
1073                unsafe { view.uget(index).clone() }
1074            }))
1075            .into_dimensionality::<D>()
1076            .unwrap()
1077        } else {
1078            let mut subs = vec![self.view(); indices.len()];
1079            for (&i, sub) in zip(indices, &mut subs[..]) {
1080                sub.collapse_axis(axis, i);
1081            }
1082            if subs.is_empty() {
1083                let mut dim = self.raw_dim();
1084                dim.set_axis(axis, 0);
1085                unsafe { Array::from_shape_vec_unchecked(dim, vec![]) }
1086            } else {
1087                concatenate(axis, &subs).unwrap()
1088            }
1089        }
1090    }
1091
1092    /// Return a producer and iterable that traverses over the *generalized*
1093    /// rows of the array. For a 2D array these are the regular rows.
1094    ///
1095    /// This is equivalent to `.lanes(Axis(n - 1))` where *n* is `self.ndim()`.
1096    ///
1097    /// For an array of dimensions *a* × *b* × *c* × ... × *l* × *m*
1098    /// it has *a* × *b* × *c* × ... × *l* rows each of length *m*.
1099    ///
1100    /// For example, in a 2 × 2 × 3 array, each row is 3 elements long
1101    /// and there are 2 × 2 = 4 rows in total.
1102    ///
1103    /// Iterator element is `ArrayView1<A>` (1D array view).
1104    ///
1105    /// ```
1106    /// use kn0sys_ndarray::arr3;
1107    ///
1108    /// let a = arr3(&[[[ 0,  1,  2],    // -- row 0, 0
1109    ///                 [ 3,  4,  5]],   // -- row 0, 1
1110    ///                [[ 6,  7,  8],    // -- row 1, 0
1111    ///                 [ 9, 10, 11]]]); // -- row 1, 1
1112    ///
1113    /// // `rows` will yield the four generalized rows of the array.
1114    /// for row in a.rows() {
1115    ///     /* loop body */
1116    /// }
1117    /// ```
1118    pub fn rows(&self) -> Lanes<'_, A, D::Smaller>
1119    where S: Data
1120    {
1121        let mut n = self.ndim();
1122        if n == 0 {
1123            n += 1;
1124        }
1125        Lanes::new(self.view(), Axis(n - 1))
1126    }
1127
1128    /// Return a producer and iterable that traverses over the *generalized*
1129    /// rows of the array and yields mutable array views.
1130    ///
1131    /// Iterator element is `ArrayView1<A>` (1D read-write array view).
1132    pub fn rows_mut(&mut self) -> LanesMut<'_, A, D::Smaller>
1133    where S: DataMut
1134    {
1135        let mut n = self.ndim();
1136        if n == 0 {
1137            n += 1;
1138        }
1139        LanesMut::new(self.view_mut(), Axis(n - 1))
1140    }
1141
1142    /// Return a producer and iterable that traverses over the *generalized*
1143    /// columns of the array. For a 2D array these are the regular columns.
1144    ///
1145    /// This is equivalent to `.lanes(Axis(0))`.
1146    ///
1147    /// For an array of dimensions *a* × *b* × *c* × ... × *l* × *m*
1148    /// it has *b* × *c* × ... × *l* × *m* columns each of length *a*.
1149    ///
1150    /// For example, in a 2 × 2 × 3 array, each column is 2 elements long
1151    /// and there are 2 × 3 = 6 columns in total.
1152    ///
1153    /// Iterator element is `ArrayView1<A>` (1D array view).
1154    ///
1155    /// ```
1156    /// use kn0sys_ndarray::arr3;
1157    ///
1158    /// // The generalized columns of a 3D array:
1159    /// // are directed along the 0th axis: 0 and 6, 1 and 7 and so on...
1160    /// let a = arr3(&[[[ 0,  1,  2], [ 3,  4,  5]],
1161    ///                [[ 6,  7,  8], [ 9, 10, 11]]]);
1162    ///
1163    /// // Here `columns` will yield the six generalized columns of the array.
1164    /// for column in a.columns() {
1165    ///     /* loop body */
1166    /// }
1167    /// ```
1168    pub fn columns(&self) -> Lanes<'_, A, D::Smaller>
1169    where S: Data
1170    {
1171        Lanes::new(self.view(), Axis(0))
1172    }
1173
1174    /// Return a producer and iterable that traverses over the *generalized*
1175    /// columns of the array and yields mutable array views.
1176    ///
1177    /// Iterator element is `ArrayView1<A>` (1D read-write array view).
1178    pub fn columns_mut(&mut self) -> LanesMut<'_, A, D::Smaller>
1179    where S: DataMut
1180    {
1181        LanesMut::new(self.view_mut(), Axis(0))
1182    }
1183
1184    /// Return a producer and iterable that traverses over all 1D lanes
1185    /// pointing in the direction of `axis`.
1186    ///
1187    /// When pointing in the direction of the first axis, they are *columns*,
1188    /// in the direction of the last axis *rows*; in general they are all
1189    /// *lanes* and are one dimensional.
1190    ///
1191    /// Iterator element is `ArrayView1<A>` (1D array view).
1192    ///
1193    /// ```
1194    /// use kn0sys_ndarray::{arr3, aview1, Axis};
1195    ///
1196    /// let a = arr3(&[[[ 0,  1,  2],
1197    ///                 [ 3,  4,  5]],
1198    ///                [[ 6,  7,  8],
1199    ///                 [ 9, 10, 11]]]);
1200    ///
1201    /// let inner0 = a.lanes(Axis(0));
1202    /// let inner1 = a.lanes(Axis(1));
1203    /// let inner2 = a.lanes(Axis(2));
1204    ///
1205    /// // The first lane for axis 0 is [0, 6]
1206    /// assert_eq!(inner0.into_iter().next().unwrap(), aview1(&[0, 6]));
1207    /// // The first lane for axis 1 is [0, 3]
1208    /// assert_eq!(inner1.into_iter().next().unwrap(), aview1(&[0, 3]));
1209    /// // The first lane for axis 2 is [0, 1, 2]
1210    /// assert_eq!(inner2.into_iter().next().unwrap(), aview1(&[0, 1, 2]));
1211    /// ```
1212    pub fn lanes(&self, axis: Axis) -> Lanes<'_, A, D::Smaller>
1213    where S: Data
1214    {
1215        Lanes::new(self.view(), axis)
1216    }
1217
1218    /// Return a producer and iterable that traverses over all 1D lanes
1219    /// pointing in the direction of `axis`.
1220    ///
1221    /// Iterator element is `ArrayViewMut1<A>` (1D read-write array view).
1222    pub fn lanes_mut(&mut self, axis: Axis) -> LanesMut<'_, A, D::Smaller>
1223    where S: DataMut
1224    {
1225        LanesMut::new(self.view_mut(), axis)
1226    }
1227
1228    /// Return an iterator that traverses over the outermost dimension
1229    /// and yields each subview.
1230    ///
1231    /// This is equivalent to `.axis_iter(Axis(0))`.
1232    ///
1233    /// Iterator element is `ArrayView<A, D::Smaller>` (read-only array view).
1234    #[allow(deprecated)]
1235    pub fn outer_iter(&self) -> AxisIter<'_, A, D::Smaller>
1236    where
1237        S: Data,
1238        D: RemoveAxis,
1239    {
1240        self.view().into_outer_iter()
1241    }
1242
1243    /// Return an iterator that traverses over the outermost dimension
1244    /// and yields each subview.
1245    ///
1246    /// This is equivalent to `.axis_iter_mut(Axis(0))`.
1247    ///
1248    /// Iterator element is `ArrayViewMut<A, D::Smaller>` (read-write array view).
1249    #[allow(deprecated)]
1250    pub fn outer_iter_mut(&mut self) -> AxisIterMut<'_, A, D::Smaller>
1251    where
1252        S: DataMut,
1253        D: RemoveAxis,
1254    {
1255        self.view_mut().into_outer_iter()
1256    }
1257
1258    /// Return an iterator that traverses over `axis`
1259    /// and yields each subview along it.
1260    ///
1261    /// For example, in a 3 × 4 × 5 array, with `axis` equal to `Axis(2)`,
1262    /// the iterator element
1263    /// is a 3 × 4 subview (and there are 5 in total), as shown
1264    /// in the picture below.
1265    ///
1266    /// Iterator element is `ArrayView<A, D::Smaller>` (read-only array view).
1267    ///
1268    /// See [*Subviews*](#subviews) for full documentation.
1269    ///
1270    /// **Panics** if `axis` is out of bounds.
1271    ///
1272    /// <img src="https://rust-ndarray.github.io/ndarray/images/axis_iter_3_4_5.svg" height="250px">
1273    #[track_caller]
1274    pub fn axis_iter(&self, axis: Axis) -> AxisIter<'_, A, D::Smaller>
1275    where
1276        S: Data,
1277        D: RemoveAxis,
1278    {
1279        AxisIter::new(self.view(), axis)
1280    }
1281
1282    /// Return an iterator that traverses over `axis`
1283    /// and yields each mutable subview along it.
1284    ///
1285    /// Iterator element is `ArrayViewMut<A, D::Smaller>`
1286    /// (read-write array view).
1287    ///
1288    /// **Panics** if `axis` is out of bounds.
1289    #[track_caller]
1290    pub fn axis_iter_mut(&mut self, axis: Axis) -> AxisIterMut<'_, A, D::Smaller>
1291    where
1292        S: DataMut,
1293        D: RemoveAxis,
1294    {
1295        AxisIterMut::new(self.view_mut(), axis)
1296    }
1297
1298    /// Return an iterator that traverses over `axis` by chunks of `size`,
1299    /// yielding non-overlapping views along that axis.
1300    ///
1301    /// Iterator element is `ArrayView<A, D>`
1302    ///
1303    /// The last view may have less elements if `size` does not divide
1304    /// the axis' dimension.
1305    ///
1306    /// **Panics** if `axis` is out of bounds or if `size` is zero.
1307    ///
1308    /// ```
1309    /// use kn0sys_ndarray::Array;
1310    /// use kn0sys_ndarray::{arr3, Axis};
1311    ///
1312    /// let a = Array::from_iter(0..28).into_shape_with_order((2, 7, 2)).unwrap();
1313    /// let mut iter = a.axis_chunks_iter(Axis(1), 2);
1314    ///
1315    /// // first iteration yields a 2 × 2 × 2 view
1316    /// assert_eq!(iter.next().unwrap(),
1317    ///            arr3(&[[[ 0,  1], [ 2, 3]],
1318    ///                   [[14, 15], [16, 17]]]));
1319    ///
1320    /// // however the last element is a 2 × 1 × 2 view since 7 % 2 == 1
1321    /// assert_eq!(iter.next_back().unwrap(), arr3(&[[[12, 13]],
1322    ///                                              [[26, 27]]]));
1323    /// ```
1324    #[track_caller]
1325    pub fn axis_chunks_iter(&self, axis: Axis, size: usize) -> AxisChunksIter<'_, A, D>
1326    where S: Data
1327    {
1328        AxisChunksIter::new(self.view(), axis, size)
1329    }
1330
1331    /// Return an iterator that traverses over `axis` by chunks of `size`,
1332    /// yielding non-overlapping read-write views along that axis.
1333    ///
1334    /// Iterator element is `ArrayViewMut<A, D>`
1335    ///
1336    /// **Panics** if `axis` is out of bounds or if `size` is zero.
1337    #[track_caller]
1338    pub fn axis_chunks_iter_mut(&mut self, axis: Axis, size: usize) -> AxisChunksIterMut<'_, A, D>
1339    where S: DataMut
1340    {
1341        AxisChunksIterMut::new(self.view_mut(), axis, size)
1342    }
1343
1344    /// Return an exact chunks producer (and iterable).
1345    ///
1346    /// It produces the whole chunks of a given n-dimensional chunk size,
1347    /// skipping the remainder along each dimension that doesn't fit evenly.
1348    ///
1349    /// The produced element is a `ArrayView<A, D>` with exactly the dimension
1350    /// `chunk_size`.
1351    ///
1352    /// **Panics** if any dimension of `chunk_size` is zero<br>
1353    /// (**Panics** if `D` is `IxDyn` and `chunk_size` does not match the
1354    /// number of array axes.)
1355    #[track_caller]
1356    pub fn exact_chunks<E>(&self, chunk_size: E) -> ExactChunks<'_, A, D>
1357    where
1358        E: IntoDimension<Dim = D>,
1359        S: Data,
1360    {
1361        ExactChunks::new(self.view(), chunk_size)
1362    }
1363
1364    /// Return an exact chunks producer (and iterable).
1365    ///
1366    /// It produces the whole chunks of a given n-dimensional chunk size,
1367    /// skipping the remainder along each dimension that doesn't fit evenly.
1368    ///
1369    /// The produced element is a `ArrayViewMut<A, D>` with exactly
1370    /// the dimension `chunk_size`.
1371    ///
1372    /// **Panics** if any dimension of `chunk_size` is zero<br>
1373    /// (**Panics** if `D` is `IxDyn` and `chunk_size` does not match the
1374    /// number of array axes.)
1375    ///
1376    /// ```rust
1377    /// use kn0sys_ndarray::Array;
1378    /// use kn0sys_ndarray::arr2;
1379    /// let mut a = Array::zeros((6, 7));
1380    ///
1381    /// // Fill each 2 × 2 chunk with the index of where it appeared in iteration
1382    /// for (i, mut chunk) in a.exact_chunks_mut((2, 2)).into_iter().enumerate() {
1383    ///     chunk.fill(i);
1384    /// }
1385    ///
1386    /// // The resulting array is:
1387    /// assert_eq!(
1388    ///   a,
1389    ///   arr2(&[[0, 0, 1, 1, 2, 2, 0],
1390    ///          [0, 0, 1, 1, 2, 2, 0],
1391    ///          [3, 3, 4, 4, 5, 5, 0],
1392    ///          [3, 3, 4, 4, 5, 5, 0],
1393    ///          [6, 6, 7, 7, 8, 8, 0],
1394    ///          [6, 6, 7, 7, 8, 8, 0]]));
1395    /// ```
1396    #[track_caller]
1397    pub fn exact_chunks_mut<E>(&mut self, chunk_size: E) -> ExactChunksMut<'_, A, D>
1398    where
1399        E: IntoDimension<Dim = D>,
1400        S: DataMut,
1401    {
1402        ExactChunksMut::new(self.view_mut(), chunk_size)
1403    }
1404
1405    /// Return a window producer and iterable.
1406    ///
1407    /// The windows are all distinct overlapping views of size `window_size`
1408    /// that fit into the array's shape.
1409    ///
1410    /// This is essentially equivalent to [`.windows_with_stride()`] with unit stride.
1411    #[track_caller]
1412    pub fn windows<E>(&self, window_size: E) -> Windows<'_, A, D>
1413    where
1414        E: IntoDimension<Dim = D>,
1415        S: Data,
1416    {
1417        Windows::new(self.view(), window_size)
1418    }
1419
1420    /// Return a window producer and iterable.
1421    ///
1422    /// The windows are all distinct views of size `window_size`
1423    /// that fit into the array's shape.
1424    ///
1425    /// The stride is ordered by the outermost axis.<br>
1426    /// Hence, a (x₀, x₁, ..., xₙ) stride will be applied to
1427    /// (A₀, A₁, ..., Aₙ) where Aₓ stands for `Axis(x)`.
1428    ///
1429    /// This produces all windows that fit within the array for the given stride,
1430    /// assuming the window size is not larger than the array size.
1431    ///
1432    /// The produced element is an `ArrayView<A, D>` with exactly the dimension
1433    /// `window_size`.
1434    ///
1435    /// Note that passing a stride of only ones is similar to
1436    /// calling [`ArrayBase::windows()`].
1437    ///
1438    /// **Panics** if any dimension of `window_size` or `stride` is zero.<br>
1439    /// (**Panics** if `D` is `IxDyn` and `window_size` or `stride` does not match the
1440    /// number of array axes.)
1441    ///
1442    /// This is the same illustration found in [`ArrayBase::windows()`],
1443    /// 2×2 windows in a 3×4 array, but now with a (1, 2) stride:
1444    ///
1445    /// ```text
1446    ///          ──▶ Axis(1)
1447    ///
1448    ///      │   ┏━━━━━┳━━━━━┱─────┬─────┐   ┌─────┬─────┲━━━━━┳━━━━━┓
1449    ///      ▼   ┃ a₀₀ ┃ a₀₁ ┃     │     │   │     │     ┃ a₀₂ ┃ a₀₃ ┃
1450    /// Axis(0)  ┣━━━━━╋━━━━━╉─────┼─────┤   ├─────┼─────╊━━━━━╋━━━━━┫
1451    ///          ┃ a₁₀ ┃ a₁₁ ┃     │     │   │     │     ┃ a₁₂ ┃ a₁₃ ┃
1452    ///          ┡━━━━━╇━━━━━╃─────┼─────┤   ├─────┼─────╄━━━━━╇━━━━━┩
1453    ///          │     │     │     │     │   │     │     │     │     │
1454    ///          └─────┴─────┴─────┴─────┘   └─────┴─────┴─────┴─────┘
1455    ///
1456    ///          ┌─────┬─────┬─────┬─────┐   ┌─────┬─────┬─────┬─────┐
1457    ///          │     │     │     │     │   │     │     │     │     │
1458    ///          ┢━━━━━╈━━━━━╅─────┼─────┤   ├─────┼─────╆━━━━━╈━━━━━┪
1459    ///          ┃ a₁₀ ┃ a₁₁ ┃     │     │   │     │     ┃ a₁₂ ┃ a₁₃ ┃
1460    ///          ┣━━━━━╋━━━━━╉─────┼─────┤   ├─────┼─────╊━━━━━╋━━━━━┫
1461    ///          ┃ a₂₀ ┃ a₂₁ ┃     │     │   │     │     ┃ a₂₂ ┃ a₂₃ ┃
1462    ///          ┗━━━━━┻━━━━━┹─────┴─────┘   └─────┴─────┺━━━━━┻━━━━━┛
1463    /// ```
1464    #[track_caller]
1465    pub fn windows_with_stride<E>(&self, window_size: E, stride: E) -> Windows<'_, A, D>
1466    where
1467        E: IntoDimension<Dim = D>,
1468        S: Data,
1469    {
1470        Windows::new_with_stride(self.view(), window_size, stride)
1471    }
1472
1473    /// Returns a producer which traverses over all windows of a given length along an axis.
1474    ///
1475    /// The windows are all distinct, possibly-overlapping views. The shape of each window
1476    /// is the shape of `self`, with the length of `axis` replaced with `window_size`.
1477    ///
1478    /// **Panics** if `axis` is out-of-bounds or if `window_size` is zero.
1479    ///
1480    /// ```
1481    /// use kn0sys_ndarray::{Array3, Axis, s};
1482    ///
1483    /// let arr = Array3::from_shape_fn([4, 5, 2], |(i, j, k)| i * 100 + j * 10 + k);
1484    /// let correct = vec![
1485    ///     arr.slice(s![.., 0..3, ..]),
1486    ///     arr.slice(s![.., 1..4, ..]),
1487    ///     arr.slice(s![.., 2..5, ..]),
1488    /// ];
1489    /// for (window, correct) in arr.axis_windows(Axis(1), 3).into_iter().zip(&correct) {
1490    ///     assert_eq!(window, correct);
1491    ///     assert_eq!(window.shape(), &[4, 3, 2]);
1492    /// }
1493    /// ```
1494    pub fn axis_windows(&self, axis: Axis, window_size: usize) -> AxisWindows<'_, A, D>
1495    where S: Data
1496    {
1497        let axis_index = axis.index();
1498
1499        ndassert!(
1500            axis_index < self.ndim(),
1501            concat!(
1502                "Window axis {} does not match array dimension {} ",
1503                "(with array of shape {:?})"
1504            ),
1505            axis_index,
1506            self.ndim(),
1507            self.shape()
1508        );
1509
1510        AxisWindows::new(self.view(), axis, window_size)
1511    }
1512
1513    // Return (length, stride) for diagonal
1514    fn diag_params(&self) -> (Ix, Ixs)
1515    {
1516        /* empty shape has len 1 */
1517        let len = self.dim.slice().iter().cloned().min().unwrap_or(1);
1518        let stride = self.strides().iter().sum();
1519        (len, stride)
1520    }
1521
1522    /// Return a view of the diagonal elements of the array.
1523    ///
1524    /// The diagonal is simply the sequence indexed by *(0, 0, .., 0)*,
1525    /// *(1, 1, ..., 1)* etc as long as all axes have elements.
1526    pub fn diag(&self) -> ArrayView1<'_, A>
1527    where S: Data
1528    {
1529        self.view().into_diag()
1530    }
1531
1532    /// Return a read-write view over the diagonal elements of the array.
1533    pub fn diag_mut(&mut self) -> ArrayViewMut1<'_, A>
1534    where S: DataMut
1535    {
1536        self.view_mut().into_diag()
1537    }
1538
1539    /// Return the diagonal as a one-dimensional array.
1540    pub fn into_diag(self) -> ArrayBase<S, Ix1>
1541    {
1542        let (len, stride) = self.diag_params();
1543        // safe because new len stride allows access to a subset of the current elements
1544        unsafe { self.with_strides_dim(Ix1(stride as Ix), Ix1(len)) }
1545    }
1546
1547    /// Try to make the array unshared.
1548    ///
1549    /// This is equivalent to `.ensure_unique()` if `S: DataMut`.
1550    ///
1551    /// This method is mostly only useful with unsafe code.
1552    fn try_ensure_unique(&mut self)
1553    where S: RawDataMut
1554    {
1555        debug_assert!(self.pointer_is_inbounds());
1556        S::try_ensure_unique(self);
1557        debug_assert!(self.pointer_is_inbounds());
1558    }
1559
1560    /// Make the array unshared.
1561    ///
1562    /// This method is mostly only useful with unsafe code.
1563    fn ensure_unique(&mut self)
1564    where S: DataMut
1565    {
1566        debug_assert!(self.pointer_is_inbounds());
1567        S::ensure_unique(self);
1568        debug_assert!(self.pointer_is_inbounds());
1569    }
1570
1571    /// Return `true` if the array data is laid out in contiguous “C order” in
1572    /// memory (where the last index is the most rapidly varying).
1573    ///
1574    /// Return `false` otherwise, i.e. the array is possibly not
1575    /// contiguous in memory, it has custom strides, etc.
1576    pub fn is_standard_layout(&self) -> bool
1577    {
1578        dimension::is_layout_c(&self.dim, &self.strides)
1579    }
1580
1581    /// Return true if the array is known to be contiguous.
1582    pub(crate) fn is_contiguous(&self) -> bool
1583    {
1584        D::is_contiguous(&self.dim, &self.strides)
1585    }
1586
1587    /// Return a standard-layout array containing the data, cloning if
1588    /// necessary.
1589    ///
1590    /// If `self` is in standard layout, a COW view of the data is returned
1591    /// without cloning. Otherwise, the data is cloned, and the returned array
1592    /// owns the cloned data.
1593    ///
1594    /// ```
1595    /// use kn0sys_ndarray::Array2;
1596    ///
1597    /// let standard = Array2::<f64>::zeros((3, 4));
1598    /// assert!(standard.is_standard_layout());
1599    /// let cow_view = standard.as_standard_layout();
1600    /// assert!(cow_view.is_view());
1601    /// assert!(cow_view.is_standard_layout());
1602    ///
1603    /// let fortran = standard.reversed_axes();
1604    /// assert!(!fortran.is_standard_layout());
1605    /// let cow_owned = fortran.as_standard_layout();
1606    /// assert!(cow_owned.is_owned());
1607    /// assert!(cow_owned.is_standard_layout());
1608    /// ```
1609    pub fn as_standard_layout(&self) -> CowArray<'_, A, D>
1610    where
1611        S: Data<Elem = A>,
1612        A: Clone,
1613    {
1614        if self.is_standard_layout() {
1615            CowArray::from(self.view())
1616        } else {
1617            let v = crate::iterators::to_vec_mapped(self.iter(), A::clone);
1618            let dim = self.dim.clone();
1619            debug_assert_eq!(v.len(), dim.size());
1620
1621            unsafe {
1622                // Safe because the shape and element type are from the existing array
1623                // and the strides are the default strides.
1624                CowArray::from(Array::from_shape_vec_unchecked(dim, v))
1625            }
1626        }
1627    }
1628
1629    /// Return a pointer to the first element in the array.
1630    ///
1631    /// Raw access to array elements needs to follow the strided indexing
1632    /// scheme: an element at multi-index *I* in an array with strides *S* is
1633    /// located at offset
1634    ///
1635    /// *Σ<sub>0 ≤ k < d</sub> I<sub>k</sub> × S<sub>k</sub>*
1636    ///
1637    /// where *d* is `self.ndim()`.
1638    #[inline(always)]
1639    pub fn as_ptr(&self) -> *const A
1640    {
1641        self.ptr.as_ptr() as *const A
1642    }
1643
1644    /// Return a mutable pointer to the first element in the array.
1645    ///
1646    /// This method attempts to unshare the data. If `S: DataMut`, then the
1647    /// data is guaranteed to be uniquely held on return.
1648    ///
1649    /// # Warning
1650    ///
1651    /// When accessing elements through this pointer, make sure to use strides
1652    /// obtained *after* calling this method, since the process of unsharing
1653    /// the data may change the strides.
1654    #[inline(always)]
1655    pub fn as_mut_ptr(&mut self) -> *mut A
1656    where S: RawDataMut
1657    {
1658        self.try_ensure_unique(); // for ArcArray
1659        self.ptr.as_ptr()
1660    }
1661
1662    /// Return a raw view of the array.
1663    #[inline]
1664    pub fn raw_view(&self) -> RawArrayView<A, D>
1665    {
1666        unsafe { RawArrayView::new(self.ptr, self.dim.clone(), self.strides.clone()) }
1667    }
1668
1669    /// Return a raw mutable view of the array.
1670    ///
1671    /// This method attempts to unshare the data. If `S: DataMut`, then the
1672    /// data is guaranteed to be uniquely held on return.
1673    #[inline]
1674    pub fn raw_view_mut(&mut self) -> RawArrayViewMut<A, D>
1675    where S: RawDataMut
1676    {
1677        self.try_ensure_unique(); // for ArcArray
1678        unsafe { RawArrayViewMut::new(self.ptr, self.dim.clone(), self.strides.clone()) }
1679    }
1680
1681    /// Return a raw mutable view of the array.
1682    ///
1683    /// Safety: The caller must ensure that the owned array is unshared when this is called
1684    #[inline]
1685    pub(crate) unsafe fn raw_view_mut_unchecked(&mut self) -> RawArrayViewMut<A, D>
1686    where S: DataOwned
1687    {
1688        RawArrayViewMut::new(self.ptr, self.dim.clone(), self.strides.clone())
1689    }
1690
1691    /// Return the array’s data as a slice, if it is contiguous and in standard order.
1692    /// Return `None` otherwise.
1693    ///
1694    /// If this function returns `Some(_)`, then the element order in the slice
1695    /// corresponds to the logical order of the array’s elements.
1696    pub fn as_slice(&self) -> Option<&[A]>
1697    where S: Data
1698    {
1699        if self.is_standard_layout() {
1700            unsafe { Some(slice::from_raw_parts(self.ptr.as_ptr(), self.len())) }
1701        } else {
1702            None
1703        }
1704    }
1705
1706    /// Return the array’s data as a slice, if it is contiguous and in standard order.
1707    /// Return `None` otherwise.
1708    pub fn as_slice_mut(&mut self) -> Option<&mut [A]>
1709    where S: DataMut
1710    {
1711        if self.is_standard_layout() {
1712            self.ensure_unique();
1713            unsafe { Some(slice::from_raw_parts_mut(self.ptr.as_ptr(), self.len())) }
1714        } else {
1715            None
1716        }
1717    }
1718
1719    /// Return the array’s data as a slice if it is contiguous,
1720    /// return `None` otherwise.
1721    ///
1722    /// If this function returns `Some(_)`, then the elements in the slice
1723    /// have whatever order the elements have in memory.
1724    pub fn as_slice_memory_order(&self) -> Option<&[A]>
1725    where S: Data
1726    {
1727        if self.is_contiguous() {
1728            let offset = offset_from_low_addr_ptr_to_logical_ptr(&self.dim, &self.strides);
1729            unsafe { Some(slice::from_raw_parts(self.ptr.sub(offset).as_ptr(), self.len())) }
1730        } else {
1731            None
1732        }
1733    }
1734
1735    /// Return the array’s data as a slice if it is contiguous,
1736    /// return `None` otherwise.
1737    ///
1738    /// In the contiguous case, in order to return a unique reference, this
1739    /// method unshares the data if necessary, but it preserves the existing
1740    /// strides.
1741    pub fn as_slice_memory_order_mut(&mut self) -> Option<&mut [A]>
1742    where S: DataMut
1743    {
1744        self.try_as_slice_memory_order_mut().ok()
1745    }
1746
1747    /// Return the array’s data as a slice if it is contiguous, otherwise
1748    /// return `self` in the `Err` variant.
1749    pub(crate) fn try_as_slice_memory_order_mut(&mut self) -> Result<&mut [A], &mut Self>
1750    where S: DataMut
1751    {
1752        if self.is_contiguous() {
1753            self.ensure_unique();
1754            let offset = offset_from_low_addr_ptr_to_logical_ptr(&self.dim, &self.strides);
1755            unsafe { Ok(slice::from_raw_parts_mut(self.ptr.sub(offset).as_ptr(), self.len())) }
1756        } else {
1757            Err(self)
1758        }
1759    }
1760
1761    /// Transform the array into `new_shape`; any shape with the same number of elements is
1762    /// accepted.
1763    ///
1764    /// `order` specifies the *logical* order in which the array is to be read and reshaped.
1765    /// The array is returned as a `CowArray`; a view if possible, otherwise an owned array.
1766    ///
1767    /// For example, when starting from the one-dimensional sequence 1 2 3 4 5 6, it would be
1768    /// understood as a 2 x 3 array in row major ("C") order this way:
1769    ///
1770    /// ```text
1771    /// 1 2 3
1772    /// 4 5 6
1773    /// ```
1774    ///
1775    /// and as 2 x 3 in column major ("F") order this way:
1776    ///
1777    /// ```text
1778    /// 1 3 5
1779    /// 2 4 6
1780    /// ```
1781    ///
1782    /// This example should show that any time we "reflow" the elements in the array to a different
1783    /// number of rows and columns (or more axes if applicable), it is important to pick an index
1784    /// ordering, and that's the reason for the function parameter for `order`.
1785    ///
1786    /// The `new_shape` parameter should be a dimension and an optional order like these examples:
1787    ///
1788    /// ```text
1789    /// (3, 4)                          // Shape 3 x 4 with default order (RowMajor)
1790    /// ((3, 4), Order::RowMajor))      // use specific order
1791    /// ((3, 4), Order::ColumnMajor))   // use specific order
1792    /// ((3, 4), Order::C))             // use shorthand for order - shorthands C and F
1793    /// ```
1794    ///
1795    /// **Errors** if the new shape doesn't have the same number of elements as the array's current
1796    /// shape.
1797    ///
1798    /// # Example
1799    ///
1800    /// ```
1801    /// use kn0sys_ndarray::array;
1802    /// use kn0sys_ndarray::Order;
1803    ///
1804    /// assert!(
1805    ///     array![1., 2., 3., 4., 5., 6.].to_shape(((2, 3), Order::RowMajor)).unwrap()
1806    ///     == array![[1., 2., 3.],
1807    ///               [4., 5., 6.]]
1808    /// );
1809    ///
1810    /// assert!(
1811    ///     array![1., 2., 3., 4., 5., 6.].to_shape(((2, 3), Order::ColumnMajor)).unwrap()
1812    ///     == array![[1., 3., 5.],
1813    ///               [2., 4., 6.]]
1814    /// );
1815    /// ```
1816    pub fn to_shape<E>(&self, new_shape: E) -> Result<CowArray<'_, A, E::Dim>, ShapeError>
1817    where
1818        E: ShapeArg,
1819        A: Clone,
1820        S: Data,
1821    {
1822        let (shape, order) = new_shape.into_shape_and_order();
1823        self.to_shape_order(shape, order.unwrap_or(Order::RowMajor))
1824    }
1825
1826    fn to_shape_order<E>(&self, shape: E, order: Order) -> Result<CowArray<'_, A, E>, ShapeError>
1827    where
1828        E: Dimension,
1829        A: Clone,
1830        S: Data,
1831    {
1832        let len = self.dim.size();
1833        if size_of_shape_checked(&shape) != Ok(len) {
1834            return Err(error::incompatible_shapes(&self.dim, &shape));
1835        }
1836
1837        // Create a view if the length is 0, safe because the array and new shape is empty.
1838        if len == 0 {
1839            unsafe {
1840                return Ok(CowArray::from(ArrayView::from_shape_ptr(shape, self.as_ptr())));
1841            }
1842        }
1843
1844        // Try to reshape the array as a view into the existing data
1845        match reshape_dim(&self.dim, &self.strides, &shape, order) {
1846            Ok(to_strides) => unsafe {
1847                return Ok(CowArray::from(ArrayView::new(self.ptr, shape, to_strides)));
1848            },
1849            Err(err) if err.kind() == ErrorKind::IncompatibleShape => {
1850                return Err(error::incompatible_shapes(&self.dim, &shape));
1851            }
1852            _otherwise => {}
1853        }
1854
1855        // otherwise create a new array and copy the elements
1856        unsafe {
1857            let (shape, view) = match order {
1858                Order::RowMajor => (shape.set_f(false), self.view()),
1859                Order::ColumnMajor => (shape.set_f(true), self.t()),
1860            };
1861            Ok(CowArray::from(Array::from_shape_trusted_iter_unchecked(shape, view.into_iter(), A::clone)))
1862        }
1863    }
1864
1865    /// Transform the array into `shape`; any shape with the same number of
1866    /// elements is accepted, but the source array must be contiguous.
1867    ///
1868    /// If an index ordering is not specified, the default is `RowMajor`.
1869    /// The operation will only succeed if the array's memory layout is compatible with
1870    /// the index ordering, so that the array elements can be rearranged in place.
1871    ///
1872    /// If required use `.to_shape()` or `.into_shape_clone` instead for more flexible reshaping of
1873    /// arrays, which allows copying elements if required.
1874    ///
1875    /// **Errors** if the shapes don't have the same number of elements.<br>
1876    /// **Errors** if order RowMajor is given but input is not c-contiguous.
1877    /// **Errors** if order ColumnMajor is given but input is not f-contiguous.
1878    ///
1879    /// If shape is not given: use memory layout of incoming array. Row major arrays are
1880    /// reshaped using row major index ordering, column major arrays with column major index
1881    /// ordering.
1882    ///
1883    /// The `new_shape` parameter should be a dimension and an optional order like these examples:
1884    ///
1885    /// ```text
1886    /// (3, 4)                          // Shape 3 x 4 with default order (RowMajor)
1887    /// ((3, 4), Order::RowMajor))      // use specific order
1888    /// ((3, 4), Order::ColumnMajor))   // use specific order
1889    /// ((3, 4), Order::C))             // use shorthand for order - shorthands C and F
1890    /// ```
1891    ///
1892    /// # Example
1893    ///
1894    /// ```
1895    /// use kn0sys_ndarray::{aview1, aview2};
1896    /// use kn0sys_ndarray::Order;
1897    ///
1898    /// assert!(
1899    ///     aview1(&[1., 2., 3., 4.]).into_shape_with_order((2, 2)).unwrap()
1900    ///     == aview2(&[[1., 2.],
1901    ///                 [3., 4.]])
1902    /// );
1903    ///
1904    /// assert!(
1905    ///     aview1(&[1., 2., 3., 4.]).into_shape_with_order(((2, 2), Order::ColumnMajor)).unwrap()
1906    ///     == aview2(&[[1., 3.],
1907    ///                 [2., 4.]])
1908    /// );
1909    /// ```
1910    pub fn into_shape_with_order<E>(self, shape: E) -> Result<ArrayBase<S, E::Dim>, ShapeError>
1911    where E: ShapeArg
1912    {
1913        let (shape, order) = shape.into_shape_and_order();
1914        self.into_shape_with_order_impl(shape, order.unwrap_or(Order::RowMajor))
1915    }
1916
1917    fn into_shape_with_order_impl<E>(self, shape: E, order: Order) -> Result<ArrayBase<S, E>, ShapeError>
1918    where E: Dimension
1919    {
1920        let shape = shape.into_dimension();
1921        if size_of_shape_checked(&shape) != Ok(self.dim.size()) {
1922            return Err(error::incompatible_shapes(&self.dim, &shape));
1923        }
1924
1925        // Check if contiguous, then we can change shape
1926        unsafe {
1927            // safe because arrays are contiguous and len is unchanged
1928            match order {
1929                Order::RowMajor if self.is_standard_layout() =>
1930                    Ok(self.with_strides_dim(shape.default_strides(), shape)),
1931                Order::ColumnMajor if self.raw_view().reversed_axes().is_standard_layout() =>
1932                    Ok(self.with_strides_dim(shape.fortran_strides(), shape)),
1933                _otherwise => Err(error::from_kind(error::ErrorKind::IncompatibleLayout)),
1934            }
1935        }
1936    }
1937
1938    /// Transform the array into `shape`; any shape with the same number of
1939    /// elements is accepted, but the source array or view must be in standard
1940    /// or column-major (Fortran) layout.
1941    ///
1942    /// **Note** that `.into_shape()` "moves" elements differently depending on if the input array
1943    /// is C-contig or F-contig, it follows the index order that corresponds to the memory order.
1944    /// Prefer to use `.to_shape()` or `.into_shape_with_order()`.
1945    ///
1946    /// Because of this, the method **is deprecated**. That reshapes depend on memory order is not
1947    /// intuitive.
1948    ///
1949    /// **Errors** if the shapes don't have the same number of elements.<br>
1950    /// **Errors** if the input array is not c- or f-contiguous.
1951    ///
1952    /// ```
1953    /// use kn0sys_ndarray::{aview1, aview2};
1954    ///
1955    /// assert!(
1956    ///     aview1(&[1., 2., 3., 4.]).into_shape((2, 2)).unwrap()
1957    ///     == aview2(&[[1., 2.],
1958    ///                 [3., 4.]])
1959    /// );
1960    /// ```
1961    #[deprecated(note = "Use `.into_shape_with_order()` or `.to_shape()`", since = "0.16.0")]
1962    pub fn into_shape<E>(self, shape: E) -> Result<ArrayBase<S, E::Dim>, ShapeError>
1963    where E: IntoDimension
1964    {
1965        let shape = shape.into_dimension();
1966        if size_of_shape_checked(&shape) != Ok(self.dim.size()) {
1967            return Err(error::incompatible_shapes(&self.dim, &shape));
1968        }
1969        // Check if contiguous, if not => copy all, else just adapt strides
1970        unsafe {
1971            // safe because arrays are contiguous and len is unchanged
1972            if self.is_standard_layout() {
1973                Ok(self.with_strides_dim(shape.default_strides(), shape))
1974            } else if self.ndim() > 1 && self.raw_view().reversed_axes().is_standard_layout() {
1975                Ok(self.with_strides_dim(shape.fortran_strides(), shape))
1976            } else {
1977                Err(error::from_kind(error::ErrorKind::IncompatibleLayout))
1978            }
1979        }
1980    }
1981
1982    /// Transform the array into `shape`; any shape with the same number of
1983    /// elements is accepted. Array elements are reordered in place if
1984    /// possible, otherwise they are copied to create a new array.
1985    ///
1986    /// If an index ordering is not specified, the default is `RowMajor`.
1987    ///
1988    /// # `.to_shape` vs `.into_shape_clone`
1989    ///
1990    /// - `to_shape` supports views and outputting views
1991    /// - `to_shape` borrows the original array, `into_shape_clone` consumes the original
1992    /// - `into_shape_clone` preserves array type (Array vs ArcArray), but does not support views.
1993    ///
1994    /// **Errors** if the shapes don't have the same number of elements.<br>
1995    pub fn into_shape_clone<E>(self, shape: E) -> Result<ArrayBase<S, E::Dim>, ShapeError>
1996    where
1997        S: DataOwned,
1998        A: Clone,
1999        E: ShapeArg,
2000    {
2001        let (shape, order) = shape.into_shape_and_order();
2002        let order = order.unwrap_or(Order::RowMajor);
2003        self.into_shape_clone_order(shape, order)
2004    }
2005
2006    fn into_shape_clone_order<E>(self, shape: E, order: Order) -> Result<ArrayBase<S, E>, ShapeError>
2007    where
2008        S: DataOwned,
2009        A: Clone,
2010        E: Dimension,
2011    {
2012        let len = self.dim.size();
2013        if size_of_shape_checked(&shape) != Ok(len) {
2014            return Err(error::incompatible_shapes(&self.dim, &shape));
2015        }
2016
2017        // Safe because the array and new shape is empty.
2018        if len == 0 {
2019            unsafe {
2020                return Ok(self.with_strides_dim(shape.default_strides(), shape));
2021            }
2022        }
2023
2024        // Try to reshape the array's current data
2025        match reshape_dim(&self.dim, &self.strides, &shape, order) {
2026            Ok(to_strides) => unsafe {
2027                return Ok(self.with_strides_dim(to_strides, shape));
2028            },
2029            Err(err) if err.kind() == ErrorKind::IncompatibleShape => {
2030                return Err(error::incompatible_shapes(&self.dim, &shape));
2031            }
2032            _otherwise => {}
2033        }
2034
2035        // otherwise, clone and allocate a new array
2036        unsafe {
2037            let (shape, view) = match order {
2038                Order::RowMajor => (shape.set_f(false), self.view()),
2039                Order::ColumnMajor => (shape.set_f(true), self.t()),
2040            };
2041
2042            Ok(ArrayBase::from_shape_trusted_iter_unchecked(shape, view.into_iter(), A::clone))
2043        }
2044    }
2045
2046    /// *Note: Reshape is for `ArcArray` only. Use `.into_shape_with_order()` for
2047    /// other arrays and array views.*
2048    ///
2049    /// Transform the array into `shape`; any shape with the same number of
2050    /// elements is accepted.
2051    ///
2052    /// May clone all elements if needed to arrange elements in standard
2053    /// layout (and break sharing).
2054    ///
2055    /// **Panics** if shapes are incompatible.
2056    ///
2057    /// *This method is obsolete, because it is inflexible in how logical order
2058    /// of the array is handled. See [`.to_shape()`].*
2059    ///
2060    /// ```
2061    /// use kn0sys_ndarray::{rcarr1, rcarr2};
2062    ///
2063    /// assert!(
2064    ///     rcarr1(&[1., 2., 3., 4.]).reshape((2, 2))
2065    ///     == rcarr2(&[[1., 2.],
2066    ///                 [3., 4.]])
2067    /// );
2068    /// ```
2069    #[track_caller]
2070    #[deprecated(note = "Use `.into_shape_with_order()` or `.to_shape()`", since = "0.16.0")]
2071    pub fn reshape<E>(&self, shape: E) -> ArrayBase<S, E::Dim>
2072    where
2073        S: DataShared + DataOwned,
2074        A: Clone,
2075        E: IntoDimension,
2076    {
2077        let shape = shape.into_dimension();
2078        if size_of_shape_checked(&shape) != Ok(self.dim.size()) {
2079            panic!(
2080                "ndarray: incompatible shapes in reshape, attempted from: {:?}, to: {:?}",
2081                self.dim.slice(),
2082                shape.slice()
2083            )
2084        }
2085        // Check if contiguous, if not => copy all, else just adapt strides
2086        if self.is_standard_layout() {
2087            let cl = self.clone();
2088            // safe because array is contiguous and shape has equal number of elements
2089            unsafe { cl.with_strides_dim(shape.default_strides(), shape) }
2090        } else {
2091            let v = self.iter().cloned().collect::<Vec<A>>();
2092            unsafe { ArrayBase::from_shape_vec_unchecked(shape, v) }
2093        }
2094    }
2095
2096    /// Flatten the array to a one-dimensional array.
2097    ///
2098    /// The array is returned as a `CowArray`; a view if possible, otherwise an owned array.
2099    ///
2100    /// ```
2101    /// use kn0sys_ndarray::{arr1, arr3};
2102    ///
2103    /// let array = arr3(&[[[1, 2], [3, 4]], [[5, 6], [7, 8]]]);
2104    /// let flattened = array.flatten();
2105    /// assert_eq!(flattened, arr1(&[1, 2, 3, 4, 5, 6, 7, 8]));
2106    /// ```
2107    pub fn flatten(&self) -> CowArray<'_, A, Ix1>
2108    where
2109        A: Clone,
2110        S: Data,
2111    {
2112        self.flatten_with_order(Order::RowMajor)
2113    }
2114
2115    /// Flatten the array to a one-dimensional array.
2116    ///
2117    /// `order` specifies the *logical* order in which the array is to be read and reshaped.
2118    /// The array is returned as a `CowArray`; a view if possible, otherwise an owned array.
2119    ///
2120    /// ```
2121    /// use kn0sys_ndarray::{arr1, arr2};
2122    /// use kn0sys_ndarray::Order;
2123    ///
2124    /// let array = arr2(&[[1, 2], [3, 4], [5, 6], [7, 8]]);
2125    /// let flattened = array.flatten_with_order(Order::RowMajor);
2126    /// assert_eq!(flattened, arr1(&[1, 2, 3, 4, 5, 6, 7, 8]));
2127    /// let flattened = array.flatten_with_order(Order::ColumnMajor);
2128    /// assert_eq!(flattened, arr1(&[1, 3, 5, 7, 2, 4, 6, 8]));
2129    /// ```
2130    pub fn flatten_with_order(&self, order: Order) -> CowArray<'_, A, Ix1>
2131    where
2132        A: Clone,
2133        S: Data,
2134    {
2135        self.to_shape((self.len(), order)).unwrap()
2136    }
2137
2138    /// Flatten the array to a one-dimensional array, consuming the array.
2139    ///
2140    /// If possible, no copy is made, and the new array use the same memory as the original array.
2141    /// Otherwise, a new array is allocated and the elements are copied.
2142    ///
2143    /// ```
2144    /// use kn0sys_ndarray::{arr1, arr3};
2145    ///
2146    /// let array = arr3(&[[[1, 2], [3, 4]], [[5, 6], [7, 8]]]);
2147    /// let flattened = array.into_flat();
2148    /// assert_eq!(flattened, arr1(&[1, 2, 3, 4, 5, 6, 7, 8]));
2149    /// ```
2150    pub fn into_flat(self) -> ArrayBase<S, Ix1>
2151    where
2152        A: Clone,
2153        S: DataOwned,
2154    {
2155        let len = self.len();
2156        self.into_shape_clone(Ix1(len)).unwrap()
2157    }
2158
2159    /// Convert any array or array view to a dynamic dimensional array or
2160    /// array view (respectively).
2161    ///
2162    /// ```
2163    /// use kn0sys_ndarray::{arr2, ArrayD};
2164    ///
2165    /// let array: ArrayD<i32> = arr2(&[[1, 2],
2166    ///                                 [3, 4]]).into_dyn();
2167    /// ```
2168    pub fn into_dyn(self) -> ArrayBase<S, IxDyn>
2169    {
2170        // safe because new dims equivalent
2171        unsafe {
2172            ArrayBase::from_data_ptr(self.data, self.ptr).with_strides_dim(self.strides.into_dyn(), self.dim.into_dyn())
2173        }
2174    }
2175
2176    /// Convert an array or array view to another with the same type, but different dimensionality
2177    /// type. Errors if the dimensions don't agree (the number of axes must match).
2178    ///
2179    /// Note that conversion to a dynamic dimensional array will never fail (and is equivalent to
2180    /// the `into_dyn` method).
2181    ///
2182    /// ```
2183    /// use kn0sys_ndarray::{ArrayD, Ix2, IxDyn};
2184    ///
2185    /// // Create a dynamic dimensionality array and convert it to an Array2
2186    /// // (Ix2 dimension type).
2187    ///
2188    /// let array = ArrayD::<f64>::zeros(IxDyn(&[10, 10]));
2189    ///
2190    /// assert!(array.into_dimensionality::<Ix2>().is_ok());
2191    /// ```
2192    pub fn into_dimensionality<D2>(self) -> Result<ArrayBase<S, D2>, ShapeError>
2193    where D2: Dimension
2194    {
2195        unsafe {
2196            if D::NDIM == D2::NDIM {
2197                // safe because D == D2
2198                let dim = unlimited_transmute::<D, D2>(self.dim);
2199                let strides = unlimited_transmute::<D, D2>(self.strides);
2200                return Ok(ArrayBase::from_data_ptr(self.data, self.ptr).with_strides_dim(strides, dim));
2201            } else if D::NDIM.is_none() || D2::NDIM.is_none() {
2202                // one is dynamic dim
2203                // safe because dim, strides are equivalent under a different type
2204                if let Some(dim) = D2::from_dimension(&self.dim) {
2205                    if let Some(strides) = D2::from_dimension(&self.strides) {
2206                        return Ok(self.with_strides_dim(strides, dim));
2207                    }
2208                }
2209            }
2210        }
2211        Err(ShapeError::from_kind(ErrorKind::IncompatibleShape))
2212    }
2213
2214    /// Act like a larger size and/or shape array by *broadcasting*
2215    /// into a larger shape, if possible.
2216    ///
2217    /// Return `None` if shapes can not be broadcast together.
2218    ///
2219    /// ***Background***
2220    ///
2221    ///  * Two axes are compatible if they are equal, or one of them is 1.
2222    ///  * In this instance, only the axes of the smaller side (self) can be 1.
2223    ///
2224    /// Compare axes beginning with the *last* axis of each shape.
2225    ///
2226    /// For example (1, 2, 4) can be broadcast into (7, 6, 2, 4)
2227    /// because its axes are either equal or 1 (or missing);
2228    /// while (2, 2) can *not* be broadcast into (2, 4).
2229    ///
2230    /// The implementation creates a view with strides set to zero for the
2231    /// axes that are to be repeated.
2232    ///
2233    /// The broadcasting documentation for Numpy has more information.
2234    ///
2235    /// ```
2236    /// use kn0sys_ndarray::{aview1, aview2};
2237    ///
2238    /// assert!(
2239    ///     aview1(&[1., 0.]).broadcast((10, 2)).unwrap()
2240    ///     == aview2(&[[1., 0.]; 10])
2241    /// );
2242    /// ```
2243    pub fn broadcast<E>(&self, dim: E) -> Option<ArrayView<'_, A, E::Dim>>
2244    where
2245        E: IntoDimension,
2246        S: Data,
2247    {
2248        /// Return new stride when trying to grow `from` into shape `to`
2249        ///
2250        /// Broadcasting works by returning a "fake stride" where elements
2251        /// to repeat are in axes with 0 stride, so that several indexes point
2252        /// to the same element.
2253        ///
2254        /// **Note:** Cannot be used for mutable iterators, since repeating
2255        /// elements would create aliasing pointers.
2256        fn upcast<D: Dimension, E: Dimension>(to: &D, from: &E, stride: &E) -> Option<D>
2257        {
2258            // Make sure the product of non-zero axis lengths does not exceed
2259            // `isize::MAX`. This is the only safety check we need to perform
2260            // because all the other constraints of `ArrayBase` are guaranteed
2261            // to be met since we're starting from a valid `ArrayBase`.
2262            let _ = size_of_shape_checked(to).ok()?;
2263
2264            let mut new_stride = to.clone();
2265            // begin at the back (the least significant dimension)
2266            // size of the axis has to either agree or `from` has to be 1
2267            if to.ndim() < from.ndim() {
2268                return None;
2269            }
2270
2271            {
2272                let mut new_stride_iter = new_stride.slice_mut().iter_mut().rev();
2273                for ((er, es), dr) in from
2274                    .slice()
2275                    .iter()
2276                    .rev()
2277                    .zip(stride.slice().iter().rev())
2278                    .zip(new_stride_iter.by_ref())
2279                {
2280                    /* update strides */
2281                    if *dr == *er {
2282                        /* keep stride */
2283                        *dr = *es;
2284                    } else if *er == 1 {
2285                        /* dead dimension, zero stride */
2286                        *dr = 0
2287                    } else {
2288                        return None;
2289                    }
2290                }
2291
2292                /* set remaining strides to zero */
2293                for dr in new_stride_iter {
2294                    *dr = 0;
2295                }
2296            }
2297            Some(new_stride)
2298        }
2299        let dim = dim.into_dimension();
2300
2301        // Note: zero strides are safe precisely because we return an read-only view
2302        let broadcast_strides = upcast(&dim, &self.dim, &self.strides)?;
2303        unsafe { Some(ArrayView::new(self.ptr, dim, broadcast_strides)) }
2304    }
2305
2306    /// For two arrays or views, find their common shape if possible and
2307    /// broadcast them as array views into that shape.
2308    ///
2309    /// Return `ShapeError` if their shapes can not be broadcast together.
2310    #[allow(clippy::type_complexity)]
2311    pub(crate) fn broadcast_with<'a, 'b, B, S2, E>(
2312        &'a self, other: &'b ArrayBase<S2, E>,
2313    ) -> Result<(ArrayView<'a, A, DimMaxOf<D, E>>, ArrayView<'b, B, DimMaxOf<D, E>>), ShapeError>
2314    where
2315        S: Data<Elem = A>,
2316        S2: Data<Elem = B>,
2317        D: Dimension + DimMax<E>,
2318        E: Dimension,
2319    {
2320        let shape = co_broadcast::<D, E, <D as DimMax<E>>::Output>(&self.dim, &other.dim)?;
2321        let view1 = if shape.slice() == self.dim.slice() {
2322            self.view()
2323                .into_dimensionality::<<D as DimMax<E>>::Output>()
2324                .unwrap()
2325        } else if let Some(view1) = self.broadcast(shape.clone()) {
2326            view1
2327        } else {
2328            return Err(from_kind(ErrorKind::IncompatibleShape));
2329        };
2330        let view2 = if shape.slice() == other.dim.slice() {
2331            other
2332                .view()
2333                .into_dimensionality::<<D as DimMax<E>>::Output>()
2334                .unwrap()
2335        } else if let Some(view2) = other.broadcast(shape) {
2336            view2
2337        } else {
2338            return Err(from_kind(ErrorKind::IncompatibleShape));
2339        };
2340        Ok((view1, view2))
2341    }
2342
2343    /// Swap axes `ax` and `bx`.
2344    ///
2345    /// This does not move any data, it just adjusts the array’s dimensions
2346    /// and strides.
2347    ///
2348    /// **Panics** if the axes are out of bounds.
2349    ///
2350    /// ```
2351    /// use kn0sys_ndarray::arr2;
2352    ///
2353    /// let mut a = arr2(&[[1., 2., 3.]]);
2354    /// a.swap_axes(0, 1);
2355    /// assert!(
2356    ///     a == arr2(&[[1.], [2.], [3.]])
2357    /// );
2358    /// ```
2359    #[track_caller]
2360    pub fn swap_axes(&mut self, ax: usize, bx: usize)
2361    {
2362        self.dim.slice_mut().swap(ax, bx);
2363        self.strides.slice_mut().swap(ax, bx);
2364    }
2365
2366    /// Permute the axes.
2367    ///
2368    /// This does not move any data, it just adjusts the array’s dimensions
2369    /// and strides.
2370    ///
2371    /// *i* in the *j*-th place in the axes sequence means `self`'s *i*-th axis
2372    /// becomes `self.permuted_axes()`'s *j*-th axis
2373    ///
2374    /// **Panics** if any of the axes are out of bounds, if an axis is missing,
2375    /// or if an axis is repeated more than once.
2376    ///
2377    /// # Examples
2378    ///
2379    /// ```
2380    /// use kn0sys_ndarray::{arr2, Array3};
2381    ///
2382    /// let a = arr2(&[[0, 1], [2, 3]]);
2383    /// assert_eq!(a.view().permuted_axes([1, 0]), a.t());
2384    ///
2385    /// let b = Array3::<u8>::zeros((1, 2, 3));
2386    /// assert_eq!(b.permuted_axes([1, 0, 2]).shape(), &[2, 1, 3]);
2387    /// ```
2388    #[track_caller]
2389    pub fn permuted_axes<T>(self, axes: T) -> ArrayBase<S, D>
2390    where T: IntoDimension<Dim = D>
2391    {
2392        let axes = axes.into_dimension();
2393        // Ensure that each axis is used exactly once.
2394        let mut usage_counts = D::zeros(self.ndim());
2395        for axis in axes.slice() {
2396            usage_counts[*axis] += 1;
2397        }
2398        for count in usage_counts.slice() {
2399            assert_eq!(*count, 1, "each axis must be listed exactly once");
2400        }
2401        // Determine the new shape and strides.
2402        let mut new_dim = usage_counts; // reuse to avoid an allocation
2403        let mut new_strides = D::zeros(self.ndim());
2404        {
2405            let dim = self.dim.slice();
2406            let strides = self.strides.slice();
2407            for (new_axis, &axis) in axes.slice().iter().enumerate() {
2408                new_dim[new_axis] = dim[axis];
2409                new_strides[new_axis] = strides[axis];
2410            }
2411        }
2412        // safe because axis invariants are checked above; they are a permutation of the old
2413        unsafe { self.with_strides_dim(new_strides, new_dim) }
2414    }
2415
2416    /// Transpose the array by reversing axes.
2417    ///
2418    /// Transposition reverses the order of the axes (dimensions and strides)
2419    /// while retaining the same data.
2420    pub fn reversed_axes(mut self) -> ArrayBase<S, D>
2421    {
2422        self.dim.slice_mut().reverse();
2423        self.strides.slice_mut().reverse();
2424        self
2425    }
2426
2427    /// Return a transposed view of the array.
2428    ///
2429    /// This is a shorthand for `self.view().reversed_axes()`.
2430    ///
2431    /// See also the more general methods `.reversed_axes()` and `.swap_axes()`.
2432    pub fn t(&self) -> ArrayView<'_, A, D>
2433    where S: Data
2434    {
2435        self.view().reversed_axes()
2436    }
2437
2438    /// Return an iterator over the length and stride of each axis.
2439    pub fn axes(&self) -> Axes<'_, D>
2440    {
2441        axes_of(&self.dim, &self.strides)
2442    }
2443
2444    /*
2445    /// Return the axis with the least stride (by absolute value)
2446    pub fn min_stride_axis(&self) -> Axis {
2447        self.dim.min_stride_axis(&self.strides)
2448    }
2449    */
2450
2451    /// Return the axis with the greatest stride (by absolute value),
2452    /// preferring axes with len > 1.
2453    pub fn max_stride_axis(&self) -> Axis
2454    {
2455        self.dim.max_stride_axis(&self.strides)
2456    }
2457
2458    /// Reverse the stride of `axis`.
2459    ///
2460    /// ***Panics*** if the axis is out of bounds.
2461    #[track_caller]
2462    pub fn invert_axis(&mut self, axis: Axis)
2463    {
2464        unsafe {
2465            let s = self.strides.axis(axis) as Ixs;
2466            let m = self.dim.axis(axis);
2467            if m != 0 {
2468                self.ptr = self.ptr.offset(stride_offset(m - 1, s as Ix));
2469            }
2470            self.strides.set_axis(axis, (-s) as Ix);
2471        }
2472    }
2473
2474    /// If possible, merge in the axis `take` to `into`.
2475    ///
2476    /// Returns `true` iff the axes are now merged.
2477    ///
2478    /// This method merges the axes if movement along the two original axes
2479    /// (moving fastest along the `into` axis) can be equivalently represented
2480    /// as movement along one (merged) axis. Merging the axes preserves this
2481    /// order in the merged axis. If `take` and `into` are the same axis, then
2482    /// the axis is "merged" if its length is ≤ 1.
2483    ///
2484    /// If the return value is `true`, then the following hold:
2485    ///
2486    /// * The new length of the `into` axis is the product of the original
2487    ///   lengths of the two axes.
2488    ///
2489    /// * The new length of the `take` axis is 0 if the product of the original
2490    ///   lengths of the two axes is 0, and 1 otherwise.
2491    ///
2492    /// If the return value is `false`, then merging is not possible, and the
2493    /// original shape and strides have been preserved.
2494    ///
2495    /// Note that the ordering constraint means that if it's possible to merge
2496    /// `take` into `into`, it's usually not possible to merge `into` into
2497    /// `take`, and vice versa.
2498    ///
2499    /// ```
2500    /// use kn0sys_ndarray::Array3;
2501    /// use kn0sys_ndarray::Axis;
2502    ///
2503    /// let mut a = Array3::<f64>::zeros((2, 3, 4));
2504    /// assert!(a.merge_axes(Axis(1), Axis(2)));
2505    /// assert_eq!(a.shape(), &[2, 1, 12]);
2506    /// ```
2507    ///
2508    /// ***Panics*** if an axis is out of bounds.
2509    #[track_caller]
2510    pub fn merge_axes(&mut self, take: Axis, into: Axis) -> bool
2511    {
2512        merge_axes(&mut self.dim, &mut self.strides, take, into)
2513    }
2514
2515    /// Insert new array axis at `axis` and return the result.
2516    ///
2517    /// ```
2518    /// use kn0sys_ndarray::{Array3, Axis, arr1, arr2};
2519    ///
2520    /// // Convert a 1-D array into a row vector (2-D).
2521    /// let a = arr1(&[1, 2, 3]);
2522    /// let row = a.insert_axis(Axis(0));
2523    /// assert_eq!(row, arr2(&[[1, 2, 3]]));
2524    ///
2525    /// // Convert a 1-D array into a column vector (2-D).
2526    /// let b = arr1(&[1, 2, 3]);
2527    /// let col = b.insert_axis(Axis(1));
2528    /// assert_eq!(col, arr2(&[[1], [2], [3]]));
2529    ///
2530    /// // The new axis always has length 1.
2531    /// let b = Array3::<f64>::zeros((3, 4, 5));
2532    /// assert_eq!(b.insert_axis(Axis(2)).shape(), &[3, 4, 1, 5]);
2533    /// ```
2534    ///
2535    /// ***Panics*** if the axis is out of bounds.
2536    #[track_caller]
2537    pub fn insert_axis(self, axis: Axis) -> ArrayBase<S, D::Larger>
2538    {
2539        assert!(axis.index() <= self.ndim());
2540        // safe because a new axis of length one does not affect memory layout
2541        unsafe {
2542            let strides = self.strides.insert_axis(axis);
2543            let dim = self.dim.insert_axis(axis);
2544            self.with_strides_dim(strides, dim)
2545        }
2546    }
2547
2548    /// Remove array axis `axis` and return the result.
2549    ///
2550    /// This is equivalent to `.index_axis_move(axis, 0)` and makes most sense to use if the
2551    /// axis to remove is of length 1.
2552    ///
2553    /// **Panics** if the axis is out of bounds or its length is zero.
2554    #[track_caller]
2555    pub fn remove_axis(self, axis: Axis) -> ArrayBase<S, D::Smaller>
2556    where D: RemoveAxis
2557    {
2558        self.index_axis_move(axis, 0)
2559    }
2560
2561    pub(crate) fn pointer_is_inbounds(&self) -> bool
2562    {
2563        self.data._is_pointer_inbounds(self.as_ptr())
2564    }
2565
2566    /// Perform an elementwise assigment to `self` from `rhs`.
2567    ///
2568    /// If their shapes disagree, `rhs` is broadcast to the shape of `self`.
2569    ///
2570    /// **Panics** if broadcasting isn’t possible.
2571    #[track_caller]
2572    pub fn assign<E: Dimension, S2>(&mut self, rhs: &ArrayBase<S2, E>)
2573    where
2574        S: DataMut,
2575        A: Clone,
2576        S2: Data<Elem = A>,
2577    {
2578        self.zip_mut_with(rhs, |x, y| x.clone_from(y));
2579    }
2580
2581    /// Perform an elementwise assigment of values cloned from `self` into array or producer `to`.
2582    ///
2583    /// The destination `to` can be another array or a producer of assignable elements.
2584    /// [`AssignElem`] determines how elements are assigned.
2585    ///
2586    /// **Panics** if shapes disagree.
2587    #[track_caller]
2588    pub fn assign_to<P>(&self, to: P)
2589    where
2590        S: Data,
2591        P: IntoNdProducer<Dim = D>,
2592        P::Item: AssignElem<A>,
2593        A: Clone,
2594    {
2595        Zip::from(self).map_assign_into(to, A::clone);
2596    }
2597
2598    /// Perform an elementwise assigment to `self` from element `x`.
2599    pub fn fill(&mut self, x: A)
2600    where
2601        S: DataMut,
2602        A: Clone,
2603    {
2604        self.map_inplace(move |elt| elt.clone_from(&x));
2605    }
2606
2607    pub(crate) fn zip_mut_with_same_shape<B, S2, E, F>(&mut self, rhs: &ArrayBase<S2, E>, mut f: F)
2608    where
2609        S: DataMut,
2610        S2: Data<Elem = B>,
2611        E: Dimension,
2612        F: FnMut(&mut A, &B),
2613    {
2614        debug_assert_eq!(self.shape(), rhs.shape());
2615
2616        if self.dim.strides_equivalent(&self.strides, &rhs.strides) {
2617            if let Some(self_s) = self.as_slice_memory_order_mut() {
2618                if let Some(rhs_s) = rhs.as_slice_memory_order() {
2619                    for (s, r) in self_s.iter_mut().zip(rhs_s) {
2620                        f(s, r);
2621                    }
2622                    return;
2623                }
2624            }
2625        }
2626
2627        // Otherwise, fall back to the outer iter
2628        self.zip_mut_with_by_rows(rhs, f);
2629    }
2630
2631    // zip two arrays where they have different layout or strides
2632    #[inline(always)]
2633    fn zip_mut_with_by_rows<B, S2, E, F>(&mut self, rhs: &ArrayBase<S2, E>, mut f: F)
2634    where
2635        S: DataMut,
2636        S2: Data<Elem = B>,
2637        E: Dimension,
2638        F: FnMut(&mut A, &B),
2639    {
2640        debug_assert_eq!(self.shape(), rhs.shape());
2641        debug_assert_ne!(self.ndim(), 0);
2642
2643        // break the arrays up into their inner rows
2644        let n = self.ndim();
2645        let dim = self.raw_dim();
2646        Zip::from(LanesMut::new(self.view_mut(), Axis(n - 1)))
2647            .and(Lanes::new(rhs.broadcast_assume(dim), Axis(n - 1)))
2648            .for_each(move |s_row, r_row| Zip::from(s_row).and(r_row).for_each(&mut f));
2649    }
2650
2651    fn zip_mut_with_elem<B, F>(&mut self, rhs_elem: &B, mut f: F)
2652    where
2653        S: DataMut,
2654        F: FnMut(&mut A, &B),
2655    {
2656        self.map_inplace(move |elt| f(elt, rhs_elem));
2657    }
2658
2659    /// Traverse two arrays in unspecified order, in lock step,
2660    /// calling the closure `f` on each element pair.
2661    ///
2662    /// If their shapes disagree, `rhs` is broadcast to the shape of `self`.
2663    ///
2664    /// **Panics** if broadcasting isn’t possible.
2665    #[track_caller]
2666    #[inline]
2667    pub fn zip_mut_with<B, S2, E, F>(&mut self, rhs: &ArrayBase<S2, E>, f: F)
2668    where
2669        S: DataMut,
2670        S2: Data<Elem = B>,
2671        E: Dimension,
2672        F: FnMut(&mut A, &B),
2673    {
2674        if rhs.dim.ndim() == 0 {
2675            // Skip broadcast from 0-dim array
2676            self.zip_mut_with_elem(rhs.get_0d(), f);
2677        } else if self.dim.ndim() == rhs.dim.ndim() && self.shape() == rhs.shape() {
2678            self.zip_mut_with_same_shape(rhs, f);
2679        } else {
2680            let rhs_broadcast = rhs.broadcast_unwrap(self.raw_dim());
2681            self.zip_mut_with_by_rows(&rhs_broadcast, f);
2682        }
2683    }
2684
2685    /// Traverse the array elements and apply a fold,
2686    /// returning the resulting value.
2687    ///
2688    /// Elements are visited in arbitrary order.
2689    pub fn fold<'a, F, B>(&'a self, init: B, f: F) -> B
2690    where
2691        F: FnMut(B, &'a A) -> B,
2692        A: 'a,
2693        S: Data,
2694    {
2695        if let Some(slc) = self.as_slice_memory_order() {
2696            slc.iter().fold(init, f)
2697        } else {
2698            let mut v = self.view();
2699            move_min_stride_axis_to_last(&mut v.dim, &mut v.strides);
2700            v.into_elements_base().fold(init, f)
2701        }
2702    }
2703
2704    /// Call `f` by reference on each element and create a new array
2705    /// with the new values.
2706    ///
2707    /// Elements are visited in arbitrary order.
2708    ///
2709    /// Return an array with the same shape as `self`.
2710    ///
2711    /// ```
2712    /// use kn0sys_ndarray::arr2;
2713    ///
2714    /// let a = arr2(&[[ 0., 1.],
2715    ///                [-1., 2.]]);
2716    /// assert!(
2717    ///     a.map(|x| *x >= 1.0)
2718    ///     == arr2(&[[false, true],
2719    ///               [false, true]])
2720    /// );
2721    /// ```
2722    pub fn map<'a, B, F>(&'a self, f: F) -> Array<B, D>
2723    where
2724        F: FnMut(&'a A) -> B,
2725        A: 'a,
2726        S: Data,
2727    {
2728        unsafe {
2729            if let Some(slc) = self.as_slice_memory_order() {
2730                ArrayBase::from_shape_trusted_iter_unchecked(
2731                    self.dim.clone().strides(self.strides.clone()),
2732                    slc.iter(),
2733                    f,
2734                )
2735            } else {
2736                ArrayBase::from_shape_trusted_iter_unchecked(self.dim.clone(), self.iter(), f)
2737            }
2738        }
2739    }
2740
2741    /// Call `f` on a mutable reference of each element and create a new array
2742    /// with the new values.
2743    ///
2744    /// Elements are visited in arbitrary order.
2745    ///
2746    /// Return an array with the same shape as `self`.
2747    pub fn map_mut<'a, B, F>(&'a mut self, f: F) -> Array<B, D>
2748    where
2749        F: FnMut(&'a mut A) -> B,
2750        A: 'a,
2751        S: DataMut,
2752    {
2753        let dim = self.dim.clone();
2754        if self.is_contiguous() {
2755            let strides = self.strides.clone();
2756            let slc = self.as_slice_memory_order_mut().unwrap();
2757            unsafe { ArrayBase::from_shape_trusted_iter_unchecked(dim.strides(strides), slc.iter_mut(), f) }
2758        } else {
2759            unsafe { ArrayBase::from_shape_trusted_iter_unchecked(dim, self.iter_mut(), f) }
2760        }
2761    }
2762
2763    /// Call `f` by **v**alue on each element and create a new array
2764    /// with the new values.
2765    ///
2766    /// Elements are visited in arbitrary order.
2767    ///
2768    /// Return an array with the same shape as `self`.
2769    ///
2770    /// ```
2771    /// use kn0sys_ndarray::arr2;
2772    ///
2773    /// let a = arr2(&[[ 0., 1.],
2774    ///                [-1., 2.]]);
2775    /// assert!(
2776    ///     a.mapv(f32::abs) == arr2(&[[0., 1.],
2777    ///                                [1., 2.]])
2778    /// );
2779    /// ```
2780    pub fn mapv<B, F>(&self, mut f: F) -> Array<B, D>
2781    where
2782        F: FnMut(A) -> B,
2783        A: Clone,
2784        S: Data,
2785    {
2786        self.map(move |x| f(x.clone()))
2787    }
2788
2789    /// Call `f` by **v**alue on each element, update the array with the new values
2790    /// and return it.
2791    ///
2792    /// Elements are visited in arbitrary order.
2793    pub fn mapv_into<F>(mut self, f: F) -> Self
2794    where
2795        S: DataMut,
2796        F: FnMut(A) -> A,
2797        A: Clone,
2798    {
2799        self.mapv_inplace(f);
2800        self
2801    }
2802
2803    /// Consume the array, call `f` by **v**alue on each element, and return an
2804    /// owned array with the new values. Works for **any** `F: FnMut(A)->B`.
2805    ///
2806    /// If `A` and `B` are the same type then the map is performed by delegating
2807    /// to [`mapv_into`] and then converting into an owned array. This avoids
2808    /// unnecessary memory allocations in [`mapv`].
2809    ///
2810    /// If `A` and `B` are different types then a new array is allocated and the
2811    /// map is performed as in [`mapv`].
2812    ///
2813    /// Elements are visited in arbitrary order.
2814    ///
2815    /// [`mapv_into`]: ArrayBase::mapv_into
2816    /// [`mapv`]: ArrayBase::mapv
2817    pub fn mapv_into_any<B, F>(self, mut f: F) -> Array<B, D>
2818    where
2819        S: DataMut,
2820        F: FnMut(A) -> B,
2821        A: Clone + 'static,
2822        B: 'static,
2823    {
2824        if core::any::TypeId::of::<A>() == core::any::TypeId::of::<B>() {
2825            // A and B are the same type.
2826            // Wrap f in a closure of type FnMut(A) -> A .
2827            let f = |a| {
2828                let b = f(a);
2829                // Safe because A and B are the same type.
2830                unsafe { unlimited_transmute::<B, A>(b) }
2831            };
2832            // Delegate to mapv_into() using the wrapped closure.
2833            // Convert output to a uniquely owned array of type Array<A, D>.
2834            let output = self.mapv_into(f).into_owned();
2835            // Change the return type from Array<A, D> to Array<B, D>.
2836            // Again, safe because A and B are the same type.
2837            unsafe { unlimited_transmute::<Array<A, D>, Array<B, D>>(output) }
2838        } else {
2839            // A and B are not the same type.
2840            // Fallback to mapv().
2841            self.mapv(f)
2842        }
2843    }
2844
2845    /// Modify the array in place by calling `f` by mutable reference on each element.
2846    ///
2847    /// Elements are visited in arbitrary order.
2848    pub fn map_inplace<'a, F>(&'a mut self, f: F)
2849    where
2850        S: DataMut,
2851        A: 'a,
2852        F: FnMut(&'a mut A),
2853    {
2854        match self.try_as_slice_memory_order_mut() {
2855            Ok(slc) => slc.iter_mut().for_each(f),
2856            Err(arr) => {
2857                let mut v = arr.view_mut();
2858                move_min_stride_axis_to_last(&mut v.dim, &mut v.strides);
2859                v.into_elements_base().for_each(f);
2860            }
2861        }
2862    }
2863
2864    /// Modify the array in place by calling `f` by **v**alue on each element.
2865    /// The array is updated with the new values.
2866    ///
2867    /// Elements are visited in arbitrary order.
2868    ///
2869    /// ```
2870    /// # #[cfg(feature = "approx")] {
2871    /// use approx::assert_abs_diff_eq;
2872    /// use kn0sys_ndarray::arr2;
2873    ///
2874    /// let mut a = arr2(&[[ 0., 1.],
2875    ///                    [-1., 2.]]);
2876    /// a.mapv_inplace(f32::exp);
2877    /// assert_abs_diff_eq!(
2878    ///     a,
2879    ///     arr2(&[[1.00000, 2.71828],
2880    ///            [0.36788, 7.38906]]),
2881    ///     epsilon = 1e-5,
2882    /// );
2883    /// # }
2884    /// ```
2885    pub fn mapv_inplace<F>(&mut self, mut f: F)
2886    where
2887        S: DataMut,
2888        F: FnMut(A) -> A,
2889        A: Clone,
2890    {
2891        self.map_inplace(move |x| *x = f(x.clone()));
2892    }
2893
2894    /// Call `f` for each element in the array.
2895    ///
2896    /// Elements are visited in arbitrary order.
2897    pub fn for_each<'a, F>(&'a self, mut f: F)
2898    where
2899        F: FnMut(&'a A),
2900        A: 'a,
2901        S: Data,
2902    {
2903        self.fold((), move |(), elt| f(elt))
2904    }
2905
2906    /// Fold along an axis.
2907    ///
2908    /// Combine the elements of each subview with the previous using the `fold`
2909    /// function and initial value `init`.
2910    ///
2911    /// Return the result as an `Array`.
2912    ///
2913    /// **Panics** if `axis` is out of bounds.
2914    #[track_caller]
2915    pub fn fold_axis<B, F>(&self, axis: Axis, init: B, mut fold: F) -> Array<B, D::Smaller>
2916    where
2917        D: RemoveAxis,
2918        F: FnMut(&B, &A) -> B,
2919        B: Clone,
2920        S: Data,
2921    {
2922        let mut res = Array::from_elem(self.raw_dim().remove_axis(axis), init);
2923        for subview in self.axis_iter(axis) {
2924            res.zip_mut_with(&subview, |x, y| *x = fold(x, y));
2925        }
2926        res
2927    }
2928
2929    /// Reduce the values along an axis into just one value, producing a new
2930    /// array with one less dimension.
2931    ///
2932    /// Elements are visited in arbitrary order.
2933    ///
2934    /// Return the result as an `Array`.
2935    ///
2936    /// **Panics** if `axis` is out of bounds.
2937    #[track_caller]
2938    pub fn map_axis<'a, B, F>(&'a self, axis: Axis, mut mapping: F) -> Array<B, D::Smaller>
2939    where
2940        D: RemoveAxis,
2941        F: FnMut(ArrayView1<'a, A>) -> B,
2942        A: 'a,
2943        S: Data,
2944    {
2945        if self.len_of(axis) == 0 {
2946            let new_dim = self.dim.remove_axis(axis);
2947            Array::from_shape_simple_fn(new_dim, move || mapping(ArrayView::from(&[])))
2948        } else {
2949            Zip::from(self.lanes(axis)).map_collect(mapping)
2950        }
2951    }
2952
2953    /// Reduce the values along an axis into just one value, producing a new
2954    /// array with one less dimension.
2955    /// 1-dimensional lanes are passed as mutable references to the reducer,
2956    /// allowing for side-effects.
2957    ///
2958    /// Elements are visited in arbitrary order.
2959    ///
2960    /// Return the result as an `Array`.
2961    ///
2962    /// **Panics** if `axis` is out of bounds.
2963    #[track_caller]
2964    pub fn map_axis_mut<'a, B, F>(&'a mut self, axis: Axis, mut mapping: F) -> Array<B, D::Smaller>
2965    where
2966        D: RemoveAxis,
2967        F: FnMut(ArrayViewMut1<'a, A>) -> B,
2968        A: 'a,
2969        S: DataMut,
2970    {
2971        if self.len_of(axis) == 0 {
2972            let new_dim = self.dim.remove_axis(axis);
2973            Array::from_shape_simple_fn(new_dim, move || mapping(ArrayViewMut::from(&mut [])))
2974        } else {
2975            Zip::from(self.lanes_mut(axis)).map_collect(mapping)
2976        }
2977    }
2978
2979    /// Remove the `index`th elements along `axis` and shift down elements from higher indexes.
2980    ///
2981    /// Note that this "removes" the elements by swapping them around to the end of the axis and
2982    /// shortening the length of the axis; the elements are not deinitialized or dropped by this,
2983    /// just moved out of view (this only matters for elements with ownership semantics). It's
2984    /// similar to slicing an owned array in place.
2985    ///
2986    /// Decreases the length of `axis` by one.
2987    ///
2988    /// ***Panics*** if `axis` is out of bounds<br>
2989    /// ***Panics*** if not `index < self.len_of(axis)`.
2990    pub fn remove_index(&mut self, axis: Axis, index: usize)
2991    where S: DataOwned + DataMut
2992    {
2993        assert!(index < self.len_of(axis), "index {} must be less than length of Axis({})",
2994                index, axis.index());
2995        let (_, mut tail) = self.view_mut().split_at(axis, index);
2996        // shift elements to the front
2997        Zip::from(tail.lanes_mut(axis)).for_each(|mut lane| lane.rotate1_front());
2998        // then slice the axis in place to cut out the removed final element
2999        self.slice_axis_inplace(axis, Slice::new(0, Some(-1), 1));
3000    }
3001
3002    /// Iterates over pairs of consecutive elements along the axis.
3003    ///
3004    /// The first argument to the closure is an element, and the second
3005    /// argument is the next element along the axis. Iteration is guaranteed to
3006    /// proceed in order along the specified axis, but in all other respects
3007    /// the iteration order is unspecified.
3008    ///
3009    /// # Example
3010    ///
3011    /// For example, this can be used to compute the cumulative sum along an
3012    /// axis:
3013    ///
3014    /// ```
3015    /// use kn0sys_ndarray::{array, Axis};
3016    ///
3017    /// let mut arr = array![
3018    ///     [[1, 2], [3, 4], [5, 6]],
3019    ///     [[7, 8], [9, 10], [11, 12]],
3020    /// ];
3021    /// arr.accumulate_axis_inplace(Axis(1), |&prev, curr| *curr += prev);
3022    /// assert_eq!(
3023    ///     arr,
3024    ///     array![
3025    ///         [[1, 2], [4, 6], [9, 12]],
3026    ///         [[7, 8], [16, 18], [27, 30]],
3027    ///     ],
3028    /// );
3029    /// ```
3030    pub fn accumulate_axis_inplace<F>(&mut self, axis: Axis, mut f: F)
3031    where
3032        F: FnMut(&A, &mut A),
3033        S: DataMut,
3034    {
3035        if self.len_of(axis) <= 1 {
3036            return;
3037        }
3038        let mut curr = self.raw_view_mut(); // mut borrow of the array here
3039        let mut prev = curr.raw_view(); // derive further raw views from the same borrow
3040        prev.slice_axis_inplace(axis, Slice::from(..-1));
3041        curr.slice_axis_inplace(axis, Slice::from(1..));
3042        // This implementation relies on `Zip` iterating along `axis` in order.
3043        Zip::from(prev).and(curr).for_each(|prev, curr| unsafe {
3044            // These pointer dereferences and borrows are safe because:
3045            //
3046            // 1. They're pointers to elements in the array.
3047            //
3048            // 2. `S: DataMut` guarantees that elements are safe to borrow
3049            //    mutably and that they don't alias.
3050            //
3051            // 3. The lifetimes of the borrows last only for the duration
3052            //    of the call to `f`, so aliasing across calls to `f`
3053            //    cannot occur.
3054            f(&*prev, &mut *curr)
3055        });
3056    }
3057}
3058
3059/// Transmute from A to B.
3060///
3061/// Like transmute, but does not have the compile-time size check which blocks
3062/// using regular transmute in some cases.
3063///
3064/// **Panics** if the size of A and B are different.
3065#[track_caller]
3066#[inline]
3067unsafe fn unlimited_transmute<A, B>(data: A) -> B
3068{
3069    // safe when sizes are equal and caller guarantees that representations are equal
3070    assert_eq!(size_of::<A>(), size_of::<B>());
3071    let old_data = ManuallyDrop::new(data);
3072    (&*old_data as *const A as *const B).read()
3073}
3074
3075type DimMaxOf<A, B> = <A as DimMax<B>>::Output;
3076
3077#[cfg(test)]
3078mod tests
3079{
3080    use super::*;
3081    use crate::arr3;
3082    use defmac::defmac;
3083
3084    #[test]
3085    fn test_flatten()
3086    {
3087        let array = arr3(&[[[1, 2], [3, 4]], [[5, 6], [7, 8]]]);
3088        let flattened = array.flatten();
3089        assert_eq!(flattened, arr1(&[1, 2, 3, 4, 5, 6, 7, 8]));
3090    }
3091
3092    #[test]
3093    fn test_flatten_with_order()
3094    {
3095        let array = arr2(&[[1, 2], [3, 4], [5, 6], [7, 8]]);
3096        let flattened = array.flatten_with_order(Order::RowMajor);
3097        assert_eq!(flattened, arr1(&[1, 2, 3, 4, 5, 6, 7, 8]));
3098        let flattened = array.flatten_with_order(Order::ColumnMajor);
3099        assert_eq!(flattened, arr1(&[1, 3, 5, 7, 2, 4, 6, 8]));
3100    }
3101
3102    #[test]
3103    fn test_into_flat()
3104    {
3105        let array = arr3(&[[[1, 2], [3, 4]], [[5, 6], [7, 8]]]);
3106        let flattened = array.into_flat();
3107        assert_eq!(flattened, arr1(&[1, 2, 3, 4, 5, 6, 7, 8]));
3108    }
3109
3110    #[test]
3111    fn test_first_last()
3112    {
3113        let first = 2;
3114        let last = 3;
3115
3116        defmac!(assert_first mut array => {
3117            assert_eq!(array.first().copied(), Some(first));
3118            assert_eq!(array.first_mut().copied(), Some(first));
3119        });
3120        defmac!(assert_last mut array => {
3121            assert_eq!(array.last().copied(), Some(last));
3122            assert_eq!(array.last_mut().copied(), Some(last));
3123        });
3124
3125        let base = Array::from_vec(vec![first, last]);
3126        let a = base.clone();
3127        assert_first!(a);
3128
3129        let a = base.clone();
3130        assert_last!(a);
3131
3132        let a = CowArray::from(base.view());
3133        assert_first!(a);
3134        let a = CowArray::from(base.view());
3135        assert_last!(a);
3136
3137        let a = CowArray::from(base.clone());
3138        assert_first!(a);
3139        let a = CowArray::from(base.clone());
3140        assert_last!(a);
3141
3142        let a = ArcArray::from(base.clone());
3143        let _a2 = a.clone();
3144        assert_last!(a);
3145
3146        let a = ArcArray::from(base.clone());
3147        let _a2 = a.clone();
3148        assert_first!(a);
3149    }
3150}