arr_rs/math/operations/
misc.rs

1use crate::{
2    core::prelude::*,
3    errors::prelude::*,
4    extensions::prelude::*,
5    math::prelude::*,
6    numeric::prelude::*,
7};
8
9/// `ArrayTrait` - Array Math Misc functions
10pub trait ArrayMathMisc<N: Numeric> where Self: Sized + Clone {
11
12    /// Returns the discrete, linear convolution of two one-dimensional sequences
13    /// arrays are flattened for computation
14    ///
15    /// # Arguments
16    ///
17    /// * `other` - array to perform the operation with
18    /// * `mode` - {`full`, `valid`, `same`}, optional. defaults to `full`
19    ///
20    /// # Examples
21    ///
22    /// ```
23    /// use arr_rs::prelude::*;
24    ///
25    /// let arr = Array::flat(vec![1., 2., 3.]);
26    /// let other = Array::flat(vec![0., 1., 0.5]);
27    /// assert_eq!(Array::flat(vec![0., 1., 2.5, 4., 1.5]), arr.convolve(&other.unwrap(), Some("full")));
28    /// ```
29    ///
30    /// # Errors
31    ///
32    /// may returns `ArrayError`
33    fn convolve(&self, other: &Array<N>, mode: Option<impl ConvolveModeType>) -> Result<Array<N>, ArrayError>;
34
35    /// Clip (limit) the values in an array
36    ///
37    /// # Arguments
38    ///
39    /// * `a_min` - minimum array value
40    /// * `a_max` - maximum array value
41    ///
42    /// # Examples
43    ///
44    /// ```
45    /// use arr_rs::prelude::*;
46    ///
47    /// let arr = Array::flat(vec![1., 2., 3., 4.]);
48    /// let a_min = Array::single(2.).unwrap();
49    /// let a_max = Array::single(3.).unwrap();
50    /// assert_eq!(Array::flat(vec![2., 2., 3., 3.]), arr.clip(Some(a_min), Some(a_max)));
51    /// ```
52    ///
53    /// # Errors
54    ///
55    /// may returns `ArrayError`
56    fn clip(&self, a_min: Option<Array<N>>, a_max: Option<Array<N>>) -> Result<Array<N>, ArrayError>;
57
58    /// Computes square root of array elements
59    ///
60    /// # Examples
61    ///
62    /// ```
63    /// use arr_rs::prelude::*;
64    ///
65    /// let arr = Array::flat(vec![1, 4, 9, 16]);
66    /// assert_eq!(Array::flat(vec![1, 2, 3, 4]), arr.sqrt());
67    /// ```
68    ///
69    /// # Errors
70    ///
71    /// may returns `ArrayError`
72    fn sqrt(&self) -> Result<Array<N>, ArrayError>;
73
74    /// Computes cube root of array elements
75    ///
76    /// # Examples
77    ///
78    /// ```
79    /// use arr_rs::prelude::*;
80    ///
81    /// let arr = Array::flat(vec![1, 8, 27, 64]);
82    /// assert_eq!(Array::flat(vec![1, 2, 3, 4]), arr.cbrt());
83    /// ```
84    ///
85    /// # Errors
86    ///
87    /// may returns `ArrayError`
88    fn cbrt(&self) -> Result<Array<N>, ArrayError>;
89
90    /// Return the element-wise square of the input
91    ///
92    /// # Examples
93    ///
94    /// ```
95    /// use arr_rs::prelude::*;
96    ///
97    /// let arr = Array::flat(vec![1, 2, 3, 4]);
98    /// assert_eq!(Array::flat(vec![1, 4, 9, 16]), arr.square());
99    /// ```
100    ///
101    /// # Errors
102    ///
103    /// may returns `ArrayError`
104    fn square(&self) -> Result<Array<N>, ArrayError>;
105
106    /// Computes absolute value of array elements
107    ///
108    /// # Examples
109    ///
110    /// ```
111    /// use arr_rs::prelude::*;
112    ///
113    /// let arr = Array::flat(vec![1, -2, 3, -4]);
114    /// assert_eq!(Array::flat(vec![1, 2, 3, 4]), arr.absolute());
115    /// ```
116    ///
117    /// # Errors
118    ///
119    /// may returns `ArrayError`
120    fn absolute(&self) -> Result<Array<N>, ArrayError>;
121
122    /// Computes absolute value of array elements
123    /// alias on `absolute`
124    ///
125    /// # Examples
126    ///
127    /// ```
128    /// use arr_rs::prelude::*;
129    ///
130    /// let arr = Array::flat(vec![1, -2, 3, -4]);
131    /// assert_eq!(Array::flat(vec![1, 2, 3, 4]), arr.abs());
132    /// ```
133    ///
134    /// # Errors
135    ///
136    /// may returns `ArrayError`
137    fn abs(&self) -> Result<Array<N>, ArrayError>;
138
139    /// Computes absolute value of array elements
140    /// alias on `absolute`
141    ///
142    /// # Examples
143    ///
144    /// ```
145    /// use arr_rs::prelude::*;
146    ///
147    /// let arr = Array::flat(vec![1, -2, 3, -4]);
148    /// assert_eq!(Array::flat(vec![1, 2, 3, 4]), arr.fabs());
149    /// ```
150    ///
151    /// # Errors
152    ///
153    /// may returns `ArrayError`
154    fn fabs(&self) -> Result<Array<N>, ArrayError>;
155
156    /// Returns an element-wise indication of the sign of a number
157    ///
158    /// # Examples
159    ///
160    /// ```
161    /// use arr_rs::prelude::*;
162    ///
163    /// let arr = Array::flat(vec![1, -2, -3, 4]);
164    /// assert_eq!(Array::flat(vec![1, -1, -1, 1]), arr.sign());
165    /// ```
166    ///
167    /// # Errors
168    ///
169    /// may returns `ArrayError`
170    fn sign(&self) -> Result<Array<isize>, ArrayError>;
171
172    /// Compute the Heaviside step function
173    ///
174    /// # Arguments
175    ///
176    /// * `other` - array to perform the operation with
177    ///
178    /// # Examples
179    ///
180    /// ```
181    /// use arr_rs::prelude::*;
182    ///
183    /// let arr = Array::flat(vec![-1.5, 0., 2.]);
184    /// assert_eq!(Array::flat(vec![0., 0.5, 1.]), arr.heaviside(&Array::single(0.5).unwrap()));
185    /// ```
186    ///
187    /// # Errors
188    ///
189    /// may returns `ArrayError`
190    fn heaviside(&self, other: &Array<N>) -> Result<Array<N>, ArrayError>;
191
192    /// Replace NaN with zero and infinity with large finite numbers
193    ///
194    /// # Examples
195    ///
196    /// ```
197    /// use arr_rs::prelude::*;
198    ///
199    /// let arr = Array::flat(vec![1., 2., f64::NAN, f64::INFINITY]);
200    /// assert_eq!(Array::flat(vec![1., 2., 0., f64::MAX]), arr.nan_to_num());
201    /// ```
202    ///
203    /// # Errors
204    ///
205    /// may returns `ArrayError`
206    fn nan_to_num(&self) -> Result<Array<N>, ArrayError>;
207}
208
209impl <N: Numeric> ArrayMathMisc<N> for Array<N> {
210
211    fn convolve(&self, other: &Self, mode: Option<impl ConvolveModeType>) -> Result<Self, ArrayError> {
212        if self.len()? == 0 || other.len()? == 0 {
213            return Err(ArrayError::ParameterError { param: "`array|other`", message: "cannot be empty", })
214        }
215
216        let mode = match mode {
217            Some(cm) => cm.to_mode()?,
218            None => ConvolveMode::Full,
219        };
220
221        let mut arrays = (self.to_array_f64()?, other.to_array_f64()?);
222        if arrays.1.len()? > arrays.0.len()? { arrays = arrays.swap() };
223        let mut out = vec![0.; arrays.0.len()? + arrays.1.len()? - 1];
224        for i in 0..arrays.0.len()? { for j in 0..arrays.1.len()? {
225            out[i + j] += arrays.0[i] * arrays.1[j];
226        } }
227        let (n, m) = (arrays.0.len()?, arrays.1.len()?);
228
229        match mode {
230            ConvolveMode::Full => out.clone(),
231            ConvolveMode::Valid => out.iter().skip(m - 1).take(n - m + 1).copied().collect(),
232            ConvolveMode::Same => out.iter().skip((m - 1) / 2).take(n).copied().collect(),
233        }.to_array()?.to_array_num()
234    }
235
236    fn clip(&self, a_min: Option<Self>, a_max: Option<Self>) -> Result<Self, ArrayError> {
237        let a_min = if let Some(min) = a_min { min } else { self.min(None)? }
238            .broadcast_to(self.get_shape()?)?;
239        let a_max = if let Some(max) = a_max { max } else { self.max(None)? }
240            .broadcast_to(self.get_shape()?)?;
241        let borders = a_min.zip(&a_max)?;
242
243        self.zip(&borders)?
244            .map(|tuple| {
245                if tuple.0 < tuple.1.0 { tuple.1.0 }
246                else if tuple.0 > tuple.1.1 { tuple.1.1 }
247                else { tuple.0 }
248            })
249    }
250
251    fn sqrt(&self) -> Result<Self, ArrayError> {
252        self.map(|i| N::from(i.to_f64().sqrt()))
253    }
254
255    fn cbrt(&self) -> Result<Self, ArrayError> {
256        self.map(|i| N::from(i.to_f64().cbrt()))
257    }
258
259    fn square(&self) -> Result<Self, ArrayError> {
260        self.map(|i| N::from(i.to_f64().powi(2)))
261    }
262
263    fn absolute(&self) -> Result<Self, ArrayError> {
264        self.map(|i| N::from(i.to_f64().abs()))
265    }
266
267    fn abs(&self) -> Result<Self, ArrayError> {
268        self.absolute()
269    }
270
271    fn fabs(&self) -> Result<Self, ArrayError> {
272        self.absolute()
273    }
274
275    fn sign(&self) -> Result<Array<isize>, ArrayError> {
276        self.map(|&i| if i < N::zero() { -1 } else { 1 })
277    }
278
279    fn heaviside(&self, other: &Self) -> Result<Self, ArrayError> {
280        self.zip(other)?
281            .map(|tuple|
282                if tuple.0 < N::zero() { N::zero() }
283                else if tuple.0 == N::zero() { tuple.1 }
284                else { N::one() }
285            )
286    }
287
288    fn nan_to_num(&self) -> Result<Self, ArrayError> {
289        self.map(|&item|
290            if item.is_nan() { N::zero() }
291            else if item.is_inf() { item.max() }
292            else { item }
293        )
294    }
295}
296
297impl <N: Numeric> ArrayMathMisc<N> for Result<Array<N>, ArrayError> {
298
299    fn convolve(&self, other: &Array<N>, mode: Option<impl ConvolveModeType>) -> Self {
300        self.clone()?.convolve(other, mode)
301    }
302
303    fn clip(&self, a_min: Option<Array<N>>, a_max: Option<Array<N>>) -> Self {
304        self.clone()?.clip(a_min, a_max)
305    }
306
307    fn sqrt(&self) -> Self {
308        self.clone()?.sqrt()
309    }
310
311    fn cbrt(&self) -> Self {
312        self.clone()?.cbrt()
313    }
314
315    fn square(&self) -> Self {
316        self.clone()?.square()
317    }
318
319    fn absolute(&self) -> Self {
320        self.clone()?.absolute()
321    }
322
323    fn abs(&self) -> Self {
324        self.clone()?.abs()
325    }
326
327    fn fabs(&self) -> Self {
328        self.clone()?.fabs()
329    }
330
331    fn sign(&self) -> Result<Array<isize>, ArrayError> {
332        self.clone()?.sign()
333    }
334
335    fn heaviside(&self, other: &Array<N>) -> Self {
336        self.clone()?.heaviside(other)
337    }
338
339    fn nan_to_num(&self) -> Self {
340        self.clone()?.nan_to_num()
341    }
342}