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