Skip to main content

conjure_cp_core/ast/
integer_arithmetic.rs

1/// Essence division rounds towards negative infinity.
2/// Returns `None` for zero divisors or a quotient outside the integer range.
3pub fn floor_div(dividend: i32, divisor: i32) -> Option<i32> {
4    let (quotient, _) = floor_div_mod(dividend, divisor)?;
5    i32::try_from(quotient).ok()
6}
7
8/// Essence modulo has the divisor's sign and is undefined for zero divisors.
9/// Widened arithmetic also handles `i32::MIN % -1`, whose remainder is zero.
10pub fn floor_mod(dividend: i32, divisor: i32) -> Option<i32> {
11    let (_, remainder) = floor_div_mod(dividend, divisor)?;
12    i32::try_from(remainder).ok()
13}
14
15fn floor_div_mod(dividend: i32, divisor: i32) -> Option<(i64, i64)> {
16    let (dividend, divisor) = (i64::from(dividend), i64::from(divisor));
17    let quotient = dividend.checked_div(divisor)?;
18    let remainder = dividend % divisor;
19    if remainder != 0 && (dividend < 0) != (divisor < 0) {
20        Some((quotient - 1, remainder + divisor))
21    } else {
22        Some((quotient, remainder))
23    }
24}