12.2.4.3. Arithmetic
Typically, arithmetic operations on integers are accessed using Lean's overloaded arithmetic notation.
In particular, the instances of Add Int
, Neg Int
, Sub Int
, and Mul Int
allow ordinary infix operators to be used.
Division is somewhat more intricate, because there are multiple sensible notions of division on integers.
🔗defInt.add (m n : Int) : Int
Addition of two integers.
13
#eval (7 : Int) + (6 : Int) -- 13
0
#eval (6 : Int) + (-6 : Int) -- 0
Implemented by efficient native code.
🔗defInt.sub (m n : Int) : Int
Subtraction of two integers.
57
#eval (63 : Int) - (6 : Int) -- 57
7
#eval (7 : Int) - (0 : Int) -- 7
-7
#eval (0 : Int) - (7 : Int) -- -7
Implemented by efficient native code.
🔗defInt.subNatNat (m n : Nat) : Int
Subtraction of two natural numbers.
🔗defInt.neg (n : Int) : Int
Negation of an integer.
Implemented by efficient native code.
🔗defInt.negOfNat : Nat → Int
Negation of a natural number.
🔗defInt.mul (m n : Int) : Int
Multiplication of two integers.
378
#eval (63 : Int) * (6 : Int) -- 378
-36
#eval (6 : Int) * (-6 : Int) -- -36
0
#eval (7 : Int) * (0 : Int) -- 0
Implemented by efficient native code.
🔗defInt.pow (m : Int) : Nat → Int
Power of an integer to some natural number.
16
#eval (2 : Int) ^ 4 -- 16
1
#eval (10 : Int) ^ 0 -- 1
0
#eval (0 : Int) ^ 10 -- 0
-343
#eval (-7 : Int) ^ 3 -- -343
🔗defInt.gcd (m n : Int) : Nat
Computes the greatest common divisor of two integers, as a Nat
.
🔗defInt.lcm (m n : Int) : Nat
Computes the least common multiple of two integers, as a Nat
.
12.2.4.3.1. Division🔗
The Div Int
and Mod Int
instances implement Euclidean division, described in the reference for Int.ediv
.
This is not, however, the only sensible convention for rounding and remainders in division.
Four pairs of division and modulus functions are available, implementing various conventions.
Division by 0
In all integer division conventions, division by 0
is defined to be 0
:
0
#eval Int.ediv 5 0
0
#eval Int.ediv 0 0
0
#eval Int.ediv (-5) 0
0
#eval Int.bdiv 5 0
0
#eval Int.bdiv 0 0
0
#eval Int.bdiv (-5) 0
0
#eval Int.fdiv 5 0
0
#eval Int.fdiv 0 0
0
#eval Int.fdiv (-5) 0
0
#eval Int.tdiv 5 0
0
#eval Int.tdiv 0 0
0
#eval Int.tdiv (-5) 0
All evaluate to 0.
🔗defInt.ediv : Int → Int → Int
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
.
This is the function powering the /
notation on integers.
Examples:
0
#eval (7 : Int) / (0 : Int) -- 0
0
#eval (0 : Int) / (7 : Int) -- 0
2
#eval (12 : Int) / (6 : Int) -- 2
-2
#eval (12 : Int) / (-6 : Int) -- -2
-2
#eval (-12 : Int) / (6 : Int) -- -2
2
#eval (-12 : Int) / (-6 : Int) -- 2
1
#eval (12 : Int) / (7 : Int) -- 1
-1
#eval (12 : Int) / (-7 : Int) -- -1
-2
#eval (-12 : Int) / (7 : Int) -- -2
2
#eval (-12 : Int) / (-7 : Int) -- 2
Implemented by efficient native code.
🔗defInt.emod : Int → Int → Int
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
.
This is the function powering the %
notation on integers.
Examples:
7
#eval (7 : Int) % (0 : Int) -- 7
0
#eval (0 : Int) % (7 : Int) -- 0
0
#eval (12 : Int) % (6 : Int) -- 0
0
#eval (12 : Int) % (-6 : Int) -- 0
0
#eval (-12 : Int) % (6 : Int) -- 0
0
#eval (-12 : Int) % (-6 : Int) -- 0
5
#eval (12 : Int) % (7 : Int) -- 5
5
#eval (12 : Int) % (-7 : Int) -- 5
2
#eval (-12 : Int) % (7 : Int) -- 2
2
#eval (-12 : Int) % (-7 : Int) -- 2
Implemented by efficient native code.
🔗defInt.bdiv (x : Int) (m : Nat) : Int
Balanced division. This returns the unique integer so that
b * (Int.bdiv a b) + Int.bmod a b = a
.
🔗defInt.bmod (x : Int) (m : Nat) : Int
Balanced modulus. This version of Integer modulus uses the
balanced rounding convention, which guarantees that
m/2 ≤ bmod x m < m/2
for m ≠ 0
and bmod x m
is congruent
to x
modulo m
.
If m = 0
, then bmod x m = x
.
🔗defInt.fdiv : Int → Int → Int
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
.
Examples:
0
#eval (7 : Int).fdiv (0 : Int) -- 0
0
#eval (0 : Int).fdiv (7 : Int) -- 0
2
#eval (12 : Int).fdiv (6 : Int) -- 2
-2
#eval (12 : Int).fdiv (-6 : Int) -- -2
-2
#eval (-12 : Int).fdiv (6 : Int) -- -2
2
#eval (-12 : Int).fdiv (-6 : Int) -- 2
1
#eval (12 : Int).fdiv (7 : Int) -- 1
-2
#eval (12 : Int).fdiv (-7 : Int) -- -2
-2
#eval (-12 : Int).fdiv (7 : Int) -- -2
1
#eval (-12 : Int).fdiv (-7 : Int) -- 1
🔗defInt.fmod : Int → Int → Int
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
.
Examples:
7
#eval (7 : Int).fmod (0 : Int) -- 7
0
#eval (0 : Int).fmod (7 : Int) -- 0
0
#eval (12 : Int).fmod (6 : Int) -- 0
0
#eval (12 : Int).fmod (-6 : Int) -- 0
0
#eval (-12 : Int).fmod (6 : Int) -- 0
0
#eval (-12 : Int).fmod (-6 : Int) -- 0
5
#eval (12 : Int).fmod (7 : Int) -- 5
-2
#eval (12 : Int).fmod (-7 : Int) -- -2
2
#eval (-12 : Int).fmod (7 : Int) -- 2
-5
#eval (-12 : Int).fmod (-7 : Int) -- -5
🔗defInt.tdiv : Int → Int → Int
tdiv
uses the "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.tmod_add_tdiv
which states that
tmod a b + b * (tdiv a b) = a
, unconditionally.
Examples:
0
#eval (7 : Int).tdiv (0 : Int) -- 0
0
#eval (0 : Int).tdiv (7 : Int) -- 0
2
#eval (12 : Int).tdiv (6 : Int) -- 2
-2
#eval (12 : Int).tdiv (-6 : Int) -- -2
-2
#eval (-12 : Int).tdiv (6 : Int) -- -2
2
#eval (-12 : Int).tdiv (-6 : Int) -- 2
1
#eval (12 : Int).tdiv (7 : Int) -- 1
-1
#eval (12 : Int).tdiv (-7 : Int) -- -1
-1
#eval (-12 : Int).tdiv (7 : Int) -- -1
1
#eval (-12 : Int).tdiv (-7 : Int) -- 1
Implemented by efficient native code.
12.2.4.6. Proof Automation
The functions in this section are primarily parts of the implementation of simplification rules employed by simp
.
They are probably only of interest to users who are implementing custom proof automation that involves integers.
🔗defInt.fromExpr? (e : Lean.Expr)
: Lean.Meta.SimpM (Option Int)
🔗defInt.isPosValue : Lean.Meta.Simp.DSimproc
Return .done
for positive Int values. We don't want to unfold in the symbolic evaluator.
🔗defInt.reduceAbs : Lean.Meta.Simp.DSimproc
🔗defInt.reduceAdd : Lean.Meta.Simp.DSimproc
🔗defInt.reduceBEq : Lean.Meta.Simp.DSimproc
🔗defInt.reduceBNe : Lean.Meta.Simp.DSimproc
🔗defInt.reduceBdiv : Lean.Meta.Simp.DSimproc
🔗defInt.reduceBin (declName : Lean.Name)
(arity : Nat) (op : Int → Int → Int)
(e : Lean.Expr)
: Lean.Meta.SimpM Lean.Meta.Simp.DStep
🔗defInt.reduceBinIntNatOp (name : Lean.Name)
(op : Int → Nat → Int) (e : Lean.Expr)
: Lean.Meta.SimpM Lean.Meta.Simp.DStep
🔗defInt.reduceBinPred (declName : Lean.Name)
(arity : Nat) (op : Int → Int → Bool)
(e : Lean.Expr)
: Lean.Meta.SimpM Lean.Meta.Simp.Step
🔗defInt.reduceBmod : Lean.Meta.Simp.DSimproc
🔗defInt.reduceBoolPred (declName : Lean.Name)
(arity : Nat) (op : Int → Int → Bool)
(e : Lean.Expr)
: Lean.Meta.SimpM Lean.Meta.Simp.DStep
🔗defInt.reduceDiv : Lean.Meta.Simp.DSimproc
🔗defInt.reduceEq : Lean.Meta.Simp.Simproc
🔗defInt.reduceFDiv : Lean.Meta.Simp.DSimproc
🔗defInt.reduceFMod : Lean.Meta.Simp.DSimproc
🔗defInt.reduceGE : Lean.Meta.Simp.Simproc
🔗defInt.reduceGT : Lean.Meta.Simp.Simproc
🔗defInt.reduceLE : Lean.Meta.Simp.Simproc
🔗defInt.reduceLT : Lean.Meta.Simp.Simproc
🔗defInt.reduceMod : Lean.Meta.Simp.DSimproc
🔗defInt.reduceMul : Lean.Meta.Simp.DSimproc
🔗defInt.reduceNatCore (declName : Lean.Name)
(op : Int → Nat) (e : Lean.Expr)
: Lean.Meta.SimpM Lean.Meta.Simp.DStep
🔗defInt.reduceNe : Lean.Meta.Simp.Simproc
🔗defInt.reduceNeg : Lean.Meta.Simp.DSimproc
🔗defInt.reduceNegSucc : Lean.Meta.Simp.DSimproc
🔗defInt.reduceOfNat : Lean.Meta.Simp.DSimproc
🔗defInt.reducePow : Lean.Meta.Simp.DSimproc
🔗defInt.reduceSub : Lean.Meta.Simp.DSimproc
🔗defInt.reduceTDiv : Lean.Meta.Simp.DSimproc
🔗defInt.reduceTMod : Lean.Meta.Simp.DSimproc
🔗defInt.reduceToNat : Lean.Meta.Simp.DSimproc
🔗defInt.reduceUnary (declName : Lean.Name)
(arity : Nat) (op : Int → Int)
(e : Lean.Expr)
: Lean.Meta.SimpM Lean.Meta.Simp.DStep