Add gcd and lcm calculation methods (#789)

This commit is contained in:
HarmoGlace 2023-04-19 16:18:31 +02:00 committed by GitHub
parent dc3017955a
commit 1e934def56
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 92 additions and 0 deletions

View File

@ -27,6 +27,8 @@ pub fn module() -> Module {
scope.define("fact", fact);
scope.define("perm", perm);
scope.define("binom", binom);
scope.define("gcd", gcd);
scope.define("lcm", lcm);
scope.define("floor", floor);
scope.define("ceil", ceil);
scope.define("round", round);
@ -522,6 +524,72 @@ fn binomial(n: u64, k: u64) -> Option<i64> {
i64::try_from(result).ok()
}
/// Calculate the greatest common divisor of two integers.
///
/// ## Example
/// ```example
/// #calc.gcd(7, 42)
/// ```
///
/// Display: Greatest Common Divisor
/// Category: calculate
/// Returns: integer
#[func]
pub fn gcd(
/// The first integer.
a: i64,
/// The second integer.
b: i64,
) -> Value {
Value::Int(calculate_gcd(a, b).into())
}
/// Calculates the greatest common divisor of two integers
/// It is always non-negative.
fn calculate_gcd(mut a: i64, mut b: i64) -> i64 {
while b != 0 {
let temp = b;
b = a % b;
a = temp;
}
a.abs()
}
/// Calculate the least common multiple of two integers.
///
/// ## Example
/// ```example
/// #calc.lcm(96, 13)
/// ```
///
/// Display: Least Common Multiple
/// Category: calculate
/// Returns: integer
#[func]
pub fn lcm(
/// The first integer.
a: i64,
/// The second integer.
b: i64,
) -> Value {
calculate_lcm(a, b)
.map(Value::Int)
.ok_or("the return value is too large")
.at(args.span)?
}
/// Calculates the least common multiple between two non-zero integers
/// Returns None if the value cannot be computed.
/// It is always non-negative.
fn calculate_lcm(a: i64, b: i64) -> Option<i64> {
if a == b {
return Some(a.abs());
}
a.checked_div(calculate_gcd(a, b))?.checked_mul(b).map(|v| v.abs())
}
/// Round a number down to the nearest integer.
///
/// If the number is already an integer, it is returned unchanged.

View File

@ -146,6 +146,30 @@
#test(calc.binom(5, 6), 0)
#test(calc.binom(6, 2), 15)
---
// Test the `gcd` function.
#test(calc.gcd(112, 77), 7)
#test(calc.gcd(12, 96), 12)
#test(calc.gcd(13, 9), 1)
#test(calc.gcd(13, -9), 1)
#test(calc.gcd(272557, 272557), 272557)
#test(calc.gcd(0, 0), 0)
#test(calc.gcd(7, 0), 7)
---
// Test the `lcm` function.
#test(calc.lcm(112, 77), 1232)
#test(calc.lcm(12, 96), 96)
#test(calc.lcm(13, 9), 117)
#test(calc.lcm(13, -9), 117)
#test(calc.lcm(272557, 272557), 272557)
#test(calc.lcm(0, 0), 0)
#test(calc.lcm(8, 0), 0)
---
// Error: 10-41 the return value is too large
#calc.lcm(15486487489457, 4874879896543)
---
// Error: 10-12 expected at least one value
#calc.min()