arr_rs/math/operations/
rational.rs

1use crate::{
2    core::prelude::*,
3    errors::prelude::*,
4    numeric::prelude::*,
5};
6use crate::prelude::ArrayMathMisc;
7
8/// `ArrayTrait` - Array Rational functions
9pub trait ArrayRational<N: Numeric> where Self: Sized + Clone {
10
11    /// Returns the lowest common multiple of |x1| and |x2|
12    ///
13    /// # Arguments
14    ///
15    /// * `other` - array to perform the operation with
16    ///
17    /// # Examples
18    ///
19    /// ```
20    /// use arr_rs::prelude::*;
21    ///
22    /// assert_eq!(Array::single(60), Array::single(12).lcm(&Array::single(20).unwrap()));
23    /// ```
24    ///
25    /// # Errors
26    ///
27    /// may returns `ArrayError`
28    fn lcm(&self, other: &Array<N>) -> Result<Array<N>, ArrayError>;
29
30    /// Returns the greatest common divisor of |x1| and |x2|
31    ///
32    /// # Arguments
33    ///
34    /// * `other` - array to perform the operation with
35    ///
36    /// # Examples
37    ///
38    /// ```
39    /// use arr_rs::prelude::*;
40    ///
41    /// assert_eq!(Array::single(4), Array::single(12).gcd(&Array::single(20).unwrap()));
42    /// ```
43    ///
44    /// # Errors
45    ///
46    /// may returns `ArrayError`
47    fn gcd(&self, other: &Array<N>) -> Result<Array<N>, ArrayError>;
48}
49
50fn _gcd(x: i32, y: i32) -> i32 {
51    if y == 0 { x }
52    else { _gcd(y, x % y) }
53}
54
55impl <N: Numeric> ArrayRational<N> for Array<N> {
56
57    fn lcm(&self, other: &Self) -> Result<Self, ArrayError> {
58        self.abs()?.zip(&other.abs()?)?
59            .map(|item| {
60                let (x, y) = (item.0.to_i32(), item.1.to_i32());
61                N::from(x * y / _gcd(x, y))
62            })
63    }
64
65    fn gcd(&self, other: &Self) -> Result<Self, ArrayError> {
66        self.abs()?.zip(&other.abs()?)?
67            .map(|item| N::from(_gcd(item.0.to_i32(), item.1.to_i32())))
68    }
69}
70
71impl <N: Numeric> ArrayRational<N> for Result<Array<N>, ArrayError> {
72
73    fn lcm(&self, other: &Array<N>) -> Self {
74        self.clone()?.lcm(other)
75    }
76
77    fn gcd(&self, other: &Array<N>) -> Self {
78        self.clone()?.gcd(other)
79    }
80}