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}