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
73
74
75
76
77
78
79
80
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()));
/// ```
///
/// # Errors
///
/// may returns `ArrayError`
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()));
/// ```
///
/// # Errors
///
/// may returns `ArrayError`
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: &Self) -> Result<Self, 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: &Self) -> Result<Self, 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>) -> Self {
self.clone()?.lcm(other)
}
fn gcd(&self, other: &Array<N>) -> Self {
self.clone()?.gcd(other)
}
}