Repository: typst/typst
File: crates/typst-library/src/foundations/calc.rs (Rust)

Code before:
    dividend: DecNum,
    /// The divisor of the remainder.
    divisor: Spanned<DecNum>,
) -> SourceResult<DecNum> {
    if divisor.v.is_zero() {
        bail!(divisor.span, "divisor must not be zero");
    }

    dividend
        .apply2(
            divisor.v,
            |a, b| a.checked_rem_euclid(b).map(DecNum::Int),
            |a, b| Some(DecNum::Float(a.rem_euclid(b))),
            |a, b| a.checked_rem_euclid(b).map(DecNum::Decimal),
        )
        .ok_or_else(cant_apply_to_decimal_and_float)
        .at(span)?
        .ok_or("dividend too small compared to divisor")
        .at(span)
}

/// Calculates the quotient (floored division) of two numbers.
///
/// Note that this function will always return an [integer]($int), and will
/// error if the resulting number is larger than the maximum 64-bit signed integer
/// or smaller than the minimum for that type.
///
/// ```example
/// $ "quo"(a, b) &= floor(a/b) \
///   "quo"(14, 5) &= #calc.quo(14, 5) \
///   "quo"(3.46, 0.5) &= #calc.quo(3.46, 0.5) $
/// ```
#[func(title = "Quotient")]
pub fn quo(
    span: Span,
    /// The dividend of the quotient.
    dividend: DecNum,
    /// The divisor of the quotient.
    divisor: Spanned<DecNum>,
) -> SourceResult<i64> {
    if divisor.v.is_zero() {
        bail!(divisor.span, "divisor must not be zero");
    }

    let divided = dividend
        .apply2(
            divisor.v,
            |a, b| a.checked_div(b).map(DecNum::Int),
            |a, b| Some(DecNum::Float(a / b)),
            |a, b| a.checked_div(b).map(DecNum::Decimal),
        )

Review comment (suggestion):
```suggestion
/// error if the resulting number is larger than the maximum 64-bit signed
/// integer or smaller than the minimum for that type.
```

Code after:
/// #calc.rem-euclid(-7, -3) \
/// #calc.rem-euclid(1.75, 0.5) \
/// #calc.rem-euclid(decimal("1.75"), decimal("0.5"))
/// ```
#[func(title = "Euclidean Remainder", keywords = ["modulo", "modulus"])]
pub fn rem_euclid(
    span: Span,
    /// The dividend of the remainder.
    dividend: DecNum,
    /// The divisor of the remainder.
    divisor: Spanned<DecNum>,
) -> SourceResult<DecNum> {
    if divisor.v.is_zero() {
        bail!(divisor.span, "divisor must not be zero");
    }

    dividend
        .apply2(
            divisor.v,
            // `checked_rem_euclid` can only overflow on `i64::MIN % -1` which
            // is mathematically zero.
            |a, b| Some(DecNum::Int(a.checked_rem_euclid(b).unwrap_or(0))),
            |a, b| Some(DecNum::Float(a.rem_euclid(b))),
            |a, b| a.checked_rem_euclid(b).map(DecNum::Decimal),
        )
        .ok_or_else(cant_apply_to_decimal_and_float)
        .at(span)?
        .ok_or("dividend too small compared to divisor")
        .at(span)
}

/// Calculates the quotient (floored division) of two numbers.
///
/// Note that this function will always return an [integer]($int), and will
/// error if the resulting number is larger than the maximum 64-bit signed
/// integer or smaller than the minimum for that type.
///
/// ```example
/// $ "quo"(a, b) &= floor(a/b) \
///   "quo"(14, 5) &= #calc.quo(14, 5) \
///   "quo"(3.46, 0.5) &= #calc.quo(3.46, 0.5) $
/// ```
#[func(title = "Quotient")]
pub fn quo(
    span: Span,
    /// The dividend of the quotient.
    dividend: DecNum,
    /// The divisor of the quotient.
    divisor: Spanned<DecNum>,
) -> SourceResult<i64> {
    if divisor.v.is_zero() {