arr_rs/math/operations/
arithmetic.rs

1use crate::{
2    core::prelude::*,
3    errors::prelude::*,
4    math::prelude::*,
5    numeric::prelude::*,
6};
7
8/// `ArrayTrait` - Array Arithmetic functions
9pub trait ArrayArithmetic<N: Numeric> where Self: Sized + Clone {
10
11    /// Add arguments element-wise
12    ///
13    /// # Arguments
14    ///
15    /// * `value` - other array to perform operations on
16    ///
17    /// # Examples
18    ///
19    /// ```
20    /// use arr_rs::prelude::*;
21    ///
22    /// let arr = Array::flat(vec![1, 2, 3, 4]);
23    /// assert_eq!(Array::flat(vec![3, 4, 5, 6]), arr.add(&Array::single(2).unwrap()));
24    /// ```
25    ///
26    /// # Errors
27    ///
28    /// may returns `ArrayError`
29    fn add(&self, value: &Array<N>) -> Result<Array<N>, ArrayError>;
30
31    /// Computes reciprocal of array elements
32    ///
33    /// # Examples
34    ///
35    /// ```
36    /// use arr_rs::prelude::*;
37    ///
38    /// let arr = Array::flat(vec![1., 2., 4., 10.]);
39    /// assert_eq!(Array::flat(vec![1., 0.5, 0.25, 0.1]), arr.reciprocal());
40    /// ```
41    ///
42    /// # Errors
43    ///
44    /// may returns `ArrayError`
45    fn reciprocal(&self) -> Result<Array<N>, ArrayError>;
46
47    /// Computes numerical positive of array elements
48    /// Equivalent to `self.clone()`
49    ///
50    /// # Examples
51    ///
52    /// ```
53    /// use arr_rs::prelude::*;
54    ///
55    /// let arr = Array::flat(vec![1., -1.]);
56    /// assert_eq!(Array::flat(vec![1., -1.]), arr.positive());
57    /// ```
58    ///
59    /// # Errors
60    ///
61    /// may returns `ArrayError`
62    fn positive(&self) -> Result<Array<N>, ArrayError>;
63
64    /// Computes numerical negative of array elements
65    ///
66    /// # Examples
67    ///
68    /// ```
69    /// use arr_rs::prelude::*;
70    ///
71    /// let arr = Array::flat(vec![1., -1.]);
72    /// assert_eq!(Array::flat(vec![-1., 1.]), arr.negative());
73    /// ```
74    ///
75    /// # Errors
76    ///
77    /// may returns `ArrayError`
78    fn negative(&self) -> Result<Array<N>, ArrayError>;
79
80    /// Multiply arguments element-wise
81    ///
82    /// # Arguments
83    ///
84    /// * `value` - other array to perform operations on
85    ///
86    /// # Examples
87    ///
88    /// ```
89    /// use arr_rs::prelude::*;
90    ///
91    /// let arr = Array::flat(vec![1, 2, 3, 4]);
92    /// assert_eq!(Array::flat(vec![2, 4, 6, 8]), arr.multiply(&Array::single(2).unwrap()));
93    /// ```
94    ///
95    /// # Errors
96    ///
97    /// may returns `ArrayError`
98    fn multiply(&self, value: &Array<N>) -> Result<Array<N>, ArrayError>;
99
100    /// Divide arguments element-wise
101    ///
102    /// # Arguments
103    ///
104    /// * `value` - other array to perform operations on
105    ///
106    /// # Examples
107    ///
108    /// ```
109    /// use arr_rs::prelude::*;
110    ///
111    /// let arr = Array::flat(vec![1., 2., 3., 4.]);
112    /// assert_eq!(Array::flat(vec![0.5, 1., 1.5, 2.]), arr.divide(&Array::single(2.).unwrap()));
113    /// ```
114    ///
115    /// # Errors
116    ///
117    /// may returns `ArrayError`
118    fn divide(&self, value: &Array<N>) -> Result<Array<N>, ArrayError>;
119
120    /// Divide arguments element-wise
121    /// alias on `divide`
122    ///
123    /// # Arguments
124    ///
125    /// * `value` - other array to perform operations on
126    ///
127    /// # Examples
128    ///
129    /// ```
130    /// use arr_rs::prelude::*;
131    ///
132    /// let arr = Array::flat(vec![1., 2., 3., 4.]);
133    /// assert_eq!(Array::flat(vec![0.5, 1., 1.5, 2.]), arr.true_divide(&Array::single(2.).unwrap()));
134    /// ```
135    ///
136    /// # Errors
137    ///
138    /// may returns `ArrayError`
139    fn true_divide(&self, value: &Array<N>) -> Result<Array<N>, ArrayError>;
140
141    /// Divide arguments element-wise, returning floor value
142    ///
143    /// # Arguments
144    ///
145    /// * `value` - other array to perform operations on
146    ///
147    /// # Examples
148    ///
149    /// ```
150    /// use arr_rs::prelude::*;
151    ///
152    /// let arr = Array::flat(vec![1., 2., 3., 4.]);
153    /// assert_eq!(Array::flat(vec![0., 1., 1., 2.]), arr.floor_divide(&Array::single(2.).unwrap()));
154    /// ```
155    ///
156    /// # Errors
157    ///
158    /// may returns `ArrayError`
159    fn floor_divide(&self, value: &Array<N>) -> Result<Array<N>, ArrayError>;
160
161    /// Computes integer power of array elements
162    ///
163    /// # Arguments
164    ///
165    /// * `value` - other array to perform operations on
166    ///
167    /// # Examples
168    ///
169    /// ```
170    /// use arr_rs::prelude::*;
171    ///
172    /// let arr = Array::flat(vec![1, 2, 3, 4]);
173    /// assert_eq!(Array::flat(vec![1, 4, 9, 16]), arr.power(&Array::single(2).unwrap()));
174    /// ```
175    ///
176    /// # Errors
177    ///
178    /// may returns `ArrayError`
179    fn power(&self, value: &Array<N>) -> Result<Array<N>, ArrayError>;
180
181    /// Computes float power of array elements
182    ///
183    /// # Arguments
184    ///
185    /// * `value` - other array to perform operations on
186    ///
187    /// # Examples
188    ///
189    /// ```
190    /// use arr_rs::prelude::*;
191    ///
192    /// let arr = Array::flat(vec![1, 2, 3, 4]);
193    /// assert_eq!(Array::flat(vec![1, 4, 9, 16]), arr.float_power(&Array::single(2).unwrap()));
194    /// ```
195    ///
196    /// # Errors
197    ///
198    /// may returns `ArrayError`
199    fn float_power(&self, value: &Array<N>) -> Result<Array<N>, ArrayError>;
200
201    /// Subtract arguments element-wise
202    ///
203    /// # Arguments
204    ///
205    /// * `value` - other array to perform operations on
206    ///
207    /// # Examples
208    ///
209    /// ```
210    /// use arr_rs::prelude::*;
211    ///
212    /// let arr = Array::flat(vec![1, 2, 3, 4]);
213    /// assert_eq!(Array::flat(vec![-1, 0, 1, 2]), arr.subtract(&Array::single(2).unwrap()));
214    /// ```
215    ///
216    /// # Errors
217    ///
218    /// may returns `ArrayError`
219    fn subtract(&self, value: &Array<N>) -> Result<Array<N>, ArrayError>;
220
221    /// Computes remainder of division element-wise
222    /// alias on `remainder`
223    ///
224    /// # Arguments
225    ///
226    /// * `value` - other array to perform operations on
227    ///
228    /// # Examples
229    ///
230    /// ```
231    /// use arr_rs::prelude::*;
232    ///
233    /// let arr = Array::flat(vec![1, 2, 3, 4]);
234    /// assert_eq!(Array::flat(vec![1, 0, 1, 0]), arr.r#mod(&Array::single(2).unwrap()));
235    /// ```
236    ///
237    /// # Errors
238    ///
239    /// may returns `ArrayError`
240    fn r#mod(&self, value: &Array<N>) -> Result<Array<N>, ArrayError>;
241
242    /// Computes remainder of division element-wise
243    ///
244    /// # Arguments
245    ///
246    /// * `value` - other array to perform operations on
247    ///
248    /// # Examples
249    ///
250    /// ```
251    /// use arr_rs::prelude::*;
252    ///
253    /// let arr = Array::flat(vec![1, 2, 3, 4]);
254    /// assert_eq!(Array::flat(vec![1, 0, 1, 0]), arr.fmod(&Array::single(2).unwrap()));
255    /// ```
256    ///
257    /// # Errors
258    ///
259    /// may returns `ArrayError`
260    fn fmod(&self, value: &Array<N>) -> Result<Array<N>, ArrayError>;
261
262    /// Computes fractional and integral parts of an array, element-wise
263    ///
264    /// # Examples
265    ///
266    /// ```
267    /// use arr_rs::prelude::*;
268    ///
269    /// let arr = Array::flat(vec![1.5, 2., 3.5]);
270    /// assert_eq!(Ok((Array::flat(vec![0.5, 0., 0.5]).unwrap(), Array::flat(vec![1., 2., 3.]).unwrap())), arr.modf());
271    /// ```
272    ///
273    /// # Errors
274    ///
275    /// may returns `ArrayError`
276    fn modf(&self) -> Result<(Array<N>, Array<N>), ArrayError>;
277
278    /// Computes remainder of division element-wise
279    ///
280    /// # Arguments
281    ///
282    /// * `value` - other array to perform operations on
283    ///
284    /// # Examples
285    ///
286    /// ```
287    /// use arr_rs::prelude::*;
288    ///
289    /// let arr = Array::flat(vec![1, 2, 3, 4]);
290    /// assert_eq!(Array::flat(vec![1, 0, 1, 0]), arr.remainder(&Array::single(2).unwrap()));
291    /// ```
292    ///
293    /// # Errors
294    ///
295    /// may returns `ArrayError`
296    fn remainder(&self, value: &Array<N>) -> Result<Array<N>, ArrayError>;
297
298    /// Computes integral and fractional parts of an array, element-wise
299    ///
300    /// # Examples
301    ///
302    /// ```
303    /// use arr_rs::prelude::*;
304    ///
305    /// let arr = Array::flat(vec![1.5, 2., 3.5]);
306    /// assert_eq!(Ok((Array::flat(vec![1., 2., 3.]).unwrap(), Array::flat(vec![0.5, 0., 0.5]).unwrap())), arr.divmod());
307    /// ```
308    ///
309    /// # Errors
310    ///
311    /// may returns `ArrayError`
312    fn divmod(&self) -> Result<(Array<N>, Array<N>), ArrayError>;
313}
314
315impl <N: Numeric> ArrayArithmetic<N> for Array<N> {
316
317    fn add(&self, value: &Self) -> Result<Self, ArrayError> {
318        let broadcasted = self.broadcast(value)?;
319        let elements = broadcasted.clone().into_iter()
320            .map(|tuple| N::from(tuple.0.to_f64() + tuple.1.to_f64()))
321            .collect();
322        Self::new(elements, broadcasted.get_shape()?)
323    }
324
325    fn reciprocal(&self) -> Result<Self, ArrayError> {
326        self.map(|i| N::from(i.to_f64().recip()))
327    }
328
329    fn positive(&self) -> Result<Self, ArrayError> {
330        Ok(self.clone())
331    }
332
333    fn negative(&self) -> Result<Self, ArrayError> {
334        self.map(|i| N::from(-i.to_f64()))
335    }
336
337    fn multiply(&self, value: &Self) -> Result<Self, ArrayError> {
338        let broadcasted = self.broadcast(value)?;
339        let elements = broadcasted.clone().into_iter()
340            .map(|tuple| N::from(tuple.0.to_f64() * tuple.1.to_f64()))
341            .collect();
342        Self::new(elements, broadcasted.get_shape()?)
343    }
344
345    fn divide(&self, value: &Self) -> Result<Self, ArrayError> {
346        if value.get_elements()?.contains(&N::zero()) {
347            return Err(ArrayError::ParameterError { param: "value", message: "cannot contain `0`", });
348        }
349        let broadcasted = self.broadcast(value)?;
350        let elements = broadcasted.clone().into_iter()
351            .map(|tuple| N::from(tuple.0.to_f64() / tuple.1.to_f64()))
352            .collect();
353        Self::new(elements, broadcasted.get_shape()?)
354    }
355
356    fn true_divide(&self, value: &Self) -> Result<Self, ArrayError> {
357        self.divide(value)
358    }
359
360    fn floor_divide(&self, value: &Self) -> Result<Self, ArrayError> {
361        self.divide(value).floor()
362    }
363
364    fn power(&self, value: &Self) -> Result<Self, ArrayError> {
365        let broadcasted = self.broadcast(value)?;
366        let elements = broadcasted.clone().into_iter()
367            .map(|tuple| N::from(tuple.0.to_f64().powi(tuple.1.to_i32())))
368            .collect();
369        Self::new(elements, broadcasted.get_shape()?)
370    }
371
372    fn float_power(&self, value: &Self) -> Result<Self, ArrayError> {
373        let broadcasted = self.broadcast(value)?;
374        let elements = broadcasted.clone().into_iter()
375            .map(|tuple| N::from(tuple.0.to_f64().powf(tuple.1.to_f64())))
376            .collect();
377        Self::new(elements, broadcasted.get_shape()?)
378    }
379
380    fn subtract(&self, value: &Self) -> Result<Self, ArrayError> {
381        let broadcasted = self.broadcast(value)?;
382        let elements = broadcasted.clone().into_iter()
383            .map(|tuple| N::from(tuple.0.to_f64() - tuple.1.to_f64()))
384            .collect();
385        Self::new(elements, broadcasted.get_shape()?)
386    }
387
388    fn r#mod(&self, value: &Self) -> Result<Self, ArrayError> {
389        self.remainder(value)
390    }
391
392    fn fmod(&self, value: &Self) -> Result<Self, ArrayError> {
393        if value.get_elements()?.contains(&N::zero()) {
394            return Err(ArrayError::ParameterError { param: "value", message: "cannot contain `0`", });
395        }
396        let broadcasted = self.broadcast(value)?;
397        let elements = broadcasted.clone().into_iter()
398            .map(|tuple| N::from((tuple.0.to_f64() / tuple.1.to_f64()).floor().mul_add(-tuple.1.to_f64(), tuple.0.to_f64())))
399            .collect();
400        Self::new(elements, broadcasted.get_shape()?)
401    }
402
403    fn modf(&self) -> Result<(Self, Self), ArrayError> {
404        let fractional = self.r#mod(&Self::single(N::one())?)?;
405        let integral = self.floor()?;
406        Ok((fractional, integral))
407    }
408
409    fn remainder(&self, value: &Self) -> Result<Self, ArrayError> {
410        if value.get_elements()?.contains(&N::zero()) {
411            return Err(ArrayError::ParameterError { param: "value", message: "cannot contain `0`", });
412        }
413        let broadcasted = self.broadcast(value)?;
414        let elements = broadcasted.clone().into_iter()
415            .map(|tuple| N::from(tuple.0.to_f64() % tuple.1.to_f64()))
416            .collect();
417        Self::new(elements, broadcasted.get_shape()?)
418    }
419
420    fn divmod(&self) -> Result<(Self, Self), ArrayError> {
421        let fractional = self.r#mod(&Self::single(N::one())?)?;
422        let integral = self.floor()?;
423        Ok((integral, fractional))
424    }
425}
426
427impl <N: Numeric> ArrayArithmetic<N> for Result<Array<N>, ArrayError> {
428
429    fn add(&self, value: &Array<N>) -> Self {
430        self.clone()?.add(value)
431    }
432
433    fn reciprocal(&self) -> Self {
434        self.clone()?.reciprocal()
435    }
436
437    fn positive(&self) -> Self {
438        self.clone()?.positive()
439    }
440
441    fn negative(&self) -> Self {
442        self.clone()?.negative()
443    }
444
445    fn multiply(&self, value: &Array<N>) -> Self {
446        self.clone()?.multiply(value)
447    }
448
449    fn divide(&self, value: &Array<N>) -> Self {
450        self.clone()?.divide(value)
451    }
452
453    fn true_divide(&self, value: &Array<N>) -> Self {
454        self.clone()?.true_divide(value)
455    }
456
457    fn floor_divide(&self, value: &Array<N>) -> Self {
458        self.clone()?.floor_divide(value)
459    }
460
461    fn power(&self, value: &Array<N>) -> Self {
462        self.clone()?.power(value)
463    }
464
465    fn float_power(&self, value: &Array<N>) -> Self {
466        self.clone()?.float_power(value)
467    }
468
469    fn subtract(&self, value: &Array<N>) -> Self {
470        self.clone()?.subtract(value)
471    }
472
473    fn r#mod(&self, value: &Array<N>) -> Self {
474        self.clone()?.r#mod(value)
475    }
476
477    fn fmod(&self, value: &Array<N>) -> Self {
478        self.clone()?.fmod(value)
479    }
480
481    fn modf(&self) -> Result<(Array<N>, Array<N>), ArrayError> {
482        self.clone()?.modf()
483    }
484
485    fn remainder(&self, value: &Array<N>) -> Self {
486        self.clone()?.remainder(value)
487    }
488
489    fn divmod(&self) -> Result<(Array<N>, Array<N>), ArrayError> {
490        self.clone()?.divmod()
491    }
492}