This doesn't completely resolve the danger (only relevant in `prelude` files) of importing `Init.Data.List.Basic` but not `Init.Data.List.Impl` and thereby not having `@[csimp]` lemmas installed for some list operations. I'm going to address this better while working on `Array`.
360 lines
9.6 KiB
Text
360 lines
9.6 KiB
Text
/-
|
||
Copyright (c) 2016 Jeremy Avigad. All rights reserved.
|
||
Released under Apache 2.0 license as described in the file LICENSE.
|
||
Authors: Jeremy Avigad, Leonardo de Moura
|
||
|
||
The integers, with addition, multiplication, and subtraction.
|
||
-/
|
||
prelude
|
||
import Init.Data.Cast
|
||
import Init.Data.Nat.Div
|
||
|
||
set_option linter.missingDocs true -- keep it documented
|
||
open Nat
|
||
|
||
/-! # Integer Type, Coercions, and Notation
|
||
|
||
This file defines the `Int` type as well as
|
||
|
||
* coercions, conversions, and compatibility with numeric literals,
|
||
* basic arithmetic operations add/sub/mul/div/mod/pow,
|
||
* a few `Nat`-related operations such as `negOfNat` and `subNatNat`,
|
||
* relations `<`/`≤`/`≥`/`>`, the `NonNeg` property and `min`/`max`,
|
||
* decidability of equality, relations and `NonNeg`.
|
||
-/
|
||
|
||
/--
|
||
The type of integers. It is defined as an inductive type based on the
|
||
natural number type `Nat` featuring two constructors: "a natural
|
||
number is an integer", and "the negation of a successor of a natural
|
||
number is an integer". The former represents integers between `0`
|
||
(inclusive) and `∞`, and the latter integers between `-∞` and `-1`
|
||
(inclusive).
|
||
|
||
This type is special-cased by the compiler. The runtime has a special
|
||
representation for `Int` which stores "small" signed numbers directly,
|
||
and larger numbers use an arbitrary precision "bignum" library
|
||
(usually [GMP](https://gmplib.org/)). A "small number" is an integer
|
||
that can be encoded with 63 bits (31 bits on 32-bits architectures).
|
||
-/
|
||
inductive Int : Type where
|
||
/-- A natural number is an integer (`0` to `∞`). -/
|
||
| ofNat : Nat → Int
|
||
/-- The negation of the successor of a natural number is an integer
|
||
(`-1` to `-∞`). -/
|
||
| negSucc : Nat → Int
|
||
|
||
attribute [extern "lean_nat_to_int"] Int.ofNat
|
||
attribute [extern "lean_int_neg_succ_of_nat"] Int.negSucc
|
||
|
||
instance : NatCast Int where natCast n := Int.ofNat n
|
||
|
||
instance instOfNat : OfNat Int n where
|
||
ofNat := Int.ofNat n
|
||
|
||
namespace Int
|
||
|
||
/--
|
||
`-[n+1]` is suggestive notation for `negSucc n`, which is the second constructor of
|
||
`Int` for making strictly negative numbers by mapping `n : Nat` to `-(n + 1)`.
|
||
-/
|
||
scoped notation "-[" n "+1]" => negSucc n
|
||
|
||
instance : Inhabited Int := ⟨ofNat 0⟩
|
||
|
||
@[simp] theorem default_eq_zero : default = (0 : Int) := rfl
|
||
|
||
protected theorem zero_ne_one : (0 : Int) ≠ 1 := nofun
|
||
|
||
/-! ## Coercions -/
|
||
|
||
@[simp] theorem ofNat_eq_coe : Int.ofNat n = Nat.cast n := rfl
|
||
|
||
@[simp] theorem ofNat_zero : ((0 : Nat) : Int) = 0 := rfl
|
||
|
||
@[simp] theorem ofNat_one : ((1 : Nat) : Int) = 1 := rfl
|
||
|
||
theorem ofNat_two : ((2 : Nat) : Int) = 2 := rfl
|
||
|
||
/-- Negation of a natural number. -/
|
||
def negOfNat : Nat → Int
|
||
| 0 => 0
|
||
| succ m => negSucc m
|
||
|
||
set_option bootstrap.genMatcherCode false in
|
||
/-- Negation of an integer.
|
||
|
||
Implemented by efficient native code. -/
|
||
@[extern "lean_int_neg"]
|
||
protected def neg (n : @& Int) : Int :=
|
||
match n with
|
||
| ofNat n => negOfNat n
|
||
| negSucc n => succ n
|
||
|
||
/-
|
||
The `Neg Int` default instance must have priority higher than `low`
|
||
since the default instance `OfNat Nat n` has `low` priority.
|
||
|
||
```
|
||
#check -42
|
||
```
|
||
-/
|
||
@[default_instance mid]
|
||
instance instNegInt : Neg Int where
|
||
neg := Int.neg
|
||
|
||
/-- Subtraction of two natural numbers. -/
|
||
def subNatNat (m n : Nat) : Int :=
|
||
match (n - m : Nat) with
|
||
| 0 => ofNat (m - n) -- m ≥ n
|
||
| (succ k) => negSucc k
|
||
|
||
set_option bootstrap.genMatcherCode false in
|
||
/-- Addition of two integers.
|
||
|
||
```
|
||
#eval (7 : Int) + (6 : Int) -- 13
|
||
#eval (6 : Int) + (-6 : Int) -- 0
|
||
```
|
||
|
||
Implemented by efficient native code. -/
|
||
@[extern "lean_int_add"]
|
||
protected def add (m n : @& Int) : Int :=
|
||
match m, n with
|
||
| ofNat m, ofNat n => ofNat (m + n)
|
||
| ofNat m, -[n +1] => subNatNat m (succ n)
|
||
| -[m +1], ofNat n => subNatNat n (succ m)
|
||
| -[m +1], -[n +1] => negSucc (succ (m + n))
|
||
|
||
instance : Add Int where
|
||
add := Int.add
|
||
|
||
set_option bootstrap.genMatcherCode false in
|
||
/-- Multiplication of two integers.
|
||
|
||
```
|
||
#eval (63 : Int) * (6 : Int) -- 378
|
||
#eval (6 : Int) * (-6 : Int) -- -36
|
||
#eval (7 : Int) * (0 : Int) -- 0
|
||
```
|
||
|
||
Implemented by efficient native code. -/
|
||
@[extern "lean_int_mul"]
|
||
protected def mul (m n : @& Int) : Int :=
|
||
match m, n with
|
||
| ofNat m, ofNat n => ofNat (m * n)
|
||
| ofNat m, -[n +1] => negOfNat (m * succ n)
|
||
| -[m +1], ofNat n => negOfNat (succ m * n)
|
||
| -[m +1], -[n +1] => ofNat (succ m * succ n)
|
||
|
||
instance : Mul Int where
|
||
mul := Int.mul
|
||
|
||
/-- Subtraction of two integers.
|
||
|
||
```
|
||
#eval (63 : Int) - (6 : Int) -- 57
|
||
#eval (7 : Int) - (0 : Int) -- 7
|
||
#eval (0 : Int) - (7 : Int) -- -7
|
||
```
|
||
|
||
Implemented by efficient native code. -/
|
||
@[extern "lean_int_sub"]
|
||
protected def sub (m n : @& Int) : Int := m + (- n)
|
||
|
||
instance : Sub Int where
|
||
sub := Int.sub
|
||
|
||
/-- A proof that an `Int` is non-negative. -/
|
||
inductive NonNeg : Int → Prop where
|
||
/-- Sole constructor, proving that `ofNat n` is positive. -/
|
||
| mk (n : Nat) : NonNeg (ofNat n)
|
||
|
||
/-- Definition of `a ≤ b`, encoded as `b - a ≥ 0`. -/
|
||
protected def le (a b : Int) : Prop := NonNeg (b - a)
|
||
|
||
instance instLEInt : LE Int where
|
||
le := Int.le
|
||
|
||
/-- Definition of `a < b`, encoded as `a + 1 ≤ b`. -/
|
||
protected def lt (a b : Int) : Prop := (a + 1) ≤ b
|
||
|
||
instance instLTInt : LT Int where
|
||
lt := Int.lt
|
||
|
||
set_option bootstrap.genMatcherCode false in
|
||
/-- Decides equality between two `Int`s.
|
||
|
||
```
|
||
#eval (7 : Int) = (3 : Int) + (4 : Int) -- true
|
||
#eval (6 : Int) = (3 : Int) * (2 : Int) -- true
|
||
#eval ¬ (6 : Int) = (3 : Int) -- true
|
||
```
|
||
|
||
Implemented by efficient native code. -/
|
||
@[extern "lean_int_dec_eq"]
|
||
protected def decEq (a b : @& Int) : Decidable (a = b) :=
|
||
match a, b with
|
||
| ofNat a, ofNat b => match decEq a b with
|
||
| isTrue h => isTrue <| h ▸ rfl
|
||
| isFalse h => isFalse <| fun h' => Int.noConfusion h' (fun h' => absurd h' h)
|
||
| ofNat _, -[_ +1] => isFalse <| fun h => Int.noConfusion h
|
||
| -[_ +1], ofNat _ => isFalse <| fun h => Int.noConfusion h
|
||
| -[a +1], -[b +1] => match decEq a b with
|
||
| isTrue h => isTrue <| h ▸ rfl
|
||
| isFalse h => isFalse <| fun h' => Int.noConfusion h' (fun h' => absurd h' h)
|
||
|
||
instance : DecidableEq Int := Int.decEq
|
||
|
||
set_option bootstrap.genMatcherCode false in
|
||
/-- Decides whether an integer is negative.
|
||
|
||
```
|
||
#eval (7 : Int).decNonneg.decide -- true
|
||
#eval (0 : Int).decNonneg.decide -- true
|
||
#eval ¬ (-7 : Int).decNonneg.decide -- true
|
||
```
|
||
|
||
Implemented by efficient native code. -/
|
||
@[extern "lean_int_dec_nonneg"]
|
||
private def decNonneg (m : @& Int) : Decidable (NonNeg m) :=
|
||
match m with
|
||
| ofNat m => isTrue <| NonNeg.mk m
|
||
| -[_ +1] => isFalse <| fun h => nomatch h
|
||
|
||
/-- Decides whether `a ≤ b`.
|
||
|
||
```
|
||
#eval ¬ ( (7 : Int) ≤ (0 : Int) ) -- true
|
||
#eval (0 : Int) ≤ (0 : Int) -- true
|
||
#eval (7 : Int) ≤ (10 : Int) -- true
|
||
```
|
||
|
||
Implemented by efficient native code. -/
|
||
@[extern "lean_int_dec_le"]
|
||
instance decLe (a b : @& Int) : Decidable (a ≤ b) :=
|
||
decNonneg _
|
||
|
||
/-- Decides whether `a < b`.
|
||
|
||
```
|
||
#eval `¬ ( (7 : Int) < 0 )` -- true
|
||
#eval `¬ ( (0 : Int) < 0 )` -- true
|
||
#eval `(7 : Int) < 10` -- true
|
||
```
|
||
|
||
Implemented by efficient native code. -/
|
||
@[extern "lean_int_dec_lt"]
|
||
instance decLt (a b : @& Int) : Decidable (a < b) :=
|
||
decNonneg _
|
||
|
||
set_option bootstrap.genMatcherCode false in
|
||
/-- Absolute value (`Nat`) of an integer.
|
||
|
||
```
|
||
#eval (7 : Int).natAbs -- 7
|
||
#eval (0 : Int).natAbs -- 0
|
||
#eval (-11 : Int).natAbs -- 11
|
||
```
|
||
|
||
Implemented by efficient native code. -/
|
||
@[extern "lean_nat_abs"]
|
||
def natAbs (m : @& Int) : Nat :=
|
||
match m with
|
||
| ofNat m => m
|
||
| -[m +1] => m.succ
|
||
|
||
/-! ## sign -/
|
||
|
||
/--
|
||
Returns the "sign" of the integer as another integer: `1` for positive numbers,
|
||
`-1` for negative numbers, and `0` for `0`.
|
||
-/
|
||
def sign : Int → Int
|
||
| Int.ofNat (succ _) => 1
|
||
| Int.ofNat 0 => 0
|
||
| -[_+1] => -1
|
||
|
||
/-! ## Conversion -/
|
||
|
||
/-- Turns an integer into a natural number, negative numbers become
|
||
`0`.
|
||
|
||
```
|
||
#eval (7 : Int).toNat -- 7
|
||
#eval (0 : Int).toNat -- 0
|
||
#eval (-7 : Int).toNat -- 0
|
||
```
|
||
-/
|
||
def toNat : Int → Nat
|
||
| ofNat n => n
|
||
| negSucc _ => 0
|
||
|
||
/--
|
||
* If `n : Nat`, then `int.toNat' n = some n`
|
||
* If `n : Int` is negative, then `int.toNat' n = none`.
|
||
-/
|
||
def toNat' : Int → Option Nat
|
||
| (n : Nat) => some n
|
||
| -[_+1] => none
|
||
|
||
/-! ## divisibility -/
|
||
|
||
/--
|
||
Divisibility of integers. `a ∣ b` (typed as `\|`) says that
|
||
there is some `c` such that `b = a * c`.
|
||
-/
|
||
instance : Dvd Int where
|
||
dvd a b := Exists (fun c => b = a * c)
|
||
|
||
/-! ## Powers -/
|
||
|
||
/-- Power of an integer to some natural number.
|
||
|
||
```
|
||
#eval (2 : Int) ^ 4 -- 16
|
||
#eval (10 : Int) ^ 0 -- 1
|
||
#eval (0 : Int) ^ 10 -- 0
|
||
#eval (-7 : Int) ^ 3 -- -343
|
||
```
|
||
-/
|
||
protected def pow (m : Int) : Nat → Int
|
||
| 0 => 1
|
||
| succ n => Int.pow m n * m
|
||
|
||
instance : NatPow Int where
|
||
pow := Int.pow
|
||
|
||
instance : LawfulBEq Int where
|
||
eq_of_beq h := by simp [BEq.beq] at h; assumption
|
||
rfl := by simp [BEq.beq]
|
||
|
||
instance : Min Int := minOfLe
|
||
|
||
instance : Max Int := maxOfLe
|
||
|
||
end Int
|
||
|
||
/--
|
||
The canonical homomorphism `Int → R`.
|
||
In most use cases `R` will have a ring structure and this will be a ring homomorphism.
|
||
-/
|
||
class IntCast (R : Type u) where
|
||
/-- The canonical map `Int → R`. -/
|
||
protected intCast : Int → R
|
||
|
||
instance : IntCast Int where intCast n := n
|
||
|
||
/--
|
||
Apply the canonical homomorphism from `Int` to a type `R` from an `IntCast R` instance.
|
||
|
||
In Mathlib there will be such a homomorphism whenever `R` is an additive group with a `1`.
|
||
-/
|
||
@[coe, reducible, match_pattern] protected def Int.cast {R : Type u} [IntCast R] : Int → R :=
|
||
IntCast.intCast
|
||
|
||
-- see the notes about coercions into arbitrary types in the module doc-string
|
||
instance [IntCast R] : CoeTail Int R where coe := Int.cast
|
||
|
||
-- see the notes about coercions into arbitrary types in the module doc-string
|
||
instance [IntCast R] : CoeHTCT Int R where coe := Int.cast
|