///|
/// Floor division: rounds toward negative infinity, unlike `Int`'s built-in
/// `/` which truncates toward zero.
fn floor_div(a : Int, b : Int) -> Int {
let q = a / b
if a % b != 0 && (a < 0) != (b < 0) {
q - 1
} else {
q
}
}
///|
/// Floor modulo: the result always has the same sign as `b` (or is zero),
/// unlike `Int`'s built-in `%` which has the same sign as `a`.
fn floor_mod(a : Int, b : Int) -> Int {
a - floor_div(a, b) * b
}
///|
/// Floor division for `Int64`: rounds toward negative infinity, unlike
/// `Int64`'s built-in `/` which truncates toward zero.
fn floor_div64(a : Int64, b : Int64) -> Int64 {
let q = a / b
if a % b != 0L && (a < 0L) != (b < 0L) {
q - 1L
} else {
q
}
}
///|
/// Floor modulo for `Int64`: the result always has the same sign as `b` (or
/// is zero), unlike `Int64`'s built-in `%` which has the same sign as `a`.
fn floor_mod64(a : Int64, b : Int64) -> Int64 {
a - floor_div64(a, b) * b
}
///|
/// Adds two `Int64` values, or `None` if the mathematical result does not
/// fit in `Int64`.
fn checked_add64(a : Int64, b : Int64) -> Int64? {
let sum = a + b
if (b > 0L && sum < a) || (b < 0L && sum > a) {
None
} else {
Some(sum)
}
}
///|
/// Multiplies two `Int64` values, or `None` if the mathematical result does
/// not fit in `Int64`.
fn checked_mul64(a : Int64, b : Int64) -> Int64? {
if a == 0L || b == 0L {
Some(0L)
} else {
let product = a * b
if product / b != a {
None
} else {
Some(product)
}
}
}
///|
fn[T] expect_in_range(value : T?, operation : String) -> T {
match value {
Some(v) => v
None => abort(operation + ": result is outside the representable range")
}
}