ndarray/impl_views/
splitting.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 crate::imp_prelude::*;
10use crate::slice::MultiSliceArg;
11use num_complex::Complex;
12
13/// Methods for read-only array views.
14impl<'a, A, D> ArrayView<'a, A, D>
15where
16    D: Dimension,
17{
18    /// Split the array view along `axis` and return one view strictly before the
19    /// split and one view after the split.
20    ///
21    /// **Panics** if `axis` or `index` is out of bounds.
22    ///
23    /// **Examples:**
24    /// ```rust
25    /// # use ndarray::prelude::*;
26    /// let a = aview2(&[[0, 1, 2, 3],
27    ///                  [4, 5, 6, 7],
28    ///                  [8, 9, 0, 1]]);
29    ///
30    /// ```
31    /// The array view `a` has two axes and shape 3 × 4:
32    /// ```text
33    ///          ──▶ Axis(1)
34    ///         ┌─────┬─────┬─────┬─────┐ 0
35    ///       │ │ a₀₀ │ a₀₁ │ a₀₂ │ a₀₃ │
36    ///       ▼ ├─────┼─────┼─────┼─────┤ 1
37    ///  Axis(0)│ a₁₀ │ a₁₁ │ a₁₂ │ a₁₃ │
38    ///         ├─────┼─────┼─────┼─────┤ 2
39    ///         │ a₂₀ │ a₂₁ │ a₂₂ │ a₂₃ │
40    ///         └─────┴─────┴─────┴─────┘ 3 ↑
41    ///         0     1     2     3     4 ← possible split_at indices.
42    /// ```
43    ///
44    /// Row indices increase along `Axis(0)`, and column indices increase along
45    /// `Axis(1)`. Note that we split “before” an element index, and that
46    /// both 0 and the endpoint are valid split indices.
47    ///
48    /// **Example 1**: Split `a` along the first axis, in this case the rows, at
49    /// index 2.<br>
50    /// This produces views v1 and v2 of shapes 2 × 4 and 1 × 4:
51    ///
52    /// ```rust
53    /// # use ndarray::prelude::*;
54    /// # let a = aview2(&[[0; 4]; 3]);
55    /// let (v1, v2) = a.split_at(Axis(0), 2);
56    /// ```
57    /// ```text
58    ///         ┌─────┬─────┬─────┬─────┐       0  ↓ indices
59    ///         │ a₀₀ │ a₀₁ │ a₀₂ │ a₀₃ │            along Axis(0)
60    ///         ├─────┼─────┼─────┼─────┤ v1    1
61    ///         │ a₁₀ │ a₁₁ │ a₁₂ │ a₁₃ │
62    ///         └─────┴─────┴─────┴─────┘
63    ///         ┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄       2
64    ///         ┌─────┬─────┬─────┬─────┐
65    ///         │ a₂₀ │ a₂₁ │ a₂₂ │ a₂₃ │ v2
66    ///         └─────┴─────┴─────┴─────┘       3
67    /// ```
68    ///
69    /// **Example 2**: Split `a` along the second axis, in this case the
70    /// columns, at index 2.<br>
71    /// This produces views u1 and u2 of shapes 3 × 2 and 3 × 2:
72    ///
73    /// ```rust
74    /// # use ndarray::prelude::*;
75    /// # let a = aview2(&[[0; 4]; 3]);
76    /// let (u1, u2) = a.split_at(Axis(1), 2);
77    ///
78    /// ```
79    /// ```text
80    ///              u1             u2
81    ///         ┌─────┬─────┐┊┌─────┬─────┐
82    ///         │ a₀₀ │ a₀₁ │┊│ a₀₂ │ a₀₃ │
83    ///         ├─────┼─────┤┊├─────┼─────┤
84    ///         │ a₁₀ │ a₁₁ │┊│ a₁₂ │ a₁₃ │
85    ///         ├─────┼─────┤┊├─────┼─────┤
86    ///         │ a₂₀ │ a₂₁ │┊│ a₂₂ │ a₂₃ │
87    ///         └─────┴─────┘┊└─────┴─────┘
88    ///         0     1      2      3     4  indices →
89    ///                                      along Axis(1)
90    /// ```
91    pub fn split_at(self, axis: Axis, index: Ix) -> (Self, Self) {
92        unsafe {
93            let (left, right) = self.into_raw_view().split_at(axis, index);
94            (left.deref_into_view(), right.deref_into_view())
95        }
96    }
97}
98
99impl<'a, T, D> ArrayView<'a, Complex<T>, D>
100where
101    D: Dimension,
102{
103    /// Splits the view into views of the real and imaginary components of the
104    /// elements.
105    ///
106    /// ```
107    /// use ndarray::prelude::*;
108    /// use num_complex::{Complex, Complex64};
109    ///
110    /// let arr = array![
111    ///     [Complex64::new(1., 2.), Complex64::new(3., 4.)],
112    ///     [Complex64::new(5., 6.), Complex64::new(7., 8.)],
113    ///     [Complex64::new(9., 10.), Complex64::new(11., 12.)],
114    /// ];
115    /// let Complex { re, im } = arr.view().split_complex();
116    /// assert_eq!(re, array![[1., 3.], [5., 7.], [9., 11.]]);
117    /// assert_eq!(im, array![[2., 4.], [6., 8.], [10., 12.]]);
118    /// ```
119    pub fn split_complex(self) -> Complex<ArrayView<'a, T, D>> {
120        unsafe {
121            let Complex { re, im } = self.into_raw_view().split_complex();
122            Complex {
123                re: re.deref_into_view(),
124                im: im.deref_into_view(),
125            }
126        }
127    }
128}
129
130/// Methods for read-write array views.
131impl<'a, A, D> ArrayViewMut<'a, A, D>
132where
133    D: Dimension,
134{
135    /// Split the array view along `axis` and return one mutable view strictly
136    /// before the split and one mutable view after the split.
137    ///
138    /// **Panics** if `axis` or `index` is out of bounds.
139    pub fn split_at(self, axis: Axis, index: Ix) -> (Self, Self) {
140        unsafe {
141            let (left, right) = self.into_raw_view_mut().split_at(axis, index);
142            (left.deref_into_view_mut(), right.deref_into_view_mut())
143        }
144    }
145
146    /// Split the view into multiple disjoint slices.
147    ///
148    /// This is similar to [`.multi_slice_mut()`], but `.multi_slice_move()`
149    /// consumes `self` and produces views with lifetimes matching that of
150    /// `self`.
151    ///
152    /// See [*Slicing*](#slicing) for full documentation. See also
153    /// [`MultiSliceArg`], [`s!`], [`SliceArg`](crate::SliceArg), and
154    /// [`SliceInfo`](crate::SliceInfo).
155    ///
156    /// [`.multi_slice_mut()`]: ArrayBase::multi_slice_mut
157    ///
158    /// **Panics** if any of the following occur:
159    ///
160    /// * if any of the views would intersect (i.e. if any element would appear in multiple slices)
161    /// * if an index is out of bounds or step size is zero
162    /// * if `D` is `IxDyn` and `info` does not match the number of array axes
163    pub fn multi_slice_move<M>(self, info: M) -> M::Output
164    where
165        M: MultiSliceArg<'a, A, D>,
166    {
167        info.multi_slice_move(self)
168    }
169}
170
171impl<'a, T, D> ArrayViewMut<'a, Complex<T>, D>
172where
173    D: Dimension,
174{
175    /// Splits the view into views of the real and imaginary components of the
176    /// elements.
177    ///
178    /// ```
179    /// use ndarray::prelude::*;
180    /// use num_complex::{Complex, Complex64};
181    ///
182    /// let mut arr = array![
183    ///     [Complex64::new(1., 2.), Complex64::new(3., 4.)],
184    ///     [Complex64::new(5., 6.), Complex64::new(7., 8.)],
185    ///     [Complex64::new(9., 10.), Complex64::new(11., 12.)],
186    /// ];
187    ///
188    /// let Complex { mut re, mut im } = arr.view_mut().split_complex();
189    /// assert_eq!(re, array![[1., 3.], [5., 7.], [9., 11.]]);
190    /// assert_eq!(im, array![[2., 4.], [6., 8.], [10., 12.]]);
191    ///
192    /// re[[0, 1]] = 13.;
193    /// im[[2, 0]] = 14.;
194    ///
195    /// assert_eq!(arr[[0, 1]], Complex64::new(13., 4.));
196    /// assert_eq!(arr[[2, 0]], Complex64::new(9., 14.));
197    /// ```
198    pub fn split_complex(self) -> Complex<ArrayViewMut<'a, T, D>> {
199        unsafe {
200            let Complex { re, im } = self.into_raw_view_mut().split_complex();
201            Complex {
202                re: re.deref_into_view_mut(),
203                im: im.deref_into_view_mut(),
204            }
205        }
206    }
207}