Skip to content

Commit 0112208

Browse files
committed
Add gcd function
1 parent b3ac9b4 commit 0112208

File tree

4 files changed

+109
-1
lines changed

4 files changed

+109
-1
lines changed

Cargo.lock

+4
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
[workspace]
2-
members = ["array-rotate", "sorting"]
2+
members = ["array-rotate", "mathematical", "sorting"]

mathematical/Cargo.toml

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
[package]
2+
name = "mathematical"
3+
version = "0.1.0"
4+
edition = "2021"
5+
6+
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
7+
8+
[dependencies]

mathematical/src/lib.rs

+96
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
pub mod math {
2+
use std::ops::{Rem, Sub};
3+
4+
trait Number<T>: Eq + Rem<Output=T> + Default + Copy {}
5+
6+
/// Calculates the GCD of 2 numbers. (Euclidean algorithm)
7+
///
8+
/// # Examples
9+
/// ```rust
10+
/// # use mathematical::math::gcd;
11+
/// # fn main() -> Result<(), &'static str> {
12+
/// let a = 20;
13+
/// let b = 30;
14+
/// let result = gcd(a, b)?;
15+
/// assert_eq!(result, 10);
16+
/// # Ok(())
17+
/// # }
18+
/// ```
19+
///
20+
/// # Failures
21+
/// If both a and b are 0, the function fails
22+
pub fn gcd<'a, T: PartialEq + Rem<Output=T> + Default + Copy + PartialOrd + Sub<Output=T>>(a: T, b: T) -> Result<T, &'a str> {
23+
if a == Default::default() && b == Default::default() {
24+
return Err("values cannot be 0");
25+
}
26+
27+
let x = gcd_loop(a, b);
28+
29+
return if a < Default::default() || b < Default::default() {
30+
let zero: T = Default::default();
31+
let neg_x = zero - x;
32+
Ok(max(x, neg_x))
33+
} else { Ok(x) };
34+
}
35+
36+
fn gcd_loop<T: PartialEq + Rem<Output=T> + Default + Copy>(mut x: T, mut y: T) -> T {
37+
while y != Default::default() {
38+
let t = y;
39+
40+
y = x % y;
41+
x = t;
42+
}
43+
44+
x
45+
}
46+
47+
fn max<T: PartialOrd>(a: T, b: T) -> T {
48+
return if a > b {
49+
a
50+
} else {
51+
b
52+
};
53+
}
54+
}
55+
56+
#[cfg(test)]
57+
mod tests {
58+
mod gcd_tests {
59+
use crate::math::gcd;
60+
61+
#[test]
62+
fn test_with_0() {
63+
let res = gcd(0, 0);
64+
assert!(res.is_err());
65+
assert_eq!(res.unwrap_err(), "values cannot be 0");
66+
}
67+
68+
#[test]
69+
fn test_gcd() {
70+
let result = gcd(-1386, 3213);
71+
assert!(result.is_ok());
72+
assert_eq!(result.unwrap(), 63);
73+
}
74+
75+
#[test]
76+
fn test_gcd_unsigned() {
77+
let result = gcd(20u8, 30u8);
78+
assert!(result.is_ok());
79+
assert_eq!(result.unwrap(), 10);
80+
}
81+
82+
#[test]
83+
fn test_gcd_neg() {
84+
let result = gcd(-20, -30);
85+
assert!(result.is_ok());
86+
assert_eq!(result.unwrap(), 10);
87+
}
88+
89+
#[test]
90+
fn test_gcd_float() {
91+
let result = gcd(-20f32, 30f32);
92+
assert!(result.is_ok());
93+
assert_eq!(result.unwrap(), 10f32);
94+
}
95+
}
96+
}

0 commit comments

Comments
 (0)