mirror of
https://github.com/typst/typst
synced 2025-05-14 04:56:26 +08:00
Implement euclidean division and remainder (#2678)
This commit is contained in:
parent
f5b3af3c1b
commit
43f90b2159
@ -50,6 +50,8 @@ fn module() -> Module {
|
|||||||
scope.define_func::<even>();
|
scope.define_func::<even>();
|
||||||
scope.define_func::<odd>();
|
scope.define_func::<odd>();
|
||||||
scope.define_func::<rem>();
|
scope.define_func::<rem>();
|
||||||
|
scope.define_func::<div_euclid>();
|
||||||
|
scope.define_func::<rem_euclid>();
|
||||||
scope.define_func::<quo>();
|
scope.define_func::<quo>();
|
||||||
scope.define("inf", f64::INFINITY);
|
scope.define("inf", f64::INFINITY);
|
||||||
scope.define("nan", f64::NAN);
|
scope.define("nan", f64::NAN);
|
||||||
@ -790,7 +792,10 @@ pub fn odd(
|
|||||||
/// in magnitude than `y`.
|
/// in magnitude than `y`.
|
||||||
///
|
///
|
||||||
/// ```example
|
/// ```example
|
||||||
/// #calc.rem(20, 6) \
|
/// #calc.rem(7, 3) \
|
||||||
|
/// #calc.rem(7, -3) \
|
||||||
|
/// #calc.rem(-7, 3) \
|
||||||
|
/// #calc.rem(-7, -3) \
|
||||||
/// #calc.rem(1.75, 0.5)
|
/// #calc.rem(1.75, 0.5)
|
||||||
/// ```
|
/// ```
|
||||||
#[func(title = "Remainder")]
|
#[func(title = "Remainder")]
|
||||||
@ -806,6 +811,57 @@ pub fn rem(
|
|||||||
Ok(dividend.apply2(divisor.v, Rem::rem, Rem::rem))
|
Ok(dividend.apply2(divisor.v, Rem::rem, Rem::rem))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Performs euclidean division of two numbers.
|
||||||
|
///
|
||||||
|
/// The result of this computation is that of a division rounded to the integer
|
||||||
|
/// `{n}` such that the dividend is greater than or equal to `{n}` times the divisor.
|
||||||
|
///
|
||||||
|
/// ```example
|
||||||
|
/// #calc.div-euclid(7, 3) \
|
||||||
|
/// #calc.div-euclid(7, -3) \
|
||||||
|
/// #calc.div-euclid(-7, 3) \
|
||||||
|
/// #calc.div-euclid(-7, -3) \
|
||||||
|
/// #calc.div-euclid(1.75, 0.5)
|
||||||
|
/// ```
|
||||||
|
#[func(title = "Euclidean Division")]
|
||||||
|
pub fn div_euclid(
|
||||||
|
/// The dividend of the division.
|
||||||
|
dividend: Num,
|
||||||
|
/// The divisor of the division.
|
||||||
|
divisor: Spanned<Num>,
|
||||||
|
) -> SourceResult<Num> {
|
||||||
|
if divisor.v.float() == 0.0 {
|
||||||
|
bail!(divisor.span, "divisor must not be zero");
|
||||||
|
}
|
||||||
|
Ok(dividend.apply2(divisor.v, i64::div_euclid, f64::div_euclid))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// This calculates the least nonnegative remainder of a division.
|
||||||
|
///
|
||||||
|
/// Warning: Due to a floating point round-off error, the remainder may equal the absolute
|
||||||
|
/// value of the divisor if the dividend is much smaller in magnitude than the divisor
|
||||||
|
/// and the dividend is negative. This only applies for floating point inputs.
|
||||||
|
///
|
||||||
|
/// ```example
|
||||||
|
/// #calc.rem-euclid(7, 3) \
|
||||||
|
/// #calc.rem-euclid(7, -3) \
|
||||||
|
/// #calc.rem-euclid(-7, 3) \
|
||||||
|
/// #calc.rem-euclid(-7, -3) \
|
||||||
|
/// #calc.rem(1.75, 0.5)
|
||||||
|
/// ```
|
||||||
|
#[func(title = "Euclidean Remainder")]
|
||||||
|
pub fn rem_euclid(
|
||||||
|
/// The dividend of the remainder.
|
||||||
|
dividend: Num,
|
||||||
|
/// The divisor of the remainder.
|
||||||
|
divisor: Spanned<Num>,
|
||||||
|
) -> SourceResult<Num> {
|
||||||
|
if divisor.v.float() == 0.0 {
|
||||||
|
bail!(divisor.span, "divisor must not be zero");
|
||||||
|
}
|
||||||
|
Ok(dividend.apply2(divisor.v, i64::rem_euclid, f64::rem_euclid))
|
||||||
|
}
|
||||||
|
|
||||||
/// Calculates the quotient (floored division) of two numbers.
|
/// Calculates the quotient (floored division) of two numbers.
|
||||||
///
|
///
|
||||||
/// ```example
|
/// ```example
|
||||||
|
@ -76,6 +76,38 @@
|
|||||||
// Error: 16-19 divisor must not be zero
|
// Error: 16-19 divisor must not be zero
|
||||||
#calc.rem(3.0, 0.0)
|
#calc.rem(3.0, 0.0)
|
||||||
|
|
||||||
|
---
|
||||||
|
// Test the `div-euclid` function.
|
||||||
|
#test(calc.div-euclid(7, 3), 2)
|
||||||
|
#test(calc.div-euclid(7, -3), -2)
|
||||||
|
#test(calc.div-euclid(-7, 3), -3)
|
||||||
|
#test(calc.div-euclid(-7, -3), 3)
|
||||||
|
#test(calc.div-euclid(2.5, 2), 1)
|
||||||
|
|
||||||
|
---
|
||||||
|
// Error: 21-22 divisor must not be zero
|
||||||
|
#calc.div-euclid(5, 0)
|
||||||
|
|
||||||
|
---
|
||||||
|
// Error: 23-26 divisor must not be zero
|
||||||
|
#calc.div-euclid(3.0, 0.0)
|
||||||
|
|
||||||
|
---
|
||||||
|
// Test the `rem-euclid` function.
|
||||||
|
#test(calc.rem-euclid(7, 3), 1)
|
||||||
|
#test(calc.rem-euclid(7, -3), 1)
|
||||||
|
#test(calc.rem-euclid(-7, 3), 2)
|
||||||
|
#test(calc.rem-euclid(-7, -3), 2)
|
||||||
|
#test(calc.rem-euclid(2.5, 2), 0.5)
|
||||||
|
|
||||||
|
---
|
||||||
|
// Error: 21-22 divisor must not be zero
|
||||||
|
#calc.rem-euclid(5, 0)
|
||||||
|
|
||||||
|
---
|
||||||
|
// Error: 23-26 divisor must not be zero
|
||||||
|
#calc.rem-euclid(3.0, 0.0)
|
||||||
|
|
||||||
---
|
---
|
||||||
// Test the `quo` function.
|
// Test the `quo` function.
|
||||||
#test(calc.quo(1, 1), 1)
|
#test(calc.quo(1, 1), 1)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user