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}