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