Quotient and remainder #
There are three main conventions for integer division,
referred here as the E, F, T rounding conventions.
All three pairs satisfy the identity x % y + (x / y) * y = x
unconditionally,
and satisfy x / 0 = 0
and x % 0 = x
.
T-rounding division #
div
uses the ["T-rounding"][t-rounding]
(Truncation-rounding) convention, meaning that it rounds toward
zero. Also note that division by zero is defined to equal zero.
The relation between integer division and modulo is found in
Int.mod_add_div
which states that
a % b + b * (a / b) = a
, unconditionally.
[t-rounding]: https://dl.acm.org/doi/pdf/10.1145/128861.128862 [theo mod_add_div]: https://leanprover-community.github.io/mathlib4_docs/find/?pattern=Int.mod_add_div#doc
Examples:
#eval (7 : Int) / (0 : Int) -- 0
#eval (0 : Int) / (7 : Int) -- 0
#eval (12 : Int) / (6 : Int) -- 2
#eval (12 : Int) / (-6 : Int) -- -2
#eval (-12 : Int) / (6 : Int) -- -2
#eval (-12 : Int) / (-6 : Int) -- 2
#eval (12 : Int) / (7 : Int) -- 1
#eval (12 : Int) / (-7 : Int) -- -1
#eval (-12 : Int) / (7 : Int) -- -1
#eval (-12 : Int) / (-7 : Int) -- 1
Implemented by efficient native code.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Integer modulo. This function uses the
"T-rounding" (Truncation-rounding) convention
to pair with Int.div
, meaning that a % b + b * (a / b) = a
unconditionally (see Int.mod_add_div
). In
particular, a % 0 = a
.
Examples:
#eval (7 : Int) % (0 : Int) -- 7
#eval (0 : Int) % (7 : Int) -- 0
#eval (12 : Int) % (6 : Int) -- 0
#eval (12 : Int) % (-6 : Int) -- 0
#eval (-12 : Int) % (6 : Int) -- 0
#eval (-12 : Int) % (-6 : Int) -- 0
#eval (12 : Int) % (7 : Int) -- 5
#eval (12 : Int) % (-7 : Int) -- 5
#eval (-12 : Int) % (7 : Int) -- 2
#eval (-12 : Int) % (-7 : Int) -- 2
Implemented by efficient native code.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Integer division. This version of division uses the F-rounding convention
(flooring division), in which Int.fdiv x y
satisfies fdiv x y = floor (x / y)
and Int.fmod
is the unique function satisfying fmod x y + (fdiv x y) * y = x
.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Integer modulus. This version of Int.mod
uses the F-rounding convention
(flooring division), in which Int.fdiv x y
satisfies fdiv x y = floor (x / y)
and Int.fmod
is the unique function satisfying fmod x y + (fdiv x y) * y = x
.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Integer division. This version of Int.div
uses the E-rounding convention
(euclidean division), in which Int.emod x y
satisfies 0 ≤ mod x y < natAbs y
for y ≠ 0
and Int.ediv
is the unique function satisfying emod x y + (ediv x y) * y = x
.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Integer modulus. This version of Int.mod
uses the E-rounding convention
(euclidean division), in which Int.emod x y
satisfies 0 ≤ emod x y < natAbs y
for y ≠ 0
and Int.ediv
is the unique function satisfying emod x y + (ediv x y) * y = x
.
Equations
- Int.emod x✝ x = match x✝, x with | Int.ofNat m, n => Int.ofNat (m % Int.natAbs n) | Int.negSucc m, n => Int.subNatNat (Int.natAbs n) (Nat.succ (m % Int.natAbs n))
Instances For
The Div and Mod syntax uses ediv and emod for compatibility with SMTLIb and mathematical reasoning tends to be easier.
Equations
- Int.instDivInt = { div := Int.ediv }
bmod
("balanced" mod) #
Balanced mod (and balanced div) are a division and modulus pair such
that b * (Int.bdiv a b) + Int.bmod a b = a
and b/2 ≤ Int.bmod a b < b/2
for all a : Int
and b > 0
.
This is used in Omega as well as signed bitvectors.