arr_rs/core/operations/
joining.rs

1use crate::{
2    core::prelude::*,
3    errors::prelude::*,
4    extensions::prelude::*,
5    validators::prelude::*,
6};
7
8/// `ArrayTrait` - Array Joining functions
9pub trait ArrayJoining<T: ArrayElement> where Self: Sized + Clone {
10
11    /// Join a sequence of arrays along an existing axis
12    ///
13    /// # Arguments
14    ///
15    /// * `arrs` - arrays to concatenate
16    /// * `axis` - the axis along which to concat. optional, if None - arrays are flattened
17    ///
18    /// # Examples
19    /// ```
20    /// use arr_rs::prelude::*;
21    ///
22    /// let arr = array!(i32, [1, 2, 3]).unwrap();
23    /// let other = array!(i32, [4, 5, 6]).unwrap();
24    /// let expected = array!(i32, [1, 2, 3, 4, 5, 6]).unwrap();
25    /// assert_eq!(expected, Array::<i32>::concatenate(vec![arr, other], None).unwrap());
26    ///
27    /// let arr = array!(i32, [[1, 2], [3, 4]]).unwrap();
28    /// let other = array!(i32, [[5, 6]]).unwrap();
29    /// let expected = array!(i32, [[1, 2], [3, 4], [5, 6]]).unwrap();
30    /// assert_eq!(expected, Array::<i32>::concatenate(vec![arr, other], Some(0)).unwrap());
31    /// ```
32    ///
33    /// # Errors
34    ///
35    /// may returns `ArrayError`
36    fn concatenate(arrs: Vec<Array<T>>, axis: Option<usize>) -> Result<Array<T>, ArrayError>;
37
38    /// Join a sequence of arrays along a new axis
39    ///
40    /// # Arguments
41    ///
42    /// * `arrs` - arrays to stack
43    /// * `axis` - the axis along which to concat. optional, defaults to 0
44    ///
45    /// # Examples
46    /// ```
47    /// use arr_rs::prelude::*;
48    ///
49    /// let arr = array!(i32, [1, 2, 3]).unwrap();
50    /// let other = array!(i32, [4, 5, 6]).unwrap();
51    /// let expected = array!(i32, [[1, 2, 3], [4, 5, 6]]).unwrap();
52    /// assert_eq!(expected, Array::<i32>::stack(vec![arr, other], None).unwrap());
53    ///
54    /// let arr = array!(i32, [[1, 2], [3, 4]]).unwrap();
55    /// let other = array!(i32, [[5, 6], [7, 8]]).unwrap();
56    /// let expected = array!(i32, [[[1, 2], [3, 4]], [[5, 6], [7, 8]]]).unwrap();
57    /// assert_eq!(expected, Array::<i32>::stack(vec![arr, other], Some(0)).unwrap());
58    /// ```
59    ///
60    /// # Errors
61    ///
62    /// may returns `ArrayError`
63    fn stack(arrs: Vec<Array<T>>, axis: Option<usize>) -> Result<Array<T>, ArrayError>;
64
65    /// Stack arrays in sequence vertically (row wise)
66    ///
67    /// # Arguments
68    ///
69    /// * `arrs` - arrays to stack
70    ///
71    /// # Examples
72    /// ```
73    /// use arr_rs::prelude::*;
74    ///
75    /// let arr = array!(i32, [1, 2, 3]).unwrap();
76    /// let other = array!(i32, [4, 5, 6]).unwrap();
77    /// let expected = array!(i32, [[1, 2, 3], [4, 5, 6]]).unwrap();
78    /// assert_eq!(expected, Array::<i32>::vstack(vec![arr, other]).unwrap());
79    ///
80    /// let arr = array!(i32, [[1], [2], [3]]).unwrap();
81    /// let other = array!(i32, [[4], [5], [6]]).unwrap();
82    /// let expected = array!(i32, [[1], [2], [3], [4], [5], [6]]).unwrap();
83    /// assert_eq!(expected, Array::<i32>::vstack(vec![arr, other]).unwrap());
84    /// ```
85    ///
86    /// # Errors
87    ///
88    /// may returns `ArrayError`
89    fn vstack(arrs: Vec<Array<T>>) -> Result<Array<T>, ArrayError>;
90
91    /// Stack arrays in sequence horizontally (column wise)
92    ///
93    /// # Arguments
94    ///
95    /// * `arrs` - arrays to stack
96    ///
97    /// # Examples
98    /// ```
99    /// use arr_rs::prelude::*;
100    ///
101    /// let arr = array!(i32, [1, 2, 3]).unwrap();
102    /// let other = array!(i32, [4, 5, 6]).unwrap();
103    /// let expected = array!(i32, [1, 2, 3, 4, 5, 6]).unwrap();
104    /// assert_eq!(expected, Array::<i32>::hstack(vec![arr, other]).unwrap());
105    ///
106    /// let arr = array!(i32, [[1], [2], [3]]).unwrap();
107    /// let other = array!(i32, [[4], [5], [6]]).unwrap();
108    /// let expected = array!(i32, [[1, 4], [2, 5], [3, 6]]).unwrap();
109    /// assert_eq!(expected, Array::<i32>::hstack(vec![arr, other]).unwrap());
110    /// ```
111    ///
112    /// # Errors
113    ///
114    /// may returns `ArrayError`
115    fn hstack(arrs: Vec<Array<T>>) -> Result<Array<T>, ArrayError>;
116
117    /// Stack arrays in sequence depth wise (along third axis)
118    ///
119    /// # Arguments
120    ///
121    /// * `arrs` - arrays to stack
122    ///
123    /// # Examples
124    /// ```
125    /// use arr_rs::prelude::*;
126    ///
127    /// let arr = array!(i32, [1, 2, 3]).unwrap();
128    /// let other = array!(i32, [4, 5, 6]).unwrap();
129    /// let expected = array!(i32, [[[1, 4], [2, 5], [3, 6]]]).unwrap();
130    /// assert_eq!(expected, Array::<i32>::dstack(vec![arr, other]).unwrap());
131    ///
132    /// let arr = array!(i32, [[1], [2], [3]]).unwrap();
133    /// let other = array!(i32, [[4], [5], [6]]).unwrap();
134    /// let expected = array!(i32, [[[1, 4]], [[2, 5]], [[3, 6]]]).unwrap();
135    /// assert_eq!(expected, Array::<i32>::dstack(vec![arr, other]).unwrap());
136    /// ```
137    ///
138    /// # Errors
139    ///
140    /// may returns `ArrayError`
141    fn dstack(arrs: Vec<Array<T>>) -> Result<Array<T>, ArrayError>;
142
143    /// Stack 1d or 2d arrays as columns into a 2d array
144    /// `row_stack` is an alias for vstack
145    ///
146    /// # Arguments
147    ///
148    /// * `arrs` - arrays to stack
149    ///
150    /// # Examples
151    /// ```
152    /// use arr_rs::prelude::*;
153    ///
154    /// let arr = array!(i32, [1, 2, 3]).unwrap();
155    /// let other = array!(i32, [4, 5, 6]).unwrap();
156    /// let expected = array!(i32, [[1, 4], [2, 5], [3, 6]]).unwrap();
157    /// assert_eq!(expected, Array::<i32>::column_stack(vec![arr, other]).unwrap());
158    /// ```
159    ///
160    /// # Errors
161    ///
162    /// may returns `ArrayError`
163    fn column_stack(arrs: Vec<Array<T>>) -> Result<Array<T>, ArrayError>;
164
165    /// Stack arrays in sequence vertically (row wise)
166    ///
167    /// # Arguments
168    ///
169    /// * `arrs` - arrays to stack
170    ///
171    /// # Examples
172    /// ```
173    /// use arr_rs::prelude::*;
174    ///
175    /// let arr = array!(i32, [1, 2, 3]).unwrap();
176    /// let other = array!(i32, [4, 5, 6]).unwrap();
177    /// let expected = array!(i32, [[1, 2, 3], [4, 5, 6]]).unwrap();
178    /// assert_eq!(expected, Array::<i32>::row_stack(vec![arr, other]).unwrap());
179    ///
180    /// let arr = array!(i32, [[1], [2], [3]]).unwrap();
181    /// let other = array!(i32, [[4], [5], [6]]).unwrap();
182    /// let expected = array!(i32, [[1], [2], [3], [4], [5], [6]]).unwrap();
183    /// assert_eq!(expected, Array::<i32>::row_stack(vec![arr, other]).unwrap());
184    /// ```
185    ///
186    /// # Errors
187    ///
188    /// may returns `ArrayError`
189    fn row_stack(arrs: Vec<Array<T>>) -> Result<Array<T>, ArrayError>;
190}
191
192impl <T: ArrayElement> ArrayJoining<T> for Array<T> {
193
194    fn concatenate(arrs: Vec<Self>, axis: Option<usize>) -> Result<Self, ArrayError> {
195        if arrs.is_empty() { Self::empty() }
196        else {
197            if let Some(axis) = axis { arrs.validate_stack_shapes(axis, axis)?; }
198
199            let (mut arrs, initial) = (arrs.clone(), arrs[0].clone());
200            let result = arrs.remove_at(0).into_iter()
201                .fold(initial, |a, b| a.append(&b, axis).unwrap());
202            Ok(result)
203        }
204    }
205
206    fn stack(arrs: Vec<Self>, axis: Option<usize>) -> Result<Self, ArrayError> {
207        arrs.axis_opt_in_bounds(axis)?;
208        if arrs.is_empty() { Self::empty() }
209        else if (0..arrs.len() - 1).any(|i| arrs[i].get_shape() != arrs[i + 1].get_shape()) {
210            Err(ArrayError::ParameterError { param: "arrs", message: "all input arrays must have the same shape", })
211        } else {
212            let axis = axis.unwrap_or(0);
213            let new_shape = arrs[0].get_shape()?.insert_at(axis, arrs.len());
214
215            let (mut arrs, initial) = (arrs.clone(), arrs[0].clone());
216            arrs.remove_at(0).into_iter()
217                .fold(initial, |a, b| a.append(&b, Some(axis)).unwrap())
218                .reshape(&new_shape)
219        }
220    }
221
222    fn vstack(arrs: Vec<Self>) -> Result<Self, ArrayError> {
223        if arrs.is_empty() { Self::empty() }
224        else {
225            arrs.validate_stack_shapes(0, 0)?;
226
227            let mut new_shape = arrs[0].get_shape()?;
228            if new_shape.len() == 1 { new_shape.insert_at(0, arrs.len()); }
229            else { new_shape[0] = arrs.iter().fold(0, |a, b| a + b.shape[0]); }
230
231            match Self::concatenate(arrs, Some(0)) {
232                Ok(c) => c.reshape(&new_shape),
233                Err(e) => Err(e),
234            }
235        }
236    }
237
238    fn hstack(arrs: Vec<Self>) -> Result<Self, ArrayError> {
239        if arrs.is_empty() { return Self::empty() }
240        arrs.iter()
241            .map(Self::ndim)
242            .collect::<Vec<Result<usize, ArrayError>>>()
243            .has_error()?;
244        if arrs.iter().all(|arr| arr.ndim().unwrap() == 1) {
245            Self::concatenate(arrs, Some(0))
246        } else {
247            let arrs = arrs.iter()
248                .map(|arr| arr.atleast(2)).collect::<Vec<Result<Self, _>>>()
249                .has_error()?.into_iter()
250                .map(Result::unwrap)
251                .collect::<Vec<Self<>>>();
252            arrs.validate_stack_shapes(1, 0)?;
253
254            let mut new_shape = arrs[0].get_shape()?;
255            new_shape[1] = arrs.iter().fold(0, |a, b| a + b.shape[1]);
256
257            match Self::concatenate(arrs, Some(1)) {
258                Ok(c) => c.reshape(&new_shape),
259                Err(e) => Err(e),
260            }
261        }
262    }
263
264    fn dstack(arrs: Vec<Self>) -> Result<Self, ArrayError> {
265        if arrs.is_empty() { Self::empty() }
266        else {
267            let arrs = arrs.iter()
268                .map(|arr| arr.atleast(3))
269                .collect::<Vec<Result<Self, _>>>()
270                .has_error()?.into_iter()
271                .map(Result::unwrap)
272                .collect::<Vec<Self<>>>();
273            arrs.validate_stack_shapes(2, 0)?;
274
275            let mut new_shape = arrs[0].get_shape()?;
276            new_shape[2] = arrs.iter().fold(0, |a, b| a + b.shape[2]);
277
278            match Self::concatenate(arrs, Some(2)) {
279                Ok(c) => c.reshape(&new_shape),
280                Err(e) => Err(e),
281            }
282        }
283    }
284
285    fn column_stack(arrs: Vec<Self>) -> Result<Self, ArrayError> {
286        if arrs.is_empty() { Self::empty() }
287        else {
288            let (num_rows, mut total_cols) = (arrs[0].shape[0], 0);
289            arrs.is_dim_supported(&[1, 2])?;
290            if arrs.iter().any(|array| array.shape[0] != num_rows) {
291                return Err(ArrayError::ParameterError { param: "arrs", message: "all input arrays must have the same first dimension", });
292            }
293
294            arrs.iter()
295                .map(Self::ndim)
296                .collect::<Vec<Result<usize, ArrayError>>>()
297                .has_error()?;
298            for array in &arrs {
299                if array.ndim().unwrap() == 1 { total_cols += 1; }
300                else { total_cols += array.shape[1]; }
301            }
302
303            let (mut new_elements, mut new_col_idx) = (vec![T::zero(); num_rows * total_cols], 0);
304            for array in &arrs {
305                let array_cols = if array.ndim().unwrap() == 1 { 1 } else { array.shape[1] };
306                (0..num_rows).for_each(|row| {
307                    (0..array_cols).for_each(|col| {
308                        let src_idx = row * array_cols + col;
309                        let dst_idx = row * total_cols + new_col_idx + col;
310                        new_elements[dst_idx] = array.elements[src_idx].clone();
311                    });
312                });
313                new_col_idx += array_cols;
314            }
315
316            Self::new(new_elements, vec![num_rows, total_cols])
317        }
318    }
319
320    fn row_stack(arrs: Vec<Self>) -> Result<Self, ArrayError> {
321        Self::vstack(arrs)
322    }
323}