1use std::cmp::Ordering;
2
3use crate::{
4 core::prelude::*,
5 errors::prelude::*,
6 extensions::prelude::*,
7 validators::prelude::*,
8};
9use crate::prelude::Numeric;
10
11pub trait ArrayManipulate<T: ArrayElement> where Array<T>: Sized + Clone {
13
14 fn insert(&self, indices: &[usize], values: &Array<T>, axis: Option<usize>) -> Result<Array<T>, ArrayError>;
37
38 fn delete(&self, indices: &[usize], axis: Option<usize>) -> Result<Array<T>, ArrayError>;
60
61 fn append(&self, values: &Array<T>, axis: Option<usize>) -> Result<Array<T>, ArrayError>;
83
84 fn reshape(&self, shape: &[usize]) -> Result<Array<T>, ArrayError>;
105
106 fn resize(&self, shape: &[usize]) -> Result<Array<T>, ArrayError>;
131
132 fn unique(&self, axis: Option<isize>) -> Result<Array<T>, ArrayError>;
153
154 fn ravel(&self) -> Result<Array<T>, ArrayError>;
177
178 fn atleast(&self, n: usize) -> Result<Array<T>, ArrayError>;
198
199 fn trim_zeros(&self) -> Result<Array<T>, ArrayError>;
214
215 fn cycle_take(&self, n: usize) -> Result<Array<T>, ArrayError>;
234}
235
236impl <T: ArrayElement> ArrayManipulate<T> for Array<T> {
237
238 fn insert(&self, indices: &[usize], values: &Self, axis: Option<usize>) -> Result<Self, ArrayError> {
239 if indices.iter().any(|&i| i > self.shape[axis.unwrap_or(0)]) { return Err(ArrayError::OutOfBounds { value: "index" }) }
240 values.ndim()?.is_dim_supported(&(1 ..= self.ndim()?).collect::<Vec<usize>>())?;
241
242 if let Some(axis) = axis {
243 vec![indices.len()].is_broadcastable(&self.get_shape()?)?;
244 let mut arrays = self.split_axis(axis)?;
245 let self_rem = self.get_shape()?.remove_at(axis);
246 let self_rem_len = self_rem.into_iter().product::<usize>();
247 let mut values = values.to_array_ndim(self.ndim()?)?;
248 let values_shape_tmp = values.get_shape()?.swap_ext(0, axis);
249
250 for i in (0..self.ndim()?).collect::<Vec<usize>>().remove_at(axis).reverse_ext() {
251 let self_shape_at_i = self.get_shape()?[i];
252 if values_shape_tmp[i] > self_shape_at_i || self_shape_at_i % values_shape_tmp[i] != 0 {
253 return Err(ArrayError::BroadcastShapeMismatch)
254 } else if values_shape_tmp[i] < self_shape_at_i {
255 values = values
256 .repeat(&[self_shape_at_i / values_shape_tmp[i]], Some(0))?
257 .to_array_ndim(self.ndim()?)?;
258 }
259 };
260
261 let mut values =
262 if indices.len() > 1 {
263 let values =
264 if values.len()? == self_rem_len { values.repeat(&[indices.len()], Some(0))? }
265 else { values };
266 values.moveaxis(vec![axis.to_isize()], vec![0])
267 .ravel()
268 .split(indices.len(), None)?
269 } else { vec![values] };
270
271 for (i, v) in indices.to_vec().reverse_ext().into_iter().zip(values.reverse_ext()) {
272 arrays.insert(i, v.clone());
273 }
274
275 let partial = arrays.into_iter()
276 .map(|arr| arr.get_elements())
277 .collect::<Vec<Result<Vec<T>, _>>>()
278 .has_error()?.into_iter()
279 .flat_map(Result::unwrap)
280 .collect::<Self>();
281 let new_shape = self.get_shape()?
282 .update_at(axis, partial.len()? / self_rem_len)
283 .swap_ext(0, axis);
284 let partial = partial.reshape(&new_shape)?;
285 let transpose_shape = (1..self.ndim()?.to_isize()).collect::<Vec<isize>>().insert_at(axis, 0);
286 partial.transpose(Some(transpose_shape))
287 } else {
288 values.ndim()?.is_dim_supported(&[1])?;
289 let (indices, values) = Array::broadcast_h2(&Array::flat(indices.to_vec())?, &values.ravel()?)?;
290 let values = values.get_elements()?;
291 let mut elements = self.get_elements()?;
292
293 indices.get_elements()?.into_iter()
294 .zip(&values)
295 .sorted_by(|(a, _), (b, _)| a.cmp(b)).rev()
296 .for_each(|(i, v)| elements.insert(i, v.clone()));
297 elements.to_array()
298 }
299 }
300
301 fn delete(&self, indices: &[usize], axis: Option<usize>) -> Result<Self, ArrayError> {
302 let mut indices = indices.to_vec();
303 indices.sort_unstable();
304 indices.dedup();
305 indices = indices.reverse_ext();
306
307 if let Some(axis) = axis {
308 self.apply_along_axis(axis, |arr| arr.delete(&indices, None))
309 } else {
310 let mut elements = self.get_elements()?;
311 if indices.iter().any(|&i| i >= elements.len()) { return Err(ArrayError::OutOfBounds { value: "index" }) }
312 for &i in &indices { elements.remove(i); }
313 elements.to_array()
314 }
315 }
316
317 fn append(&self, values: &Self, axis: Option<usize>) -> Result<Self, ArrayError> {
318 if let Some(axis) = axis {
319 self.axis_in_bounds(axis)?;
320 if self.ndim().is_equal(&values.ndim()).is_err() {
321 return Err(ArrayError::ParameterError { param: "values", message: "input array should have the same dimension as the original one", })
322 } else if self.get_shape()?.remove_at(axis).is_equal(&values.get_shape()?.remove_at(axis)).is_err() {
323 return Err(ArrayError::ParameterError { param: "axis", message: "input array dimensions for the concatenation axis must match exactly", })
324 }
325
326 let mut arrays = self.split_axis(axis)?;
327 let self_rem = self.get_shape()?.remove_at(axis);
328 let self_rem_len = self_rem.into_iter().product::<usize>();
329 let values = values.split_axis(axis)?;
330 arrays.extend_from_slice(&values);
331 let array = arrays.into_iter().flatten().collect::<Self>();
332 let new_shape = self.get_shape()?.update_at(axis, array.len()? / self_rem_len);
333 let tmp_shape = new_shape.clone().swap_ext(0, axis);
334 let transpose_shape = (1..self.ndim()?.to_isize()).collect::<Vec<isize>>().insert_at(axis, 0);
335 array.reshape(&tmp_shape).transpose(Some(transpose_shape)).reshape(&new_shape)
336 } else {
337 let mut elements = self.get_elements()?;
338 elements.extend_from_slice(&values.get_elements()?);
339 elements.to_array()
340 }
341 }
342
343 fn reshape(&self, shape: &[usize]) -> Result<Self, ArrayError> {
344 shape.to_vec().matches_values_len(&self.get_elements()?)?;
345 Self::new(self.elements.clone(), shape.to_vec())
346 }
347
348 fn resize(&self, shape: &[usize]) -> Result<Self, ArrayError> {
349 self.get_elements()?.into_iter().cycle()
350 .take(shape.iter().product::<usize>())
351 .collect::<Self>()
352 .reshape(shape)
353 }
354
355 fn unique(&self, axis: Option<isize>) -> Result<Self, ArrayError> {
356 if let Some(axis) = axis {
357 let axis = self.normalize_axis(axis);
358 self.apply_along_axis(axis, |arr| arr.unique(None))
359 } else {
360 let mut new_elements = self.get_elements()?.into_iter()
361 .sorted_by(|a, b| a.clone().partial_cmp(b).unwrap_or(Ordering::Equal))
362 .collect::<Vec<T>>();
363 new_elements.dedup();
364 new_elements.to_array()
365 }
366 }
367
368 fn ravel(&self) -> Result<Self, ArrayError> {
369 self.elements.to_array()
370 }
371
372 fn atleast(&self, n: usize) -> Result<Self, ArrayError> {
373 match n {
374 0 => Ok(self.clone()),
375 1 => Self::atleast_1d(self),
376 2 => Self::atleast_2d(self),
377 3 => Self::atleast_3d(self),
378 _ => Err(ArrayError::UnsupportedDimension { supported: vec![0, 1, 2, 3] }),
379 }
380 }
381
382 fn trim_zeros(&self) -> Result<Self, ArrayError> {
383 self.is_dim_supported(&[1])?;
384
385 self.get_elements()?
386 .into_iter().rev()
387 .skip_while(|e| e.clone() == T::zero())
388 .collect::<Vec<_>>()
389 .into_iter().rev()
390 .skip_while(|e| e.clone() == T::zero())
391 .collect::<Vec<_>>()
392 .to_array()
393 }
394
395 fn cycle_take(&self, n: usize) -> Result<Self, ArrayError> {
396 Ok(self.into_iter().cycle().take(n).cloned().collect())
397 }
398}
399
400impl <T: ArrayElement> ArrayManipulate<T> for Result<Array<T>, ArrayError> {
401
402 fn insert(&self, indices: &[usize], values: &Array<T>, axis: Option<usize>) -> Self {
403 self.clone()?.insert(indices, values, axis)
404 }
405
406 fn delete(&self, indices: &[usize], axis: Option<usize>) -> Self {
407 self.clone()?.delete(indices, axis)
408 }
409
410 fn append(&self, values: &Array<T>, axis: Option<usize>) -> Self {
411 self.clone()?.append(values, axis)
412 }
413
414 fn reshape(&self, shape: &[usize]) -> Self {
415 self.clone()?.reshape(shape)
416 }
417
418 fn resize(&self, shape: &[usize]) -> Self {
419 self.clone()?.resize(shape)
420 }
421
422 fn unique(&self, axis: Option<isize>) -> Self {
423 self.clone()?.unique(axis)
424 }
425
426 fn ravel(&self) -> Self {
427 self.clone()?.ravel()
428 }
429
430 fn atleast(&self, n: usize) -> Self {
431 self.clone()?.atleast(n)
432 }
433
434 fn trim_zeros(&self) -> Self {
435 self.clone()?.trim_zeros()
436 }
437
438 fn cycle_take(&self, n: usize) -> Self {
439 self.clone()?.cycle_take(n)
440 }
441}
442
443impl <T: ArrayElement> Array<T> {
444
445 fn atleast_1d(&self) -> Result<Self, ArrayError> {
446 if !self.ndim()? >= 1 { Ok(self.clone()) }
447 else { self.reshape(&[1]) }
448 }
449
450 fn atleast_2d(&self) -> Result<Self, ArrayError> {
451 if self.ndim()? >= 2 { Ok(self.clone()) }
452 else {
453 match self.ndim()? {
454 0 => self.reshape(&[1, 1]),
455 1 => self.reshape(&[1, self.get_shape()?[0]]),
456 _ => self.reshape(&[self.get_shape()?[0], 1]),
457 }
458 }
459 }
460
461 fn atleast_3d(&self) -> Result<Self, ArrayError> {
462 if self.ndim()? >= 3 { Ok(self.clone()) }
463 else {
464 match self.ndim()? {
465 0 => self.reshape(&[1, 1, 1]),
466 1 => self.reshape(&[1, self.get_shape()?[0], 1]),
467 2 => self.reshape(&[self.get_shape()?[0], self.get_shape()?[1], 1]),
468 _ => Ok(self.clone()),
469 }
470 }
471 }
472}
473
474impl <T: ArrayElement> Array<T> {
475
476 pub(crate) fn normalize_axis(&self, axis: isize) -> usize {
477 if axis < 0 { (axis + self.ndim().unwrap().to_isize()).to_usize() }
478 else { axis.to_usize() }
479 }
480
481 pub(crate) fn normalize_axis_dim(&self, axis: isize, ndim: usize) -> usize {
482 if axis < 0 { (self.ndim().unwrap().to_isize() + axis + ndim.to_isize()).to_usize() }
483 else { axis.to_usize() }
484 }
485}