| /- | |
| 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 |