mirror of
https://github.com/typst/typst
synced 2025-05-14 04:56:26 +08:00
Add gcd
and lcm
calculation methods (#789)
This commit is contained in:
parent
dc3017955a
commit
1e934def56
@ -27,6 +27,8 @@ pub fn module() -> Module {
|
|||||||
scope.define("fact", fact);
|
scope.define("fact", fact);
|
||||||
scope.define("perm", perm);
|
scope.define("perm", perm);
|
||||||
scope.define("binom", binom);
|
scope.define("binom", binom);
|
||||||
|
scope.define("gcd", gcd);
|
||||||
|
scope.define("lcm", lcm);
|
||||||
scope.define("floor", floor);
|
scope.define("floor", floor);
|
||||||
scope.define("ceil", ceil);
|
scope.define("ceil", ceil);
|
||||||
scope.define("round", round);
|
scope.define("round", round);
|
||||||
@ -522,6 +524,72 @@ fn binomial(n: u64, k: u64) -> Option<i64> {
|
|||||||
i64::try_from(result).ok()
|
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.
|
/// Round a number down to the nearest integer.
|
||||||
///
|
///
|
||||||
/// If the number is already an integer, it is returned unchanged.
|
/// If the number is already an integer, it is returned unchanged.
|
||||||
|
@ -146,6 +146,30 @@
|
|||||||
#test(calc.binom(5, 6), 0)
|
#test(calc.binom(5, 6), 0)
|
||||||
#test(calc.binom(6, 2), 15)
|
#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
|
// Error: 10-12 expected at least one value
|
||||||
#calc.min()
|
#calc.min()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user