12.2.4.3. 算術(Arithmetic)
通常、整数に対する算術操作は Lean のオーバーロードされた算術記法を用いてアクセスします。特に、 Add Int ・ Neg Int ・ Sub Int ・ and Mul Int インスタンスによって通常の中置演算子を使うことができます。 除算 は、整数の除算に複数の意味があるため、やや複雑です。
🔗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)🔗
Div Int と Mod Int のインスタンスは Int.ediv のリファレンスで説明されているユークリッド除算を実装しています。しかし、これは除算における丸めや余りのための唯一の賢明な慣習ではありません。除算と剰余の関数の4つのペアが利用可能であり、さまざまな慣習を実装しています。
ゼロ除算
すべての整数の除算の慣習において、 0 による除算は 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
すべて 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)
本節の関数は主に simp で採用される単純化規則の実装の一部です。これらはおそらく、整数を含むカスタムの証明自動化を実装しているユーザにとっては興味深いものになるでしょう。
🔗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