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