doc: review of Nat docstrings (#7552)

This PR adds missing `Nat` docstrings and makes their style consistent.

---------

Co-authored-by: Bhavik Mehta <bm489@cam.ac.uk>
This commit is contained in:
David Thrane Christiansen 2025-03-20 10:13:36 +01:00 committed by GitHub
parent 1fb4a32c8d
commit cbfb9e482f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
18 changed files with 696 additions and 136 deletions

View file

@ -23,35 +23,69 @@ private theorem rec_eq_recCompiled : @Nat.rec = @Nat.recCompiled :=
funext fun _ => funext fun _ => funext fun succ => funext fun t =>
Nat.recOn t rfl (fun n ih => congrArg (succ n) ih)
/-- Recursor identical to `Nat.rec` but uses notations `0` for `Nat.zero` and `· + 1` for `Nat.succ`.
Used as the default `Nat` eliminator by the `induction` tactic. -/
/--
A recursor for `Nat` that uses the notations `0` for `Nat.zero` and `n + 1` for `Nat.succ`.
It is otherwise identical to the default recursor `Nat.rec`. It is used by the `induction` tactic
by default for `Nat`.
-/
@[elab_as_elim, induction_eliminator]
protected abbrev recAux {motive : Nat → Sort u} (zero : motive 0) (succ : (n : Nat) → motive n → motive (n + 1)) (t : Nat) : motive t :=
Nat.rec zero succ t
/-- Recursor identical to `Nat.casesOn` but uses notations `0` for `Nat.zero` and `· + 1` for `Nat.succ`.
Used as the default `Nat` eliminator by the `cases` tactic. -/
/--
A case analysis principle for `Nat` that uses the notations `0` for `Nat.zero` and `n + 1` for
`Nat.succ`.
It is otherwise identical to the default recursor `Nat.casesOn`. It is used as the default `Nat`
case analysis principle for `Nat` by the `cases` tactic.
-/
@[elab_as_elim, cases_eliminator]
protected abbrev casesAuxOn {motive : Nat → Sort u} (t : Nat) (zero : motive 0) (succ : (n : Nat) → motive (n + 1)) : motive t :=
Nat.casesOn t zero succ
/--
`Nat.repeat f n a` is `f^(n) a`; that is, it iterates `f` `n` times on `a`.
Applies a function to a starting value the specified number of times.
In other words, `f` is iterated `n` times on `a`.
Examples:
* `Nat.repeat f 3 a = f <| f <| f <| a`
* `Nat.repeat (· ++ "!") 4 "Hello" = "Hello!!!!"`
-/
@[specialize] def repeat {α : Type u} (f : αα) : (n : Nat) → (a : α) → α
| 0, a => a
| succ n, a => f (repeat f n a)
/-- Tail-recursive version of `Nat.repeat`. -/
/--
Applies a function to a starting value the specified number of times.
In other words, `f` is iterated `n` times on `a`.
This is a tail-recursive version of `Nat.repeat` that's used at runtime.
Examples:
* `Nat.repeatTR f 3 a = f <| f <| f <| a`
* `Nat.repeatTR (· ++ "!") 4 "Hello" = "Hello!!!!"`
-/
@[inline] def repeatTR {α : Type u} (f : αα) (n : Nat) (a : α) : α :=
let rec @[specialize] loop
| 0, a => a
| succ n, a => loop n (f a)
loop n a
/-- Boolean less-than of natural numbers. -/
/--
The Boolean less-than comparison on natural numbers.
This function is overridden in both the kernel and the compiler to efficiently evaluate using the
arbitrary-precision arithmetic library. The definition provided here is the logical model.
Examples:
* `Nat.blt 2 5 = true`
* `Nat.blt 5 2 = false`
* `Nat.blt 5 5 = false`
-/
def blt (a b : Nat) : Bool :=
ble a.succ b
@ -785,9 +819,15 @@ instance {n m : Nat} [NeZero n] : NeZero (n^m) :=
/-! # min/max -/
/--
`Nat.min a b` is the minimum of `a` and `b`:
* if `a ≤ b` then `Nat.min a b = a`
* if `b ≤ a` then `Nat.min a b = b`
Returns the lesser of two natural numbers. Usually accessed via `Min.min`.
Returns `n` if `n ≤ m`, or `m` if `m ≤ n`.
Examples:
* `min 0 5 = 0`
* `min 4 5 = 4`
* `min 4 3 = 3`
* `min 8 8 = 8`
-/
protected abbrev min (n m : Nat) := min n m
@ -796,9 +836,15 @@ protected theorem min_def {n m : Nat} : min n m = if n ≤ m then n else m := rf
instance : Max Nat := maxOfLe
/--
`Nat.max a b` is the maximum of `a` and `b`:
* if `a ≤ b` then `Nat.max a b = b`
* if `b ≤ a` then `Nat.max a b = a`
Returns the greater of two natural numbers. Usually accessed via `Max.max`.
Returns `m` if `n ≤ m`, or `n` if `m ≤ n`.
Examples:
* `max 0 5 = 5`
* `max 4 5 = 5`
* `max 4 3 = 4`
* `max 8 8 = 8`
-/
protected abbrev max (n m : Nat) := max n m

View file

@ -13,6 +13,12 @@ namespace Nat
theorem bitwise_rec_lemma {n : Nat} (hNe : n ≠ 0) : n / 2 < n :=
Nat.div_lt_self (Nat.zero_lt_of_ne_zero hNe) (Nat.lt_succ_self _)
/--
A helper for implementing bitwise operators on `Nat`.
Each bit of the resulting `Nat` is the result of applying `f` to the corresponding bits of the input
`Nat`s, up to the position of the highest set bit in either input.
-/
def bitwise (f : Bool → Bool → Bool) (n m : Nat) : Nat :=
if n = 0 then
if f false true then m else 0
@ -30,16 +36,56 @@ def bitwise (f : Bool → Bool → Bool) (n m : Nat) : Nat :=
r+r
decreasing_by apply bitwise_rec_lemma; assumption
/--
Bitwise and. Usually accessed via the `&&&` operator.
Each bit of the resulting value is set if the corresponding bit is set in both of the inputs.
-/
@[extern "lean_nat_land"]
def land : @& Nat → @& Nat → Nat := bitwise and
/--
Bitwise or. Usually accessed via the `|||` operator.
Each bit of the resulting value is set if the corresponding bit is set in at least one of the inputs.
-/
@[extern "lean_nat_lor"]
def lor : @& Nat → @& Nat → Nat := bitwise or
/--
Bitwise exclusive or. Usually accessed via the `^^^` operator.
Each bit of the resulting value is set if the corresponding bit is set in exactly one of the inputs.
-/
@[extern "lean_nat_lxor"]
def xor : @& Nat → @& Nat → Nat := bitwise bne
/--
Shifts the binary representation of a value left by the specified number of bits. Usually accessed
via the `<<<` operator.
Examples:
* `1 <<< 2 = 4`
* `1 <<< 3 = 8`
* `0 <<< 3 = 0`
* `0xf1 <<< 4 = 0xf10`
-/
@[extern "lean_nat_shiftl"]
def shiftLeft : @& Nat → @& Nat → Nat
| n, 0 => n
| n, succ m => shiftLeft (2*n) m
/--
Shifts the binary representation of a value right by the specified number of bits. Usually accessed
via the `>>>` operator.
Examples:
* `4 >>> 2 = 1`
* `8 >>> 2 = 2`
* `8 >>> 3 = 1`
* `0 >>> 3 = 0`
* `0xf13a >>> 8 = 0xf1`
-/
@[extern "lean_nat_shiftr"]
def shiftRight : @& Nat → @& Nat → Nat
| n, 0 => n
@ -84,7 +130,9 @@ We define an operation for testing individual bits in the binary representation
of a number.
-/
/-- `testBit m n` returns whether the `(n+1)` least significant bit is `1` or `0`-/
/--
Returns `true` if the `(n+1)`th least significant bit is `1`, or `false` if it is `0`.
-/
def testBit (m n : Nat) : Bool :=
-- `1 &&& n` is faster than `n &&& 1` for big `n`.
1 &&& (m >>> n) != 0

View file

@ -36,7 +36,10 @@ private theorem two_mul_sub_one {n : Nat} (n_pos : n > 0) : (2*n - 1) % 2 = 1 :=
/-! ### Preliminaries -/
/--
An induction principal that works on division by two.
An induction principle for the natural numbers with two cases:
* `n = 0`, and the motive is satisfied for `0`
* `n > 0`, and the motive should be satisfied for `n` on the assumption that it is satisfied for
`n / 2`.
-/
noncomputable def div2Induction {motive : Nat → Sort u}
(n : Nat) (ind : ∀(n : Nat), (n > 0 → motive (n/2)) → motive n) : motive n := by

View file

@ -8,33 +8,79 @@ import Init.Control.Basic
import Init.Data.Nat.Basic
import Init.Omega
set_option linter.missingDocs true
namespace Nat
universe u v
/--
Executes a monadic action on all the numbers less than some bound, in increasing order.
Example:
````lean example
#eval Nat.forM 5 fun i _ => IO.println i
````
````output
0
1
2
3
4
````
-/
@[inline] def forM {m} [Monad m] (n : Nat) (f : (i : Nat) → i < n → m Unit) : m Unit :=
let rec @[specialize] loop : ∀ i, i ≤ n → m Unit
| 0, _ => pure ()
| i+1, h => do f (n-i-1) (by omega); loop i (Nat.le_of_succ_le h)
loop n (by simp)
/--
Executes a monadic action on all the numbers less than some bound, in decreasing order.
Example:
````lean example
#eval Nat.forRevM 5 fun i _ => IO.println i
````
````output
4
3
2
1
0
````
-/
@[inline] def forRevM {m} [Monad m] (n : Nat) (f : (i : Nat) → i < n → m Unit) : m Unit :=
let rec @[specialize] loop : ∀ i, i ≤ n → m Unit
| 0, _ => pure ()
| i+1, h => do f i (by omega); loop i (Nat.le_of_succ_le h)
loop n (by simp)
/--
Iterates the application of a monadic function `f` to a starting value `init`, `n` times. At each
step, `f` is applied to the current value and to the next natural number less than `n`, in
increasing order.
-/
@[inline] def foldM {α : Type u} {m : Type u → Type v} [Monad m] (n : Nat) (f : (i : Nat) → i < n → α → m α) (init : α) : m α :=
let rec @[specialize] loop : ∀ i, i ≤ n → α → m α
| 0, h, a => pure a
| i+1, h, a => f (n-i-1) (by omega) a >>= loop i (Nat.le_of_succ_le h)
loop n (by omega) init
/--
Iterates the application of a monadic function `f` to a starting value `init`, `n` times. At each
step, `f` is applied to the current value and to the next natural number less than `n`, in
decreasing order.
-/
@[inline] def foldRevM {α : Type u} {m : Type u → Type v} [Monad m] (n : Nat) (f : (i : Nat) → i < n → α → m α) (init : α) : m α :=
let rec @[specialize] loop : ∀ i, i ≤ n → α → m α
| 0, h, a => pure a
| i+1, h, a => f i (by omega) a >>= loop i (Nat.le_of_succ_le h)
loop n (by omega) init
/--
Checks whether the monadic predicate `p` returns `true` for all numbers less that the given bound.
Numbers are checked in increasing order until `p` returns false, after which no further are checked.
-/
@[inline] def allM {m} [Monad m] (n : Nat) (p : (i : Nat) → i < n → m Bool) : m Bool :=
let rec @[specialize] loop : ∀ i, i ≤ n → m Bool
| 0, _ => pure true
@ -44,6 +90,11 @@ universe u v
| false => pure false
loop n (by simp)
/--
Checks whether there is some number less that the given bound for which the monadic predicate `p`
returns `true`. Numbers are checked in increasing order until `p` returns true, after which
no further are checked.
-/
@[inline] def anyM {m} [Monad m] (n : Nat) (p : (i : Nat) → i < n → m Bool) : m Bool :=
let rec @[specialize] loop : ∀ i, i ≤ n → m Bool
| 0, _ => pure false

View file

@ -24,6 +24,21 @@ theorem div_rec_fuel_lemma {x y fuel : Nat} (hy : 0 < y) (hle : y ≤ x) (hfuel
x - y < fuel :=
Nat.lt_of_lt_of_le (div_rec_lemma ⟨hy, hle⟩) (Nat.le_of_lt_succ hfuel)
/--
Division of natural numbers, discarding the remainder. Division by `0` returns `0`. Usually accessed
via the `/` operator.
This operation is sometimes called “floor division.”
This function is overridden at runtime with an efficient implementation. This definition is
the logical model.
Examples:
* `21 / 3 = 7`
* `21 / 5 = 4`
* `0 / 22 = 0`
* `5 / 0 = 0`
-/
@[extern "lean_nat_div"]
protected def div (x y : @& Nat) : Nat :=
if hy : 0 < y then
@ -71,6 +86,10 @@ theorem div_eq (x y : Nat) : x / y = if 0 < y ∧ y ≤ x then (x - y) / y + 1 e
next =>
simp only [false_and, ↓reduceIte, *]
/--
An induction principle customized for reasoning about the recursion pattern of natural number
division by iterated subtraction.
-/
def div.inductionOn.{u}
{motive : Nat → Nat → Sort u}
(x y : Nat)
@ -108,6 +127,20 @@ theorem div_lt_self {n k : Nat} (hLtN : 0 < n) (hLtK : 1 < k) : n / k < n := by
have := Nat.add_le_of_le_sub hKN this
exact Nat.lt_of_lt_of_le (Nat.add_lt_add_left hLtK _) this
/--
The modulo operator, which computes the remainder when dividing one natural number by another.
Usually accessed via the `%` operator. When the divisor is `0`, the result is the dividend rather
than an error.
This is the core implementation of `Nat.mod`. It computes the correct result for any two closed
natural numbers, but it does not have some convenient [definitional
reductions](lean-manual://section/type-system) when the `Nat`s contain free variables. The wrapper
`Nat.mod` handles those cases specially and then calls `Nat.modCore`.
This function is overridden at runtime with an efficient implementation. This definition is the
logical model.
-/
@[extern "lean_nat_mod"]
protected noncomputable def modCore (x y : Nat) : Nat :=
if hy : 0 < y then
let rec
@ -155,13 +188,38 @@ protected theorem modCore_eq (x y : Nat) : Nat.modCore x y =
simp only [false_and, ↓reduceIte, *]
/--
The modulo operator, which computes the remainder when dividing one natural number by another.
Usually accessed via the `%` operator. When the divisor is `0`, the result is the dividend rather
than an error.
`Nat.mod` is a wrapper around `Nat.modCore` that special-cases two situations, giving better
definitional reductions:
* `Nat.mod 0 m` should reduce to `m`, for all terms `m : Nat`.
* `Nat.mod n (m + n + 1)` should reduce to `n` for concrete `Nat` literals `n`.
These reductions help `Fin n` literals work well, because the `OfNat` instance for `Fin` uses
`Nat.mod`. In particular, `(0 : Fin (n + 1)).val` should reduce definitionally to `0`. `Nat.modCore`
can handle all numbers, but its definitional reductions are not as convenient.
This function is overridden at runtime with an efficient implementation. This definition is the
logical model.
Examples:
* `7 % 2 = 1`
* `9 % 3 = 0`
* `5 % 7 = 5`
* `5 % 0 = 5`
* `show ∀ (n : Nat), 0 % n = 0 from fun _ => rfl`
* `show ∀ (m : Nat), 5 % (m + 6) = 5 from fun _ => rfl`
-/
@[extern "lean_nat_mod"]
protected def mod : @& Nat → @& Nat → Nat
/-
Nat.modCore is defined with fuel and thus does not reduce with open terms very well.
Nevertheless it is desirable for trivial `Nat.mod` calculations, namely
* `Nat.mod 0 m` for all `m`
* `Nat.mod n (m+n)` for concrete literals `n`,
* `Nat.mod n (m + n + 1)` for concrete literals `n`,
to reduce definitionally.
This property is desirable for `Fin n` literals, as it means `(ofNat 0 : Fin n).val = 0` by
definition.
@ -189,6 +247,9 @@ protected theorem modCore_eq_mod (n m : Nat) : Nat.modCore n m = n % m := by
theorem mod_eq (x y : Nat) : x % y = if 0 < y ∧ y ≤ x then (x - y) % y else x := by
rw [←Nat.modCore_eq_mod, ←Nat.modCore_eq_mod, Nat.modCore_eq]
/--
An induction principle customized for reasoning about the recursion pattern of `Nat.mod`.
-/
def mod.inductionOn.{u}
{motive : Nat → Nat → Sort u}
(x y : Nat)

View file

@ -13,14 +13,30 @@ universe u
namespace Nat
/--
`Nat.fold` evaluates `f` on the numbers up to `n` exclusive, in increasing order:
* `Nat.fold f 3 init = init |> f 0 |> f 1 |> f 2`
Iterates the application of a function `f` to a starting value `init`, `n` times. At each step, `f`
is applied to the current value and to the next natural number less than `n`, in increasing order.
Examples:
* `Nat.fold 3 f init = (init |> f 0 (by simp) |> f 1 (by simp) |> f 2 (by simp))`
* `Nat.fold 4 (fun i _ xs => xs.push i) #[] = #[0, 1, 2, 3]`
* `Nat.fold 0 (fun i _ xs => xs.push i) #[] = #[]`
-/
@[specialize] def fold {α : Type u} : (n : Nat) → (f : (i : Nat) → i < n → αα) → (init : α) → α
| 0, f, a => a
| succ n, f, a => f n (by omega) (fold n (fun i h => f i (by omega)) a)
/-- Tail-recursive version of `Nat.fold`. -/
/--
Iterates the application of a function `f` to a starting value `init`, `n` times. At each step, `f`
is applied to the current value and to the next natural number less than `n`, in increasing order.
This is a tail-recursive version of `Nat.fold` that's used at runtime.
Examples:
* `Nat.foldTR 3 f init = (init |> f 0 (by simp) |> f 1 (by simp) |> f 2 (by simp))`
* `Nat.foldTR 4 (fun i _ xs => xs.push i) #[] = #[0, 1, 2, 3]`
* `Nat.foldTR 0 (fun i _ xs => xs.push i) #[] = #[]`
-/
@[inline] def foldTR {α : Type u} (n : Nat) (f : (i : Nat) → i < n → αα) (init : α) : α :=
let rec @[specialize] loop : ∀ j, j ≤ n → αα
| 0, h, a => a
@ -28,31 +44,72 @@ namespace Nat
loop n (by omega) init
/--
`Nat.foldRev` evaluates `f` on the numbers up to `n` exclusive, in decreasing order:
* `Nat.foldRev f 3 init = f 0 <| f 1 <| f 2 <| init`
Iterates the application of a function `f` to a starting value `init`, `n` times. At each step, `f`
is applied to the current value and to the next natural number less than `n`, in decreasing order.
Examples:
* `Nat.foldRev 3 f init = (f 0 (by simp) <| f 1 (by simp) <| f 2 (by simp) init)`
* `Nat.foldRev 4 (fun i _ xs => xs.push i) #[] = #[3, 2, 1, 0]`
* `Nat.foldRev 0 (fun i _ xs => xs.push i) #[] = #[]`
-/
@[specialize] def foldRev {α : Type u} : (n : Nat) → (f : (i : Nat) → i < n → αα) → (init : α) → α
| 0, f, a => a
| succ n, f, a => foldRev n (fun i h => f i (by omega)) (f n (by omega) a)
/-- `any f n = true` iff there is `i in [0, n-1]` s.t. `f i = true` -/
/--
Checks whether there is some number less that the given bound for which `f` returns `true`.
Examples:
* `Nat.any 4 (fun i _ => i < 5) = true`
* `Nat.any 7 (fun i _ => i < 5) = true`
* `Nat.any 7 (fun i _ => i % 2 = 0) = true`
* `Nat.any 1 (fun i _ => i % 2 = 1) = false`
-/
@[specialize] def any : (n : Nat) → (f : (i : Nat) → i < n → Bool) → Bool
| 0, f => false
| succ n, f => any n (fun i h => f i (by omega)) || f n (by omega)
/-- Tail-recursive version of `Nat.any`. -/
/--
Checks whether there is some number less that the given bound for which `f` returns `true`.
This is a tail-recursive equivalent of `Nat.any` that's used at runtime.
Examples:
* `Nat.anyTR 4 (fun i _ => i < 5) = true`
* `Nat.anyTR 7 (fun i _ => i < 5) = true`
* `Nat.anyTR 7 (fun i _ => i % 2 = 0) = true`
* `Nat.anyTR 1 (fun i _ => i % 2 = 1) = false`
-/
@[inline] def anyTR (n : Nat) (f : (i : Nat) → i < n → Bool) : Bool :=
let rec @[specialize] loop : (i : Nat) → i ≤ n → Bool
| 0, h => false
| succ m, h => f (n - succ m) (by omega) || loop m (by omega)
loop n (by omega)
/-- `all f n = true` iff every `i in [0, n-1]` satisfies `f i = true` -/
/--
Checks whether `f` returns `true` for every number strictly less than a bound.
Examples:
* `Nat.all 4 (fun i _ => i < 5) = true`
* `Nat.all 7 (fun i _ => i < 5) = false`
* `Nat.all 7 (fun i _ => i % 2 = 0) = false`
* `Nat.all 1 (fun i _ => i % 2 = 0) = true`
-/
@[specialize] def all : (n : Nat) → (f : (i : Nat) → i < n → Bool) → Bool
| 0, f => true
| succ n, f => all n (fun i h => f i (by omega)) && f n (by omega)
/-- Tail-recursive version of `Nat.all`. -/
/--
Checks whether `f` returns `true` for every number strictly less than a bound.
This is a tail-recursive equivalent of `Nat.all` that's used at runtime.
Examples:
* `Nat.allTR 4 (fun i _ => i < 5) = true`
* `Nat.allTR 7 (fun i _ => i < 5) = false`
* `Nat.allTR 7 (fun i _ => i % 2 = 0) = false`
* `Nat.allTR 1 (fun i _ => i % 2 = 0) = true`
-/
@[inline] def allTR (n : Nat) (f : (i : Nat) → i < n → Bool) : Bool :=
let rec @[specialize] loop : (i : Nat) → i ≤ n → Bool
| 0, h => true

View file

@ -11,22 +11,19 @@ import Init.RCases
namespace Nat
/--
Computes the greatest common divisor of two natural numbers.
Computes the greatest common divisor of two natural numbers. The GCD of two natural numbers is the
largest natural number that evenly divides both.
This reference implementation via the Euclidean algorithm
is overridden in both the kernel and the compiler to efficiently
evaluate using the "bignum" representation (see `Nat`).
The definition provided here is the logical model
(and it is soundness-critical that they coincide).
In particular, the GCD of a number and `0` is the number itself.
The GCD of two natural numbers is the largest natural number
that divides both arguments.
In particular, the GCD of a number and `0` is the number itself:
```
example : Nat.gcd 10 15 = 5 := rfl
example : Nat.gcd 0 5 = 5 := rfl
example : Nat.gcd 7 0 = 7 := rfl
```
This reference implementation via the Euclidean algorithm is overridden in both the kernel and the
compiler to efficiently evaluate using arbitrary-precision arithmetic. The definition provided here
is the logical model.
Examples:
* `Nat.gcd 10 15 = 5`
* `Nat.gcd 0 5 = 5`
* `Nat.gcd 7 0 = 7`
-/
@[extern "lean_nat_gcd"]
def gcd (m n : @& Nat) : Nat :=

View file

@ -17,7 +17,16 @@ that should be added to this file.
namespace Nat
/-- The least common multiple of `m` and `n`, defined using `gcd`. -/
/--
The least common multiple of `m` and `n` is the smallest natural number that's evenly divisible by
both `m` and `n`. Returns `0` if either `m` or `n` is `0`.
Examples:
* `Nat.lcm 9 6 = 18`
* `Nat.lcm 9 3 = 9`
* `Nat.lcm 0 3 = 0`
* `Nat.lcm 3 0 = 0`
-/
def lcm (m n : Nat) : Nat := m * n / gcd m n
theorem lcm_comm (m n : Nat) : lcm m n = lcm n m := by

View file

@ -18,9 +18,18 @@ theorem log2_terminates : ∀ n, n ≥ 2 → n / 2 < n
simp
/--
Computes `⌊max 0 (log₂ n)⌋`.
Base-two logarithm of natural numbers. Returns `⌊max 0 (log₂ n)⌋`.
`log2 0 = log2 1 = 0`, `log2 2 = 1`, ..., `log2 (2^i) = i`, etc.
This function is overridden at runtime with an efficient implementation. This definition is
the logical model.
Examples:
* `Nat.log2 0 = 0`
* `Nat.log2 1 = 0`
* `Nat.log2 2 = 1`
* `Nat.log2 4 = 2`
* `Nat.log2 7 = 2`
* `Nat.log2 8 = 3`
-/
@[extern "lean_nat_log2"]
def log2 (n : @& Nat) : Nat :=

View file

@ -13,6 +13,16 @@ theorem nextPowerOfTwo_dec {n power : Nat} (h₁ : power > 0) (h₂ : power < n)
rw [this, Nat.sub_add_eq]
exact Nat.sub_lt (Nat.zero_lt_sub_of_lt h₂) h₁
/--
Returns the least power of two that's greater than or equal to `n`.
Examples:
* `Nat.nextPowerOfTwo 0 = 1`
* `Nat.nextPowerOfTwo 1 = 1`
* `Nat.nextPowerOfTwo 2 = 2`
* `Nat.nextPowerOfTwo 3 = 4`
* `Nat.nextPowerOfTwo 5 = 8`
-/
def nextPowerOfTwo (n : Nat) : Nat :=
go 1 (by decide)
where
@ -24,6 +34,9 @@ where
termination_by n - power
decreasing_by simp_wf; apply nextPowerOfTwo_dec <;> assumption
/--
A natural number `n` is a power of two if there exists some `k : Nat` such that `n = 2 ^ k`.
-/
def isPowerOfTwo (n : Nat) := ∃ k, n = 2 ^ k
theorem isPowerOfTwo_one : isPowerOfTwo 1 :=

View file

@ -45,6 +45,9 @@ protected opaque Float.ofScientific (m : Nat) (s : Bool) (e : Nat) : Float :=
instance : OfScientific Float where
ofScientific := Float.ofScientific
/--
Converts a natural number into a 64-bit floating point number.
-/
@[export lean_float_of_nat]
def Float.ofNat (n : Nat) : Float :=
OfScientific.ofScientific n false 0
@ -55,7 +58,7 @@ def Float.ofInt : Int → Float
instance : OfNat Float n := ⟨Float.ofNat n⟩
abbrev Nat.toFloat (n : Nat) : Float :=
@[inherit_doc Float.ofNat] abbrev Nat.toFloat (n : Nat) : Float :=
Float.ofNat n
/-- Computes `m * 2^e`. -/
@ -76,6 +79,9 @@ protected opaque Float32.ofScientific (m : Nat) (s : Bool) (e : Nat) : Float32 :
instance : OfScientific Float32 where
ofScientific := Float32.ofScientific
/--
Converts a natural number into a 32-bit floating point number.
-/
@[export lean_float32_of_nat]
def Float32.ofNat (n : Nat) : Float32 :=
OfScientific.ofScientific n false 0
@ -86,5 +92,5 @@ def Float32.ofInt : Int → Float32
instance : OfNat Float32 n := ⟨Float32.ofNat n⟩
abbrev Nat.toFloat32 (n : Nat) : Float32 :=
@[inherit_doc Float32.ofNat] abbrev Nat.toFloat32 (n : Nat) : Float32 :=
Float32.ofNat n

View file

@ -129,6 +129,17 @@ We have pure functions for calculating the decimal representation of a `Nat` (`t
a fast variant that handles small numbers (`USize`) via C code (`lean_string_of_usize`).
-/
/--
Returns a single digit representation of `n`, which is assumed to be in a base less than or equal to
`16`. Returns `'*'` if `n > 15`.
Examples:
* `Nat.digitChar 5 = '5'`
* `Nat.digitChar 12 = 'c'`
* `Nat.digitChar 15 = 'f'`
* `Nat.digitChar 16 = '*'`
* `Nat.digitChar 85 = '*'`
-/
def digitChar (n : Nat) : Char :=
if n = 0 then '0' else
if n = 1 then '1' else
@ -156,6 +167,16 @@ def toDigitsCore (base : Nat) : Nat → Nat → List Char → List Char
if n' = 0 then d::ds
else toDigitsCore base fuel n' (d::ds)
/--
Returns the decimal representation of a natural number as a list of digit characters in the given
base. If the base is greater than `16` then `'*'` is returned for digits greater than `0xf`.
Examples:
* `Nat.toDigits 10 0xff = ['2', '5', '5']`
* `Nat.toDigits 8 0xc = ['1', '4']`
* `Nat.toDigits 16 0xcafe = ['c', 'a', 'f', 'e']`
* `Nat.toDigits 80 200 = ['2', '*']`
-/
def toDigits (base : Nat) (n : Nat) : List Char :=
toDigitsCore base (n+1) n []
@ -172,10 +193,22 @@ private def reprFast (n : Nat) : String :=
if h : n < USize.size then (USize.ofNatLT n h).repr
else (toDigits 10 n).asString
/--
Converts a natural number to its decimal string representation.
-/
@[implemented_by reprFast]
protected def repr (n : Nat) : String :=
(toDigits 10 n).asString
/--
Converts a natural number less than `10` to the corresponding Unicode superscript digit character.
Returns `'*'` for other numbers.
Examples:
* `Nat.superDigitChar 3 = '³'`
* `Nat.superDigitChar 7 = '⁷'`
* `Nat.superDigitChar 10 = '*'`
-/
def superDigitChar (n : Nat) : Char :=
if n = 0 then '⁰' else
if n = 1 then '¹' else
@ -196,12 +229,37 @@ partial def toSuperDigitsAux : Nat → List Char → List Char
if n' = 0 then d::ds
else toSuperDigitsAux n' (d::ds)
/--
Converts a natural number to the list of Unicode superscript digit characters that corresponds to
its decimal representation.
Examples:
* `Nat.toSuperDigits 0 = ['⁰']`
* `Nat.toSuperDigits 35 = ['³', '⁵']`
-/
def toSuperDigits (n : Nat) : List Char :=
toSuperDigitsAux n []
/--
Converts a natural number to a string that contains the its decimal representation as Unicode
superscript digit characters.
Examples:
* `Nat.toSuperscriptString 0 = "⁰"`
* `Nat.toSuperscriptString 35 = "³⁵"`
-/
def toSuperscriptString (n : Nat) : String :=
(toSuperDigits n).asString
/--
Converts a natural number less than `10` to the corresponding Unicode subscript digit character.
Returns `'*'` for other numbers.
Examples:
* `Nat.subDigitChar 3 = '₃'`
* `Nat.subDigitChar 7 = '₇'`
* `Nat.subDigitChar 10 = '*'`
-/
def subDigitChar (n : Nat) : Char :=
if n = 0 then '₀' else
if n = 1 then '₁' else
@ -222,9 +280,25 @@ partial def toSubDigitsAux : Nat → List Char → List Char
if n' = 0 then d::ds
else toSubDigitsAux n' (d::ds)
/--
Converts a natural number to the list of Unicode subscript digit characters that corresponds to
its decimal representation.
Examples:
* `Nat.toSubDigits 0 = ['₀']`
* `Nat.toSubDigits 35 = ['₃', '₅']`
-/
def toSubDigits (n : Nat) : List Char :=
toSubDigitsAux n []
/--
Converts a natural number to a string that contains the its decimal representation as Unicode
subscript digit characters.
Examples:
* `Nat.toSubscriptString 0 = "₀"`
* `Nat.toSubscriptString 35 = "₃₅"`
-/
def toSubscriptString (n : Nat) : String :=
(toSubDigits n).asString

View file

@ -86,9 +86,29 @@ theorem Int8.toBitVec.inj : {x y : Int8} → x.toBitVec = y.toBitVec → x = y
def Int8.mk (i : UInt8) : Int8 := UInt8.toInt8 i
@[extern "lean_int8_of_int"]
def Int8.ofInt (i : @& Int) : Int8 := ⟨⟨BitVec.ofInt 8 i⟩⟩
/--
Converts a natural number to an 8-bit signed integer, wrapping around to negative numbers on
overflow.
Examples:
* `Int8.ofNat 53 = 53`
* `Int8.ofNat 127 = 127`
* `Int8.ofNat 128 = -128`
* `Int8.ofNat 255 = -1`
-/
@[extern "lean_int8_of_nat"]
def Int8.ofNat (n : @& Nat) : Int8 := ⟨⟨BitVec.ofNat 8 n⟩⟩
abbrev Int.toInt8 := Int8.ofInt
/--
Converts a natural number to an 8-bit signed integer, wrapping around to negative numbers on
overflow.
Examples:
* `Nat.toInt8 53 = 53`
* `Nat.toInt8 127 = 127`
* `Nat.toInt8 128 = -128`
* `Nat.toInt8 255 = -1`
-/
abbrev Nat.toInt8 := Int8.ofNat
@[extern "lean_int8_to_int"]
def Int8.toInt (i : Int8) : Int := i.toBitVec.toInt
@ -228,9 +248,29 @@ theorem Int16.toBitVec.inj : {x y : Int16} → x.toBitVec = y.toBitVec → x = y
def Int16.mk (i : UInt16) : Int16 := UInt16.toInt16 i
@[extern "lean_int16_of_int"]
def Int16.ofInt (i : @& Int) : Int16 := ⟨⟨BitVec.ofInt 16 i⟩⟩
/--
Converts a natural number to a 16-bit signed integer, wrapping around to negative numbers on
overflow.
Examples:
* `Int16.ofNat 127 = 127`
* `Int16.ofNat 32767 = 32767`
* `Int16.ofNat 32768 = -32768`
* `Int16.ofNat 32770 = -32766`
-/
@[extern "lean_int16_of_nat"]
def Int16.ofNat (n : @& Nat) : Int16 := ⟨⟨BitVec.ofNat 16 n⟩⟩
abbrev Int.toInt16 := Int16.ofInt
/--
Converts a natural number to a 16-bit signed integer, wrapping around to negative numbers on
overflow.
Examples:
* `Nat.toInt16 127 = 127`
* `Nat.toInt16 32767 = 32767`
* `Nat.toInt16 32768 = -32768`
* `Nat.toInt16 32770 = -32766`
-/
abbrev Nat.toInt16 := Int16.ofNat
@[extern "lean_int16_to_int"]
def Int16.toInt (i : Int16) : Int := i.toBitVec.toInt
@ -374,9 +414,29 @@ theorem Int32.toBitVec.inj : {x y : Int32} → x.toBitVec = y.toBitVec → x = y
def Int32.mk (i : UInt32) : Int32 := UInt32.toInt32 i
@[extern "lean_int32_of_int"]
def Int32.ofInt (i : @& Int) : Int32 := ⟨⟨BitVec.ofInt 32 i⟩⟩
/--
Converts a natural number to a 32-bit signed integer, wrapping around to negative numbers on
overflow.
Examples:
* `Int32.ofNat 127 = 127`
* `Int32.ofNat 32770 = 32770`
* `Int32.ofNat 2_147_483_647 = 2_147_483_647`
* `Int32.ofNat 2_147_483_648 = -2_147_483_648`
-/
@[extern "lean_int32_of_nat"]
def Int32.ofNat (n : @& Nat) : Int32 := ⟨⟨BitVec.ofNat 32 n⟩⟩
abbrev Int.toInt32 := Int32.ofInt
/--
Converts a natural number to a 32-bit signed integer, wrapping around to negative numbers on
overflow.
Examples:
* `Nat.toInt32 127 = 127`
* `Nat.toInt32 32770 = 32770`
* `Nat.toInt32 2_147_483_647 = 2_147_483_647`
* `Nat.toInt32 2_147_483_648 = -2_147_483_648`
-/
abbrev Nat.toInt32 := Int32.ofNat
@[extern "lean_int32_to_int"]
def Int32.toInt (i : Int32) : Int := i.toBitVec.toInt
@ -524,9 +584,31 @@ theorem Int64.toBitVec.inj : {x y : Int64} → x.toBitVec = y.toBitVec → x = y
def Int64.mk (i : UInt64) : Int64 := UInt64.toInt64 i
@[extern "lean_int64_of_int"]
def Int64.ofInt (i : @& Int) : Int64 := ⟨⟨BitVec.ofInt 64 i⟩⟩
/--
Converts a natural number to a 64-bit signed integer, wrapping around to negative numbers on
overflow.
Examples:
* `Int64.ofNat 127 = 127`
* `Int64.ofNat 2_147_483_648 = 2_147_483_648`
* `Int64.ofNat 9_223_372_036_854_775_807 = 9_223_372_036_854_775_807`
* `Int64.ofNat 9_223_372_036_854_775_808 = -9_223_372_036_854_775_808`
* `Int64.ofNat 18_446_744_073_709_551_618 = 0`
-/
@[extern "lean_int64_of_nat"]
def Int64.ofNat (n : @& Nat) : Int64 := ⟨⟨BitVec.ofNat 64 n⟩⟩
abbrev Int.toInt64 := Int64.ofInt
/--
Converts a natural number to a 64-bit signed integer, wrapping around to negative numbers on
overflow.
Examples:
* `Nat.toInt64 127 = 127`
* `Nat.toInt64 2_147_483_648 = 2_147_483_648`
* `Nat.toInt64 9_223_372_036_854_775_807 = 9_223_372_036_854_775_807`
* `Nat.toInt64 9_223_372_036_854_775_808 = -9_223_372_036_854_775_808`
* `Nat.toInt64 18_446_744_073_709_551_618 = 0`
-/
abbrev Nat.toInt64 := Int64.ofNat
@[extern "lean_int64_to_int_sint"]
def Int64.toInt (i : Int64) : Int := i.toBitVec.toInt
@ -678,10 +760,13 @@ theorem ISize.toBitVec.inj : {x y : ISize} → x.toBitVec = y.toBitVec → x = y
def ISize.mk (i : USize) : ISize := USize.toISize i
@[extern "lean_isize_of_int"]
def ISize.ofInt (i : @& Int) : ISize := ⟨⟨BitVec.ofInt System.Platform.numBits i⟩⟩
/--
Converts a natural number to an `ISize`, wrapping around to negative numbers on overflow.
-/
@[extern "lean_isize_of_nat"]
def ISize.ofNat (n : @& Nat) : ISize := ⟨⟨BitVec.ofNat System.Platform.numBits n⟩⟩
abbrev Int.toISize := ISize.ofInt
abbrev Nat.toISize := ISize.ofNat
@[inherit_doc ISize.ofNat] abbrev Nat.toISize := ISize.ofNat
@[extern "lean_isize_to_int"]
def ISize.toInt (i : ISize) : Int := i.toBitVec.toInt
/--

View file

@ -20,6 +20,17 @@ open Nat
def UInt8.toFin (x : UInt8) : Fin UInt8.size := x.toBitVec.toFin
@[deprecated UInt8.toFin (since := "2025-02-12"), inherit_doc UInt8.toFin]
def UInt8.val (x : UInt8) : Fin UInt8.size := x.toFin
/--
Converts a natural number to an 8-bit unsigned integer, wrapping on overflow.
Examples:
* `UInt8.ofNat 5 = 5`
* `UInt8.ofNat 255 = 255`
* `UInt8.ofNat 256 = 0`
* `UInt8.ofNat 259 = 3`
* `UInt8.ofNat 32770 = 2`
-/
@[extern "lean_uint8_of_nat"]
def UInt8.ofNat (n : @& Nat) : UInt8 := ⟨BitVec.ofNat 8 n⟩
/--
@ -30,6 +41,17 @@ def UInt8.ofNatTruncate (n : Nat) : UInt8 :=
UInt8.ofNatLT n h
else
UInt8.ofNatLT (UInt8.size - 1) (by decide)
/--
Converts a natural number to an 8-bit unsigned integer, wrapping on overflow.
Examples:
* `Nat.toUInt8 5 = 5`
* `Nat.toUInt8 255 = 255`
* `Nat.toUInt8 256 = 0`
* `Nat.toUInt8 259 = 3`
* `Nat.toUInt8 32770 = 2`
-/
abbrev Nat.toUInt8 := UInt8.ofNat
@[extern "lean_uint8_to_nat"]
def UInt8.toNat (n : UInt8) : Nat := n.toBitVec.toNat
@ -40,6 +62,16 @@ instance UInt8.instOfNat : OfNat UInt8 n := ⟨UInt8.ofNat n⟩
def UInt16.toFin (x : UInt16) : Fin UInt16.size := x.toBitVec.toFin
@[deprecated UInt16.toFin (since := "2025-02-12"), inherit_doc UInt16.toFin]
def UInt16.val (x : UInt16) : Fin UInt16.size := x.toFin
/--
Converts a natural number to a 16-bit unsigned integer, wrapping on overflow.
Examples:
* `UInt16.ofNat 5 = 5`
* `UInt16.ofNat 255 = 255`
* `UInt16.ofNat 32770 = 32770`
* `UInt16.ofNat 65537 = 1`
-/
@[extern "lean_uint16_of_nat"]
def UInt16.ofNat (n : @& Nat) : UInt16 := ⟨BitVec.ofNat 16 n⟩
/--
@ -50,6 +82,16 @@ def UInt16.ofNatTruncate (n : Nat) : UInt16 :=
UInt16.ofNatLT n h
else
UInt16.ofNatLT (UInt16.size - 1) (by decide)
/--
Converts a natural number to a 16-bit unsigned integer, wrapping on overflow.
Examples:
* `Nat.toUInt16 5 = 5`
* `Nat.toUInt16 255 = 255`
* `Nat.toUInt16 32770 = 32770`
* `Nat.toUInt16 65537 = 1`
-/
abbrev Nat.toUInt16 := UInt16.ofNat
@[extern "lean_uint16_to_nat"]
def UInt16.toNat (n : UInt16) : Nat := n.toBitVec.toNat
@ -64,6 +106,15 @@ instance UInt16.instOfNat : OfNat UInt16 n := ⟨UInt16.ofNat n⟩
def UInt32.toFin (x : UInt32) : Fin UInt32.size := x.toBitVec.toFin
@[deprecated UInt32.toFin (since := "2025-02-12"), inherit_doc UInt32.toFin]
def UInt32.val (x : UInt32) : Fin UInt32.size := x.toFin
/--
Converts a natural number to a 32-bit unsigned integer, wrapping on overflow.
Examples:
* `UInt32.ofNat 5 = 5`
* `UInt32.ofNat 65539 = 65539`
* `UInt32.ofNat 4_294_967_299 = 3`
-/
@[extern "lean_uint32_of_nat"]
def UInt32.ofNat (n : @& Nat) : UInt32 := ⟨BitVec.ofNat 32 n⟩
@[inline, deprecated UInt32.ofNatLT (since := "2025-02-13"), inherit_doc UInt32.ofNatLT]
@ -76,6 +127,14 @@ def UInt32.ofNatTruncate (n : Nat) : UInt32 :=
UInt32.ofNatLT n h
else
UInt32.ofNatLT (UInt32.size - 1) (by decide)
/--
Converts a natural number to a 32-bit unsigned integer, wrapping on overflow.
Examples:
* `Nat.toUInt32 5 = 5`
* `Nat.toUInt32 65_539 = 65_539`
* `Nat.toUInt32 4_294_967_299 = 3`
-/
abbrev Nat.toUInt32 := UInt32.ofNat
@[extern "lean_uint32_to_uint8"]
def UInt32.toUInt8 (a : UInt32) : UInt8 := a.toNat.toUInt8
@ -110,6 +169,15 @@ theorem UInt32.lt_ofNat'_of_lt {n m : Nat} (h1 : n < UInt32.size) (h2 : m < UInt
def UInt64.toFin (x : UInt64) : Fin UInt64.size := x.toBitVec.toFin
@[deprecated UInt64.toFin (since := "2025-02-12"), inherit_doc UInt64.toFin]
def UInt64.val (x : UInt64) : Fin UInt64.size := x.toFin
/--
Converts a natural number to a 64-bit unsigned integer, wrapping on overflow.
Examples:
* `UInt64.ofNat 5 = 5`
* `UInt64.ofNat 65539 = 65539`
* `UInt64.ofNat 4_294_967_299 = 4_294_967_299`
* `UInt64.ofNat 18_446_744_073_709_551_620 = 4`
-/
@[extern "lean_uint64_of_nat"]
def UInt64.ofNat (n : @& Nat) : UInt64 := ⟨BitVec.ofNat 64 n⟩
/--
@ -120,6 +188,15 @@ def UInt64.ofNatTruncate (n : Nat) : UInt64 :=
UInt64.ofNatLT n h
else
UInt64.ofNatLT (UInt64.size - 1) (by decide)
/--
Converts a natural number to a 64-bit unsigned integer, wrapping on overflow.
Examples:
* `Nat.toUInt64 5 = 5`
* `Nat.toUInt64 65539 = 65539`
* `Nat.toUInt64 4_294_967_299 = 4_294_967_299`
* `Nat.toUInt64 18_446_744_073_709_551_620 = 4`
-/
abbrev Nat.toUInt64 := UInt64.ofNat
@[extern "lean_uint64_to_nat"]
def UInt64.toNat (n : UInt64) : Nat := n.toBitVec.toNat
@ -153,6 +230,7 @@ theorem usize_size_pos : 0 < USize.size :=
def USize.toFin (x : USize) : Fin USize.size := x.toBitVec.toFin
@[deprecated USize.toFin (since := "2025-02-12"), inherit_doc USize.toFin]
def USize.val (x : USize) : Fin USize.size := x.toFin
/-- Converts a natural number to a `USize`, wrapping on overflow. -/
@[extern "lean_usize_of_nat"]
def USize.ofNat (n : @& Nat) : USize := ⟨BitVec.ofNat _ n⟩
/--
@ -164,7 +242,7 @@ def USize.ofNatTruncate (n : Nat) : USize :=
USize.ofNatLT n h
else
USize.ofNatLT (USize.size - 1) (Nat.pred_lt (Nat.ne_zero_of_lt USize.size_pos))
abbrev Nat.toUSize := USize.ofNat
@[inherit_doc USize.ofNat] abbrev Nat.toUSize := USize.ofNat
@[extern "lean_usize_to_nat"]
def USize.toNat (n : USize) : Nat := n.toBitVec.toNat
@[extern "lean_usize_add"]

View file

@ -1121,47 +1121,26 @@ propositional connective is `Not : Prop → Prop`.
export Bool (or and not)
/--
The type of natural numbers, starting at zero. It is defined as an
inductive type freely generated by "zero is a natural number" and
"the successor of a natural number is a natural number".
The natural numbers, starting at zero.
You can prove a theorem `P n` about `n : Nat` by `induction n`, which will
expect a proof of the theorem for `P 0`, and a proof of `P (succ i)` assuming
a proof of `P i`. The same method also works to define functions by recursion
on natural numbers: induction and recursion are two expressions of the same
operation from Lean's point of view.
```
open Nat
example (n : Nat) : n < succ n := by
induction n with
| zero =>
show 0 < 1
decide
| succ i ih => -- ih : i < succ i
show succ i < succ (succ i)
exact Nat.succ_lt_succ ih
```
This type is special-cased by both the kernel and the compiler:
* The type of expressions contains "`Nat` literals" as a primitive constructor,
and the kernel knows how to reduce zero/succ expressions to nat literals.
* If implemented naively, this type would represent a numeral `n` in unary as a
linked list with `n` links, which is horribly inefficient. Instead, the
runtime itself has a special representation for `Nat` which stores numbers up
to 2^63 directly and larger numbers use an arbitrary precision "bignum"
library (usually [GMP](https://gmplib.org/)).
This type is special-cased by both the kernel and the compiler, and overridden with an efficient
implementation. Both use a fast arbitrary-precision arithmetic library (usually
[GMP](https://gmplib.org/)); at runtime, `Nat` values that are sufficiently small are unboxed.
-/
inductive Nat where
/-- `Nat.zero`, is the smallest natural number. This is one of the two
constructors of `Nat`. Using `Nat.zero` should usually be avoided in favor of
`0 : Nat` or simply `0`, in order to remain compatible with the simp normal
form defined by `Nat.zero_eq`. -/
/--
Zero, the smallest natural number.
Using `Nat.zero` explicitly should usually be avoided in favor of the literal `0`, which is the
[simp normal form](lean-manual://section/simp-normal-forms).
-/
| zero : Nat
/-- The successor function on natural numbers, `succ n = n + 1`.
This is one of the two constructors of `Nat`. Using `succ n` should usually
be avoided in favor of `n + 1`, in order to remain compatible with the simp
normal form defined by `Nat.succ_eq_add_one`. -/
/--
The successor of a natural number `n`.
Using `Nat.succ n` should usually be avoided in favor of `n + 1`, which is the [simp normal
form](lean-manual://section/simp-normal-forms).
-/
| succ (n : Nat) : Nat
instance : Inhabited Nat where
@ -1619,11 +1598,10 @@ class Membership (α : outParam (Type u)) (γ : Type v) where
set_option bootstrap.genMatcherCode false in
/--
Addition of natural numbers.
Addition of natural numbers, typically used via the `+` operator.
This definition is overridden in both the kernel and the compiler to efficiently
evaluate using the "bignum" representation (see `Nat`). The definition provided
here is the logical model (and it is soundness-critical that they coincide).
This function is overridden in both the kernel and the compiler to efficiently evaluate using the
arbitrary-precision arithmetic library. The definition provided here is the logical model.
-/
@[extern "lean_nat_add"]
protected def Nat.add : (@& Nat) → (@& Nat) → Nat
@ -1639,11 +1617,10 @@ attribute [match_pattern] Nat.add Add.add HAdd.hAdd Neg.neg Mul.mul HMul.hMul
set_option bootstrap.genMatcherCode false in
/--
Multiplication of natural numbers.
Multiplication of natural numbers, usually accessed via the `*` operator.
This definition is overridden in both the kernel and the compiler to efficiently
evaluate using the "bignum" representation (see `Nat`). The definition provided
here is the logical model (and it is soundness-critical that they coincide).
This function is overridden in both the kernel and the compiler to efficiently evaluate using the
arbitrary-precision arithmetic library. The definition provided here is the logical model.
-/
@[extern "lean_nat_mul"]
protected def Nat.mul : (@& Nat) → (@& Nat) → Nat
@ -1655,11 +1632,10 @@ instance instMulNat : Mul Nat where
set_option bootstrap.genMatcherCode false in
/--
The power operation on natural numbers.
The power operation on natural numbers, usually accessed via the `^` operator.
This definition is overridden in both the kernel and the compiler to efficiently
evaluate using the "bignum" representation (see `Nat`). The definition provided
here is the logical model.
This function is overridden in both the kernel and the compiler to efficiently evaluate using the
arbitrary-precision arithmetic library. The definition provided here is the logical model.
-/
@[extern "lean_nat_pow"]
protected def Nat.pow (m : @& Nat) : (@& Nat) → Nat
@ -1670,11 +1646,10 @@ instance instNatPowNat : NatPow Nat := ⟨Nat.pow⟩
set_option bootstrap.genMatcherCode false in
/--
(Boolean) equality of natural numbers.
Boolean equality of natural numbers, usually accessed via the `==` operator.
This definition is overridden in both the kernel and the compiler to efficiently
evaluate using the "bignum" representation (see `Nat`). The definition provided
here is the logical model (and it is soundness-critical that they coincide).
This function is overridden in both the kernel and the compiler to efficiently evaluate using the
arbitrary-precision arithmetic library. The definition provided here is the logical model.
-/
@[extern "lean_nat_dec_eq"]
def Nat.beq : (@& Nat) → (@& Nat) → Bool
@ -1701,11 +1676,16 @@ theorem Nat.ne_of_beq_eq_false : {n m : Nat} → Eq (beq n m) false → Not (Eq
Nat.noConfusion h₂ (fun h₂ => absurd h₂ (ne_of_beq_eq_false this))
/--
A decision procedure for equality of natural numbers.
A decision procedure for equality of natural numbers, usually accessed via the `DecidableEq Nat`
instance.
This definition is overridden in the compiler to efficiently
evaluate using the "bignum" representation (see `Nat`). The definition provided
here is the logical model.
This function is overridden in both the kernel and the compiler to efficiently evaluate using the
arbitrary-precision arithmetic library. The definition provided here is the logical model.
Examples:
* `Nat.decEq 5 5 = isTrue rfl`
* `(if 3 = 4 then "yes" else "no") = "no"`
* `show 12 = 12 by decide`
-/
@[reducible, extern "lean_nat_dec_eq"]
protected def Nat.decEq (n m : @& Nat) : Decidable (Eq n m) :=
@ -1717,11 +1697,15 @@ protected def Nat.decEq (n m : @& Nat) : Decidable (Eq n m) :=
set_option bootstrap.genMatcherCode false in
/--
The (Boolean) less-equal relation on natural numbers.
The Boolean less-than-or-equal-to comparison on natural numbers.
This definition is overridden in both the kernel and the compiler to efficiently
evaluate using the "bignum" representation (see `Nat`). The definition provided
here is the logical model (and it is soundness-critical that they coincide).
This function is overridden in both the kernel and the compiler to efficiently evaluate using the
arbitrary-precision arithmetic library. The definition provided here is the logical model.
Examples:
* `Nat.ble 2 5 = true`
* `Nat.ble 5 2 = false`
* `Nat.ble 5 5 = true`
-/
@[extern "lean_nat_dec_le"]
def Nat.ble : @& Nat → @& Nat → Bool
@ -1731,11 +1715,10 @@ def Nat.ble : @& Nat → @& Nat → Bool
| succ n, succ m => ble n m
/--
An inductive definition of the less-equal relation on natural numbers,
characterized as the least relation `≤` such that `n ≤ n` and `n ≤ m → n ≤ m + 1`.
Non-strict, or weak, inequality of natural numbers, usually accessed via the `≤` operator.
-/
protected inductive Nat.le (n : Nat) : Nat → Prop
/-- Less-equal is reflexive: `n ≤ n` -/
/-- Non-strict inequality is reflexive: `n ≤ n` -/
| refl : Nat.le n n
/-- If `n ≤ m`, then `n ≤ m + 1`. -/
| step {m} : Nat.le n m → Nat.le n (succ m)
@ -1743,7 +1726,11 @@ protected inductive Nat.le (n : Nat) : Nat → Prop
instance instLENat : LE Nat where
le := Nat.le
/-- The strict less than relation on natural numbers is defined as `n < m := n + 1 ≤ m`. -/
/--
Strict inequality of natural numbers, usually accessed via the `<` operator.
It is defined as `n < m = n + 1 ≤ m`.
-/
protected def Nat.lt (n m : Nat) : Prop :=
Nat.le (succ n) m
@ -1792,10 +1779,11 @@ theorem Nat.succ_pos (n : Nat) : LT.lt 0 (succ n) :=
set_option bootstrap.genMatcherCode false in
/--
The predecessor function on natural numbers.
The predecessor of a natural number is one less than it. The precedessor of `0` is defined to be
`0`.
This definition is overridden in the compiler to use `n - 1` instead.
The definition provided here is the logical model.
This definition is overridden in the compiler with an efficient implementation. This definition is
the logical model.
-/
@[extern "lean_nat_pred"]
def Nat.pred : (@& Nat) → Nat
@ -1875,10 +1863,30 @@ theorem Nat.ble_eq_true_of_le (h : LE.le n m) : Eq (Nat.ble n m) true :=
theorem Nat.not_le_of_not_ble_eq_true (h : Not (Eq (Nat.ble n m) true)) : Not (LE.le n m) :=
fun h' => absurd (Nat.ble_eq_true_of_le h') h
/--
A decision procedure for non-strict inequality of natural numbers, usually accessed via the
`DecidableLE Nat` instance.
Examples:
* `(if 3 ≤ 4 then "yes" else "no") = "yes"`
* `(if 6 ≤ 4 then "yes" else "no") = "no"`
* `show 12 ≤ 12 by decide`
* `show 5 ≤ 12 by decide`
-/
@[extern "lean_nat_dec_le"]
instance Nat.decLe (n m : @& Nat) : Decidable (LE.le n m) :=
dite (Eq (Nat.ble n m) true) (fun h => isTrue (Nat.le_of_ble_eq_true h)) (fun h => isFalse (Nat.not_le_of_not_ble_eq_true h))
/--
A decision procedure for strict inequality of natural numbers, usually accessed via the
`DecidableLT Nat` instance.
Examples:
* `(if 3 < 4 then "yes" else "no") = "yes"`
* `(if 4 < 4 then "yes" else "no") = "no"`
* `(if 6 < 4 then "yes" else "no") = "no"`
* `show 5 < 12 by decide`
-/
@[extern "lean_nat_dec_lt"]
instance Nat.decLt (n m : @& Nat) : Decidable (LT.lt n m) :=
decLe (succ n) m
@ -1887,12 +1895,18 @@ instance : Min Nat := minOfLe
set_option bootstrap.genMatcherCode false in
/--
(Truncated) subtraction of natural numbers. Because natural numbers are not
closed under subtraction, we define `n - m` to be `0` when `n < m`.
Subtraction of natural numbers, truncated at `0`. Usually used via the `-` operator.
This definition is overridden in both the kernel and the compiler to efficiently
evaluate using the "bignum" representation (see `Nat`). The definition provided
here is the logical model (and it is soundness-critical that they coincide).
If a result would be less than zero, then the result is zero.
This definition is overridden in both the kernel and the compiler to efficiently evaluate using the
arbitrary-precision arithmetic library. The definition provided here is the logical model.
Examples:
* `5 - 3 = 2`
* `8 - 2 = 6`
* `8 - 8 = 0`
* `8 - 20 = 0`
-/
@[extern "lean_nat_sub"]
protected def Nat.sub : (@& Nat) → (@& Nat) → Nat
@ -2293,15 +2307,15 @@ instance : Inhabited USize where
default := USize.ofNatLT 0 USize.size_pos
/--
A `Nat` denotes a valid unicode codepoint if it is less than `0x110000`, and
it is also not a "surrogate" character (the range `0xd800` to `0xdfff` inclusive).
A `Nat` denotes a valid Unicode code point if it is less than `0x110000` and it is also not a
surrogate code point (the range `0xd800` to `0xdfff` inclusive).
-/
abbrev Nat.isValidChar (n : Nat) : Prop :=
Or (LT.lt n 0xd800) (And (LT.lt 0xdfff n) (LT.lt n 0x110000))
/--
A `UInt32` denotes a valid unicode codepoint if it is less than `0x110000`, and
it is also not a "surrogate" character (the range `0xd800` to `0xdfff` inclusive).
A `UInt32` denotes a valid Unicode code point if it is less than `0x110000` and it is also not a
surrogate code point (the range `0xd800` to `0xdfff` inclusive).
-/
abbrev UInt32.isValidChar (n : UInt32) : Prop :=
n.toNat.isValidChar

View file

@ -189,12 +189,21 @@ def lt_wfRel : WellFoundedRelation Nat where
| Or.inl e => subst e; assumption
| Or.inr e => exact Acc.inv ih e
/--
Strong induction on the natural numbers.
The induction hypothesis is that all numbers less than a given number satisfy the motive, which
should be demonstrated for the given number.
-/
@[elab_as_elim] protected noncomputable def strongRecOn
{motive : Nat → Sort u}
(n : Nat)
(ind : ∀ n, (∀ m, m < n → motive m) → motive n) : motive n :=
Nat.lt_wfRel.wf.fix ind n
/--
Case analysis based on strong induction for the natural numbers.
-/
@[elab_as_elim] protected noncomputable def caseStrongRecOn
{motive : Nat → Sort u}
(a : Nat)

View file

@ -20,7 +20,7 @@
{"start": {"line": 12, "character": 4}, "end": {"line": 12, "character": 12}},
"contents":
{"value":
"```lean\nNat.zero : Nat\n```\n***\n`Nat.zero`, is the smallest natural number. This is one of the two\nconstructors of `Nat`. Using `Nat.zero` should usually be avoided in favor of\n`0 : Nat` or simply `0`, in order to remain compatible with the simp normal\nform defined by `Nat.zero_eq`. \n***\n*import Init.Prelude*",
"```lean\nNat.zero : Nat\n```\n***\nZero, the smallest natural number.\n\nUsing `Nat.zero` explicitly should usually be avoided in favor of the literal `0`, which is the\n[simp normal form](https://lean-lang.org/doc/reference/latest/find/?domain=Verso.Genre.Manual.section&name=simp-normal-forms).\n\n***\n*import Init.Prelude*",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 21, "character": 2}}
@ -120,7 +120,7 @@
{"start": {"line": 73, "character": 38}, "end": {"line": 73, "character": 45}},
"contents":
{"value":
"```lean\nNat.add : Nat → Nat → Nat\n```\n***\nAddition of natural numbers.\n\nThis definition is overridden in both the kernel and the compiler to efficiently\nevaluate using the \"bignum\" representation (see `Nat`). The definition provided\nhere is the logical model (and it is soundness-critical that they coincide).\n\n***\n*import Init.Prelude*",
"```lean\nNat.add : Nat → Nat → Nat\n```\n***\nAddition of natural numbers, typically used via the `+` operator.\n\nThis function is overridden in both the kernel and the compiler to efficiently evaluate using the\narbitrary-precision arithmetic library. The definition provided here is the logical model.\n\n***\n*import Init.Prelude*",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 77, "character": 10}}
@ -128,7 +128,7 @@
{"start": {"line": 77, "character": 7}, "end": {"line": 77, "character": 14}},
"contents":
{"value":
"```lean\nNat\n```\n***\nAddition of natural numbers.\n\nThis definition is overridden in both the kernel and the compiler to efficiently\nevaluate using the \"bignum\" representation (see `Nat`). The definition provided\nhere is the logical model (and it is soundness-critical that they coincide).\n",
"```lean\nNat\n```\n***\nAddition of natural numbers, typically used via the `+` operator.\n\nThis function is overridden in both the kernel and the compiler to efficiently evaluate using the\narbitrary-precision arithmetic library. The definition provided here is the logical model.\n",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 82, "character": 7}}
@ -136,7 +136,7 @@
{"start": {"line": 82, "character": 7}, "end": {"line": 82, "character": 8}},
"contents":
{"value":
"```lean\nNat : Type\n```\n***\nThe type of natural numbers, starting at zero. It is defined as an\ninductive type freely generated by \"zero is a natural number\" and\n\"the successor of a natural number is a natural number\".\n\nYou can prove a theorem `P n` about `n : Nat` by `induction n`, which will\nexpect a proof of the theorem for `P 0`, and a proof of `P (succ i)` assuming\na proof of `P i`. The same method also works to define functions by recursion\non natural numbers: induction and recursion are two expressions of the same\noperation from Lean's point of view.\n\n```\nopen Nat\nexample (n : Nat) : n < succ n := by\n induction n with\n | zero =>\n show 0 < 1\n decide\n | succ i ih => -- ih : i < succ i\n show succ i < succ (succ i)\n exact Nat.succ_lt_succ ih\n```\n\nThis type is special-cased by both the kernel and the compiler:\n* The type of expressions contains \"`Nat` literals\" as a primitive constructor,\n and the kernel knows how to reduce zero/succ expressions to nat literals.\n* If implemented naively, this type would represent a numeral `n` in unary as a\n linked list with `n` links, which is horribly inefficient. Instead, the\n runtime itself has a special representation for `Nat` which stores numbers up\n to 2^63 directly and larger numbers use an arbitrary precision \"bignum\"\n library (usually [GMP](https://gmplib.org/)).\n\n***\n*import Init.Prelude*",
"```lean\nNat : Type\n```\n***\nThe natural numbers, starting at zero.\n\nThis type is special-cased by both the kernel and the compiler, and overridden with an efficient\nimplementation. Both use a fast arbitrary-precision arithmetic library (usually\n[GMP](https://gmplib.org/)); at runtime, `Nat` values that are sufficiently small are unboxed.\n\n***\n*import Init.Prelude*",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 87, "character": 14}}
@ -521,7 +521,7 @@
{"start": {"line": 257, "character": 4}, "end": {"line": 257, "character": 9}},
"contents":
{"value":
"```lean\nNat.zero : \n```\n***\n`Nat.zero`, is the smallest natural number. This is one of the two\nconstructors of `Nat`. Using `Nat.zero` should usually be avoided in favor of\n`0 : Nat` or simply `0`, in order to remain compatible with the simp normal\nform defined by `Nat.zero_eq`. \n***\n*import Init.Prelude*",
"```lean\nNat.zero : \n```\n***\nZero, the smallest natural number.\n\nUsing `Nat.zero` explicitly should usually be avoided in favor of the literal `0`, which is the\n[simp normal form](https://lean-lang.org/doc/reference/latest/find/?domain=Verso.Genre.Manual.section&name=simp-normal-forms).\n\n***\n*import Init.Prelude*",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 257, "character": 15}}
@ -530,7 +530,7 @@
"end": {"line": 257, "character": 18}},
"contents":
{"value":
"```lean\nNat.zero : \n```\n***\n`Nat.zero`, is the smallest natural number. This is one of the two\nconstructors of `Nat`. Using `Nat.zero` should usually be avoided in favor of\n`0 : Nat` or simply `0`, in order to remain compatible with the simp normal\nform defined by `Nat.zero_eq`. \n***\n*import Init.Prelude*",
"```lean\nNat.zero : \n```\n***\nZero, the smallest natural number.\n\nUsing `Nat.zero` explicitly should usually be avoided in favor of the literal `0`, which is the\n[simp normal form](https://lean-lang.org/doc/reference/latest/find/?domain=Verso.Genre.Manual.section&name=simp-normal-forms).\n\n***\n*import Init.Prelude*",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 260, "character": 6}}
@ -538,7 +538,7 @@
{"start": {"line": 260, "character": 4}, "end": {"line": 260, "character": 9}},
"contents":
{"value":
"```lean\nNat.succ (n : ) : \n```\n***\nThe successor function on natural numbers, `succ n = n + 1`.\nThis is one of the two constructors of `Nat`. Using `succ n` should usually\nbe avoided in favor of `n + 1`, in order to remain compatible with the simp\nnormal form defined by `Nat.succ_eq_add_one`. \n***\n*import Init.Prelude*",
"```lean\nNat.succ (n : ) : \n```\n***\nThe successor of a natural number `n`.\n\nUsing `Nat.succ n` should usually be avoided in favor of `n + 1`, which is the [simp normal\nform](https://lean-lang.org/doc/reference/latest/find/?domain=Verso.Genre.Manual.section&name=simp-normal-forms).\n\n***\n*import Init.Prelude*",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 260, "character": 17}}
@ -547,7 +547,7 @@
"end": {"line": 260, "character": 20}},
"contents":
{"value":
"```lean\nNat.succ (n : ) : \n```\n***\nThe successor function on natural numbers, `succ n = n + 1`.\nThis is one of the two constructors of `Nat`. Using `succ n` should usually\nbe avoided in favor of `n + 1`, in order to remain compatible with the simp\nnormal form defined by `Nat.succ_eq_add_one`. \n***\n*import Init.Prelude*",
"```lean\nNat.succ (n : ) : \n```\n***\nThe successor of a natural number `n`.\n\nUsing `Nat.succ n` should usually be avoided in favor of `n + 1`, which is the [simp normal\nform](https://lean-lang.org/doc/reference/latest/find/?domain=Verso.Genre.Manual.section&name=simp-normal-forms).\n\n***\n*import Init.Prelude*",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 263, "character": 27}}
@ -565,7 +565,7 @@
"end": {"line": 263, "character": 36}},
"contents":
{"value":
"```lean\nNat.zero : \n```\n***\n`Nat.zero`, is the smallest natural number. This is one of the two\nconstructors of `Nat`. Using `Nat.zero` should usually be avoided in favor of\n`0 : Nat` or simply `0`, in order to remain compatible with the simp normal\nform defined by `Nat.zero_eq`. \n***\n*import Init.Prelude*",
"```lean\nNat.zero : \n```\n***\nZero, the smallest natural number.\n\nUsing `Nat.zero` explicitly should usually be avoided in favor of the literal `0`, which is the\n[simp normal form](https://lean-lang.org/doc/reference/latest/find/?domain=Verso.Genre.Manual.section&name=simp-normal-forms).\n\n***\n*import Init.Prelude*",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hover.lean"},
"position": {"line": 269, "character": 2}}

View file

@ -20,7 +20,7 @@
{"start": {"line": 12, "character": 14}, "end": {"line": 12, "character": 18}},
"contents":
{"value":
"```lean\nNat.succ (n : Nat) : Nat\n```\n***\nThe successor function on natural numbers, `succ n = n + 1`.\nThis is one of the two constructors of `Nat`. Using `succ n` should usually\nbe avoided in favor of `n + 1`, in order to remain compatible with the simp\nnormal form defined by `Nat.succ_eq_add_one`. \n***\n*import Init.Prelude*",
"```lean\nNat.succ (n : Nat) : Nat\n```\n***\nThe successor of a natural number `n`.\n\nUsing `Nat.succ n` should usually be avoided in favor of `n + 1`, which is the [simp normal\nform](https://lean-lang.org/doc/reference/latest/find/?domain=Verso.Genre.Manual.section&name=simp-normal-forms).\n\n***\n*import Init.Prelude*",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hoverDot.lean"},
"position": {"line": 16, "character": 11}}
@ -34,7 +34,7 @@
{"start": {"line": 16, "character": 14}, "end": {"line": 16, "character": 18}},
"contents":
{"value":
"```lean\nNat.succ (n : Nat) : Nat\n```\n***\nThe successor function on natural numbers, `succ n = n + 1`.\nThis is one of the two constructors of `Nat`. Using `succ n` should usually\nbe avoided in favor of `n + 1`, in order to remain compatible with the simp\nnormal form defined by `Nat.succ_eq_add_one`. \n***\n*import Init.Prelude*",
"```lean\nNat.succ (n : Nat) : Nat\n```\n***\nThe successor of a natural number `n`.\n\nUsing `Nat.succ n` should usually be avoided in favor of `n + 1`, which is the [simp normal\nform](https://lean-lang.org/doc/reference/latest/find/?domain=Verso.Genre.Manual.section&name=simp-normal-forms).\n\n***\n*import Init.Prelude*",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hoverDot.lean"},
"position": {"line": 19, "character": 13}}
@ -48,7 +48,7 @@
{"start": {"line": 19, "character": 16}, "end": {"line": 19, "character": 20}},
"contents":
{"value":
"```lean\nNat.succ (n : Nat) : Nat\n```\n***\nThe successor function on natural numbers, `succ n = n + 1`.\nThis is one of the two constructors of `Nat`. Using `succ n` should usually\nbe avoided in favor of `n + 1`, in order to remain compatible with the simp\nnormal form defined by `Nat.succ_eq_add_one`. \n***\n*import Init.Prelude*",
"```lean\nNat.succ (n : Nat) : Nat\n```\n***\nThe successor of a natural number `n`.\n\nUsing `Nat.succ n` should usually be avoided in favor of `n + 1`, which is the [simp normal\nform](https://lean-lang.org/doc/reference/latest/find/?domain=Verso.Genre.Manual.section&name=simp-normal-forms).\n\n***\n*import Init.Prelude*",
"kind": "markdown"}}
{"textDocument": {"uri": "file:///hoverDot.lean"},
"position": {"line": 22, "character": 14}}
@ -62,5 +62,5 @@
{"start": {"line": 22, "character": 17}, "end": {"line": 22, "character": 21}},
"contents":
{"value":
"```lean\nNat.succ (n : Nat) : Nat\n```\n***\nThe successor function on natural numbers, `succ n = n + 1`.\nThis is one of the two constructors of `Nat`. Using `succ n` should usually\nbe avoided in favor of `n + 1`, in order to remain compatible with the simp\nnormal form defined by `Nat.succ_eq_add_one`. \n***\n*import Init.Prelude*",
"```lean\nNat.succ (n : Nat) : Nat\n```\n***\nThe successor of a natural number `n`.\n\nUsing `Nat.succ n` should usually be avoided in favor of `n + 1`, which is the [simp normal\nform](https://lean-lang.org/doc/reference/latest/find/?domain=Verso.Genre.Manual.section&name=simp-normal-forms).\n\n***\n*import Init.Prelude*",
"kind": "markdown"}}