mirror of
https://github.com/leanprover/lean4.git
synced 2026-03-23 13:24:11 +00:00
Compare commits
70 Commits
divmod_boo
...
array_any2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
aef3269113 | ||
|
|
c4ec0a9f9c | ||
|
|
2e66341f69 | ||
|
|
2e44585ce9 | ||
|
|
e2f0e14b04 | ||
|
|
e801dc96ca | ||
|
|
56a3ac1814 | ||
|
|
6c62f720c8 | ||
|
|
a57efd0a88 | ||
|
|
7e2d6e2254 | ||
|
|
4603e1a6ad | ||
|
|
896b3f8933 | ||
|
|
816fadb57b | ||
|
|
550d2918b8 | ||
|
|
eb5ad2c03a | ||
|
|
769fe4ebf6 | ||
|
|
8130fdc474 | ||
|
|
41bba59868 | ||
|
|
115f06c32a | ||
|
|
1e1e17cb35 | ||
|
|
831e8d768b | ||
|
|
b4b878b2d0 | ||
|
|
2377f35426 | ||
|
|
c7f706baeb | ||
|
|
c3402b85ab | ||
|
|
a68b986616 | ||
|
|
a2dc17055b | ||
|
|
c9c85c7d83 | ||
|
|
d615e615d9 | ||
|
|
a84639f63e | ||
|
|
d9ab758af5 | ||
|
|
5cbeb22564 | ||
|
|
77e0fa4efe | ||
|
|
69efb78319 | ||
|
|
32a9392a11 | ||
|
|
af741abbf5 | ||
|
|
36723d38b9 | ||
|
|
3ebce4e190 | ||
|
|
c934e6c247 | ||
|
|
57c8ab269b | ||
|
|
e7dc0d31f4 | ||
|
|
1819dc88ff | ||
|
|
e1fade23ec | ||
|
|
27e1391e6d | ||
|
|
da32bdd79c | ||
|
|
b863ca9ae9 | ||
|
|
c3b01fbd53 | ||
|
|
ad1e04c826 | ||
|
|
c8dc66b6c1 | ||
|
|
d234b78cc0 | ||
|
|
1ae084b5f8 | ||
|
|
ddeb5ac535 | ||
|
|
6ff5c4c278 | ||
|
|
087f0b4a69 | ||
|
|
a7bdc55244 | ||
|
|
647573d269 | ||
|
|
788a7ec502 | ||
|
|
3aef45c45b | ||
|
|
1f5c66db79 | ||
|
|
d42d6c5246 | ||
|
|
d1aba29b57 | ||
|
|
0c35ca2e39 | ||
|
|
6e77bee098 | ||
|
|
1ee21c17fc | ||
|
|
aea58113cb | ||
|
|
36c798964e | ||
|
|
6c609028b3 | ||
|
|
a3a99d3875 | ||
|
|
970732ea11 | ||
|
|
2eb478787f |
@@ -764,11 +764,12 @@ Structures and Records
|
||||
The ``structure`` command in Lean is used to define an inductive data type with a single constructor and to define its projections at the same time. The syntax is as follows:
|
||||
|
||||
```
|
||||
structure Foo (a : α) extends Bar, Baz : Sort u :=
|
||||
structure Foo (a : α) : Sort u extends Bar, Baz :=
|
||||
constructor :: (field₁ : β₁) ... (fieldₙ : βₙ)
|
||||
```
|
||||
|
||||
Here ``(a : α)`` is a telescope, that is, the parameters to the inductive definition. The name ``constructor`` followed by the double colon is optional; if it is not present, the name ``mk`` is used by default. The keyword ``extends`` followed by a list of previously defined structures is also optional; if it is present, an instance of each of these structures is included among the fields to ``Foo``, and the types ``βᵢ`` can refer to their fields as well. The output type, ``Sort u``, can be omitted, in which case Lean infers to smallest non-``Prop`` sort possible. Finally, ``(field₁ : β₁) ... (fieldₙ : βₙ)`` is a telescope relative to ``(a : α)`` and the fields in ``bar`` and ``baz``.
|
||||
Here ``(a : α)`` is a telescope, that is, the parameters to the inductive definition. The name ``constructor`` followed by the double colon is optional; if it is not present, the name ``mk`` is used by default. The keyword ``extends`` followed by a list of previously defined structures is also optional; if it is present, an instance of each of these structures is included among the fields to ``Foo``, and the types ``βᵢ`` can refer to their fields as well. The output type, ``Sort u``, can be omitted, in which case Lean infers to smallest non-``Prop`` sort possible (unless all the fields are ``Prop``, in which case it infers ``Prop``).
|
||||
Finally, ``(field₁ : β₁) ... (fieldₙ : βₙ)`` is a telescope relative to ``(a : α)`` and the fields in ``bar`` and ``baz``.
|
||||
|
||||
The declaration above is syntactic sugar for an inductive type declaration, and so results in the addition of the following constants to the environment:
|
||||
|
||||
|
||||
@@ -25,7 +25,10 @@ cp llvm/lib/clang/*/include/{std*,__std*,limits}.h stage1/include/clang
|
||||
echo '
|
||||
// https://docs.microsoft.com/en-us/windows/win32/api/errhandlingapi/nf-errhandlingapi-seterrormode
|
||||
#define SEM_FAILCRITICALERRORS 0x0001
|
||||
__declspec(dllimport) __stdcall unsigned int SetErrorMode(unsigned int uMode);' > stage1/include/clang/windows.h
|
||||
__declspec(dllimport) __stdcall unsigned int SetErrorMode(unsigned int uMode);
|
||||
// https://docs.microsoft.com/en-us/windows/console/setconsoleoutputcp
|
||||
#define CP_UTF8 65001
|
||||
__declspec(dllimport) __stdcall int SetConsoleOutputCP(unsigned int wCodePageID);' > stage1/include/clang/windows.h
|
||||
# COFF dependencies
|
||||
cp /clang64/lib/{crtbegin,crtend,crt2,dllcrt2}.o stage1/lib/
|
||||
# runtime
|
||||
|
||||
@@ -144,11 +144,12 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "Windows")
|
||||
# do not import the world from windows.h using appropriately named flag
|
||||
string(APPEND LEAN_EXTRA_CXX_FLAGS " -D WIN32_LEAN_AND_MEAN")
|
||||
# DLLs must go next to executables on Windows
|
||||
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin")
|
||||
set(CMAKE_RELATIVE_LIBRARY_OUTPUT_DIRECTORY "bin")
|
||||
else()
|
||||
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib/lean")
|
||||
set(CMAKE_RELATIVE_LIBRARY_OUTPUT_DIRECTORY "lib/lean")
|
||||
endif()
|
||||
|
||||
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${CMAKE_RELATIVE_LIBRARY_OUTPUT_DIRECTORY}")
|
||||
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib/lean")
|
||||
|
||||
# OSX default thread stack size is very small. Moreover, in Debug mode, each new stack frame consumes a lot of extra memory.
|
||||
|
||||
@@ -78,7 +78,7 @@ Error recovery and state can interact subtly. For example, the implementation of
|
||||
-/
|
||||
-- NB: List instance is in mathlib. Once upstreamed, add
|
||||
-- * `List`, where `failure` is the empty list and `<|>` concatenates.
|
||||
class Alternative (f : Type u → Type v) extends Applicative f : Type (max (u+1) v) where
|
||||
class Alternative (f : Type u → Type v) : Type (max (u+1) v) extends Applicative f where
|
||||
/--
|
||||
Produces an empty collection or recoverable failure. The `<|>` operator collects values or recovers
|
||||
from failures. See `Alternative` for more details.
|
||||
|
||||
@@ -47,7 +47,7 @@ pure f <*> pure x = pure (f x)
|
||||
u <*> pure y = pure (· y) <*> u
|
||||
```
|
||||
-/
|
||||
class LawfulApplicative (f : Type u → Type v) [Applicative f] extends LawfulFunctor f : Prop where
|
||||
class LawfulApplicative (f : Type u → Type v) [Applicative f] : Prop extends LawfulFunctor f where
|
||||
seqLeft_eq (x : f α) (y : f β) : x <* y = const β <$> x <*> y
|
||||
seqRight_eq (x : f α) (y : f β) : x *> y = const α id <$> x <*> y
|
||||
pure_seq (g : α → β) (x : f α) : pure g <*> x = g <$> x
|
||||
@@ -77,7 +77,7 @@ x >>= f >>= g = x >>= (fun x => f x >>= g)
|
||||
|
||||
`LawfulMonad.mk'` is an alternative constructor containing useful defaults for many fields.
|
||||
-/
|
||||
class LawfulMonad (m : Type u → Type v) [Monad m] extends LawfulApplicative m : Prop where
|
||||
class LawfulMonad (m : Type u → Type v) [Monad m] : Prop extends LawfulApplicative m where
|
||||
bind_pure_comp (f : α → β) (x : m α) : x >>= (fun a => pure (f a)) = f <$> x
|
||||
bind_map {α β : Type u} (f : m (α → β)) (x : m α) : f >>= (. <$> x) = f <*> x
|
||||
pure_bind (x : α) (f : α → m β) : pure x >>= f = f x
|
||||
|
||||
@@ -2020,7 +2020,7 @@ free variables. The frontend automatically declares a fresh auxiliary constant `
|
||||
|
||||
Warning: by using this feature, the Lean compiler and interpreter become part of your trusted code base.
|
||||
This is extra 30k lines of code. More importantly, you will probably not be able to check your development using
|
||||
external type checkers (e.g., Trepplein) that do not implement this feature.
|
||||
external type checkers that do not implement this feature.
|
||||
Keep in mind that if you are using Lean as programming language, you are already trusting the Lean compiler and interpreter.
|
||||
So, you are mainly losing the capability of type checking your development using external checkers.
|
||||
|
||||
@@ -2055,7 +2055,7 @@ decidability instance can be evaluated to `true` using the lean compiler / inter
|
||||
|
||||
Warning: by using this feature, the Lean compiler and interpreter become part of your trusted code base.
|
||||
This is extra 30k lines of code. More importantly, you will probably not be able to check your development using
|
||||
external type checkers (e.g., Trepplein) that do not implement this feature.
|
||||
external type checkers that do not implement this feature.
|
||||
Keep in mind that if you are using Lean as programming language, you are already trusting the Lean compiler and interpreter.
|
||||
So, you are mainly losing the capability of type checking your development using external checkers.
|
||||
-/
|
||||
@@ -2066,7 +2066,7 @@ The axiom `ofReduceNat` is used to perform proofs by reflection. See `reduceBool
|
||||
|
||||
Warning: by using this feature, the Lean compiler and interpreter become part of your trusted code base.
|
||||
This is extra 30k lines of code. More importantly, you will probably not be able to check your development using
|
||||
external type checkers (e.g., Trepplein) that do not implement this feature.
|
||||
external type checkers that do not implement this feature.
|
||||
Keep in mind that if you are using Lean as programming language, you are already trusting the Lean compiler and interpreter.
|
||||
So, you are mainly losing the capability of type checking your development using external checkers.
|
||||
-/
|
||||
@@ -2125,7 +2125,7 @@ class LeftIdentity (op : α → β → β) (o : outParam α) : Prop
|
||||
`LawfulLeftIdentify op o` indicates `o` is a verified left identity of
|
||||
`op`.
|
||||
-/
|
||||
class LawfulLeftIdentity (op : α → β → β) (o : outParam α) extends LeftIdentity op o : Prop where
|
||||
class LawfulLeftIdentity (op : α → β → β) (o : outParam α) : Prop extends LeftIdentity op o where
|
||||
/-- Left identity `o` is an identity. -/
|
||||
left_id : ∀ a, op o a = a
|
||||
|
||||
@@ -2141,7 +2141,7 @@ class RightIdentity (op : α → β → α) (o : outParam β) : Prop
|
||||
`LawfulRightIdentify op o` indicates `o` is a verified right identity of
|
||||
`op`.
|
||||
-/
|
||||
class LawfulRightIdentity (op : α → β → α) (o : outParam β) extends RightIdentity op o : Prop where
|
||||
class LawfulRightIdentity (op : α → β → α) (o : outParam β) : Prop extends RightIdentity op o where
|
||||
/-- Right identity `o` is an identity. -/
|
||||
right_id : ∀ a, op a o = a
|
||||
|
||||
@@ -2151,13 +2151,13 @@ class LawfulRightIdentity (op : α → β → α) (o : outParam β) extends Righ
|
||||
This class does not require a proof that `o` is an identity, and is used
|
||||
primarily for inferring the identity using class resolution.
|
||||
-/
|
||||
class Identity (op : α → α → α) (o : outParam α) extends LeftIdentity op o, RightIdentity op o : Prop
|
||||
class Identity (op : α → α → α) (o : outParam α) : Prop extends LeftIdentity op o, RightIdentity op o
|
||||
|
||||
/--
|
||||
`LawfulIdentity op o` indicates `o` is a verified left and right
|
||||
identity of `op`.
|
||||
-/
|
||||
class LawfulIdentity (op : α → α → α) (o : outParam α) extends Identity op o, LawfulLeftIdentity op o, LawfulRightIdentity op o : Prop
|
||||
class LawfulIdentity (op : α → α → α) (o : outParam α) : Prop extends Identity op o, LawfulLeftIdentity op o, LawfulRightIdentity op o
|
||||
|
||||
/--
|
||||
`LawfulCommIdentity` can simplify defining instances of `LawfulIdentity`
|
||||
@@ -2168,7 +2168,7 @@ This class is intended for simplifying defining instances of
|
||||
`LawfulIdentity` and functions needed commutative operations with
|
||||
identity should just add a `LawfulIdentity` constraint.
|
||||
-/
|
||||
class LawfulCommIdentity (op : α → α → α) (o : outParam α) [hc : Commutative op] extends LawfulIdentity op o : Prop where
|
||||
class LawfulCommIdentity (op : α → α → α) (o : outParam α) [hc : Commutative op] : Prop extends LawfulIdentity op o where
|
||||
left_id a := Eq.trans (hc.comm o a) (right_id a)
|
||||
right_id a := Eq.trans (hc.comm a o) (left_id a)
|
||||
|
||||
|
||||
@@ -8,8 +8,9 @@ import Init.Data.Array.Mem
|
||||
import Init.Data.Array.Lemmas
|
||||
import Init.Data.Array.Count
|
||||
import Init.Data.List.Attach
|
||||
-- set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
-- set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
|
||||
set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
|
||||
namespace Array
|
||||
|
||||
@@ -554,6 +555,10 @@ def unattach {α : Type _} {p : α → Prop} (xs : Array { x // p x }) : Array
|
||||
(xs.push a).unattach = xs.unattach.push a.1 := by
|
||||
simp only [unattach, Array.map_push]
|
||||
|
||||
@[simp] theorem mem_unattach {p : α → Prop} {xs : Array { x // p x }} {a} :
|
||||
a ∈ xs.unattach ↔ ∃ h : p a, ⟨a, h⟩ ∈ xs := by
|
||||
simp only [unattach, mem_map, Subtype.exists, exists_and_right, exists_eq_right]
|
||||
|
||||
@[simp] theorem size_unattach {p : α → Prop} {xs : Array { x // p x }} :
|
||||
xs.unattach.size = xs.size := by
|
||||
unfold unattach
|
||||
@@ -675,6 +680,20 @@ and simplifies these to the function directly taking the value.
|
||||
simp
|
||||
rw [List.find?_subtype hf]
|
||||
|
||||
@[simp] theorem all_subtype {p : α → Prop} {xs : Array { x // p x }} {f : { x // p x } → Bool} {g : α → Bool}
|
||||
(hf : ∀ x h, f ⟨x, h⟩ = g x) (w : stop = xs.size) :
|
||||
xs.all f 0 stop = xs.unattach.all g := by
|
||||
subst w
|
||||
rcases xs with ⟨xs⟩
|
||||
simp [hf]
|
||||
|
||||
@[simp] theorem any_subtype {p : α → Prop} {xs : Array { x // p x }} {f : { x // p x } → Bool} {g : α → Bool}
|
||||
(hf : ∀ x h, f ⟨x, h⟩ = g x) (w : stop = xs.size) :
|
||||
xs.any f 0 stop = xs.unattach.any g := by
|
||||
subst w
|
||||
rcases xs with ⟨xs⟩
|
||||
simp [hf]
|
||||
|
||||
/-! ### Simp lemmas pushing `unattach` inwards. -/
|
||||
|
||||
@[simp] theorem unattach_filter {p : α → Prop} {xs : Array { x // p x }}
|
||||
|
||||
@@ -14,8 +14,8 @@ import Init.GetElem
|
||||
import Init.Data.List.ToArrayImpl
|
||||
import Init.Data.Array.Set
|
||||
|
||||
-- set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
-- set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
|
||||
universe u v w
|
||||
|
||||
@@ -1090,6 +1090,11 @@ def split (as : Array α) (p : α → Bool) : Array α × Array α :=
|
||||
as.foldl (init := (#[], #[])) fun (as, bs) a =>
|
||||
if p a then (as.push a, bs) else (as, bs.push a)
|
||||
|
||||
def replace [BEq α] (xs : Array α) (a b : α) : Array α :=
|
||||
match xs.finIdxOf? a with
|
||||
| none => xs
|
||||
| some i => xs.set i b
|
||||
|
||||
/-! ### Lexicographic ordering -/
|
||||
|
||||
instance instLT [LT α] : LT (Array α) := ⟨fun as bs => as.toList < bs.toList⟩
|
||||
@@ -1102,6 +1107,20 @@ instance instLE [LT α] : LE (Array α) := ⟨fun as bs => as.toList ≤ bs.toLi
|
||||
We do not currently intend to provide verification theorems for these functions.
|
||||
-/
|
||||
|
||||
/-! ### leftpad and rightpad -/
|
||||
|
||||
/--
|
||||
Pads `l : Array α` on the left with repeated occurrences of `a : α` until it is of size `n`.
|
||||
If `l` is initially larger than `n`, just return `l`.
|
||||
-/
|
||||
def leftpad (n : Nat) (a : α) (xs : Array α) : Array α := mkArray (n - xs.size) a ++ xs
|
||||
|
||||
/--
|
||||
Pads `l : Array α` on the right with repeated occurrences of `a : α` until it is of size `n`.
|
||||
If `l` is initially larger than `n`, just return `l`.
|
||||
-/
|
||||
def rightpad (n : Nat) (a : α) (xs : Array α) : Array α := xs ++ mkArray (n - xs.size) a
|
||||
|
||||
/- ### reduceOption -/
|
||||
|
||||
/-- Drop `none`s from a Array, and replace each remaining `some a` with `a`. -/
|
||||
|
||||
@@ -8,8 +8,8 @@ import Init.Data.Array.Basic
|
||||
import Init.Data.Nat.Linear
|
||||
import Init.NotationExtra
|
||||
|
||||
-- set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
-- set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
|
||||
theorem Array.of_push_eq_push {as bs : Array α} (h : as.push a = bs.push b) : as = bs ∧ a = b := by
|
||||
simp only [push, mk.injEq] at h
|
||||
|
||||
@@ -5,10 +5,11 @@ Authors: Leonardo de Moura
|
||||
-/
|
||||
prelude
|
||||
import Init.Data.Array.Basic
|
||||
import Init.Data.Int.DivMod.Lemmas
|
||||
import Init.Omega
|
||||
universe u v
|
||||
|
||||
-- set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
-- We do not use `linter.indexVariables` here as it is helpful to name the index variables as `lo`, `mid`, and `hi`.
|
||||
|
||||
namespace Array
|
||||
|
||||
@@ -13,8 +13,8 @@ import Init.Data.List.TakeDrop
|
||||
This file contains some theorems about `Array` and `List` needed for `Init.Data.List.Impl`.
|
||||
-/
|
||||
|
||||
-- set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
-- set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
|
||||
namespace Array
|
||||
|
||||
|
||||
@@ -11,8 +11,8 @@ import Init.Data.List.Nat.Count
|
||||
# Lemmas about `Array.countP` and `Array.count`.
|
||||
-/
|
||||
|
||||
-- set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
-- set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
|
||||
namespace Array
|
||||
|
||||
|
||||
@@ -9,8 +9,8 @@ import Init.Data.BEq
|
||||
import Init.Data.List.Nat.BEq
|
||||
import Init.ByCases
|
||||
|
||||
-- set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
-- set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
|
||||
namespace Array
|
||||
|
||||
|
||||
@@ -12,8 +12,8 @@ import Init.Data.List.Nat.Basic
|
||||
# Lemmas about `Array.eraseP`, `Array.erase`, and `Array.eraseIdx`.
|
||||
-/
|
||||
|
||||
-- set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
-- set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
|
||||
namespace Array
|
||||
|
||||
|
||||
@@ -13,8 +13,8 @@ import Init.Data.List.Nat.TakeDrop
|
||||
This file follows the contents of `Init.Data.List.TakeDrop` and `Init.Data.List.Nat.TakeDrop`.
|
||||
-/
|
||||
|
||||
-- set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
-- set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
|
||||
open Nat
|
||||
namespace Array
|
||||
|
||||
@@ -7,8 +7,8 @@ prelude
|
||||
import Init.Data.List.FinRange
|
||||
import Init.Data.Array.OfFn
|
||||
|
||||
-- set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
-- set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
|
||||
namespace Array
|
||||
|
||||
|
||||
@@ -13,8 +13,8 @@ import Init.Data.Array.Range
|
||||
# Lemmas about `Array.findSome?`, `Array.find?, `Array.findIdx`, `Array.findIdx?`, `Array.idxOf`.
|
||||
-/
|
||||
|
||||
-- set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
-- set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
namespace Array
|
||||
|
||||
open Nat
|
||||
@@ -99,11 +99,6 @@ theorem getElem_zero_flatten {xss : Array (Array α)} (h) :
|
||||
simp [getElem?_eq_getElem, h] at t
|
||||
simp [← t]
|
||||
|
||||
theorem back?_flatten {xss : Array (Array α)} :
|
||||
(flatten xss).back? = (xss.findSomeRev? fun xs => xs.back?) := by
|
||||
cases xss using array₂_induction
|
||||
simp [List.getLast?_flatten, ← List.map_reverse, List.findSome?_map, Function.comp_def]
|
||||
|
||||
theorem findSome?_mkArray : findSome? f (mkArray n a) = if n = 0 then none else f a := by
|
||||
simp [← List.toArray_replicate, List.findSome?_replicate]
|
||||
|
||||
@@ -304,24 +299,6 @@ theorem find?_eq_some_iff_getElem {xs : Array α} {p : α → Bool} {b : α} :
|
||||
rcases xs with ⟨xs⟩
|
||||
simp [List.find?_eq_some_iff_getElem]
|
||||
|
||||
/-! ### findFinIdx? -/
|
||||
|
||||
@[simp] theorem findFinIdx?_empty {p : α → Bool} : findFinIdx? p #[] = none := rfl
|
||||
|
||||
-- We can't mark this as a `@[congr]` lemma since the head of the RHS is not `findFinIdx?`.
|
||||
theorem findFinIdx?_congr {p : α → Bool} {xs ys : Array α} (w : xs = ys) :
|
||||
findFinIdx? p xs = (findFinIdx? p ys).map (fun i => i.cast (by simp [w])) := by
|
||||
subst w
|
||||
simp
|
||||
|
||||
@[simp] theorem findFinIdx?_subtype {p : α → Prop} {xs : Array { x // p x }}
|
||||
{f : { x // p x } → Bool} {g : α → Bool} (hf : ∀ x h, f ⟨x, h⟩ = g x) :
|
||||
xs.findFinIdx? f = (xs.unattach.findFinIdx? g).map (fun i => i.cast (by simp)) := by
|
||||
cases xs
|
||||
simp only [List.findFinIdx?_toArray, hf, List.findFinIdx?_subtype]
|
||||
rw [findFinIdx?_congr List.unattach_toArray]
|
||||
simp [Function.comp_def]
|
||||
|
||||
/-! ### findIdx -/
|
||||
|
||||
theorem findIdx_of_getElem?_eq_some {xs : Array α} (w : xs[xs.findIdx p]? = some y) : p y := by
|
||||
@@ -547,6 +524,47 @@ theorem findIdx?_eq_some_le_of_findIdx?_eq_some {xs : Array α} {p q : α → Bo
|
||||
cases xs
|
||||
simp
|
||||
|
||||
/-! ### findFinIdx? -/
|
||||
|
||||
@[simp] theorem findFinIdx?_empty {p : α → Bool} : findFinIdx? p #[] = none := rfl
|
||||
|
||||
-- We can't mark this as a `@[congr]` lemma since the head of the RHS is not `findFinIdx?`.
|
||||
theorem findFinIdx?_congr {p : α → Bool} {xs ys : Array α} (w : xs = ys) :
|
||||
findFinIdx? p xs = (findFinIdx? p ys).map (fun i => i.cast (by simp [w])) := by
|
||||
subst w
|
||||
simp
|
||||
|
||||
theorem findFinIdx?_eq_pmap_findIdx? {xs : Array α} {p : α → Bool} :
|
||||
xs.findFinIdx? p =
|
||||
(xs.findIdx? p).pmap
|
||||
(fun i m => by simp [findIdx?_eq_some_iff_getElem] at m; exact ⟨i, m.choose⟩)
|
||||
(fun i h => h) := by
|
||||
simp [findIdx?_eq_map_findFinIdx?_val, Option.pmap_map]
|
||||
|
||||
@[simp] theorem findFinIdx?_eq_none_iff {xs : Array α} {p : α → Bool} :
|
||||
xs.findFinIdx? p = none ↔ ∀ x, x ∈ xs → ¬ p x := by
|
||||
simp [findFinIdx?_eq_pmap_findIdx?]
|
||||
|
||||
@[simp]
|
||||
theorem findFinIdx?_eq_some_iff {xs : Array α} {p : α → Bool} {i : Fin xs.size} :
|
||||
xs.findFinIdx? p = some i ↔
|
||||
p xs[i] ∧ ∀ j (hji : j < i), ¬p (xs[j]'(Nat.lt_trans hji i.2)) := by
|
||||
simp only [findFinIdx?_eq_pmap_findIdx?, Option.pmap_eq_some_iff, findIdx?_eq_some_iff_getElem,
|
||||
Bool.not_eq_true, Option.mem_def, exists_and_left, and_exists_self, Fin.getElem_fin]
|
||||
constructor
|
||||
· rintro ⟨a, ⟨h, w₁, w₂⟩, rfl⟩
|
||||
exact ⟨w₁, fun j hji => by simpa using w₂ j hji⟩
|
||||
· rintro ⟨h, w⟩
|
||||
exact ⟨i, ⟨i.2, h, fun j hji => w ⟨j, by omega⟩ hji⟩, rfl⟩
|
||||
|
||||
@[simp] theorem findFinIdx?_subtype {p : α → Prop} {xs : Array { x // p x }}
|
||||
{f : { x // p x } → Bool} {g : α → Bool} (hf : ∀ x h, f ⟨x, h⟩ = g x) :
|
||||
xs.findFinIdx? f = (xs.unattach.findFinIdx? g).map (fun i => i.cast (by simp)) := by
|
||||
cases xs
|
||||
simp only [List.findFinIdx?_toArray, hf, List.findFinIdx?_subtype]
|
||||
rw [findFinIdx?_congr List.unattach_toArray]
|
||||
simp [Function.comp_def]
|
||||
|
||||
/-! ### idxOf
|
||||
|
||||
The verification API for `idxOf` is still incomplete.
|
||||
@@ -584,10 +602,26 @@ The lemmas below should be made consistent with those for `findIdx?` (and proved
|
||||
rcases xs with ⟨xs⟩
|
||||
simp [List.idxOf?_eq_none_iff]
|
||||
|
||||
/-! ### finIdxOf? -/
|
||||
/-! ### finIdxOf?
|
||||
|
||||
The verification API for `finIdxOf?` is still incomplete.
|
||||
The lemmas below should be made consistent with those for `findFinIdx?` (and proved using them).
|
||||
-/
|
||||
|
||||
theorem idxOf?_eq_map_finIdxOf?_val [BEq α] {xs : Array α} {a : α} :
|
||||
xs.idxOf? a = (xs.finIdxOf? a).map (·.val) := by
|
||||
simp [idxOf?, finIdxOf?, findIdx?_eq_map_findFinIdx?_val]
|
||||
|
||||
@[simp] theorem finIdxOf?_empty [BEq α] : (#[] : Array α).finIdxOf? a = none := rfl
|
||||
|
||||
@[simp] theorem finIdxOf?_eq_none_iff [BEq α] [LawfulBEq α] {xs : Array α} {a : α} :
|
||||
xs.finIdxOf? a = none ↔ a ∉ xs := by
|
||||
rcases xs with ⟨xs⟩
|
||||
simp [List.finIdxOf?_eq_none_iff]
|
||||
|
||||
@[simp] theorem finIdxOf?_eq_some_iff [BEq α] [LawfulBEq α] {xs : Array α} {a : α} {i : Fin xs.size} :
|
||||
xs.finIdxOf? a = some i ↔ xs[i] = a ∧ ∀ j (_ : j < i), ¬xs[j] = a := by
|
||||
rcases xs with ⟨xs⟩
|
||||
simp [List.finIdxOf?_eq_some_iff]
|
||||
|
||||
end Array
|
||||
|
||||
@@ -7,8 +7,8 @@ Authors: Leonardo de Moura
|
||||
prelude
|
||||
import Init.Data.Array.Basic
|
||||
|
||||
-- set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
-- set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
|
||||
namespace Array
|
||||
|
||||
|
||||
@@ -13,8 +13,8 @@ import Init.Data.List.Nat.InsertIdx
|
||||
Proves various lemmas about `Array.insertIdx`.
|
||||
-/
|
||||
|
||||
-- set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
-- set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
|
||||
open Function
|
||||
|
||||
|
||||
@@ -6,8 +6,8 @@ Authors: Leonardo de Moura
|
||||
prelude
|
||||
import Init.Data.Array.Basic
|
||||
|
||||
-- set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
-- set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
|
||||
@[inline] def Array.insertionSort (xs : Array α) (lt : α → α → Bool := by exact (· < ·)) : Array α :=
|
||||
traverse xs 0 xs.size
|
||||
|
||||
@@ -8,6 +8,7 @@ import Init.Data.Nat.Lemmas
|
||||
import Init.Data.List.Range
|
||||
import Init.Data.List.Nat.TakeDrop
|
||||
import Init.Data.List.Nat.Modify
|
||||
import Init.Data.List.Nat.Basic
|
||||
import Init.Data.List.Monadic
|
||||
import Init.Data.List.OfFn
|
||||
import Init.Data.Array.Mem
|
||||
@@ -21,8 +22,8 @@ import Init.Data.List.ToArray
|
||||
## Theorems about `Array`.
|
||||
-/
|
||||
|
||||
-- set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
-- set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
|
||||
namespace Array
|
||||
|
||||
@@ -60,21 +61,27 @@ theorem size_empty : (#[] : Array α).size = 0 := rfl
|
||||
|
||||
/-! ### size -/
|
||||
|
||||
theorem eq_empty_of_size_eq_zero (h : l.size = 0) : l = #[] := by
|
||||
cases l
|
||||
theorem eq_empty_of_size_eq_zero (h : xs.size = 0) : xs = #[] := by
|
||||
cases xs
|
||||
simp_all
|
||||
|
||||
theorem ne_empty_of_size_eq_add_one (h : l.size = n + 1) : l ≠ #[] := by
|
||||
cases l
|
||||
theorem ne_empty_of_size_eq_add_one (h : xs.size = n + 1) : xs ≠ #[] := by
|
||||
cases xs
|
||||
simpa using List.ne_nil_of_length_eq_add_one h
|
||||
|
||||
theorem ne_empty_of_size_pos (h : 0 < l.size) : l ≠ #[] := by
|
||||
cases l
|
||||
theorem ne_empty_of_size_pos (h : 0 < xs.size) : xs ≠ #[] := by
|
||||
cases xs
|
||||
simpa using List.ne_nil_of_length_pos h
|
||||
|
||||
theorem size_eq_zero : l.size = 0 ↔ l = #[] :=
|
||||
theorem size_eq_zero_iff : xs.size = 0 ↔ xs = #[] :=
|
||||
⟨eq_empty_of_size_eq_zero, fun h => h ▸ rfl⟩
|
||||
|
||||
@[deprecated size_eq_zero_iff (since := "2025-02-24")]
|
||||
abbrev size_eq_zero := @size_eq_zero_iff
|
||||
|
||||
theorem eq_empty_iff_size_eq_zero : xs = #[] ↔ xs.size = 0 :=
|
||||
size_eq_zero_iff.symm
|
||||
|
||||
theorem size_pos_of_mem {a : α} {xs : Array α} (h : a ∈ xs) : 0 < xs.size := by
|
||||
cases xs
|
||||
simp only [mem_toArray] at h
|
||||
@@ -91,12 +98,18 @@ theorem exists_mem_of_size_eq_add_one {xs : Array α} (h : xs.size = n + 1) :
|
||||
cases xs
|
||||
simpa using List.exists_mem_of_length_eq_add_one h
|
||||
|
||||
theorem size_pos {xs : Array α} : 0 < xs.size ↔ xs ≠ #[] :=
|
||||
Nat.pos_iff_ne_zero.trans (not_congr size_eq_zero)
|
||||
theorem size_pos_iff {xs : Array α} : 0 < xs.size ↔ xs ≠ #[] :=
|
||||
Nat.pos_iff_ne_zero.trans (not_congr size_eq_zero_iff)
|
||||
|
||||
theorem size_eq_one {xs : Array α} : xs.size = 1 ↔ ∃ a, xs = #[a] := by
|
||||
@[deprecated size_pos_iff (since := "2025-02-24")]
|
||||
abbrev size_pos := @size_pos_iff
|
||||
|
||||
theorem size_eq_one_iff {xs : Array α} : xs.size = 1 ↔ ∃ a, xs = #[a] := by
|
||||
cases xs
|
||||
simpa using List.length_eq_one
|
||||
simpa using List.length_eq_one_iff
|
||||
|
||||
@[deprecated size_eq_one_iff (since := "2025-02-24")]
|
||||
abbrev size_eq_one := @size_eq_one_iff
|
||||
|
||||
/-! ### push -/
|
||||
|
||||
@@ -153,7 +166,7 @@ theorem ne_empty_iff_exists_push {xs : Array α} :
|
||||
|
||||
theorem exists_push_of_size_pos {xs : Array α} (h : 0 < xs.size) :
|
||||
∃ (ys : Array α) (a : α), xs = ys.push a := by
|
||||
replace h : xs ≠ #[] := size_pos.mp h
|
||||
replace h : xs ≠ #[] := size_pos_iff.mp h
|
||||
exact exists_push_of_ne_empty h
|
||||
|
||||
theorem size_pos_iff_exists_push {xs : Array α} :
|
||||
@@ -440,7 +453,7 @@ abbrev isEmpty_eq_true := @isEmpty_iff
|
||||
abbrev isEmpty_eq_false := @isEmpty_eq_false_iff
|
||||
|
||||
theorem isEmpty_iff_size_eq_zero {xs : Array α} : xs.isEmpty ↔ xs.size = 0 := by
|
||||
rw [isEmpty_iff, size_eq_zero]
|
||||
rw [isEmpty_iff, size_eq_zero_iff]
|
||||
|
||||
/-! ### Decidability of bounded quantifiers -/
|
||||
|
||||
@@ -820,9 +833,9 @@ theorem getElem?_set (xs : Array α) (i : Nat) (h : i < xs.size) (v : α) (j : N
|
||||
cases xs
|
||||
simp
|
||||
|
||||
@[simp] theorem set_eq_empty_iff {xs : Array α} (n : Nat) (a : α) (h) :
|
||||
xs.set n a = #[] ↔ xs = #[] := by
|
||||
cases xs <;> cases n <;> simp [set]
|
||||
@[simp] theorem set_eq_empty_iff {xs : Array α} (i : Nat) (a : α) (h) :
|
||||
xs.set i a = #[] ↔ xs = #[] := by
|
||||
cases xs <;> cases i <;> simp [set]
|
||||
|
||||
theorem set_comm (a b : α)
|
||||
{i j : Nat} (xs : Array α) {hi : i < xs.size} {hj : j < (xs.set i a).size} (h : i ≠ j) :
|
||||
@@ -1023,6 +1036,20 @@ private theorem beq_of_beq_singleton [BEq α] {a b : α} : #[a] == #[b] → a ==
|
||||
cases ys
|
||||
simp
|
||||
|
||||
/-! ### back -/
|
||||
|
||||
theorem back_eq_getElem (xs : Array α) (h : 0 < xs.size) : xs.back = xs[xs.size - 1] := by
|
||||
cases xs
|
||||
simp [List.getLast_eq_getElem]
|
||||
|
||||
theorem back?_eq_getElem? (xs : Array α) : xs.back? = xs[xs.size - 1]? := by
|
||||
cases xs
|
||||
simp [List.getLast?_eq_getElem?]
|
||||
|
||||
@[simp] theorem back_mem {xs : Array α} (h : 0 < xs.size) : xs.back h ∈ xs := by
|
||||
cases xs
|
||||
simp
|
||||
|
||||
/-! ### map -/
|
||||
|
||||
theorem mapM_eq_foldlM [Monad m] [LawfulMonad m] (f : α → m β) (xs : Array α) :
|
||||
@@ -1397,6 +1424,18 @@ theorem filter_eq_push_iff {p : α → Bool} {xs ys : Array α} {a : α} :
|
||||
theorem mem_of_mem_filter {a : α} {xs : Array α} (h : a ∈ filter p xs) : a ∈ xs :=
|
||||
(mem_filter.mp h).1
|
||||
|
||||
@[simp]
|
||||
theorem size_filter_pos_iff {xs : Array α} {p : α → Bool} :
|
||||
0 < (filter p xs).size ↔ ∃ x ∈ xs, p x := by
|
||||
rcases xs with ⟨xs⟩
|
||||
simp
|
||||
|
||||
@[simp]
|
||||
theorem size_filter_lt_size_iff_exists {xs : Array α} {p : α → Bool} :
|
||||
(filter p xs).size < xs.size ↔ ∃ x ∈ xs, ¬p x := by
|
||||
rcases xs with ⟨xs⟩
|
||||
simp
|
||||
|
||||
/-! ### filterMap -/
|
||||
|
||||
@[congr]
|
||||
@@ -1563,6 +1602,18 @@ theorem filterMap_eq_push_iff {f : α → Option β} {xs : Array α} {ys : Array
|
||||
· rintro ⟨⟨l₁⟩, a, ⟨l₂⟩, h₁, h₂, h₃, h₄⟩
|
||||
refine ⟨l₂.reverse, a, l₁.reverse, by simp_all⟩
|
||||
|
||||
@[simp]
|
||||
theorem size_filterMap_pos_iff {xs : Array α} {f : α → Option β} :
|
||||
0 < (filterMap f xs).size ↔ ∃ (x : α) (_ : x ∈ xs) (b : β), f x = some b := by
|
||||
rcases xs with ⟨xs⟩
|
||||
simp
|
||||
|
||||
@[simp]
|
||||
theorem size_filterMap_lt_size_iff_exists {xs : Array α} {f : α → Option β} :
|
||||
(filterMap f xs).size < xs.size ↔ ∃ (x : α) (_ : x ∈ xs), f x = none := by
|
||||
rcases xs with ⟨xs⟩
|
||||
simp
|
||||
|
||||
/-! ### singleton -/
|
||||
|
||||
@[simp] theorem singleton_def (v : α) : Array.singleton v = #[v] := rfl
|
||||
@@ -1970,7 +2021,7 @@ theorem flatten_eq_flatMap {xss : Array (Array α)} : flatten xss = xss.flatMap
|
||||
rw [← Function.comp_def, ← List.map_map, flatten_toArray_map]
|
||||
|
||||
theorem flatten_filter_not_isEmpty {xss : Array (Array α)} :
|
||||
flatten (xss.filter fun l => !l.isEmpty) = xss.flatten := by
|
||||
flatten (xss.filter fun xs => !xs.isEmpty) = xss.flatten := by
|
||||
induction xss using array₂_induction
|
||||
simp [List.filter_map, Function.comp_def, List.flatten_filter_not_isEmpty]
|
||||
|
||||
@@ -3185,6 +3236,499 @@ theorem foldr_rel {xs : Array α} {f g : α → β → β} {a b : β} (r : β
|
||||
rcases xs with ⟨xs⟩
|
||||
simp
|
||||
|
||||
/-! #### Further results about `back` and `back?` -/
|
||||
|
||||
@[simp] theorem back?_eq_none_iff {xs : Array α} : xs.back? = none ↔ xs = #[] := by
|
||||
simp only [back?_eq_getElem?, ← size_eq_zero_iff]
|
||||
simp only [_root_.getElem?_eq_none_iff]
|
||||
omega
|
||||
|
||||
theorem back?_eq_some_iff {xs : Array α} {a : α} :
|
||||
xs.back? = some a ↔ ∃ ys : Array α, xs = ys.push a := by
|
||||
rcases xs with ⟨xs⟩
|
||||
simp only [List.back?_toArray, List.getLast?_eq_some_iff, toArray_eq, push_toList]
|
||||
constructor
|
||||
· rintro ⟨ys, rfl⟩
|
||||
exact ⟨ys.toArray, by simp⟩
|
||||
· rintro ⟨ys, rfl⟩
|
||||
exact ⟨ys.toList, by simp⟩
|
||||
|
||||
@[simp] theorem back?_isSome : xs.back?.isSome ↔ xs ≠ #[] := by
|
||||
cases xs
|
||||
simp
|
||||
|
||||
theorem mem_of_back? {xs : Array α} {a : α} (h : xs.back? = some a) : a ∈ xs := by
|
||||
obtain ⟨ys, rfl⟩ := back?_eq_some_iff.1 h
|
||||
simp
|
||||
|
||||
@[simp] theorem back_append_of_size_pos {xs ys : Array α} {h₁} (h₂ : 0 < ys.size) :
|
||||
(xs ++ ys).back h₁ = ys.back h₂ := by
|
||||
rcases xs with ⟨l⟩
|
||||
rcases ys with ⟨l'⟩
|
||||
simp only [List.append_toArray, List.back_toArray]
|
||||
rw [List.getLast_append_of_ne_nil]
|
||||
|
||||
theorem back_append {xs : Array α} (h : 0 < (xs ++ ys).size) :
|
||||
(xs ++ ys).back h =
|
||||
if h' : ys.isEmpty then
|
||||
xs.back (by simp_all)
|
||||
else
|
||||
ys.back (by simp only [isEmpty_iff, eq_empty_iff_size_eq_zero] at h'; omega) := by
|
||||
rcases xs with ⟨xs⟩
|
||||
rcases ys with ⟨ys⟩
|
||||
simp only [List.append_toArray, List.back_toArray, List.getLast_append, List.isEmpty_iff,
|
||||
List.isEmpty_toArray]
|
||||
split
|
||||
· rw [dif_pos]
|
||||
simpa only [List.isEmpty_toArray]
|
||||
· rw [dif_neg]
|
||||
simpa only [List.isEmpty_toArray]
|
||||
|
||||
theorem back_append_right {xs ys : Array α} (h : 0 < ys.size) :
|
||||
(xs ++ ys).back (by simp; omega) = ys.back h := by
|
||||
rcases xs with ⟨xs⟩
|
||||
rcases ys with ⟨ys⟩
|
||||
simp only [List.append_toArray, List.back_toArray]
|
||||
rw [List.getLast_append_right]
|
||||
|
||||
theorem back_append_left {xs ys : Array α} (w : 0 < (xs ++ ys).size) (h : ys.size = 0) :
|
||||
(xs ++ ys).back w = xs.back (by simp_all) := by
|
||||
rcases xs with ⟨xs⟩
|
||||
rcases ys with ⟨ys⟩
|
||||
simp only [List.append_toArray, List.back_toArray]
|
||||
rw [List.getLast_append_left]
|
||||
simpa using h
|
||||
|
||||
@[simp] theorem back?_append {xs ys : Array α} : (xs ++ ys).back? = ys.back?.or xs.back? := by
|
||||
rcases xs with ⟨xs⟩
|
||||
rcases ys with ⟨ys⟩
|
||||
simp only [List.append_toArray, List.back?_toArray]
|
||||
rw [List.getLast?_append]
|
||||
|
||||
theorem back_filter_of_pos {p : α → Bool} {xs : Array α} (w : 0 < xs.size) (h : p (back xs w) = true) :
|
||||
(filter p xs).back (by simpa using ⟨_, by simp, h⟩) = xs.back w := by
|
||||
rcases xs with ⟨xs⟩
|
||||
simp only [List.back_toArray] at h
|
||||
simp only [List.size_toArray, List.filter_toArray', List.back_toArray]
|
||||
rw [List.getLast_filter_of_pos _ h]
|
||||
|
||||
theorem back_filterMap_of_eq_some {f : α → Option β} {xs : Array α} {w : 0 < xs.size} {b : β} (h : f (xs.back w) = some b) :
|
||||
(filterMap f xs).back (by simpa using ⟨_, by simp, b, h⟩) = some b := by
|
||||
rcases xs with ⟨xs⟩
|
||||
simp only [List.back_toArray] at h
|
||||
simp only [List.size_toArray, List.filterMap_toArray', List.back_toArray]
|
||||
rw [List.getLast_filterMap_of_eq_some h]
|
||||
|
||||
theorem back?_flatMap {xs : Array α} {f : α → Array β} :
|
||||
(xs.flatMap f).back? = xs.reverse.findSome? fun a => (f a).back? := by
|
||||
rcases xs with ⟨xs⟩
|
||||
simp [List.getLast?_flatMap]
|
||||
|
||||
theorem back?_flatten {xss : Array (Array α)} :
|
||||
(flatten xss).back? = xss.reverse.findSome? fun xs => xs.back? := by
|
||||
simp [← flatMap_id, back?_flatMap]
|
||||
|
||||
theorem back?_mkArray (a : α) (n : Nat) :
|
||||
(mkArray n a).back? = if n = 0 then none else some a := by
|
||||
rw [mkArray_eq_toArray_replicate]
|
||||
simp only [List.back?_toArray, List.getLast?_replicate]
|
||||
|
||||
@[simp] theorem back_mkArray (w : 0 < n) : (mkArray n a).back (by simpa using w) = a := by
|
||||
simp [back_eq_getElem]
|
||||
|
||||
/-! ## Additional operations -/
|
||||
|
||||
/-! ### leftpad -/
|
||||
|
||||
-- We unfold `leftpad` and `rightpad` for verification purposes.
|
||||
attribute [simp] leftpad rightpad
|
||||
|
||||
theorem size_leftpad (n : Nat) (a : α) (xs : Array α) :
|
||||
(leftpad n a xs).size = max n xs.size := by simp; omega
|
||||
|
||||
theorem size_rightpad (n : Nat) (a : α) (xs : Array α) :
|
||||
(rightpad n a xs).size = max n xs.size := by simp; omega
|
||||
|
||||
/-! ### contains -/
|
||||
|
||||
theorem elem_cons_self [BEq α] [LawfulBEq α] {xs : Array α} {a : α} : (xs.push a).elem a = true := by simp
|
||||
|
||||
theorem contains_eq_any_beq [BEq α] (xs : Array α) (a : α) : xs.contains a = xs.any (a == ·) := by
|
||||
rcases xs with ⟨xs⟩
|
||||
simp [List.contains_eq_any_beq]
|
||||
|
||||
theorem contains_iff_exists_mem_beq [BEq α] {xs : Array α} {a : α} :
|
||||
xs.contains a ↔ ∃ a' ∈ xs, a == a' := by
|
||||
rcases xs with ⟨xs⟩
|
||||
simp [List.contains_iff_exists_mem_beq]
|
||||
|
||||
theorem contains_iff_mem [BEq α] [LawfulBEq α] {xs : Array α} {a : α} :
|
||||
xs.contains a ↔ a ∈ xs := by
|
||||
simp
|
||||
|
||||
/-! ### more lemmas about `pop` -/
|
||||
|
||||
@[simp] theorem pop_empty : (#[] : Array α).pop = #[] := rfl
|
||||
|
||||
@[simp] theorem pop_push (xs : Array α) : (xs.push x).pop = xs := by simp [pop]
|
||||
|
||||
@[simp] theorem getElem_pop {xs : Array α} {i : Nat} (h : i < xs.pop.size) :
|
||||
xs.pop[i] = xs[i]'(by simp at h; omega) := by
|
||||
rcases xs with ⟨xs⟩
|
||||
simp [List.getElem_dropLast]
|
||||
|
||||
theorem getElem?_pop (xs : Array α) (i : Nat) :
|
||||
xs.pop[i]? = if i < xs.size - 1 then xs[i]? else none := by
|
||||
rcases xs with ⟨xs⟩
|
||||
simp [List.getElem?_dropLast]
|
||||
|
||||
theorem back_pop {xs : Array α} (h) :
|
||||
xs.pop.back h =
|
||||
xs[xs.size - 2]'(by simp at h; omega) := by
|
||||
rcases xs with ⟨xs⟩
|
||||
simp [List.getLast_dropLast]
|
||||
|
||||
theorem back?_pop {xs : Array α} :
|
||||
xs.pop.back? = if xs.size ≤ 1 then none else xs[xs.size - 2]? := by
|
||||
rcases xs with ⟨xs⟩
|
||||
simp [List.getLast?_dropLast]
|
||||
|
||||
@[simp] theorem pop_append_of_ne_empty {xs : Array α} {ys : Array α} (h : ys ≠ #[]) :
|
||||
(xs ++ ys).pop = xs ++ ys.pop := by
|
||||
rcases xs with ⟨xs⟩
|
||||
rcases ys with ⟨ys⟩
|
||||
simp only [List.append_toArray, List.pop_toArray, mk.injEq]
|
||||
rw [List.dropLast_append_of_ne_nil _ (by simpa using h)]
|
||||
|
||||
theorem pop_append {xs ys : Array α} :
|
||||
(xs ++ ys).pop = if ys.isEmpty then xs.pop else xs ++ ys.pop := by
|
||||
split <;> simp_all
|
||||
|
||||
@[simp] theorem pop_mkArray (n) (a : α) : (mkArray n a).pop = mkArray (n - 1) a := by
|
||||
ext <;> simp
|
||||
|
||||
theorem eq_push_pop_back!_of_size_ne_zero [Inhabited α] {xs : Array α} (h : xs.size ≠ 0) :
|
||||
xs = xs.pop.push xs.back! := by
|
||||
apply ext
|
||||
· simp [Nat.sub_add_cancel (Nat.zero_lt_of_ne_zero h)]
|
||||
· intros i h h'
|
||||
if hlt : i < xs.pop.size then
|
||||
rw [getElem_push_lt (h:=hlt), getElem_pop]
|
||||
else
|
||||
have heq : i = xs.pop.size :=
|
||||
Nat.le_antisymm (size_pop .. ▸ Nat.le_pred_of_lt h) (Nat.le_of_not_gt hlt)
|
||||
cases heq
|
||||
rw [getElem_push_eq, back!]
|
||||
simp [← getElem!_pos]
|
||||
|
||||
/-! ### replace -/
|
||||
|
||||
section replace
|
||||
variable [BEq α]
|
||||
|
||||
@[simp] theorem size_replace {xs : Array α} : (xs.replace a b).size = xs.size := by
|
||||
simp only [replace]
|
||||
split <;> simp
|
||||
|
||||
-- This hypothesis could probably be dropped from some of the lemmas below,
|
||||
-- by proving them direct from the definition rather than going via `List`.
|
||||
variable [LawfulBEq α]
|
||||
|
||||
@[simp] theorem replace_of_not_mem {xs : Array α} (h : ¬ a ∈ xs) : xs.replace a b = xs := by
|
||||
cases xs
|
||||
simp_all
|
||||
|
||||
theorem getElem?_replace {xs : Array α} {i : Nat} :
|
||||
(xs.replace a b)[i]? = if xs[i]? == some a then if a ∈ xs.take i then some a else some b else xs[i]? := by
|
||||
rcases xs with ⟨xs⟩
|
||||
simp only [List.replace_toArray, List.getElem?_toArray, List.getElem?_replace, beq_iff_eq,
|
||||
take_eq_extract, List.extract_toArray, List.extract_eq_drop_take, Nat.sub_zero, List.drop_zero,
|
||||
mem_toArray]
|
||||
split <;> rename_i h
|
||||
· rw (occs := [2]) [if_pos]
|
||||
simpa using h
|
||||
· rw [if_neg]
|
||||
simpa using h
|
||||
|
||||
theorem getElem?_replace_of_ne {xs : Array α} {i : Nat} (h : xs[i]? ≠ some a) :
|
||||
(xs.replace a b)[i]? = xs[i]? := by
|
||||
simp_all [getElem?_replace]
|
||||
|
||||
theorem getElem_replace {xs : Array α} {i : Nat} (h : i < xs.size) :
|
||||
(xs.replace a b)[i]'(by simpa) = if xs[i] == a then if a ∈ xs.take i then a else b else xs[i] := by
|
||||
apply Option.some.inj
|
||||
rw [← getElem?_eq_getElem, getElem?_replace]
|
||||
split <;> split <;> simp_all
|
||||
|
||||
theorem getElem_replace_of_ne {xs : Array α} {i : Nat} {h : i < xs.size} (h' : xs[i] ≠ a) :
|
||||
(xs.replace a b)[i]'(by simpa) = xs[i]'(h) := by
|
||||
rw [getElem_replace h]
|
||||
simp [h']
|
||||
|
||||
theorem replace_append {xs ys : Array α} :
|
||||
(xs ++ ys).replace a b = if a ∈ xs then xs.replace a b ++ ys else xs ++ ys.replace a b := by
|
||||
rcases xs with ⟨xs⟩
|
||||
rcases ys with ⟨ys⟩
|
||||
simp only [List.append_toArray, List.replace_toArray, List.replace_append, mem_toArray]
|
||||
split <;> simp
|
||||
|
||||
theorem replace_append_left {xs ys : Array α} (h : a ∈ xs) :
|
||||
(xs ++ ys).replace a b = xs.replace a b ++ ys := by
|
||||
simp [replace_append, h]
|
||||
|
||||
theorem replace_append_right {xs ys : Array α} (h : ¬ a ∈ xs) :
|
||||
(xs ++ ys).replace a b = xs ++ ys.replace a b := by
|
||||
simp [replace_append, h]
|
||||
|
||||
theorem replace_extract {xs : Array α} {i : Nat} :
|
||||
(xs.extract 0 i).replace a b = (xs.replace a b).extract 0 i := by
|
||||
rcases xs with ⟨xs⟩
|
||||
simp [List.replace_take]
|
||||
|
||||
@[simp] theorem replace_mkArray_self {a : α} (h : 0 < n) :
|
||||
(mkArray n a).replace a b = #[b] ++ mkArray (n - 1) a := by
|
||||
cases n <;> simp_all [mkArray_succ', replace_append]
|
||||
|
||||
@[simp] theorem replace_mkArray_ne {a b c : α} (h : !b == a) :
|
||||
(mkArray n a).replace b c = mkArray n a := by
|
||||
rw [replace_of_not_mem]
|
||||
simp_all
|
||||
|
||||
end replace
|
||||
|
||||
/-! ## Logic -/
|
||||
|
||||
/-! ### any / all -/
|
||||
|
||||
theorem not_any_eq_all_not (xs : Array α) (p : α → Bool) : (!xs.any p) = xs.all fun a => !p a := by
|
||||
rcases xs with ⟨xs⟩
|
||||
simp [List.not_any_eq_all_not]
|
||||
|
||||
theorem not_all_eq_any_not (xs : Array α) (p : α → Bool) : (!xs.all p) = xs.any fun a => !p a := by
|
||||
rcases xs with ⟨xs⟩
|
||||
simp [List.not_all_eq_any_not]
|
||||
|
||||
theorem and_any_distrib_left (xs : Array α) (p : α → Bool) (q : Bool) :
|
||||
(q && xs.any p) = xs.any fun a => q && p a := by
|
||||
rcases xs with ⟨xs⟩
|
||||
simp [List.and_any_distrib_left]
|
||||
|
||||
theorem and_any_distrib_right (xs : Array α) (p : α → Bool) (q : Bool) :
|
||||
(xs.any p && q) = xs.any fun a => p a && q := by
|
||||
rcases xs with ⟨xs⟩
|
||||
simp [List.and_any_distrib_right]
|
||||
|
||||
theorem or_all_distrib_left (xs : Array α) (p : α → Bool) (q : Bool) :
|
||||
(q || xs.all p) = xs.all fun a => q || p a := by
|
||||
rcases xs with ⟨xs⟩
|
||||
simp [List.or_all_distrib_left]
|
||||
|
||||
theorem or_all_distrib_right (xs : Array α) (p : α → Bool) (q : Bool) :
|
||||
(xs.all p || q) = xs.all fun a => p a || q := by
|
||||
rcases xs with ⟨xs⟩
|
||||
simp [List.or_all_distrib_right]
|
||||
|
||||
theorem any_eq_not_all_not (xs : Array α) (p : α → Bool) : xs.any p = !xs.all (!p .) := by
|
||||
simp only [not_all_eq_any_not, Bool.not_not]
|
||||
|
||||
/-- Variant of `any_map` with a side condition for the `stop` argument. -/
|
||||
@[simp] theorem any_map' {xs : Array α} {p : β → Bool} (w : stop = xs.size):
|
||||
(xs.map f).any p 0 stop = xs.any (p ∘ f) := by
|
||||
subst w
|
||||
rcases xs with ⟨xs⟩
|
||||
rw [List.map_toArray]
|
||||
simp [List.any_map]
|
||||
|
||||
/-- Variant of `all_map` with a side condition for the `stop` argument. -/
|
||||
@[simp] theorem all_map' {xs : Array α} {p : β → Bool} (w : stop = xs.size):
|
||||
(xs.map f).all p 0 stop = xs.all (p ∘ f) := by
|
||||
subst w
|
||||
rcases xs with ⟨xs⟩
|
||||
rw [List.map_toArray]
|
||||
simp [List.all_map]
|
||||
|
||||
theorem any_map {xs : Array α} {p : β → Bool} : (xs.map f).any p = xs.any (p ∘ f) := by
|
||||
simp
|
||||
|
||||
theorem all_map {xs : Array α} {p : β → Bool} : (xs.map f).all p = xs.all (p ∘ f) := by
|
||||
simp
|
||||
|
||||
/-- Variant of `any_filter` with a side condition for the `stop` argument. -/
|
||||
@[simp] theorem any_filter' {xs : Array α} {p q : α → Bool} (w : stop = (xs.filter p).size) :
|
||||
(xs.filter p).any q 0 stop = xs.any fun a => p a && q a := by
|
||||
subst w
|
||||
rcases xs with ⟨xs⟩
|
||||
rw [List.filter_toArray]
|
||||
simp [List.any_filter]
|
||||
|
||||
/-- Variant of `all_filter` with a side condition for the `stop` argument. -/
|
||||
@[simp] theorem all_filter' {xs : Array α} {p q : α → Bool} (w : stop = (xs.filter p).size) :
|
||||
(xs.filter p).all q 0 stop = xs.all fun a => p a → q a := by
|
||||
subst w
|
||||
rcases xs with ⟨xs⟩
|
||||
rw [List.filter_toArray]
|
||||
simp [List.all_filter]
|
||||
|
||||
theorem any_filter {xs : Array α} {p q : α → Bool} :
|
||||
(xs.filter p).any q 0 = xs.any fun a => p a && q a := by
|
||||
simp
|
||||
|
||||
theorem all_filter {xs : Array α} {p q : α → Bool} :
|
||||
(xs.filter p).all q 0 = xs.all fun a => p a → q a := by
|
||||
simp
|
||||
|
||||
/-- Variant of `any_filterMap` with a side condition for the `stop` argument. -/
|
||||
@[simp] theorem any_filterMap' {xs : Array α} {f : α → Option β} {p : β → Bool} (w : stop = (xs.filterMap f).size) :
|
||||
(xs.filterMap f).any p 0 stop = xs.any fun a => match f a with | some b => p b | none => false := by
|
||||
subst w
|
||||
rcases xs with ⟨xs⟩
|
||||
rw [List.filterMap_toArray]
|
||||
simp [List.any_filterMap]
|
||||
rfl
|
||||
|
||||
/-- Variant of `all_filterMap` with a side condition for the `stop` argument. -/
|
||||
@[simp] theorem all_filterMap' {xs : Array α} {f : α → Option β} {p : β → Bool} (w : stop = (xs.filterMap f).size) :
|
||||
(xs.filterMap f).all p 0 stop = xs.all fun a => match f a with | some b => p b | none => true := by
|
||||
subst w
|
||||
rcases xs with ⟨xs⟩
|
||||
rw [List.filterMap_toArray]
|
||||
simp [List.all_filterMap]
|
||||
rfl
|
||||
|
||||
theorem any_filterMap {xs : Array α} {f : α → Option β} {p : β → Bool} :
|
||||
(xs.filterMap f).any p 0 = xs.any fun a => match f a with | some b => p b | none => false := by
|
||||
simp
|
||||
|
||||
theorem all_filterMap {xs : Array α} {f : α → Option β} {p : β → Bool} :
|
||||
(xs.filterMap f).all p 0 = xs.all fun a => match f a with | some b => p b | none => true := by
|
||||
simp
|
||||
|
||||
/-- Variant of `any_append` with a side condition for the `stop` argument. -/
|
||||
@[simp] theorem any_append' {xs ys : Array α} (w : stop = (xs ++ ys).size) :
|
||||
(xs ++ ys).any f 0 stop = (xs.any f || ys.any f) := by
|
||||
subst w
|
||||
rcases xs with ⟨xs⟩
|
||||
rcases ys with ⟨ys⟩
|
||||
rw [List.append_toArray]
|
||||
simp [List.any_append]
|
||||
|
||||
/-- Variant of `all_append` with a side condition for the `stop` argument. -/
|
||||
@[simp] theorem all_append' {xs ys : Array α} (w : stop = (xs ++ ys).size) :
|
||||
(xs ++ ys).all f 0 stop = (xs.all f && ys.all f) := by
|
||||
subst w
|
||||
rcases xs with ⟨xs⟩
|
||||
rcases ys with ⟨ys⟩
|
||||
rw [List.append_toArray]
|
||||
simp [List.all_append]
|
||||
|
||||
theorem any_append {xs ys : Array α} :
|
||||
(xs ++ ys).any f 0 = (xs.any f || ys.any f) := by
|
||||
simp
|
||||
|
||||
theorem all_append {xs ys : Array α} :
|
||||
(xs ++ ys).all f 0 = (xs.all f && ys.all f) := by
|
||||
simp
|
||||
|
||||
@[congr] theorem anyM_congr [Monad m]
|
||||
{xs ys : Array α} (w : xs = ys) {p q : α → m Bool} (h : ∀ a, p a = q a) (wstart : start₁ = start₂) (wstop : stop₁ = stop₂) :
|
||||
xs.anyM p start₁ stop₁ = ys.anyM q start₂ stop₂ := by
|
||||
have : p = q := by funext a; apply h
|
||||
subst this
|
||||
subst w
|
||||
subst wstart
|
||||
subst wstop
|
||||
rfl
|
||||
|
||||
@[congr] theorem any_congr
|
||||
{xs ys : Array α} (w : xs = ys) {p q : α → Bool} (h : ∀ a, p a = q a) (wstart : start₁ = start₂) (wstop : stop₁ = stop₂) :
|
||||
xs.any p start₁ stop₁ = ys.any q start₂ stop₂ := by
|
||||
unfold any
|
||||
apply anyM_congr w h wstart wstop
|
||||
|
||||
@[congr] theorem allM_congr [Monad m]
|
||||
{xs ys : Array α} (w : xs = ys) {p q : α → m Bool} (h : ∀ a, p a = q a) (wstart : start₁ = start₂) (wstop : stop₁ = stop₂) :
|
||||
xs.allM p start₁ stop₁ = ys.allM q start₂ stop₂ := by
|
||||
have : p = q := by funext a; apply h
|
||||
subst this
|
||||
subst w
|
||||
subst wstart
|
||||
subst wstop
|
||||
rfl
|
||||
|
||||
@[congr] theorem all_congr
|
||||
{xs ys : Array α} (w : xs = ys) {p q : α → Bool} (h : ∀ a, p a = q a) (wstart : start₁ = start₂) (wstop : stop₁ = stop₂) :
|
||||
xs.all p start₁ stop₁ = ys.all q start₂ stop₂ := by
|
||||
unfold all
|
||||
apply allM_congr w h wstart wstop
|
||||
|
||||
@[simp] theorem any_flatten' {xss : Array (Array α)} (w : stop = xss.flatten.size) : xss.flatten.any f 0 stop = xss.any (any · f) := by
|
||||
subst w
|
||||
cases xss using array₂_induction
|
||||
simp [Function.comp_def]
|
||||
|
||||
@[simp] theorem all_flatten' {xss : Array (Array α)} (w : stop = xss.flatten.size) : xss.flatten.all f 0 stop = xss.all (all · f) := by
|
||||
subst w
|
||||
cases xss using array₂_induction
|
||||
simp [Function.comp_def]
|
||||
|
||||
theorem any_flatten {xss : Array (Array α)} : xss.flatten.any f = xss.any (any · f) := by
|
||||
simp
|
||||
|
||||
theorem all_flatten {xss : Array (Array α)} : xss.flatten.all f = xss.all (all · f) := by
|
||||
simp
|
||||
|
||||
/-- Variant of `any_flatMap` with a side condition for the `stop` argument. -/
|
||||
@[simp] theorem any_flatMap' {xs : Array α} {f : α → Array β} {p : β → Bool} (w : stop = (xs.flatMap f).size) :
|
||||
(xs.flatMap f).any p 0 stop = xs.any fun a => (f a).any p := by
|
||||
subst w
|
||||
rcases xs with ⟨xs⟩
|
||||
rw [List.flatMap_toArray]
|
||||
simp [List.any_flatMap]
|
||||
|
||||
/-- Variant of `all_flatMap` with a side condition for the `stop` argument. -/
|
||||
@[simp] theorem all_flatMap' {xs : Array α} {f : α → Array β} {p : β → Bool} (w : stop = (xs.flatMap f).size) :
|
||||
(xs.flatMap f).all p 0 stop = xs.all fun a => (f a).all p := by
|
||||
subst w
|
||||
rcases xs with ⟨xs⟩
|
||||
rw [List.flatMap_toArray]
|
||||
simp [List.all_flatMap]
|
||||
|
||||
theorem any_flatMap {xs : Array α} {f : α → Array β} {p : β → Bool} :
|
||||
(xs.flatMap f).any p 0 = xs.any fun a => (f a).any p := by
|
||||
simp
|
||||
|
||||
theorem all_flatMap {xs : Array α} {f : α → Array β} {p : β → Bool} :
|
||||
(xs.flatMap f).all p 0 = xs.all fun a => (f a).all p := by
|
||||
simp
|
||||
|
||||
/-- Variant of `any_reverse` with a side condition for the `stop` argument. -/
|
||||
@[simp] theorem any_reverse' {xs : Array α} (w : stop = xs.size) : xs.reverse.any f 0 stop = xs.any f := by
|
||||
subst w
|
||||
rcases xs with ⟨xs⟩
|
||||
rw [List.reverse_toArray]
|
||||
simp [List.any_reverse]
|
||||
|
||||
/-- Variant of `all_reverse` with a side condition for the `stop` argument. -/
|
||||
@[simp] theorem all_reverse' {xs : Array α} (w : stop = xs.size) : xs.reverse.all f 0 stop = xs.all f := by
|
||||
subst w
|
||||
rcases xs with ⟨xs⟩
|
||||
rw [List.reverse_toArray]
|
||||
simp [List.all_reverse]
|
||||
|
||||
theorem any_reverse {xs : Array α} : xs.reverse.any f 0 = xs.any f := by
|
||||
simp
|
||||
|
||||
theorem all_reverse {xs : Array α} : xs.reverse.all f 0 = xs.all f := by
|
||||
simp
|
||||
|
||||
@[simp] theorem any_mkArray {n : Nat} {a : α} :
|
||||
(mkArray n a).any f = if n = 0 then false else f a := by
|
||||
induction n <;> simp_all [mkArray_succ']
|
||||
|
||||
@[simp] theorem all_mkArray {n : Nat} {a : α} :
|
||||
(mkArray n a).all f = if n = 0 then true else f a := by
|
||||
induction n <;> simp_all +contextual [mkArray_succ']
|
||||
|
||||
/-! Content below this point has not yet been aligned with `List`. -/
|
||||
|
||||
/-! ### sum -/
|
||||
@@ -3363,10 +3907,6 @@ theorem back!_eq_back? [Inhabited α] (xs : Array α) : xs.back! = xs.back?.getD
|
||||
@[simp] theorem back!_push [Inhabited α] (xs : Array α) : (xs.push x).back! = x := by
|
||||
simp [back!_eq_back?]
|
||||
|
||||
theorem mem_of_back? {xs : Array α} {a : α} (h : xs.back? = some a) : a ∈ xs := by
|
||||
cases xs
|
||||
simpa using List.mem_of_getLast? (by simpa using h)
|
||||
|
||||
@[deprecated mem_of_back? (since := "2024-10-21")] abbrev mem_of_back?_eq_some := @mem_of_back?
|
||||
|
||||
theorem getElem?_push_lt (xs : Array α) (x : α) (i : Nat) (h : i < xs.size) :
|
||||
@@ -3428,28 +3968,6 @@ theorem swapAt!_def (xs : Array α) (i : Nat) (v : α) (h : i < xs.size) :
|
||||
· simp
|
||||
· rfl
|
||||
|
||||
@[simp] theorem pop_empty : (#[] : Array α).pop = #[] := rfl
|
||||
|
||||
@[simp] theorem pop_push (xs : Array α) : (xs.push x).pop = xs := by simp [pop]
|
||||
|
||||
@[simp] theorem getElem_pop (xs : Array α) (i : Nat) (hi : i < xs.pop.size) :
|
||||
xs.pop[i] = xs[i]'(Nat.lt_of_lt_of_le (xs.size_pop ▸ hi) (Nat.sub_le _ _)) :=
|
||||
List.getElem_dropLast ..
|
||||
|
||||
theorem eq_push_pop_back!_of_size_ne_zero [Inhabited α] {xs : Array α} (h : xs.size ≠ 0) :
|
||||
xs = xs.pop.push xs.back! := by
|
||||
apply ext
|
||||
· simp [Nat.sub_add_cancel (Nat.zero_lt_of_ne_zero h)]
|
||||
· intros i h h'
|
||||
if hlt : i < xs.pop.size then
|
||||
rw [getElem_push_lt (h:=hlt), getElem_pop]
|
||||
else
|
||||
have heq : i = xs.pop.size :=
|
||||
Nat.le_antisymm (size_pop .. ▸ Nat.le_pred_of_lt h) (Nat.le_of_not_gt hlt)
|
||||
cases heq
|
||||
rw [getElem_push_eq, back!]
|
||||
simp [← getElem!_pos]
|
||||
|
||||
theorem eq_push_of_size_ne_zero {xs : Array α} (h : xs.size ≠ 0) :
|
||||
∃ (bs : Array α) (c : α), xs = bs.push c :=
|
||||
let _ : Inhabited α := ⟨xs[0]⟩
|
||||
|
||||
@@ -8,8 +8,8 @@ import Init.Data.Array.Basic
|
||||
import Init.Data.Nat.Lemmas
|
||||
import Init.Data.Range
|
||||
|
||||
-- set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
-- set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
|
||||
namespace Array
|
||||
|
||||
|
||||
@@ -7,8 +7,8 @@ prelude
|
||||
import Init.Data.Array.Lemmas
|
||||
import Init.Data.List.Lex
|
||||
|
||||
-- set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
-- set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
|
||||
namespace Array
|
||||
|
||||
|
||||
@@ -8,8 +8,8 @@ import Init.Data.Array.Lemmas
|
||||
import Init.Data.Array.Attach
|
||||
import Init.Data.List.MapIdx
|
||||
|
||||
-- set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
-- set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
|
||||
namespace Array
|
||||
|
||||
|
||||
@@ -8,8 +8,8 @@ import Init.Data.Array.Basic
|
||||
import Init.Data.Nat.Linear
|
||||
import Init.Data.List.BasicAux
|
||||
|
||||
-- set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
-- set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
|
||||
namespace Array
|
||||
|
||||
|
||||
@@ -12,8 +12,8 @@ import Init.Data.List.Monadic
|
||||
# Lemmas about `Array.forIn'` and `Array.forIn`.
|
||||
-/
|
||||
|
||||
-- set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
-- set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
|
||||
namespace Array
|
||||
|
||||
|
||||
@@ -11,8 +11,8 @@ import Init.Data.List.OfFn
|
||||
# Theorems about `Array.ofFn`
|
||||
-/
|
||||
|
||||
-- set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
-- set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
|
||||
namespace Array
|
||||
|
||||
|
||||
@@ -7,8 +7,8 @@ prelude
|
||||
import Init.Data.List.Nat.Perm
|
||||
import Init.Data.Array.Lemmas
|
||||
|
||||
-- set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
-- set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
|
||||
namespace Array
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ prelude
|
||||
import Init.Data.Vector.Basic
|
||||
import Init.Data.Ord
|
||||
|
||||
-- set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
-- We do not enable `linter.indexVariables` because it is helpful to name index variables `lo`, `mid`, `hi`, etc.
|
||||
|
||||
namespace Array
|
||||
|
||||
@@ -15,8 +15,8 @@ import Init.Data.List.Nat.Range
|
||||
|
||||
-/
|
||||
|
||||
-- set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
-- set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
|
||||
namespace Array
|
||||
|
||||
@@ -31,7 +31,7 @@ theorem range'_succ (s n step) : range' s (n + 1) step = #[s] ++ range' (s + ste
|
||||
simp [List.range'_succ]
|
||||
|
||||
@[simp] theorem range'_eq_empty_iff : range' s n step = #[] ↔ n = 0 := by
|
||||
rw [← size_eq_zero, size_range']
|
||||
rw [← size_eq_zero_iff, size_range']
|
||||
|
||||
theorem range'_ne_empty_iff (s : Nat) {n step : Nat} : range' s n step ≠ #[] ↔ n ≠ 0 := by
|
||||
cases n <;> simp
|
||||
@@ -136,7 +136,7 @@ theorem range'_eq_map_range (s n : Nat) : range' s n = map (s + ·) (range n) :=
|
||||
rw [range_eq_range', map_add_range']; rfl
|
||||
|
||||
@[simp] theorem range_eq_empty_iff {n : Nat} : range n = #[] ↔ n = 0 := by
|
||||
rw [← size_eq_zero, size_range]
|
||||
rw [← size_eq_zero_iff, size_range]
|
||||
|
||||
theorem range_ne_empty_iff {n : Nat} : range n ≠ #[] ↔ n ≠ 0 := by
|
||||
cases n <;> simp
|
||||
@@ -149,9 +149,9 @@ theorem range_succ (n : Nat) : range (succ n) = range n ++ #[n] := by
|
||||
dite_eq_ite]
|
||||
split <;> omega
|
||||
|
||||
theorem range_add (a b : Nat) : range (a + b) = range a ++ (range b).map (a + ·) := by
|
||||
theorem range_add (n m : Nat) : range (n + m) = range n ++ (range m).map (n + ·) := by
|
||||
rw [← range'_eq_map_range]
|
||||
simpa [range_eq_range', Nat.add_comm] using (range'_append_1 0 a b).symm
|
||||
simpa [range_eq_range', Nat.add_comm] using (range'_append_1 0 n m).symm
|
||||
|
||||
theorem reverse_range' (s n : Nat) : reverse (range' s n) = map (s + n - 1 - ·) (range n) := by
|
||||
simp [← toList_inj, List.reverse_range']
|
||||
@@ -164,7 +164,7 @@ theorem not_mem_range_self {n : Nat} : n ∉ range n := by simp
|
||||
|
||||
theorem self_mem_range_succ (n : Nat) : n ∈ range (n + 1) := by simp
|
||||
|
||||
@[simp] theorem take_range (m n : Nat) : take (range n) m = range (min m n) := by
|
||||
@[simp] theorem take_range (i n : Nat) : take (range n) i = range (min i n) := by
|
||||
ext <;> simp
|
||||
|
||||
@[simp] theorem find?_range_eq_some {n : Nat} {i : Nat} {p : Nat → Bool} :
|
||||
|
||||
@@ -6,8 +6,8 @@ Authors: Leonardo de Moura, Mario Carneiro
|
||||
prelude
|
||||
import Init.Tactics
|
||||
|
||||
-- set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
-- set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
|
||||
|
||||
/--
|
||||
|
||||
@@ -6,7 +6,7 @@ Authors: Leonardo de Moura
|
||||
prelude
|
||||
import Init.Data.Array.Basic
|
||||
|
||||
-- set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
|
||||
universe u v w
|
||||
|
||||
|
||||
@@ -15,8 +15,8 @@ automation. Placing them in another module breaks an import cycle, because `omeg
|
||||
array library.
|
||||
-/
|
||||
|
||||
-- set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
-- set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
|
||||
namespace Subarray
|
||||
/--
|
||||
|
||||
@@ -12,8 +12,8 @@ These lemmas are used in the internals of HashMap.
|
||||
They should find a new home and/or be reformulated.
|
||||
-/
|
||||
|
||||
-- set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
-- set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
|
||||
namespace List
|
||||
|
||||
|
||||
@@ -11,8 +11,8 @@ import Init.Data.List.Zip
|
||||
# Lemmas about `Array.zip`, `Array.zipWith`, `Array.zipWithAll`, and `Array.unzip`.
|
||||
-/
|
||||
|
||||
-- set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
-- set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
|
||||
namespace Array
|
||||
|
||||
@@ -114,7 +114,7 @@ theorem map_zipWith {δ : Type _} (f : α → β) (g : γ → δ → α) (cs : A
|
||||
cases ds
|
||||
simp [List.map_zipWith]
|
||||
|
||||
theorem take_zipWith : (zipWith f as bs).take n = zipWith f (as.take n) (bs.take n) := by
|
||||
theorem take_zipWith : (zipWith f as bs).take i = zipWith f (as.take i) (bs.take i) := by
|
||||
cases as
|
||||
cases bs
|
||||
simp [List.take_zipWith]
|
||||
|
||||
@@ -25,7 +25,7 @@ class ReflBEq (α) [BEq α] : Prop where
|
||||
refl : (a : α) == a
|
||||
|
||||
/-- `EquivBEq` says that the `BEq` implementation is an equivalence relation. -/
|
||||
class EquivBEq (α) [BEq α] extends PartialEquivBEq α, ReflBEq α : Prop
|
||||
class EquivBEq (α) [BEq α] : Prop extends PartialEquivBEq α, ReflBEq α
|
||||
|
||||
@[simp]
|
||||
theorem BEq.refl [BEq α] [ReflBEq α] {a : α} : a == a :=
|
||||
|
||||
@@ -907,7 +907,7 @@ The input to the shift subtractor is a legal input to `divrem`, and we also need
|
||||
input bit to perform shift subtraction on, and thus we need `0 < wn`.
|
||||
-/
|
||||
structure DivModState.Poised {w : Nat} (args : DivModArgs w) (qr : DivModState w)
|
||||
extends DivModState.Lawful args qr : Type where
|
||||
extends DivModState.Lawful args qr where
|
||||
/-- Only perform a round of shift-subtract if we have dividend bits. -/
|
||||
hwn_lt : 0 < qr.wn
|
||||
|
||||
|
||||
@@ -1517,8 +1517,8 @@ theorem zero_shiftLeft (n : Nat) : 0#w <<< n = 0#w := by
|
||||
all_goals { simp_all <;> omega }
|
||||
|
||||
@[simp] theorem getElem_shiftLeft {x : BitVec m} {n : Nat} (h : i < m) :
|
||||
(x <<< n)[i] = (!decide (i < n) && getLsbD x (i - n)) := by
|
||||
rw [← testBit_toNat, getElem_eq_testBit_toNat]
|
||||
(x <<< n)[i] = (!decide (i < n) && x[i - n]) := by
|
||||
rw [getElem_eq_testBit_toNat, getElem_eq_testBit_toNat]
|
||||
simp only [toNat_shiftLeft, Nat.testBit_mod_two_pow, Nat.testBit_shiftLeft, ge_iff_le]
|
||||
-- This step could be a case bashing tactic.
|
||||
cases h₁ : decide (i < m) <;> cases h₂ : decide (n ≤ i) <;> cases h₃ : decide (i < n)
|
||||
@@ -1568,8 +1568,8 @@ theorem shiftLeftZeroExtend_eq {x : BitVec w} :
|
||||
· omega
|
||||
|
||||
@[simp] theorem getElem_shiftLeftZeroExtend {x : BitVec m} {n : Nat} (h : i < m + n) :
|
||||
(shiftLeftZeroExtend x n)[i] = ((! decide (i < n)) && getLsbD x (i - n)) := by
|
||||
rw [shiftLeftZeroExtend_eq, getLsbD]
|
||||
(shiftLeftZeroExtend x n)[i] = if h' : i < n then false else x[i - n] := by
|
||||
rw [shiftLeftZeroExtend_eq]
|
||||
simp only [getElem_eq_testBit_toNat, getLsbD_shiftLeft, getLsbD_setWidth]
|
||||
cases h₁ : decide (i < n) <;> cases h₂ : decide (i - n < m + n)
|
||||
<;> simp_all [h]
|
||||
@@ -1598,8 +1598,8 @@ theorem shiftLeftZeroExtend_eq {x : BitVec w} :
|
||||
theorem shiftLeft_add {w : Nat} (x : BitVec w) (n m : Nat) :
|
||||
x <<< (n + m) = (x <<< n) <<< m := by
|
||||
ext i
|
||||
simp only [getElem_shiftLeft, Fin.is_lt, decide_true, Bool.true_and]
|
||||
rw [show i - (n + m) = (i - m - n) by omega]
|
||||
simp only [getElem_shiftLeft]
|
||||
rw [show x[i - (n + m)] = x[i - m - n] by congr 1; omega]
|
||||
cases h₂ : decide (i < m) <;>
|
||||
cases h₃ : decide (i - m < w) <;>
|
||||
cases h₄ : decide (i - m < n) <;>
|
||||
@@ -1632,7 +1632,7 @@ theorem getLsbD_shiftLeft' {x : BitVec w₁} {y : BitVec w₂} {i : Nat} :
|
||||
simp [shiftLeft_eq', getLsbD_shiftLeft]
|
||||
|
||||
theorem getElem_shiftLeft' {x : BitVec w₁} {y : BitVec w₂} {i : Nat} (h : i < w₁) :
|
||||
(x <<< y)[i] = (!decide (i < y.toNat) && x.getLsbD (i - y.toNat)) := by
|
||||
(x <<< y)[i] = (!decide (i < y.toNat) && x[i - y.toNat]) := by
|
||||
simp
|
||||
|
||||
@[simp] theorem shiftLeft_eq_zero {x : BitVec w} {n : Nat} (hn : w ≤ n) : x <<< n = 0#w := by
|
||||
@@ -1844,13 +1844,10 @@ theorem getLsbD_sshiftRight (x : BitVec w) (s i : Nat) :
|
||||
omega
|
||||
|
||||
theorem getElem_sshiftRight {x : BitVec w} {s i : Nat} (h : i < w) :
|
||||
(x.sshiftRight s)[i] = (if s + i < w then x.getLsbD (s + i) else x.msb) := by
|
||||
rcases hmsb : x.msb with rfl | rfl
|
||||
· simp only [sshiftRight_eq_of_msb_false hmsb, getElem_ushiftRight, Bool.if_false_right,
|
||||
Bool.iff_and_self, decide_eq_true_eq]
|
||||
intros hlsb
|
||||
apply BitVec.lt_of_getLsbD hlsb
|
||||
· simp [sshiftRight_eq_of_msb_true hmsb]
|
||||
(x.sshiftRight s)[i] = (if h : s + i < w then x[s + i] else x.msb) := by
|
||||
rw [← getLsbD_eq_getElem, getLsbD_sshiftRight]
|
||||
simp only [show ¬(w ≤ i) by omega, decide_false, Bool.not_false, Bool.true_and]
|
||||
by_cases h' : s + i < w <;> simp [h']
|
||||
|
||||
theorem sshiftRight_xor_distrib (x y : BitVec w) (n : Nat) :
|
||||
(x ^^^ y).sshiftRight n = (x.sshiftRight n) ^^^ (y.sshiftRight n) := by
|
||||
@@ -1957,9 +1954,8 @@ theorem getLsbD_sshiftRight' {x y : BitVec w} {i : Nat} :
|
||||
|
||||
-- This should not be a `@[simp]` lemma as the left hand side is not in simp normal form.
|
||||
theorem getElem_sshiftRight' {x y : BitVec w} {i : Nat} (h : i < w) :
|
||||
(x.sshiftRight' y)[i] =
|
||||
(!decide (w ≤ i) && if y.toNat + i < w then x.getLsbD (y.toNat + i) else x.msb) := by
|
||||
simp only [← getLsbD_eq_getElem, BitVec.sshiftRight', BitVec.getLsbD_sshiftRight]
|
||||
(x.sshiftRight' y)[i] = (if h : y.toNat + i < w then x[y.toNat + i] else x.msb) := by
|
||||
simp [show ¬ w ≤ i by omega, getElem_sshiftRight]
|
||||
|
||||
theorem getMsbD_sshiftRight' {x y: BitVec w} {i : Nat} :
|
||||
(x.sshiftRight y.toNat).getMsbD i =
|
||||
@@ -2030,9 +2026,8 @@ theorem getMsbD_signExtend {x : BitVec w} {v i : Nat} :
|
||||
by_cases h : i < v <;> by_cases h' : v - w ≤ i <;> simp [h, h'] <;> omega
|
||||
|
||||
theorem getElem_signExtend {x : BitVec w} {v i : Nat} (h : i < v) :
|
||||
(x.signExtend v)[i] = if i < w then x.getLsbD i else x.msb := by
|
||||
rw [←getLsbD_eq_getElem, getLsbD_signExtend]
|
||||
simp [h]
|
||||
(x.signExtend v)[i] = if h : i < w then x[i] else x.msb := by
|
||||
simp [←getLsbD_eq_getElem, getLsbD_signExtend, h]
|
||||
|
||||
theorem msb_signExtend {x : BitVec w} :
|
||||
(x.signExtend v).msb = (decide (0 < v) && if w ≥ v then x.getMsbD (w - v) else x.msb) := by
|
||||
@@ -2044,9 +2039,7 @@ theorem msb_signExtend {x : BitVec w} :
|
||||
theorem signExtend_eq_setWidth_of_lt (x : BitVec w) {v : Nat} (hv : v ≤ w):
|
||||
x.signExtend v = x.setWidth v := by
|
||||
ext i h
|
||||
simp only [getElem_signExtend, h, decide_true, Bool.true_and, getElem_setWidth,
|
||||
ite_eq_left_iff, Nat.not_lt]
|
||||
omega
|
||||
simp [getElem_signExtend, show i < w by omega]
|
||||
|
||||
/-- Sign extending to the same bitwidth is a no op. -/
|
||||
theorem signExtend_eq (x : BitVec w) : x.signExtend w = x := by
|
||||
@@ -2101,6 +2094,7 @@ theorem toInt_signExtend_of_lt {x : BitVec w} (hv : w < v):
|
||||
have : (x.signExtend v).msb = x.msb := by
|
||||
rw [msb_eq_getLsbD_last, getLsbD_eq_getElem (Nat.sub_one_lt_of_lt hv)]
|
||||
simp [getElem_signExtend, Nat.le_sub_one_of_lt hv]
|
||||
omega
|
||||
have H : 2^w ≤ 2^v := Nat.pow_le_pow_right (by omega) (by omega)
|
||||
simp only [this, toNat_setWidth, Int.natCast_add, Int.ofNat_emod, Int.natCast_mul]
|
||||
by_cases h : x.msb
|
||||
@@ -2282,11 +2276,11 @@ theorem ushiftRight_eq_extractLsb'_of_lt {x : BitVec w} {n : Nat} (hn : n < w) :
|
||||
theorem shiftLeft_eq_concat_of_lt {x : BitVec w} {n : Nat} (hn : n < w) :
|
||||
x <<< n = (x.extractLsb' 0 (w - n) ++ 0#n).cast (by omega) := by
|
||||
ext i hi
|
||||
simp only [getElem_shiftLeft, getElem_cast, getElem_append, getLsbD_zero, getLsbD_extractLsb',
|
||||
simp only [getElem_shiftLeft, getElem_cast, getElem_append, getElem_zero, getElem_extractLsb',
|
||||
Nat.zero_add, Bool.if_false_left]
|
||||
by_cases hi' : i < n
|
||||
· simp [hi']
|
||||
· simp [hi']
|
||||
· simp [hi', show i - n < w by omega]
|
||||
|
||||
/-! ### rev -/
|
||||
|
||||
@@ -2336,7 +2330,7 @@ theorem getLsbD_cons (b : Bool) {n} (x : BitVec n) (i : Nat) :
|
||||
simp [p1, p2, Nat.testBit_bool_to_nat]
|
||||
|
||||
theorem getElem_cons {b : Bool} {n} {x : BitVec n} {i : Nat} (h : i < n + 1) :
|
||||
(cons b x)[i] = if i = n then b else getLsbD x i := by
|
||||
(cons b x)[i] = if h : i = n then b else x[i] := by
|
||||
simp only [getElem_eq_testBit_toNat, toNat_cons, Nat.testBit_or, getLsbD]
|
||||
rw [Nat.testBit_shiftLeft]
|
||||
rcases Nat.lt_trichotomy i n with i_lt_n | i_eq_n | n_lt_i
|
||||
@@ -2444,7 +2438,7 @@ theorem getLsbD_concat (x : BitVec w) (b : Bool) (i : Nat) :
|
||||
· simp [Nat.div_eq_of_lt b.toNat_lt, Nat.testBit_add_one]
|
||||
|
||||
theorem getElem_concat (x : BitVec w) (b : Bool) (i : Nat) (h : i < w + 1) :
|
||||
(concat x b)[i] = if i = 0 then b else x.getLsbD (i - 1) := by
|
||||
(concat x b)[i] = if h : i = 0 then b else x[i - 1] := by
|
||||
simp only [concat, getElem_eq_testBit_toNat, getLsbD, toNat_append,
|
||||
toNat_ofBool, Nat.testBit_or, Nat.shiftLeft_eq]
|
||||
cases i
|
||||
@@ -2484,10 +2478,7 @@ theorem msb_concat {w : Nat} {b : Bool} {x : BitVec w} :
|
||||
simp only [BitVec.msb, getMsbD_eq_getLsbD, Nat.zero_lt_succ, decide_true, Nat.add_one_sub_one,
|
||||
Nat.sub_zero, Bool.true_and]
|
||||
by_cases h₀ : 0 < w
|
||||
· simp only [Nat.lt_add_one, getLsbD_eq_getElem, getElem_concat, h₀, ↓reduceIte, decide_true,
|
||||
Bool.true_and, ite_eq_right_iff]
|
||||
intro
|
||||
omega
|
||||
· simp [getElem_concat, h₀, show ¬ w = 0 by omega, show w - 1 < w by omega]
|
||||
· simp [h₀, show w = 0 by omega]
|
||||
|
||||
@[simp] theorem toInt_concat (x : BitVec w) (b : Bool) :
|
||||
@@ -4217,6 +4208,10 @@ theorem toInt_abs_eq_natAbs_of_ne_intMin {x : BitVec w} (hx : x ≠ intMin w) :
|
||||
x.abs.toInt = x.toInt.natAbs := by
|
||||
simp [toInt_abs_eq_natAbs, hx]
|
||||
|
||||
theorem toFin_abs {x : BitVec w} :
|
||||
x.abs.toFin = if x.msb then Fin.ofNat' (2 ^ w) (2 ^ w - x.toNat) else x.toFin := by
|
||||
by_cases h : x.msb <;> simp [BitVec.abs, h]
|
||||
|
||||
/-! ### Reverse -/
|
||||
|
||||
theorem getLsbD_reverse {i : Nat} {x : BitVec w} :
|
||||
|
||||
@@ -7,7 +7,6 @@ prelude
|
||||
import Init.Data.Int.Basic
|
||||
import Init.Data.Int.Bitwise
|
||||
import Init.Data.Int.DivMod
|
||||
import Init.Data.Int.DivModLemmas
|
||||
import Init.Data.Int.Gcd
|
||||
import Init.Data.Int.Lemmas
|
||||
import Init.Data.Int.LemmasAux
|
||||
|
||||
@@ -6,6 +6,7 @@ Authors: Siddharth Bhat, Jeremy Avigad
|
||||
prelude
|
||||
import Init.Data.Nat.Bitwise.Lemmas
|
||||
import Init.Data.Int.Bitwise
|
||||
import Init.Data.Int.DivMod.Lemmas
|
||||
|
||||
namespace Int
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE.
|
||||
Authors: Kim Morrison
|
||||
-/
|
||||
prelude
|
||||
import Init.Data.Int.DivModLemmas
|
||||
import Init.Data.Int.DivMod.Lemmas
|
||||
import Init.Data.Int.Gcd
|
||||
|
||||
/-!
|
||||
|
||||
@@ -1,335 +1,9 @@
|
||||
/-
|
||||
Copyright (c) 2016 Jeremy Avigad. All rights reserved.
|
||||
Copyright (c) 2025 Lean FRO, LLC. All rights reserved.
|
||||
Released under Apache 2.0 license as described in the file LICENSE.
|
||||
Authors: Jeremy Avigad, Mario Carneiro
|
||||
Authors: Kim Morrison
|
||||
-/
|
||||
prelude
|
||||
import Init.Data.Int.Basic
|
||||
|
||||
open Nat
|
||||
|
||||
namespace Int
|
||||
|
||||
/-! ## Quotient and remainder
|
||||
|
||||
There are three main conventions for integer division,
|
||||
referred here as the E, F, T rounding conventions.
|
||||
All three pairs satisfy the identity `x % y + (x / y) * y = x` unconditionally,
|
||||
and satisfy `x / 0 = 0` and `x % 0 = x`.
|
||||
|
||||
### Historical notes
|
||||
In early versions of Lean, the typeclasses provided by `/` and `%`
|
||||
were defined in terms of `tdiv` and `tmod`, and these were named simply as `div` and `mod`.
|
||||
|
||||
However we decided it was better to use `ediv` and `emod`,
|
||||
as they are consistent with the conventions used in SMTLib, and Mathlib,
|
||||
and often mathematical reasoning is easier with these conventions.
|
||||
|
||||
At that time, we did not rename `div` and `mod` to `tdiv` and `tmod` (along with all their lemma).
|
||||
In September 2024, we decided to do this rename (with deprecations in place),
|
||||
and later we intend to rename `ediv` and `emod` to `div` and `mod`, as nearly all users will only
|
||||
ever need to use these functions and their associated lemmas.
|
||||
|
||||
In December 2024, we removed `tdiv` and `tmod`, but have not yet renamed `ediv` and `emod`.
|
||||
-/
|
||||
|
||||
/-! ### E-rounding division
|
||||
This pair satisfies `0 ≤ mod x y < natAbs y` for `y ≠ 0`.
|
||||
-/
|
||||
|
||||
/--
|
||||
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:
|
||||
```
|
||||
#eval (7 : Int) / (0 : Int) -- 0
|
||||
#eval (0 : Int) / (7 : Int) -- 0
|
||||
|
||||
#eval (12 : Int) / (6 : Int) -- 2
|
||||
#eval (12 : Int) / (-6 : Int) -- -2
|
||||
#eval (-12 : Int) / (6 : Int) -- -2
|
||||
#eval (-12 : Int) / (-6 : Int) -- 2
|
||||
|
||||
#eval (12 : Int) / (7 : Int) -- 1
|
||||
#eval (12 : Int) / (-7 : Int) -- -1
|
||||
#eval (-12 : Int) / (7 : Int) -- -2
|
||||
#eval (-12 : Int) / (-7 : Int) -- 2
|
||||
```
|
||||
|
||||
Implemented by efficient native code.
|
||||
-/
|
||||
@[extern "lean_int_ediv"]
|
||||
def ediv : (@& Int) → (@& Int) → Int
|
||||
| ofNat m, ofNat n => ofNat (m / n)
|
||||
| ofNat m, -[n+1] => -ofNat (m / succ n)
|
||||
| -[_+1], 0 => 0
|
||||
| -[m+1], ofNat (succ n) => -[m / succ n +1]
|
||||
| -[m+1], -[n+1] => ofNat (succ (m / succ n))
|
||||
|
||||
/--
|
||||
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:
|
||||
```
|
||||
#eval (7 : Int) % (0 : Int) -- 7
|
||||
#eval (0 : Int) % (7 : Int) -- 0
|
||||
|
||||
#eval (12 : Int) % (6 : Int) -- 0
|
||||
#eval (12 : Int) % (-6 : Int) -- 0
|
||||
#eval (-12 : Int) % (6 : Int) -- 0
|
||||
#eval (-12 : Int) % (-6 : Int) -- 0
|
||||
|
||||
#eval (12 : Int) % (7 : Int) -- 5
|
||||
#eval (12 : Int) % (-7 : Int) -- 5
|
||||
#eval (-12 : Int) % (7 : Int) -- 2
|
||||
#eval (-12 : Int) % (-7 : Int) -- 2
|
||||
```
|
||||
|
||||
Implemented by efficient native code.
|
||||
-/
|
||||
@[extern "lean_int_emod"]
|
||||
def emod : (@& Int) → (@& Int) → Int
|
||||
| ofNat m, n => ofNat (m % natAbs n)
|
||||
| -[m+1], n => subNatNat (natAbs n) (succ (m % natAbs n))
|
||||
|
||||
/--
|
||||
The Div and Mod syntax uses ediv and emod for compatibility with SMTLIb and mathematical
|
||||
reasoning tends to be easier.
|
||||
-/
|
||||
instance : Div Int where
|
||||
div := Int.ediv
|
||||
instance : Mod Int where
|
||||
mod := Int.emod
|
||||
|
||||
@[simp, norm_cast] theorem ofNat_ediv (m n : Nat) : (↑(m / n) : Int) = ↑m / ↑n := rfl
|
||||
|
||||
theorem ofNat_ediv_ofNat {a b : Nat} : (↑a / ↑b : Int) = (a / b : Nat) := rfl
|
||||
theorem negSucc_ediv_ofNat_succ {a b : Nat} : ((-[a+1]) / ↑(b+1) : Int) = -[a / succ b +1] := rfl
|
||||
theorem negSucc_ediv_negSucc {a b : Nat} : ((-[a+1]) / (-[b+1]) : Int) = ((a / (b + 1)) + 1 : Nat) := rfl
|
||||
|
||||
theorem negSucc_emod_ofNat {a b : Nat} : -[a+1] % (b : Int) = subNatNat b (succ (a % b)) := rfl
|
||||
theorem negSucc_emod_negSucc {a b : Nat} : -[a+1] % -[b+1] = subNatNat (b + 1) (succ (a % (b + 1))) := rfl
|
||||
|
||||
/-! ### T-rounding division -/
|
||||
|
||||
/--
|
||||
`tdiv` uses the [*"T-rounding"*][t-rounding]
|
||||
(**T**runcation-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.
|
||||
|
||||
[t-rounding]: https://dl.acm.org/doi/pdf/10.1145/128861.128862
|
||||
[theo tmod_add_tdiv]: https://leanprover-community.github.io/mathlib4_docs/find/?pattern=Int.tmod_add_tdiv#doc
|
||||
|
||||
Examples:
|
||||
|
||||
```
|
||||
#eval (7 : Int).tdiv (0 : Int) -- 0
|
||||
#eval (0 : Int).tdiv (7 : Int) -- 0
|
||||
|
||||
#eval (12 : Int).tdiv (6 : Int) -- 2
|
||||
#eval (12 : Int).tdiv (-6 : Int) -- -2
|
||||
#eval (-12 : Int).tdiv (6 : Int) -- -2
|
||||
#eval (-12 : Int).tdiv (-6 : Int) -- 2
|
||||
|
||||
#eval (12 : Int).tdiv (7 : Int) -- 1
|
||||
#eval (12 : Int).tdiv (-7 : Int) -- -1
|
||||
#eval (-12 : Int).tdiv (7 : Int) -- -1
|
||||
#eval (-12 : Int).tdiv (-7 : Int) -- 1
|
||||
```
|
||||
|
||||
Implemented by efficient native code.
|
||||
-/
|
||||
@[extern "lean_int_div"]
|
||||
def tdiv : (@& Int) → (@& Int) → Int
|
||||
| ofNat m, ofNat n => ofNat (m / n)
|
||||
| ofNat m, -[n +1] => -ofNat (m / succ n)
|
||||
| -[m +1], ofNat n => -ofNat (succ m / n)
|
||||
| -[m +1], -[n +1] => ofNat (succ m / succ n)
|
||||
|
||||
/-- Integer modulo. This function uses the
|
||||
[*"T-rounding"*][t-rounding] (**T**runcation-rounding) convention
|
||||
to pair with `Int.tdiv`, meaning that `tmod a b + b * (tdiv a b) = a`
|
||||
unconditionally (see [`Int.tmod_add_tdiv`][theo tmod_add_tdiv]). In
|
||||
particular, `a % 0 = a`.
|
||||
|
||||
[t-rounding]: https://dl.acm.org/doi/pdf/10.1145/128861.128862
|
||||
[theo tmod_add_tdiv]: https://leanprover-community.github.io/mathlib4_docs/find/?pattern=Int.tmod_add_tdiv#doc
|
||||
|
||||
Examples:
|
||||
|
||||
```
|
||||
#eval (7 : Int).tmod (0 : Int) -- 7
|
||||
#eval (0 : Int).tmod (7 : Int) -- 0
|
||||
|
||||
#eval (12 : Int).tmod (6 : Int) -- 0
|
||||
#eval (12 : Int).tmod (-6 : Int) -- 0
|
||||
#eval (-12 : Int).tmod (6 : Int) -- 0
|
||||
#eval (-12 : Int).tmod (-6 : Int) -- 0
|
||||
|
||||
#eval (12 : Int).tmod (7 : Int) -- 5
|
||||
#eval (12 : Int).tmod (-7 : Int) -- 5
|
||||
#eval (-12 : Int).tmod (7 : Int) -- -5
|
||||
#eval (-12 : Int).tmod (-7 : Int) -- -5
|
||||
```
|
||||
|
||||
Implemented by efficient native code. -/
|
||||
@[extern "lean_int_mod"]
|
||||
def tmod : (@& Int) → (@& Int) → Int
|
||||
| ofNat m, ofNat n => ofNat (m % n)
|
||||
| ofNat m, -[n +1] => ofNat (m % succ n)
|
||||
| -[m +1], ofNat n => -ofNat (succ m % n)
|
||||
| -[m +1], -[n +1] => -ofNat (succ m % succ n)
|
||||
|
||||
theorem ofNat_tdiv (m n : Nat) : ↑(m / n) = tdiv ↑m ↑n := rfl
|
||||
|
||||
/-! ### F-rounding division
|
||||
This pair satisfies `fdiv x y = floor (x / y)`.
|
||||
-/
|
||||
|
||||
/--
|
||||
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:
|
||||
```
|
||||
#eval (7 : Int).fdiv (0 : Int) -- 0
|
||||
#eval (0 : Int).fdiv (7 : Int) -- 0
|
||||
|
||||
#eval (12 : Int).fdiv (6 : Int) -- 2
|
||||
#eval (12 : Int).fdiv (-6 : Int) -- -2
|
||||
#eval (-12 : Int).fdiv (6 : Int) -- -2
|
||||
#eval (-12 : Int).fdiv (-6 : Int) -- 2
|
||||
|
||||
#eval (12 : Int).fdiv (7 : Int) -- 1
|
||||
#eval (12 : Int).fdiv (-7 : Int) -- -2
|
||||
#eval (-12 : Int).fdiv (7 : Int) -- -2
|
||||
#eval (-12 : Int).fdiv (-7 : Int) -- 1
|
||||
```
|
||||
-/
|
||||
def fdiv : Int → Int → Int
|
||||
| 0, _ => 0
|
||||
| ofNat m, ofNat n => ofNat (m / n)
|
||||
| ofNat (succ m), -[n+1] => -[m / succ n +1]
|
||||
| -[_+1], 0 => 0
|
||||
| -[m+1], ofNat (succ n) => -[m / succ n +1]
|
||||
| -[m+1], -[n+1] => ofNat (succ m / succ n)
|
||||
|
||||
/--
|
||||
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:
|
||||
|
||||
```
|
||||
#eval (7 : Int).fmod (0 : Int) -- 7
|
||||
#eval (0 : Int).fmod (7 : Int) -- 0
|
||||
|
||||
#eval (12 : Int).fmod (6 : Int) -- 0
|
||||
#eval (12 : Int).fmod (-6 : Int) -- 0
|
||||
#eval (-12 : Int).fmod (6 : Int) -- 0
|
||||
#eval (-12 : Int).fmod (-6 : Int) -- 0
|
||||
|
||||
#eval (12 : Int).fmod (7 : Int) -- 5
|
||||
#eval (12 : Int).fmod (-7 : Int) -- -2
|
||||
#eval (-12 : Int).fmod (7 : Int) -- 2
|
||||
#eval (-12 : Int).fmod (-7 : Int) -- -5
|
||||
```
|
||||
-/
|
||||
def fmod : Int → Int → Int
|
||||
| 0, _ => 0
|
||||
| ofNat m, ofNat n => ofNat (m % n)
|
||||
| ofNat (succ m), -[n+1] => subNatNat (m % succ n) n
|
||||
| -[m+1], ofNat n => subNatNat n (succ (m % n))
|
||||
| -[m+1], -[n+1] => -ofNat (succ m % succ n)
|
||||
|
||||
theorem ofNat_fdiv : ∀ m n : Nat, ↑(m / n) = fdiv ↑m ↑n
|
||||
| 0, _ => by simp [fdiv]
|
||||
| succ _, _ => rfl
|
||||
|
||||
/-!
|
||||
# `bmod` ("balanced" mod)
|
||||
|
||||
Balanced mod (and balanced div) are a division and modulus pair such
|
||||
that `b * (Int.bdiv a b) + Int.bmod a b = a` and
|
||||
`-b/2 ≤ Int.bmod a b < b/2` for all `a : Int` and `b > 0`.
|
||||
|
||||
This is used in Omega as well as signed bitvectors.
|
||||
-/
|
||||
|
||||
/--
|
||||
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`.
|
||||
|
||||
Examples:
|
||||
```
|
||||
#eval (7 : Int).bdiv 0 -- 0
|
||||
#eval (0 : Int).bdiv 7 -- 0
|
||||
|
||||
#eval (12 : Int).bdiv 6 -- 2
|
||||
#eval (12 : Int).bdiv 7 -- 2
|
||||
#eval (12 : Int).bdiv 8 -- 2
|
||||
#eval (12 : Int).bdiv 9 -- 1
|
||||
|
||||
#eval (-12 : Int).bdiv 6 -- -2
|
||||
#eval (-12 : Int).bdiv 7 -- -2
|
||||
#eval (-12 : Int).bdiv 8 -- -1
|
||||
#eval (-12 : Int).bdiv 9 -- -1
|
||||
```
|
||||
-/
|
||||
def bmod (x : Int) (m : Nat) : Int :=
|
||||
let r := x % m
|
||||
if r < (m + 1) / 2 then
|
||||
r
|
||||
else
|
||||
r - m
|
||||
|
||||
/--
|
||||
Balanced division. This returns the unique integer so that
|
||||
`b * (Int.bdiv a b) + Int.bmod a b = a`.
|
||||
|
||||
Examples:
|
||||
```
|
||||
#eval (7 : Int).bmod 0 -- 7
|
||||
#eval (0 : Int).bmod 7 -- 0
|
||||
|
||||
#eval (12 : Int).bmod 6 -- 0
|
||||
#eval (12 : Int).bmod 7 -- -2
|
||||
#eval (12 : Int).bmod 8 -- -4
|
||||
#eval (12 : Int).bmod 9 -- 3
|
||||
|
||||
#eval (-12 : Int).bmod 6 -- 0
|
||||
#eval (-12 : Int).bmod 7 -- 2
|
||||
#eval (-12 : Int).bmod 8 -- -4
|
||||
#eval (-12 : Int).bmod 9 -- -3
|
||||
```
|
||||
-/
|
||||
def bdiv (x : Int) (m : Nat) : Int :=
|
||||
if m = 0 then
|
||||
0
|
||||
else
|
||||
let q := x / m
|
||||
let r := x % m
|
||||
if r < (m + 1) / 2 then
|
||||
q
|
||||
else
|
||||
q + 1
|
||||
|
||||
end Int
|
||||
import Init.Data.Int.DivMod.Basic
|
||||
import Init.Data.Int.DivMod.Bootstrap
|
||||
import Init.Data.Int.DivMod.Lemmas
|
||||
|
||||
336
src/Init/Data/Int/DivMod/Basic.lean
Normal file
336
src/Init/Data/Int/DivMod/Basic.lean
Normal file
@@ -0,0 +1,336 @@
|
||||
/-
|
||||
Copyright (c) 2016 Jeremy Avigad. All rights reserved.
|
||||
Released under Apache 2.0 license as described in the file LICENSE.
|
||||
Authors: Jeremy Avigad, Mario Carneiro
|
||||
-/
|
||||
prelude
|
||||
import Init.Data.Int.Basic
|
||||
|
||||
open Nat
|
||||
|
||||
namespace Int
|
||||
|
||||
/-! ## Quotient and remainder
|
||||
|
||||
There are three main conventions for integer division,
|
||||
referred here as the E, F, T rounding conventions.
|
||||
All three pairs satisfy the identity `x % y + (x / y) * y = x` unconditionally,
|
||||
and satisfy `x / 0 = 0` and `x % 0 = x`.
|
||||
|
||||
### Historical notes
|
||||
In early versions of Lean, the typeclasses provided by `/` and `%`
|
||||
were defined in terms of `tdiv` and `tmod`, and these were named simply as `div` and `mod`.
|
||||
|
||||
However we decided it was better to use `ediv` and `emod`,
|
||||
as they are consistent with the conventions used in SMTLib, and Mathlib,
|
||||
and often mathematical reasoning is easier with these conventions.
|
||||
|
||||
At that time, we did not rename `div` and `mod` to `tdiv` and `tmod` (along with all their lemma).
|
||||
In September 2024, we decided to do this rename (with deprecations in place),
|
||||
and later we intend to rename `ediv` and `emod` to `div` and `mod`, as nearly all users will only
|
||||
ever need to use these functions and their associated lemmas.
|
||||
|
||||
In December 2024, we removed `tdiv` and `tmod`, but have not yet renamed `ediv` and `emod`.
|
||||
-/
|
||||
|
||||
/-! ### E-rounding division
|
||||
This pair satisfies `0 ≤ mod x y < natAbs y` for `y ≠ 0`.
|
||||
-/
|
||||
|
||||
/--
|
||||
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:
|
||||
```
|
||||
#eval (7 : Int) / (0 : Int) -- 0
|
||||
#eval (0 : Int) / (7 : Int) -- 0
|
||||
|
||||
#eval (12 : Int) / (6 : Int) -- 2
|
||||
#eval (12 : Int) / (-6 : Int) -- -2
|
||||
#eval (-12 : Int) / (6 : Int) -- -2
|
||||
#eval (-12 : Int) / (-6 : Int) -- 2
|
||||
|
||||
#eval (12 : Int) / (7 : Int) -- 1
|
||||
#eval (12 : Int) / (-7 : Int) -- -1
|
||||
#eval (-12 : Int) / (7 : Int) -- -2
|
||||
#eval (-12 : Int) / (-7 : Int) -- 2
|
||||
```
|
||||
|
||||
Implemented by efficient native code.
|
||||
-/
|
||||
@[extern "lean_int_ediv"]
|
||||
def ediv : (@& Int) → (@& Int) → Int
|
||||
| ofNat m, ofNat n => ofNat (m / n)
|
||||
| ofNat m, -[n+1] => -ofNat (m / succ n)
|
||||
| -[_+1], 0 => 0
|
||||
| -[m+1], ofNat (succ n) => -[m / succ n +1]
|
||||
| -[m+1], -[n+1] => ofNat (succ (m / succ n))
|
||||
|
||||
/--
|
||||
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:
|
||||
```
|
||||
#eval (7 : Int) % (0 : Int) -- 7
|
||||
#eval (0 : Int) % (7 : Int) -- 0
|
||||
|
||||
#eval (12 : Int) % (6 : Int) -- 0
|
||||
#eval (12 : Int) % (-6 : Int) -- 0
|
||||
#eval (-12 : Int) % (6 : Int) -- 0
|
||||
#eval (-12 : Int) % (-6 : Int) -- 0
|
||||
|
||||
#eval (12 : Int) % (7 : Int) -- 5
|
||||
#eval (12 : Int) % (-7 : Int) -- 5
|
||||
#eval (-12 : Int) % (7 : Int) -- 2
|
||||
#eval (-12 : Int) % (-7 : Int) -- 2
|
||||
```
|
||||
|
||||
Implemented by efficient native code.
|
||||
-/
|
||||
@[extern "lean_int_emod"]
|
||||
def emod : (@& Int) → (@& Int) → Int
|
||||
| ofNat m, n => ofNat (m % natAbs n)
|
||||
| -[m+1], n => subNatNat (natAbs n) (succ (m % natAbs n))
|
||||
|
||||
/--
|
||||
The Div and Mod syntax uses ediv and emod for compatibility with SMTLIb and mathematical
|
||||
reasoning tends to be easier.
|
||||
-/
|
||||
instance : Div Int where
|
||||
div := Int.ediv
|
||||
instance : Mod Int where
|
||||
mod := Int.emod
|
||||
|
||||
@[simp, norm_cast] theorem ofNat_ediv (m n : Nat) : (↑(m / n) : Int) = ↑m / ↑n := rfl
|
||||
|
||||
theorem ofNat_ediv_ofNat {a b : Nat} : (↑a / ↑b : Int) = (a / b : Nat) := rfl
|
||||
@[norm_cast]
|
||||
theorem negSucc_ediv_ofNat_succ {a b : Nat} : ((-[a+1]) / ↑(b+1) : Int) = -[a / succ b +1] := rfl
|
||||
theorem negSucc_ediv_negSucc {a b : Nat} : ((-[a+1]) / (-[b+1]) : Int) = ((a / (b + 1)) + 1 : Nat) := rfl
|
||||
theorem ofNat_ediv_negSucc {a b : Nat} : (ofNat a / (-[b+1])) = -(a / (b + 1) : Nat) := rfl
|
||||
theorem negSucc_emod_ofNat {a b : Nat} : -[a+1] % (b : Int) = subNatNat b (succ (a % b)) := rfl
|
||||
theorem negSucc_emod_negSucc {a b : Nat} : -[a+1] % -[b+1] = subNatNat (b + 1) (succ (a % (b + 1))) := rfl
|
||||
|
||||
/-! ### T-rounding division -/
|
||||
|
||||
/--
|
||||
`tdiv` uses the [*"T-rounding"*][t-rounding]
|
||||
(**T**runcation-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.
|
||||
|
||||
[t-rounding]: https://dl.acm.org/doi/pdf/10.1145/128861.128862
|
||||
[theo tmod_add_tdiv]: https://leanprover-community.github.io/mathlib4_docs/find/?pattern=Int.tmod_add_tdiv#doc
|
||||
|
||||
Examples:
|
||||
|
||||
```
|
||||
#eval (7 : Int).tdiv (0 : Int) -- 0
|
||||
#eval (0 : Int).tdiv (7 : Int) -- 0
|
||||
|
||||
#eval (12 : Int).tdiv (6 : Int) -- 2
|
||||
#eval (12 : Int).tdiv (-6 : Int) -- -2
|
||||
#eval (-12 : Int).tdiv (6 : Int) -- -2
|
||||
#eval (-12 : Int).tdiv (-6 : Int) -- 2
|
||||
|
||||
#eval (12 : Int).tdiv (7 : Int) -- 1
|
||||
#eval (12 : Int).tdiv (-7 : Int) -- -1
|
||||
#eval (-12 : Int).tdiv (7 : Int) -- -1
|
||||
#eval (-12 : Int).tdiv (-7 : Int) -- 1
|
||||
```
|
||||
|
||||
Implemented by efficient native code.
|
||||
-/
|
||||
@[extern "lean_int_div"]
|
||||
def tdiv : (@& Int) → (@& Int) → Int
|
||||
| ofNat m, ofNat n => ofNat (m / n)
|
||||
| ofNat m, -[n +1] => -ofNat (m / succ n)
|
||||
| -[m +1], ofNat n => -ofNat (succ m / n)
|
||||
| -[m +1], -[n +1] => ofNat (succ m / succ n)
|
||||
|
||||
/-- Integer modulo. This function uses the
|
||||
[*"T-rounding"*][t-rounding] (**T**runcation-rounding) convention
|
||||
to pair with `Int.tdiv`, meaning that `tmod a b + b * (tdiv a b) = a`
|
||||
unconditionally (see [`Int.tmod_add_tdiv`][theo tmod_add_tdiv]). In
|
||||
particular, `a % 0 = a`.
|
||||
|
||||
[t-rounding]: https://dl.acm.org/doi/pdf/10.1145/128861.128862
|
||||
[theo tmod_add_tdiv]: https://leanprover-community.github.io/mathlib4_docs/find/?pattern=Int.tmod_add_tdiv#doc
|
||||
|
||||
Examples:
|
||||
|
||||
```
|
||||
#eval (7 : Int).tmod (0 : Int) -- 7
|
||||
#eval (0 : Int).tmod (7 : Int) -- 0
|
||||
|
||||
#eval (12 : Int).tmod (6 : Int) -- 0
|
||||
#eval (12 : Int).tmod (-6 : Int) -- 0
|
||||
#eval (-12 : Int).tmod (6 : Int) -- 0
|
||||
#eval (-12 : Int).tmod (-6 : Int) -- 0
|
||||
|
||||
#eval (12 : Int).tmod (7 : Int) -- 5
|
||||
#eval (12 : Int).tmod (-7 : Int) -- 5
|
||||
#eval (-12 : Int).tmod (7 : Int) -- -5
|
||||
#eval (-12 : Int).tmod (-7 : Int) -- -5
|
||||
```
|
||||
|
||||
Implemented by efficient native code. -/
|
||||
@[extern "lean_int_mod"]
|
||||
def tmod : (@& Int) → (@& Int) → Int
|
||||
| ofNat m, ofNat n => ofNat (m % n)
|
||||
| ofNat m, -[n +1] => ofNat (m % succ n)
|
||||
| -[m +1], ofNat n => -ofNat (succ m % n)
|
||||
| -[m +1], -[n +1] => -ofNat (succ m % succ n)
|
||||
|
||||
theorem ofNat_tdiv (m n : Nat) : ↑(m / n) = tdiv ↑m ↑n := rfl
|
||||
|
||||
/-! ### F-rounding division
|
||||
This pair satisfies `fdiv x y = floor (x / y)`.
|
||||
-/
|
||||
|
||||
/--
|
||||
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:
|
||||
```
|
||||
#eval (7 : Int).fdiv (0 : Int) -- 0
|
||||
#eval (0 : Int).fdiv (7 : Int) -- 0
|
||||
|
||||
#eval (12 : Int).fdiv (6 : Int) -- 2
|
||||
#eval (12 : Int).fdiv (-6 : Int) -- -2
|
||||
#eval (-12 : Int).fdiv (6 : Int) -- -2
|
||||
#eval (-12 : Int).fdiv (-6 : Int) -- 2
|
||||
|
||||
#eval (12 : Int).fdiv (7 : Int) -- 1
|
||||
#eval (12 : Int).fdiv (-7 : Int) -- -2
|
||||
#eval (-12 : Int).fdiv (7 : Int) -- -2
|
||||
#eval (-12 : Int).fdiv (-7 : Int) -- 1
|
||||
```
|
||||
-/
|
||||
def fdiv : Int → Int → Int
|
||||
| 0, _ => 0
|
||||
| ofNat m, ofNat n => ofNat (m / n)
|
||||
| ofNat (succ m), -[n+1] => -[m / succ n +1]
|
||||
| -[_+1], 0 => 0
|
||||
| -[m+1], ofNat (succ n) => -[m / succ n +1]
|
||||
| -[m+1], -[n+1] => ofNat (succ m / succ n)
|
||||
|
||||
/--
|
||||
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:
|
||||
|
||||
```
|
||||
#eval (7 : Int).fmod (0 : Int) -- 7
|
||||
#eval (0 : Int).fmod (7 : Int) -- 0
|
||||
|
||||
#eval (12 : Int).fmod (6 : Int) -- 0
|
||||
#eval (12 : Int).fmod (-6 : Int) -- 0
|
||||
#eval (-12 : Int).fmod (6 : Int) -- 0
|
||||
#eval (-12 : Int).fmod (-6 : Int) -- 0
|
||||
|
||||
#eval (12 : Int).fmod (7 : Int) -- 5
|
||||
#eval (12 : Int).fmod (-7 : Int) -- -2
|
||||
#eval (-12 : Int).fmod (7 : Int) -- 2
|
||||
#eval (-12 : Int).fmod (-7 : Int) -- -5
|
||||
```
|
||||
-/
|
||||
def fmod : Int → Int → Int
|
||||
| 0, _ => 0
|
||||
| ofNat m, ofNat n => ofNat (m % n)
|
||||
| ofNat (succ m), -[n+1] => subNatNat (m % succ n) n
|
||||
| -[m+1], ofNat n => subNatNat n (succ (m % n))
|
||||
| -[m+1], -[n+1] => -ofNat (succ m % succ n)
|
||||
|
||||
theorem ofNat_fdiv : ∀ m n : Nat, ↑(m / n) = fdiv ↑m ↑n
|
||||
| 0, _ => by simp [fdiv]
|
||||
| succ _, _ => rfl
|
||||
|
||||
/-!
|
||||
# `bmod` ("balanced" mod)
|
||||
|
||||
Balanced mod (and balanced div) are a division and modulus pair such
|
||||
that `b * (Int.bdiv a b) + Int.bmod a b = a` and
|
||||
`-b/2 ≤ Int.bmod a b < b/2` for all `a : Int` and `b > 0`.
|
||||
|
||||
This is used in Omega as well as signed bitvectors.
|
||||
-/
|
||||
|
||||
/--
|
||||
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`.
|
||||
|
||||
Examples:
|
||||
```
|
||||
#eval (7 : Int).bdiv 0 -- 0
|
||||
#eval (0 : Int).bdiv 7 -- 0
|
||||
|
||||
#eval (12 : Int).bdiv 6 -- 2
|
||||
#eval (12 : Int).bdiv 7 -- 2
|
||||
#eval (12 : Int).bdiv 8 -- 2
|
||||
#eval (12 : Int).bdiv 9 -- 1
|
||||
|
||||
#eval (-12 : Int).bdiv 6 -- -2
|
||||
#eval (-12 : Int).bdiv 7 -- -2
|
||||
#eval (-12 : Int).bdiv 8 -- -1
|
||||
#eval (-12 : Int).bdiv 9 -- -1
|
||||
```
|
||||
-/
|
||||
def bmod (x : Int) (m : Nat) : Int :=
|
||||
let r := x % m
|
||||
if r < (m + 1) / 2 then
|
||||
r
|
||||
else
|
||||
r - m
|
||||
|
||||
/--
|
||||
Balanced division. This returns the unique integer so that
|
||||
`b * (Int.bdiv a b) + Int.bmod a b = a`.
|
||||
|
||||
Examples:
|
||||
```
|
||||
#eval (7 : Int).bmod 0 -- 7
|
||||
#eval (0 : Int).bmod 7 -- 0
|
||||
|
||||
#eval (12 : Int).bmod 6 -- 0
|
||||
#eval (12 : Int).bmod 7 -- -2
|
||||
#eval (12 : Int).bmod 8 -- -4
|
||||
#eval (12 : Int).bmod 9 -- 3
|
||||
|
||||
#eval (-12 : Int).bmod 6 -- 0
|
||||
#eval (-12 : Int).bmod 7 -- 2
|
||||
#eval (-12 : Int).bmod 8 -- -4
|
||||
#eval (-12 : Int).bmod 9 -- -3
|
||||
```
|
||||
-/
|
||||
def bdiv (x : Int) (m : Nat) : Int :=
|
||||
if m = 0 then
|
||||
0
|
||||
else
|
||||
let q := x / m
|
||||
let r := x % m
|
||||
if r < (m + 1) / 2 then
|
||||
q
|
||||
else
|
||||
q + 1
|
||||
|
||||
end Int
|
||||
322
src/Init/Data/Int/DivMod/Bootstrap.lean
Normal file
322
src/Init/Data/Int/DivMod/Bootstrap.lean
Normal file
@@ -0,0 +1,322 @@
|
||||
/-
|
||||
Copyright (c) 2016 Jeremy Avigad. All rights reserved.
|
||||
Released under Apache 2.0 license as described in the file LICENSE.
|
||||
Authors: Jeremy Avigad, Mario Carneiro
|
||||
-/
|
||||
|
||||
prelude
|
||||
import Init.Data.Int.DivMod.Basic
|
||||
import Init.Data.Int.Order
|
||||
import Init.Data.Nat.Dvd
|
||||
import Init.RCases
|
||||
|
||||
/-!
|
||||
# Lemmas about integer division needed to bootstrap `omega`.
|
||||
-/
|
||||
|
||||
open Nat (succ)
|
||||
|
||||
namespace Int
|
||||
|
||||
-- /-! ### dvd -/
|
||||
|
||||
protected theorem dvd_def (a b : Int) : (a ∣ b) = Exists (fun c => b = a * c) := rfl
|
||||
|
||||
@[simp] protected theorem dvd_zero (n : Int) : n ∣ 0 := ⟨0, (Int.mul_zero _).symm⟩
|
||||
|
||||
@[simp] protected theorem dvd_refl (n : Int) : n ∣ n := ⟨1, (Int.mul_one _).symm⟩
|
||||
|
||||
@[simp] protected theorem one_dvd (n : Int) : 1 ∣ n := ⟨n, (Int.one_mul n).symm⟩
|
||||
|
||||
protected theorem dvd_trans : ∀ {a b c : Int}, a ∣ b → b ∣ c → a ∣ c
|
||||
| _, _, _, ⟨d, rfl⟩, ⟨e, rfl⟩ => Exists.intro (d * e) (by rw [Int.mul_assoc])
|
||||
|
||||
@[norm_cast] theorem ofNat_dvd {m n : Nat} : (↑m : Int) ∣ ↑n ↔ m ∣ n := by
|
||||
refine ⟨fun ⟨a, ae⟩ => ?_, fun ⟨k, e⟩ => ⟨k, by rw [e, Int.ofNat_mul]⟩⟩
|
||||
match Int.le_total a 0 with
|
||||
| .inl h =>
|
||||
have := ae.symm ▸ Int.mul_nonpos_of_nonneg_of_nonpos (ofNat_zero_le _) h
|
||||
rw [Nat.le_antisymm (ofNat_le.1 this) (Nat.zero_le _)]
|
||||
apply Nat.dvd_zero
|
||||
| .inr h => match a, eq_ofNat_of_zero_le h with
|
||||
| _, ⟨k, rfl⟩ => exact ⟨k, Int.ofNat.inj ae⟩
|
||||
|
||||
@[simp] protected theorem zero_dvd {n : Int} : 0 ∣ n ↔ n = 0 :=
|
||||
Iff.intro (fun ⟨k, e⟩ => by rw [e, Int.zero_mul])
|
||||
(fun h => h.symm ▸ Int.dvd_refl _)
|
||||
|
||||
protected theorem dvd_mul_right (a b : Int) : a ∣ a * b := ⟨_, rfl⟩
|
||||
|
||||
protected theorem dvd_mul_left (a b : Int) : b ∣ a * b := ⟨_, Int.mul_comm ..⟩
|
||||
|
||||
@[simp] protected theorem neg_dvd {a b : Int} : -a ∣ b ↔ a ∣ b := by
|
||||
constructor <;> exact fun ⟨k, e⟩ =>
|
||||
⟨-k, by simp [e, Int.neg_mul, Int.mul_neg, Int.neg_neg]⟩
|
||||
|
||||
protected theorem dvd_neg {a b : Int} : a ∣ -b ↔ a ∣ b := by
|
||||
constructor <;> exact fun ⟨k, e⟩ =>
|
||||
⟨-k, by simp [← e, Int.neg_mul, Int.mul_neg, Int.neg_neg]⟩
|
||||
|
||||
@[simp] theorem natAbs_dvd_natAbs {a b : Int} : natAbs a ∣ natAbs b ↔ a ∣ b := by
|
||||
refine ⟨fun ⟨k, hk⟩ => ?_, fun ⟨k, hk⟩ => ⟨natAbs k, hk.symm ▸ natAbs_mul a k⟩⟩
|
||||
rw [← natAbs_ofNat k, ← natAbs_mul, natAbs_eq_natAbs_iff] at hk
|
||||
cases hk <;> subst b
|
||||
· apply Int.dvd_mul_right
|
||||
· rw [← Int.mul_neg]; apply Int.dvd_mul_right
|
||||
|
||||
theorem ofNat_dvd_left {n : Nat} {z : Int} : (↑n : Int) ∣ z ↔ n ∣ z.natAbs := by
|
||||
rw [← natAbs_dvd_natAbs, natAbs_ofNat]
|
||||
|
||||
/-! ### *div zero -/
|
||||
|
||||
@[simp] theorem zero_ediv : ∀ b : Int, 0 / b = 0
|
||||
| ofNat _ => show ofNat _ = _ by simp
|
||||
| -[_+1] => show -ofNat _ = _ by simp
|
||||
|
||||
@[simp] protected theorem ediv_zero : ∀ a : Int, a / 0 = 0
|
||||
| ofNat _ => show ofNat _ = _ by simp
|
||||
| -[_+1] => rfl
|
||||
|
||||
/-! ### mod zero -/
|
||||
|
||||
@[simp] theorem zero_emod (b : Int) : 0 % b = 0 := rfl
|
||||
|
||||
@[simp] theorem emod_zero : ∀ a : Int, a % 0 = a
|
||||
| ofNat _ => congrArg ofNat <| Nat.mod_zero _
|
||||
| -[_+1] => congrArg negSucc <| Nat.mod_zero _
|
||||
|
||||
/-! ### ofNat mod -/
|
||||
|
||||
@[simp, norm_cast] theorem ofNat_emod (m n : Nat) : (↑(m % n) : Int) = m % n := rfl
|
||||
|
||||
|
||||
/-! ### mod definitions -/
|
||||
|
||||
theorem emod_add_ediv : ∀ a b : Int, a % b + b * (a / b) = a
|
||||
| ofNat _, ofNat _ => congrArg ofNat <| Nat.mod_add_div ..
|
||||
| ofNat m, -[n+1] => by
|
||||
show (m % succ n + -↑(succ n) * -↑(m / succ n) : Int) = m
|
||||
rw [Int.neg_mul_neg]; exact congrArg ofNat <| Nat.mod_add_div ..
|
||||
| -[_+1], 0 => by rw [emod_zero]; rfl
|
||||
| -[m+1], succ n => aux m n.succ
|
||||
| -[m+1], -[n+1] => aux m n.succ
|
||||
where
|
||||
aux (m n : Nat) : n - (m % n + 1) - (n * (m / n) + n) = -[m+1] := by
|
||||
rw [← ofNat_emod, ← ofNat_ediv, ← Int.sub_sub, negSucc_eq, Int.sub_sub n,
|
||||
← Int.neg_neg (_-_), Int.neg_sub, Int.sub_sub_self, Int.add_right_comm]
|
||||
exact congrArg (fun x => -(ofNat x + 1)) (Nat.mod_add_div ..)
|
||||
|
||||
theorem emod_add_ediv' (a b : Int) : a % b + a / b * b = a := by
|
||||
rw [Int.mul_comm]; exact emod_add_ediv ..
|
||||
|
||||
theorem ediv_add_emod (a b : Int) : b * (a / b) + a % b = a := by
|
||||
rw [Int.add_comm]; exact emod_add_ediv ..
|
||||
|
||||
theorem emod_def (a b : Int) : a % b = a - b * (a / b) := by
|
||||
rw [← Int.add_sub_cancel (a % b), emod_add_ediv]
|
||||
|
||||
/-! ### `/` ediv -/
|
||||
|
||||
@[simp] protected theorem ediv_neg : ∀ a b : Int, a / (-b) = -(a / b)
|
||||
| ofNat m, 0 => show ofNat (m / 0) = -↑(m / 0) by rw [Nat.div_zero]; rfl
|
||||
| ofNat _, -[_+1] => (Int.neg_neg _).symm
|
||||
| ofNat _, succ _ | -[_+1], 0 | -[_+1], succ _ | -[_+1], -[_+1] => rfl
|
||||
|
||||
protected theorem div_def (a b : Int) : a / b = Int.ediv a b := rfl
|
||||
|
||||
theorem add_mul_ediv_right (a b : Int) {c : Int} (H : c ≠ 0) : (a + b * c) / c = a / c + b :=
|
||||
suffices ∀ {{a b c : Int}}, 0 < c → (a + b * c).ediv c = a.ediv c + b from
|
||||
match Int.lt_trichotomy c 0 with
|
||||
| Or.inl hlt => by
|
||||
rw [← Int.neg_inj, ← Int.ediv_neg, Int.neg_add, ← Int.ediv_neg, ← Int.neg_mul_neg]
|
||||
exact this (Int.neg_pos_of_neg hlt)
|
||||
| Or.inr (Or.inl HEq) => absurd HEq H
|
||||
| Or.inr (Or.inr hgt) => this hgt
|
||||
suffices ∀ {k n : Nat} {a : Int}, (a + n * k.succ).ediv k.succ = a.ediv k.succ + n from
|
||||
fun a b c H => match c, eq_succ_of_zero_lt H, b with
|
||||
| _, ⟨_, rfl⟩, ofNat _ => this
|
||||
| _, ⟨k, rfl⟩, -[n+1] => show (a - n.succ * k.succ).ediv k.succ = a.ediv k.succ - n.succ by
|
||||
rw [← Int.add_sub_cancel (ediv ..), ← this, Int.sub_add_cancel]
|
||||
fun {k n} => @fun
|
||||
| ofNat _ => congrArg ofNat <| Nat.add_mul_div_right _ _ k.succ_pos
|
||||
| -[m+1] => by
|
||||
show ((n * k.succ : Nat) - m.succ : Int).ediv k.succ = n - (m / k.succ + 1 : Nat)
|
||||
by_cases h : m < n * k.succ
|
||||
· rw [← Int.ofNat_sub h, ← Int.ofNat_sub ((Nat.div_lt_iff_lt_mul k.succ_pos).2 h)]
|
||||
apply congrArg ofNat
|
||||
rw [Nat.mul_comm, Nat.mul_sub_div]; rwa [Nat.mul_comm]
|
||||
· have h := Nat.not_lt.1 h
|
||||
have H {a b : Nat} (h : a ≤ b) : (a : Int) + -((b : Int) + 1) = -[b - a +1] := by
|
||||
rw [negSucc_eq, Int.ofNat_sub h]
|
||||
simp only [Int.sub_eq_add_neg, Int.neg_add, Int.neg_neg, Int.add_left_comm, Int.add_assoc]
|
||||
show ediv (↑(n * succ k) + -((m : Int) + 1)) (succ k) = n + -(↑(m / succ k) + 1 : Int)
|
||||
rw [H h, H ((Nat.le_div_iff_mul_le k.succ_pos).2 h)]
|
||||
apply congrArg negSucc
|
||||
rw [Nat.mul_comm, Nat.sub_mul_div]; rwa [Nat.mul_comm]
|
||||
|
||||
theorem add_ediv_of_dvd_right {a b c : Int} (H : c ∣ b) : (a + b) / c = a / c + b / c :=
|
||||
if h : c = 0 then by simp [h] else by
|
||||
let ⟨k, hk⟩ := H
|
||||
rw [hk, Int.mul_comm c k, Int.add_mul_ediv_right _ _ h,
|
||||
← Int.zero_add (k * c), Int.add_mul_ediv_right _ _ h, Int.zero_ediv, Int.zero_add]
|
||||
|
||||
theorem add_ediv_of_dvd_left {a b c : Int} (H : c ∣ a) : (a + b) / c = a / c + b / c := by
|
||||
rw [Int.add_comm, Int.add_ediv_of_dvd_right H, Int.add_comm]
|
||||
|
||||
@[simp] theorem mul_ediv_cancel (a : Int) {b : Int} (H : b ≠ 0) : (a * b) / b = a := by
|
||||
have := Int.add_mul_ediv_right 0 a H
|
||||
rwa [Int.zero_add, Int.zero_ediv, Int.zero_add] at this
|
||||
|
||||
@[simp] theorem mul_ediv_cancel_left (b : Int) (H : a ≠ 0) : (a * b) / a = b :=
|
||||
Int.mul_comm .. ▸ Int.mul_ediv_cancel _ H
|
||||
|
||||
theorem div_nonneg_iff_of_pos {a b : Int} (h : 0 < b) : a / b ≥ 0 ↔ a ≥ 0 := by
|
||||
rw [Int.div_def]
|
||||
match b, h with
|
||||
| Int.ofNat (b+1), _ =>
|
||||
rcases a with ⟨a⟩ <;> simp [Int.ediv]
|
||||
norm_cast
|
||||
simp
|
||||
|
||||
/-! ### emod -/
|
||||
|
||||
theorem emod_nonneg : ∀ (a : Int) {b : Int}, b ≠ 0 → 0 ≤ a % b
|
||||
| ofNat _, _, _ => ofNat_zero_le _
|
||||
| -[_+1], _, H => Int.sub_nonneg_of_le <| ofNat_le.2 <| Nat.mod_lt _ (natAbs_pos.2 H)
|
||||
|
||||
theorem emod_lt_of_pos (a : Int) {b : Int} (H : 0 < b) : a % b < b :=
|
||||
match a, b, eq_succ_of_zero_lt H with
|
||||
| ofNat _, _, ⟨_, rfl⟩ => ofNat_lt.2 (Nat.mod_lt _ (Nat.succ_pos _))
|
||||
| -[_+1], _, ⟨_, rfl⟩ => Int.sub_lt_self _ (ofNat_lt.2 <| Nat.succ_pos _)
|
||||
|
||||
theorem mul_ediv_self_le {x k : Int} (h : k ≠ 0) : k * (x / k) ≤ x :=
|
||||
calc k * (x / k)
|
||||
_ ≤ k * (x / k) + x % k := Int.le_add_of_nonneg_right (emod_nonneg x h)
|
||||
_ = x := ediv_add_emod _ _
|
||||
|
||||
theorem lt_mul_ediv_self_add {x k : Int} (h : 0 < k) : x < k * (x / k) + k :=
|
||||
calc x
|
||||
_ = k * (x / k) + x % k := (ediv_add_emod _ _).symm
|
||||
_ < k * (x / k) + k := Int.add_lt_add_left (emod_lt_of_pos x h) _
|
||||
|
||||
@[simp] theorem add_mul_emod_self {a b c : Int} : (a + b * c) % c = a % c :=
|
||||
if cz : c = 0 then by
|
||||
rw [cz, Int.mul_zero, Int.add_zero]
|
||||
else by
|
||||
rw [Int.emod_def, Int.emod_def, Int.add_mul_ediv_right _ _ cz, Int.add_comm _ b,
|
||||
Int.mul_add, Int.mul_comm, ← Int.sub_sub, Int.add_sub_cancel]
|
||||
|
||||
@[simp] theorem add_mul_emod_self_left (a b c : Int) : (a + b * c) % b = a % b := by
|
||||
rw [Int.mul_comm, Int.add_mul_emod_self]
|
||||
|
||||
@[simp] theorem emod_add_emod (m n k : Int) : (m % n + k) % n = (m + k) % n := by
|
||||
have := (add_mul_emod_self_left (m % n + k) n (m / n)).symm
|
||||
rwa [Int.add_right_comm, emod_add_ediv] at this
|
||||
|
||||
@[simp] theorem add_emod_emod (m n k : Int) : (m + n % k) % k = (m + n) % k := by
|
||||
rw [Int.add_comm, emod_add_emod, Int.add_comm]
|
||||
|
||||
theorem add_emod (a b n : Int) : (a + b) % n = (a % n + b % n) % n := by
|
||||
rw [add_emod_emod, emod_add_emod]
|
||||
|
||||
theorem add_emod_eq_add_emod_right {m n k : Int} (i : Int)
|
||||
(H : m % n = k % n) : (m + i) % n = (k + i) % n := by
|
||||
rw [← emod_add_emod, ← emod_add_emod k, H]
|
||||
|
||||
theorem emod_add_cancel_right {m n k : Int} (i) : (m + i) % n = (k + i) % n ↔ m % n = k % n :=
|
||||
⟨fun H => by
|
||||
have := add_emod_eq_add_emod_right (-i) H
|
||||
rwa [Int.add_neg_cancel_right, Int.add_neg_cancel_right] at this,
|
||||
add_emod_eq_add_emod_right _⟩
|
||||
|
||||
@[simp] theorem mul_emod_left (a b : Int) : (a * b) % b = 0 := by
|
||||
rw [← Int.zero_add (a * b), Int.add_mul_emod_self, Int.zero_emod]
|
||||
|
||||
@[simp] theorem mul_emod_right (a b : Int) : (a * b) % a = 0 := by
|
||||
rw [Int.mul_comm, mul_emod_left]
|
||||
|
||||
theorem mul_emod (a b n : Int) : (a * b) % n = (a % n) * (b % n) % n := by
|
||||
conv => lhs; rw [
|
||||
← emod_add_ediv a n, ← emod_add_ediv' b n, Int.add_mul, Int.mul_add, Int.mul_add,
|
||||
Int.mul_assoc, Int.mul_assoc, ← Int.mul_add n _ _, add_mul_emod_self_left,
|
||||
← Int.mul_assoc, add_mul_emod_self]
|
||||
|
||||
@[simp] theorem emod_self {a : Int} : a % a = 0 := by
|
||||
have := mul_emod_left 1 a; rwa [Int.one_mul] at this
|
||||
|
||||
@[simp] theorem emod_emod_of_dvd (n : Int) {m k : Int}
|
||||
(h : m ∣ k) : (n % k) % m = n % m := by
|
||||
conv => rhs; rw [← emod_add_ediv n k]
|
||||
match k, h with
|
||||
| _, ⟨t, rfl⟩ => rw [Int.mul_assoc, add_mul_emod_self_left]
|
||||
|
||||
@[simp] theorem emod_emod (a b : Int) : (a % b) % b = a % b := by
|
||||
conv => rhs; rw [← emod_add_ediv a b, add_mul_emod_self_left]
|
||||
|
||||
theorem sub_emod (a b n : Int) : (a - b) % n = (a % n - b % n) % n := by
|
||||
apply (emod_add_cancel_right b).mp
|
||||
rw [Int.sub_add_cancel, ← Int.add_emod_emod, Int.sub_add_cancel, emod_emod]
|
||||
|
||||
/-! ### properties of `/` and `%` -/
|
||||
|
||||
theorem mul_ediv_cancel_of_emod_eq_zero {a b : Int} (H : a % b = 0) : b * (a / b) = a := by
|
||||
have := emod_add_ediv a b; rwa [H, Int.zero_add] at this
|
||||
|
||||
theorem ediv_mul_cancel_of_emod_eq_zero {a b : Int} (H : a % b = 0) : a / b * b = a := by
|
||||
rw [Int.mul_comm, mul_ediv_cancel_of_emod_eq_zero H]
|
||||
|
||||
theorem dvd_of_emod_eq_zero {a b : Int} (H : b % a = 0) : a ∣ b :=
|
||||
⟨b / a, (mul_ediv_cancel_of_emod_eq_zero H).symm⟩
|
||||
|
||||
theorem emod_eq_zero_of_dvd : ∀ {a b : Int}, a ∣ b → b % a = 0
|
||||
| _, _, ⟨_, rfl⟩ => mul_emod_right ..
|
||||
|
||||
theorem dvd_iff_emod_eq_zero {a b : Int} : a ∣ b ↔ b % a = 0 :=
|
||||
⟨emod_eq_zero_of_dvd, dvd_of_emod_eq_zero⟩
|
||||
|
||||
protected theorem mul_ediv_assoc (a : Int) : ∀ {b c : Int}, c ∣ b → (a * b) / c = a * (b / c)
|
||||
| _, c, ⟨d, rfl⟩ =>
|
||||
if cz : c = 0 then by simp [cz, Int.mul_zero] else by
|
||||
rw [Int.mul_left_comm, Int.mul_ediv_cancel_left _ cz, Int.mul_ediv_cancel_left _ cz]
|
||||
|
||||
protected theorem mul_ediv_assoc' (b : Int) {a c : Int}
|
||||
(h : c ∣ a) : (a * b) / c = a / c * b := by
|
||||
rw [Int.mul_comm, Int.mul_ediv_assoc _ h, Int.mul_comm]
|
||||
|
||||
theorem neg_ediv_of_dvd : ∀ {a b : Int}, b ∣ a → (-a) / b = -(a / b)
|
||||
| _, b, ⟨c, rfl⟩ => by
|
||||
by_cases bz : b = 0
|
||||
· simp [bz]
|
||||
· rw [Int.neg_mul_eq_mul_neg, Int.mul_ediv_cancel_left _ bz, Int.mul_ediv_cancel_left _ bz]
|
||||
|
||||
theorem sub_ediv_of_dvd (a : Int) {b c : Int}
|
||||
(hcb : c ∣ b) : (a - b) / c = a / c - b / c := by
|
||||
rw [Int.sub_eq_add_neg, Int.sub_eq_add_neg, Int.add_ediv_of_dvd_right (Int.dvd_neg.2 hcb)]
|
||||
congr; exact Int.neg_ediv_of_dvd hcb
|
||||
|
||||
protected theorem ediv_mul_cancel {a b : Int} (H : b ∣ a) : a / b * b = a :=
|
||||
ediv_mul_cancel_of_emod_eq_zero (emod_eq_zero_of_dvd H)
|
||||
|
||||
protected theorem mul_ediv_cancel' {a b : Int} (H : a ∣ b) : a * (b / a) = b := by
|
||||
rw [Int.mul_comm, Int.ediv_mul_cancel H]
|
||||
|
||||
theorem emod_pos_of_not_dvd {a b : Int} (h : ¬ a ∣ b) : a = 0 ∨ 0 < b % a := by
|
||||
rw [dvd_iff_emod_eq_zero] at h
|
||||
by_cases w : a = 0
|
||||
· simp_all
|
||||
· exact Or.inr (Int.lt_iff_le_and_ne.mpr ⟨emod_nonneg b w, Ne.symm h⟩)
|
||||
|
||||
/-! ### bmod -/
|
||||
|
||||
@[simp] theorem bmod_emod : bmod x m % m = x % m := by
|
||||
dsimp [bmod]
|
||||
split <;> simp [Int.sub_emod]
|
||||
|
||||
theorem bmod_def (x : Int) (m : Nat) : bmod x m =
|
||||
if (x % m) < (m + 1) / 2 then
|
||||
x % m
|
||||
else
|
||||
(x % m) - m :=
|
||||
rfl
|
||||
|
||||
end Int
|
||||
@@ -5,13 +5,16 @@ Authors: Jeremy Avigad, Mario Carneiro
|
||||
-/
|
||||
|
||||
prelude
|
||||
import Init.Data.Int.DivMod
|
||||
import Init.Data.Int.DivMod.Bootstrap
|
||||
import Init.Data.Nat.Lemmas
|
||||
import Init.Data.Nat.Div.Lemmas
|
||||
import Init.Data.Int.Order
|
||||
import Init.Data.Int.Lemmas
|
||||
import Init.Data.Nat.Dvd
|
||||
import Init.RCases
|
||||
|
||||
/-!
|
||||
# Lemmas about integer division needed to bootstrap `omega`.
|
||||
# Further lemmas about integer division, now that `omega` is available.
|
||||
-/
|
||||
|
||||
open Nat (succ)
|
||||
@@ -20,58 +23,11 @@ namespace Int
|
||||
|
||||
/-! ### dvd -/
|
||||
|
||||
protected theorem dvd_def (a b : Int) : (a ∣ b) = Exists (fun c => b = a * c) := rfl
|
||||
|
||||
@[simp] protected theorem dvd_zero (n : Int) : n ∣ 0 := ⟨0, (Int.mul_zero _).symm⟩
|
||||
|
||||
@[simp] protected theorem dvd_refl (n : Int) : n ∣ n := ⟨1, (Int.mul_one _).symm⟩
|
||||
|
||||
@[simp] protected theorem one_dvd (n : Int) : 1 ∣ n := ⟨n, (Int.one_mul n).symm⟩
|
||||
|
||||
protected theorem dvd_trans : ∀ {a b c : Int}, a ∣ b → b ∣ c → a ∣ c
|
||||
| _, _, _, ⟨d, rfl⟩, ⟨e, rfl⟩ => Exists.intro (d * e) (by rw [Int.mul_assoc])
|
||||
|
||||
@[norm_cast] theorem ofNat_dvd {m n : Nat} : (↑m : Int) ∣ ↑n ↔ m ∣ n := by
|
||||
refine ⟨fun ⟨a, ae⟩ => ?_, fun ⟨k, e⟩ => ⟨k, by rw [e, Int.ofNat_mul]⟩⟩
|
||||
match Int.le_total a 0 with
|
||||
| .inl h =>
|
||||
have := ae.symm ▸ Int.mul_nonpos_of_nonneg_of_nonpos (ofNat_zero_le _) h
|
||||
rw [Nat.le_antisymm (ofNat_le.1 this) (Nat.zero_le _)]
|
||||
apply Nat.dvd_zero
|
||||
| .inr h => match a, eq_ofNat_of_zero_le h with
|
||||
| _, ⟨k, rfl⟩ => exact ⟨k, Int.ofNat.inj ae⟩
|
||||
|
||||
theorem dvd_antisymm {a b : Int} (H1 : 0 ≤ a) (H2 : 0 ≤ b) : a ∣ b → b ∣ a → a = b := by
|
||||
rw [← natAbs_of_nonneg H1, ← natAbs_of_nonneg H2]
|
||||
rw [ofNat_dvd, ofNat_dvd, ofNat_inj]
|
||||
apply Nat.dvd_antisymm
|
||||
|
||||
@[simp] protected theorem zero_dvd {n : Int} : 0 ∣ n ↔ n = 0 :=
|
||||
Iff.intro (fun ⟨k, e⟩ => by rw [e, Int.zero_mul])
|
||||
(fun h => h.symm ▸ Int.dvd_refl _)
|
||||
|
||||
protected theorem dvd_mul_right (a b : Int) : a ∣ a * b := ⟨_, rfl⟩
|
||||
|
||||
protected theorem dvd_mul_left (a b : Int) : b ∣ a * b := ⟨_, Int.mul_comm ..⟩
|
||||
|
||||
@[simp] protected theorem neg_dvd {a b : Int} : -a ∣ b ↔ a ∣ b := by
|
||||
constructor <;> exact fun ⟨k, e⟩ =>
|
||||
⟨-k, by simp [e, Int.neg_mul, Int.mul_neg, Int.neg_neg]⟩
|
||||
|
||||
protected theorem dvd_neg {a b : Int} : a ∣ -b ↔ a ∣ b := by
|
||||
constructor <;> exact fun ⟨k, e⟩ =>
|
||||
⟨-k, by simp [← e, Int.neg_mul, Int.mul_neg, Int.neg_neg]⟩
|
||||
|
||||
@[simp] theorem natAbs_dvd_natAbs {a b : Int} : natAbs a ∣ natAbs b ↔ a ∣ b := by
|
||||
refine ⟨fun ⟨k, hk⟩ => ?_, fun ⟨k, hk⟩ => ⟨natAbs k, hk.symm ▸ natAbs_mul a k⟩⟩
|
||||
rw [← natAbs_ofNat k, ← natAbs_mul, natAbs_eq_natAbs_iff] at hk
|
||||
cases hk <;> subst b
|
||||
· apply Int.dvd_mul_right
|
||||
· rw [← Int.mul_neg]; apply Int.dvd_mul_right
|
||||
|
||||
theorem ofNat_dvd_left {n : Nat} {z : Int} : (↑n : Int) ∣ z ↔ n ∣ z.natAbs := by
|
||||
rw [← natAbs_dvd_natAbs, natAbs_ofNat]
|
||||
|
||||
protected theorem dvd_add : ∀ {a b c : Int}, a ∣ b → a ∣ c → a ∣ b + c
|
||||
| _, _, _, ⟨d, rfl⟩, ⟨e, rfl⟩ => ⟨d + e, by rw [Int.mul_add]⟩
|
||||
|
||||
@@ -117,6 +73,14 @@ theorem dvd_natAbs_self {a : Int} : a ∣ (a.natAbs : Int) := by
|
||||
theorem ofNat_dvd_right {n : Nat} {z : Int} : z ∣ (↑n : Int) ↔ z.natAbs ∣ n := by
|
||||
rw [← natAbs_dvd_natAbs, natAbs_ofNat]
|
||||
|
||||
@[simp] theorem negSucc_dvd {a : Nat} {b : Int} : -[a+1] ∣ b ↔ ((a + 1 : Nat) : Int) ∣ b := by
|
||||
rw [← natAbs_dvd]
|
||||
norm_cast
|
||||
|
||||
@[simp] theorem dvd_negSucc {a : Int} {b : Nat} : a ∣ -[b+1] ↔ a ∣ ((b + 1 : Nat) : Int) := by
|
||||
rw [← dvd_natAbs]
|
||||
norm_cast
|
||||
|
||||
theorem eq_one_of_dvd_one {a : Int} (H : 0 ≤ a) (H' : a ∣ 1) : a = 1 :=
|
||||
match a, eq_ofNat_of_zero_le H, H' with
|
||||
| _, ⟨_, rfl⟩, H' => congrArg ofNat <| Nat.eq_one_of_dvd_one <| ofNat_dvd.1 H'
|
||||
@@ -127,16 +91,11 @@ theorem eq_one_of_mul_eq_one_right {a b : Int} (H : 0 ≤ a) (H' : a * b = 1) :
|
||||
theorem eq_one_of_mul_eq_one_left {a b : Int} (H : 0 ≤ b) (H' : a * b = 1) : b = 1 :=
|
||||
eq_one_of_mul_eq_one_right (b := a) H <| by rw [Int.mul_comm, H']
|
||||
|
||||
instance decidableDvd : DecidableRel (α := Int) (· ∣ ·) := fun _ _ =>
|
||||
decidable_of_decidable_of_iff (dvd_iff_emod_eq_zero ..).symm
|
||||
|
||||
/-! ### *div zero -/
|
||||
|
||||
@[simp] theorem zero_ediv : ∀ b : Int, 0 / b = 0
|
||||
| ofNat _ => show ofNat _ = _ by simp
|
||||
| -[_+1] => show -ofNat _ = _ by simp
|
||||
|
||||
@[simp] protected theorem ediv_zero : ∀ a : Int, a / 0 = 0
|
||||
| ofNat _ => show ofNat _ = _ by simp
|
||||
| -[_+1] => rfl
|
||||
|
||||
@[simp] protected theorem zero_tdiv : ∀ b : Int, tdiv 0 b = 0
|
||||
| ofNat _ => show ofNat _ = _ by simp
|
||||
| -[_+1] => show -ofNat _ = _ by simp
|
||||
@@ -154,29 +113,129 @@ unseal Nat.div in
|
||||
| succ _ => rfl
|
||||
| -[_+1] => rfl
|
||||
|
||||
/-! ### preliminaries for div equivalences -/
|
||||
|
||||
theorem negSucc_emod_ofNat_succ_eq_zero_iff {a b : Nat} :
|
||||
-[a+1] % (b + 1 : Int) = 0 ↔ (a + 1) % (b + 1) = 0 := by
|
||||
rw [← natCast_one, ← natCast_add]
|
||||
change Int.emod _ _ = 0 ↔ _
|
||||
rw [emod, natAbs_ofNat]
|
||||
simp only [Nat.succ_eq_add_one, subNat_eq_zero_iff, Nat.add_right_cancel_iff]
|
||||
rw [eq_comm]
|
||||
apply Nat.succ_mod_succ_eq_zero_iff.symm
|
||||
|
||||
theorem negSucc_emod_negSucc_eq_zero_iff {a b : Nat} :
|
||||
-[a+1] % -[b+1] = 0 ↔ (a + 1) % (b + 1) = 0 := by
|
||||
change Int.emod _ _ = 0 ↔ _
|
||||
rw [emod, natAbs_negSucc]
|
||||
simp only [Nat.succ_eq_add_one, subNat_eq_zero_iff, Nat.add_right_cancel_iff]
|
||||
rw [eq_comm]
|
||||
apply Nat.succ_mod_succ_eq_zero_iff.symm
|
||||
|
||||
/-! ### div equivalences -/
|
||||
|
||||
theorem tdiv_eq_ediv : ∀ {a b : Int}, 0 ≤ a → a.tdiv b = a / b
|
||||
theorem tdiv_eq_ediv_of_nonneg : ∀ {a b : Int}, 0 ≤ a → a.tdiv b = a / b
|
||||
| 0, _, _
|
||||
| _, 0, _ => by simp
|
||||
| succ _, succ _, _ => rfl
|
||||
| succ _, -[_+1], _ => rfl
|
||||
|
||||
theorem fdiv_eq_ediv : ∀ (a : Int) {b : Int}, 0 ≤ b → fdiv a b = a / b
|
||||
theorem tdiv_eq_ediv {a b : Int} :
|
||||
a.tdiv b = a / b + if 0 ≤ a ∨ b ∣ a then 0 else sign b := by
|
||||
simp only [dvd_iff_emod_eq_zero]
|
||||
match a, b with
|
||||
| ofNat a, ofNat b => simp [tdiv_eq_ediv_of_nonneg]
|
||||
| ofNat a, -[b+1] => simp [tdiv_eq_ediv_of_nonneg]
|
||||
| -[a+1], 0 => simp
|
||||
| -[a+1], ofNat (succ b) =>
|
||||
simp only [tdiv, Nat.succ_eq_add_one, ofNat_eq_coe, natCast_add, Nat.cast_ofNat_Int,
|
||||
negSucc_not_nonneg, sign_of_add_one]
|
||||
simp only [negSucc_emod_ofNat_succ_eq_zero_iff]
|
||||
norm_cast
|
||||
simp only [subNat_eq_zero_iff, Nat.succ_eq_add_one, sign_negSucc, Int.sub_neg, false_or]
|
||||
split <;> rename_i h
|
||||
· rw [Int.add_zero, neg_ofNat_eq_negSucc_iff]
|
||||
exact Nat.succ_div_of_mod_eq_zero h
|
||||
· rw [neg_ofNat_eq_negSucc_add_one_iff]
|
||||
exact Nat.succ_div_of_mod_ne_zero h
|
||||
| -[a+1], -[b+1] =>
|
||||
simp only [tdiv, ofNat_eq_coe, negSucc_not_nonneg, false_or, sign_negSucc]
|
||||
norm_cast
|
||||
simp only [negSucc_ediv_negSucc]
|
||||
rw [natCast_add, natCast_one]
|
||||
simp only [negSucc_emod_negSucc_eq_zero_iff]
|
||||
split <;> rename_i h
|
||||
· norm_cast
|
||||
exact Nat.succ_div_of_mod_eq_zero h
|
||||
· rw [← Int.sub_eq_add_neg, Int.add_sub_cancel]
|
||||
norm_cast
|
||||
exact Nat.succ_div_of_mod_ne_zero h
|
||||
|
||||
theorem ediv_eq_tdiv {a b : Int} :
|
||||
a / b = a.tdiv b - if 0 ≤ a ∨ b ∣ a then 0 else sign b := by
|
||||
simp [tdiv_eq_ediv]
|
||||
|
||||
theorem fdiv_eq_ediv_of_nonneg : ∀ (a : Int) {b : Int}, 0 ≤ b → fdiv a b = a / b
|
||||
| 0, _, _ | -[_+1], 0, _ => by simp
|
||||
| succ _, ofNat _, _ | -[_+1], succ _, _ => rfl
|
||||
|
||||
theorem fdiv_eq_tdiv {a b : Int} (Ha : 0 ≤ a) (Hb : 0 ≤ b) : fdiv a b = tdiv a b :=
|
||||
tdiv_eq_ediv Ha ▸ fdiv_eq_ediv _ Hb
|
||||
theorem fdiv_eq_ediv {a b : Int} :
|
||||
a.fdiv b = a / b - if 0 ≤ b ∨ b ∣ a then 0 else 1 := by
|
||||
match a, b with
|
||||
| ofNat a, ofNat b => simp [fdiv_eq_ediv_of_nonneg]
|
||||
| -[a+1], ofNat b => simp [fdiv_eq_ediv_of_nonneg]
|
||||
| 0, -[b+1] => simp
|
||||
| ofNat (a + 1), -[b+1] =>
|
||||
simp only [fdiv, ofNat_ediv_negSucc, negSucc_not_nonneg, negSucc_dvd, false_or]
|
||||
simp only [ofNat_eq_coe, ofNat_dvd]
|
||||
norm_cast
|
||||
rw [Nat.succ_div, negSucc_eq]
|
||||
split <;> rename_i h
|
||||
· simp
|
||||
· simp [Int.neg_add]
|
||||
norm_cast
|
||||
| -[a+1], -[b+1] =>
|
||||
simp only [fdiv, ofNat_eq_coe, negSucc_ediv_negSucc, negSucc_not_nonneg, dvd_negSucc, negSucc_dvd,
|
||||
false_or]
|
||||
norm_cast
|
||||
rw [natCast_add, natCast_one, Nat.succ_div]
|
||||
split <;> simp
|
||||
|
||||
theorem ediv_eq_fdiv {a b : Int} :
|
||||
a / b = a.fdiv b + if 0 ≤ b ∨ b ∣ a then 0 else 1 := by
|
||||
simp [fdiv_eq_ediv]
|
||||
|
||||
theorem fdiv_eq_tdiv_of_nonneg {a b : Int} (Ha : 0 ≤ a) (Hb : 0 ≤ b) : fdiv a b = tdiv a b :=
|
||||
tdiv_eq_ediv_of_nonneg Ha ▸ fdiv_eq_ediv_of_nonneg _ Hb
|
||||
|
||||
theorem fdiv_eq_tdiv {a b : Int} :
|
||||
a.fdiv b = a.tdiv b -
|
||||
if b ∣ a then 0
|
||||
else
|
||||
if 0 ≤ a then
|
||||
if 0 ≤ b then 0
|
||||
else 1
|
||||
else
|
||||
if 0 ≤ b then b.sign
|
||||
else 1 + b.sign := by
|
||||
rw [fdiv_eq_ediv, tdiv_eq_ediv]
|
||||
by_cases h : b ∣ a <;> simp [h] <;> omega
|
||||
|
||||
theorem tdiv_eq_fdiv {a b : Int} :
|
||||
a.tdiv b = a.fdiv b +
|
||||
if b ∣ a then 0
|
||||
else
|
||||
if 0 ≤ a then
|
||||
if 0 ≤ b then 0
|
||||
else 1
|
||||
else
|
||||
if 0 ≤ b then b.sign
|
||||
else 1 + b.sign := by
|
||||
rw [fdiv_eq_tdiv]
|
||||
omega
|
||||
|
||||
/-! ### mod zero -/
|
||||
|
||||
@[simp] theorem zero_emod (b : Int) : 0 % b = 0 := rfl
|
||||
|
||||
@[simp] theorem emod_zero : ∀ a : Int, a % 0 = a
|
||||
| ofNat _ => congrArg ofNat <| Nat.mod_zero _
|
||||
| -[_+1] => congrArg negSucc <| Nat.mod_zero _
|
||||
|
||||
@[simp] theorem zero_tmod (b : Int) : tmod 0 b = 0 := by cases b <;> simp [tmod]
|
||||
|
||||
@[simp] theorem tmod_zero : ∀ a : Int, tmod a 0 = a
|
||||
@@ -190,39 +249,11 @@ theorem fdiv_eq_tdiv {a b : Int} (Ha : 0 ≤ a) (Hb : 0 ≤ b) : fdiv a b = tdiv
|
||||
| succ _ => congrArg ofNat <| Nat.mod_zero _
|
||||
| -[_+1] => congrArg negSucc <| Nat.mod_zero _
|
||||
|
||||
/-! ### ofNat mod -/
|
||||
|
||||
@[simp, norm_cast] theorem ofNat_emod (m n : Nat) : (↑(m % n) : Int) = m % n := rfl
|
||||
|
||||
|
||||
/-! ### mod definitions -/
|
||||
|
||||
theorem emod_add_ediv : ∀ a b : Int, a % b + b * (a / b) = a
|
||||
| ofNat _, ofNat _ => congrArg ofNat <| Nat.mod_add_div ..
|
||||
| ofNat m, -[n+1] => by
|
||||
show (m % succ n + -↑(succ n) * -↑(m / succ n) : Int) = m
|
||||
rw [Int.neg_mul_neg]; exact congrArg ofNat <| Nat.mod_add_div ..
|
||||
| -[_+1], 0 => by rw [emod_zero]; rfl
|
||||
| -[m+1], succ n => aux m n.succ
|
||||
| -[m+1], -[n+1] => aux m n.succ
|
||||
where
|
||||
aux (m n : Nat) : n - (m % n + 1) - (n * (m / n) + n) = -[m+1] := by
|
||||
rw [← ofNat_emod, ← ofNat_ediv, ← Int.sub_sub, negSucc_eq, Int.sub_sub n,
|
||||
← Int.neg_neg (_-_), Int.neg_sub, Int.sub_sub_self, Int.add_right_comm]
|
||||
exact congrArg (fun x => -(ofNat x + 1)) (Nat.mod_add_div ..)
|
||||
|
||||
theorem emod_add_ediv' (a b : Int) : a % b + a / b * b = a := by
|
||||
rw [Int.mul_comm]; exact emod_add_ediv ..
|
||||
|
||||
theorem ediv_add_emod (a b : Int) : b * (a / b) + a % b = a := by
|
||||
rw [Int.add_comm]; exact emod_add_ediv ..
|
||||
|
||||
theorem ediv_add_emod' (a b : Int) : a / b * b + a % b = a := by
|
||||
rw [Int.mul_comm]; exact ediv_add_emod ..
|
||||
|
||||
theorem emod_def (a b : Int) : a % b = a - b * (a / b) := by
|
||||
rw [← Int.add_sub_cancel (a % b), emod_add_ediv]
|
||||
|
||||
theorem tmod_add_tdiv : ∀ a b : Int, tmod a b + b * (a.tdiv b) = a
|
||||
| ofNat _, ofNat _ => congrArg ofNat (Nat.mod_add_div ..)
|
||||
| ofNat m, -[n+1] => by
|
||||
@@ -277,28 +308,70 @@ theorem fmod_def (a b : Int) : a.fmod b = a - b * a.fdiv b := by
|
||||
|
||||
/-! ### mod equivalences -/
|
||||
|
||||
theorem fmod_eq_emod (a : Int) {b : Int} (hb : 0 ≤ b) : fmod a b = a % b := by
|
||||
simp [fmod_def, emod_def, fdiv_eq_ediv _ hb]
|
||||
theorem fmod_eq_emod_of_nonneg (a : Int) {b : Int} (hb : 0 ≤ b) : fmod a b = a % b := by
|
||||
simp [fmod_def, emod_def, fdiv_eq_ediv_of_nonneg _ hb]
|
||||
|
||||
theorem tmod_eq_emod {a b : Int} (ha : 0 ≤ a) : tmod a b = a % b := by
|
||||
simp [emod_def, tmod_def, tdiv_eq_ediv ha]
|
||||
theorem fmod_eq_emod {a b : Int} :
|
||||
fmod a b = a % b + if 0 ≤ b ∨ b ∣ a then 0 else b := by
|
||||
simp [fmod_def, emod_def, fdiv_eq_ediv]
|
||||
split <;> simp [Int.mul_sub]
|
||||
omega
|
||||
|
||||
theorem fmod_eq_tmod {a b : Int} (Ha : 0 ≤ a) (Hb : 0 ≤ b) : fmod a b = tmod a b :=
|
||||
tmod_eq_emod Ha ▸ fmod_eq_emod _ Hb
|
||||
theorem emod_eq_fmod {a b : Int} :
|
||||
a % b = fmod a b - if 0 ≤ b ∨ b ∣ a then 0 else b := by
|
||||
simp [fmod_eq_emod]
|
||||
|
||||
theorem tmod_eq_emod_of_nonneg {a b : Int} (ha : 0 ≤ a) : tmod a b = a % b := by
|
||||
simp [emod_def, tmod_def, tdiv_eq_ediv_of_nonneg ha]
|
||||
|
||||
theorem tmod_eq_emod {a b : Int} :
|
||||
tmod a b = a % b - if 0 ≤ a ∨ b ∣ a then 0 else b.natAbs := by
|
||||
rw [tmod_def, tdiv_eq_ediv]
|
||||
simp only [dvd_iff_emod_eq_zero]
|
||||
split
|
||||
· simp [emod_def]
|
||||
· rw [Int.mul_add, ← Int.sub_sub, emod_def]
|
||||
simp
|
||||
|
||||
theorem emod_eq_tmod {a b : Int} :
|
||||
a % b = tmod a b + if 0 ≤ a ∨ b ∣ a then 0 else b.natAbs := by
|
||||
simp [tmod_eq_emod]
|
||||
|
||||
theorem fmod_eq_tmod_of_nonneg {a b : Int} (ha : 0 ≤ a) (hb : 0 ≤ b) : fmod a b = tmod a b :=
|
||||
tmod_eq_emod_of_nonneg ha ▸ fmod_eq_emod_of_nonneg _ hb
|
||||
|
||||
theorem fmod_eq_tmod {a b : Int} :
|
||||
fmod a b = tmod a b +
|
||||
if b ∣ a then 0
|
||||
else
|
||||
if 0 ≤ a then
|
||||
if 0 ≤ b then 0
|
||||
else b
|
||||
else
|
||||
if 0 ≤ b then b.natAbs
|
||||
else 2 * b.toNat := by
|
||||
simp [fmod_eq_emod, tmod_eq_emod]
|
||||
by_cases h : b ∣ a <;> simp [h]
|
||||
split <;> split <;> omega
|
||||
|
||||
theorem tmod_eq_fmod {a b : Int} :
|
||||
tmod a b = fmod a b -
|
||||
if b ∣ a then 0
|
||||
else
|
||||
if 0 ≤ a then
|
||||
if 0 ≤ b then 0
|
||||
else b
|
||||
else
|
||||
if 0 ≤ b then b.natAbs
|
||||
else 2 * b.toNat := by
|
||||
simp [fmod_eq_tmod]
|
||||
|
||||
/-! ### `/` ediv -/
|
||||
|
||||
@[simp] protected theorem ediv_neg : ∀ a b : Int, a / (-b) = -(a / b)
|
||||
| ofNat m, 0 => show ofNat (m / 0) = -↑(m / 0) by rw [Nat.div_zero]; rfl
|
||||
| ofNat _, -[_+1] => (Int.neg_neg _).symm
|
||||
| ofNat _, succ _ | -[_+1], 0 | -[_+1], succ _ | -[_+1], -[_+1] => rfl
|
||||
|
||||
theorem ediv_neg' {a b : Int} (Ha : a < 0) (Hb : 0 < b) : a / b < 0 :=
|
||||
match a, b, eq_negSucc_of_lt_zero Ha, eq_succ_of_zero_lt Hb with
|
||||
| _, _, ⟨_, rfl⟩, ⟨_, rfl⟩ => negSucc_lt_zero _
|
||||
|
||||
protected theorem div_def (a b : Int) : a / b = Int.ediv a b := rfl
|
||||
|
||||
theorem negSucc_ediv (m : Nat) {b : Int} (H : 0 < b) : -[m+1] / b = -(ediv m b + 1) :=
|
||||
match b, eq_succ_of_zero_lt H with
|
||||
| _, ⟨_, rfl⟩ => rfl
|
||||
@@ -326,61 +399,6 @@ theorem ediv_nonneg_of_nonpos_of_nonpos {a b : Int} (Ha : a ≤ 0) (Hb : b ≤ 0
|
||||
theorem ediv_nonpos {a b : Int} (Ha : 0 ≤ a) (Hb : b ≤ 0) : a / b ≤ 0 :=
|
||||
Int.nonpos_of_neg_nonneg <| Int.ediv_neg .. ▸ Int.ediv_nonneg Ha (Int.neg_nonneg_of_nonpos Hb)
|
||||
|
||||
theorem add_mul_ediv_right (a b : Int) {c : Int} (H : c ≠ 0) : (a + b * c) / c = a / c + b :=
|
||||
suffices ∀ {{a b c : Int}}, 0 < c → (a + b * c).ediv c = a.ediv c + b from
|
||||
match Int.lt_trichotomy c 0 with
|
||||
| Or.inl hlt => by
|
||||
rw [← Int.neg_inj, ← Int.ediv_neg, Int.neg_add, ← Int.ediv_neg, ← Int.neg_mul_neg]
|
||||
exact this (Int.neg_pos_of_neg hlt)
|
||||
| Or.inr (Or.inl HEq) => absurd HEq H
|
||||
| Or.inr (Or.inr hgt) => this hgt
|
||||
suffices ∀ {k n : Nat} {a : Int}, (a + n * k.succ).ediv k.succ = a.ediv k.succ + n from
|
||||
fun a b c H => match c, eq_succ_of_zero_lt H, b with
|
||||
| _, ⟨_, rfl⟩, ofNat _ => this
|
||||
| _, ⟨k, rfl⟩, -[n+1] => show (a - n.succ * k.succ).ediv k.succ = a.ediv k.succ - n.succ by
|
||||
rw [← Int.add_sub_cancel (ediv ..), ← this, Int.sub_add_cancel]
|
||||
fun {k n} => @fun
|
||||
| ofNat _ => congrArg ofNat <| Nat.add_mul_div_right _ _ k.succ_pos
|
||||
| -[m+1] => by
|
||||
show ((n * k.succ : Nat) - m.succ : Int).ediv k.succ = n - (m / k.succ + 1 : Nat)
|
||||
by_cases h : m < n * k.succ
|
||||
· rw [← Int.ofNat_sub h, ← Int.ofNat_sub ((Nat.div_lt_iff_lt_mul k.succ_pos).2 h)]
|
||||
apply congrArg ofNat
|
||||
rw [Nat.mul_comm, Nat.mul_sub_div]; rwa [Nat.mul_comm]
|
||||
· have h := Nat.not_lt.1 h
|
||||
have H {a b : Nat} (h : a ≤ b) : (a : Int) + -((b : Int) + 1) = -[b - a +1] := by
|
||||
rw [negSucc_eq, Int.ofNat_sub h]
|
||||
simp only [Int.sub_eq_add_neg, Int.neg_add, Int.neg_neg, Int.add_left_comm, Int.add_assoc]
|
||||
show ediv (↑(n * succ k) + -((m : Int) + 1)) (succ k) = n + -(↑(m / succ k) + 1 : Int)
|
||||
rw [H h, H ((Nat.le_div_iff_mul_le k.succ_pos).2 h)]
|
||||
apply congrArg negSucc
|
||||
rw [Nat.mul_comm, Nat.sub_mul_div]; rwa [Nat.mul_comm]
|
||||
|
||||
theorem add_ediv_of_dvd_right {a b c : Int} (H : c ∣ b) : (a + b) / c = a / c + b / c :=
|
||||
if h : c = 0 then by simp [h] else by
|
||||
let ⟨k, hk⟩ := H
|
||||
rw [hk, Int.mul_comm c k, Int.add_mul_ediv_right _ _ h,
|
||||
← Int.zero_add (k * c), Int.add_mul_ediv_right _ _ h, Int.zero_ediv, Int.zero_add]
|
||||
|
||||
theorem add_ediv_of_dvd_left {a b c : Int} (H : c ∣ a) : (a + b) / c = a / c + b / c := by
|
||||
rw [Int.add_comm, Int.add_ediv_of_dvd_right H, Int.add_comm]
|
||||
|
||||
@[simp] theorem mul_ediv_cancel (a : Int) {b : Int} (H : b ≠ 0) : (a * b) / b = a := by
|
||||
have := Int.add_mul_ediv_right 0 a H
|
||||
rwa [Int.zero_add, Int.zero_ediv, Int.zero_add] at this
|
||||
|
||||
@[simp] theorem mul_ediv_cancel_left (b : Int) (H : a ≠ 0) : (a * b) / a = b :=
|
||||
Int.mul_comm .. ▸ Int.mul_ediv_cancel _ H
|
||||
|
||||
|
||||
theorem div_nonneg_iff_of_pos {a b : Int} (h : 0 < b) : a / b ≥ 0 ↔ a ≥ 0 := by
|
||||
rw [Int.div_def]
|
||||
match b, h with
|
||||
| Int.ofNat (b+1), _ =>
|
||||
rcases a with ⟨a⟩ <;> simp [Int.ediv]
|
||||
norm_cast
|
||||
simp
|
||||
|
||||
theorem ediv_eq_zero_of_lt {a b : Int} (H1 : 0 ≤ a) (H2 : a < b) : a / b = 0 :=
|
||||
match a, b, eq_ofNat_of_zero_le H1, eq_succ_of_zero_lt (Int.lt_of_le_of_lt H1 H2) with
|
||||
| _, _, ⟨_, rfl⟩, ⟨_, rfl⟩ => congrArg Nat.cast <| Nat.div_eq_of_lt <| ofNat_lt.1 H2
|
||||
@@ -442,35 +460,6 @@ theorem emod_negSucc (m : Nat) (n : Int) :
|
||||
|
||||
theorem ofNat_mod_ofNat (m n : Nat) : (m % n : Int) = ↑(m % n) := rfl
|
||||
|
||||
theorem emod_nonneg : ∀ (a : Int) {b : Int}, b ≠ 0 → 0 ≤ a % b
|
||||
| ofNat _, _, _ => ofNat_zero_le _
|
||||
| -[_+1], _, H => Int.sub_nonneg_of_le <| ofNat_le.2 <| Nat.mod_lt _ (natAbs_pos.2 H)
|
||||
|
||||
theorem emod_lt_of_pos (a : Int) {b : Int} (H : 0 < b) : a % b < b :=
|
||||
match a, b, eq_succ_of_zero_lt H with
|
||||
| ofNat _, _, ⟨_, rfl⟩ => ofNat_lt.2 (Nat.mod_lt _ (Nat.succ_pos _))
|
||||
| -[_+1], _, ⟨_, rfl⟩ => Int.sub_lt_self _ (ofNat_lt.2 <| Nat.succ_pos _)
|
||||
|
||||
theorem mul_ediv_self_le {x k : Int} (h : k ≠ 0) : k * (x / k) ≤ x :=
|
||||
calc k * (x / k)
|
||||
_ ≤ k * (x / k) + x % k := Int.le_add_of_nonneg_right (emod_nonneg x h)
|
||||
_ = x := ediv_add_emod _ _
|
||||
|
||||
theorem lt_mul_ediv_self_add {x k : Int} (h : 0 < k) : x < k * (x / k) + k :=
|
||||
calc x
|
||||
_ = k * (x / k) + x % k := (ediv_add_emod _ _).symm
|
||||
_ < k * (x / k) + k := Int.add_lt_add_left (emod_lt_of_pos x h) _
|
||||
|
||||
@[simp] theorem add_mul_emod_self {a b c : Int} : (a + b * c) % c = a % c :=
|
||||
if cz : c = 0 then by
|
||||
rw [cz, Int.mul_zero, Int.add_zero]
|
||||
else by
|
||||
rw [Int.emod_def, Int.emod_def, Int.add_mul_ediv_right _ _ cz, Int.add_comm _ b,
|
||||
Int.mul_add, Int.mul_comm, ← Int.sub_sub, Int.add_sub_cancel]
|
||||
|
||||
@[simp] theorem add_mul_emod_self_left (a b c : Int) : (a + b * c) % b = a % b := by
|
||||
rw [Int.mul_comm, Int.add_mul_emod_self]
|
||||
|
||||
@[simp] theorem add_neg_mul_emod_self {a b c : Int} : (a + -(b * c)) % c = a % c := by
|
||||
rw [Int.neg_mul_eq_neg_mul, add_mul_emod_self]
|
||||
|
||||
@@ -489,53 +478,9 @@ theorem neg_emod {a b : Int} : -a % b = (b - a) % b := by
|
||||
@[simp] theorem emod_neg (a b : Int) : a % -b = a % b := by
|
||||
rw [emod_def, emod_def, Int.ediv_neg, Int.neg_mul_neg]
|
||||
|
||||
@[simp] theorem emod_add_emod (m n k : Int) : (m % n + k) % n = (m + k) % n := by
|
||||
have := (add_mul_emod_self_left (m % n + k) n (m / n)).symm
|
||||
rwa [Int.add_right_comm, emod_add_ediv] at this
|
||||
|
||||
@[simp] theorem add_emod_emod (m n k : Int) : (m + n % k) % k = (m + n) % k := by
|
||||
rw [Int.add_comm, emod_add_emod, Int.add_comm]
|
||||
|
||||
theorem add_emod (a b n : Int) : (a + b) % n = (a % n + b % n) % n := by
|
||||
rw [add_emod_emod, emod_add_emod]
|
||||
|
||||
theorem add_emod_eq_add_emod_right {m n k : Int} (i : Int)
|
||||
(H : m % n = k % n) : (m + i) % n = (k + i) % n := by
|
||||
rw [← emod_add_emod, ← emod_add_emod k, H]
|
||||
|
||||
theorem emod_add_cancel_right {m n k : Int} (i) : (m + i) % n = (k + i) % n ↔ m % n = k % n :=
|
||||
⟨fun H => by
|
||||
have := add_emod_eq_add_emod_right (-i) H
|
||||
rwa [Int.add_neg_cancel_right, Int.add_neg_cancel_right] at this,
|
||||
add_emod_eq_add_emod_right _⟩
|
||||
|
||||
@[simp] theorem mul_emod_left (a b : Int) : (a * b) % b = 0 := by
|
||||
rw [← Int.zero_add (a * b), Int.add_mul_emod_self, Int.zero_emod]
|
||||
|
||||
@[simp] theorem mul_emod_right (a b : Int) : (a * b) % a = 0 := by
|
||||
rw [Int.mul_comm, mul_emod_left]
|
||||
|
||||
theorem mul_emod (a b n : Int) : (a * b) % n = (a % n) * (b % n) % n := by
|
||||
conv => lhs; rw [
|
||||
← emod_add_ediv a n, ← emod_add_ediv' b n, Int.add_mul, Int.mul_add, Int.mul_add,
|
||||
Int.mul_assoc, Int.mul_assoc, ← Int.mul_add n _ _, add_mul_emod_self_left,
|
||||
← Int.mul_assoc, add_mul_emod_self]
|
||||
|
||||
@[simp] theorem emod_self {a : Int} : a % a = 0 := by
|
||||
have := mul_emod_left 1 a; rwa [Int.one_mul] at this
|
||||
|
||||
@[simp] theorem neg_emod_self (a : Int) : -a % a = 0 := by
|
||||
rw [neg_emod, Int.sub_self, zero_emod]
|
||||
|
||||
@[simp] theorem emod_emod_of_dvd (n : Int) {m k : Int}
|
||||
(h : m ∣ k) : (n % k) % m = n % m := by
|
||||
conv => rhs; rw [← emod_add_ediv n k]
|
||||
match k, h with
|
||||
| _, ⟨t, rfl⟩ => rw [Int.mul_assoc, add_mul_emod_self_left]
|
||||
|
||||
@[simp] theorem emod_emod (a b : Int) : (a % b) % b = a % b := by
|
||||
conv => rhs; rw [← emod_add_ediv a b, add_mul_emod_self_left]
|
||||
|
||||
@[simp] theorem emod_sub_emod (m n k : Int) : (m % n - k) % n = (m - k) % n :=
|
||||
Int.emod_add_emod m n (-k)
|
||||
|
||||
@@ -543,10 +488,6 @@ theorem mul_emod (a b n : Int) : (a * b) % n = (a % n) * (b % n) % n := by
|
||||
apply (emod_add_cancel_right (n % k)).mp
|
||||
rw [Int.sub_add_cancel, Int.add_emod_emod, Int.sub_add_cancel]
|
||||
|
||||
theorem sub_emod (a b n : Int) : (a - b) % n = (a % n - b % n) % n := by
|
||||
apply (emod_add_cancel_right b).mp
|
||||
rw [Int.sub_add_cancel, ← Int.add_emod_emod, Int.sub_add_cancel, emod_emod]
|
||||
|
||||
theorem emod_eq_of_lt {a b : Int} (H1 : 0 ≤ a) (H2 : a < b) : a % b = a :=
|
||||
have b0 := Int.le_trans H1 (Int.le_of_lt H2)
|
||||
match a, b, eq_ofNat_of_zero_le H1, eq_ofNat_of_zero_le b0 with
|
||||
@@ -557,12 +498,6 @@ theorem emod_eq_of_lt {a b : Int} (H1 : 0 ≤ a) (H2 : a < b) : a % b = a :=
|
||||
|
||||
/-! ### properties of `/` and `%` -/
|
||||
|
||||
theorem mul_ediv_cancel_of_emod_eq_zero {a b : Int} (H : a % b = 0) : b * (a / b) = a := by
|
||||
have := emod_add_ediv a b; rwa [H, Int.zero_add] at this
|
||||
|
||||
theorem ediv_mul_cancel_of_emod_eq_zero {a b : Int} (H : a % b = 0) : a / b * b = a := by
|
||||
rw [Int.mul_comm, mul_ediv_cancel_of_emod_eq_zero H]
|
||||
|
||||
theorem emod_two_eq (x : Int) : x % 2 = 0 ∨ x % 2 = 1 := by
|
||||
have h₁ : 0 ≤ x % 2 := Int.emod_nonneg x (by decide)
|
||||
have h₂ : x % 2 < 2 := Int.emod_lt_of_pos x (by decide)
|
||||
@@ -616,19 +551,10 @@ theorem ediv_le_self {a : Int} (b : Int) (Ha : 0 ≤ a) : a / b ≤ a := by
|
||||
have := Int.le_trans le_natAbs (ofNat_le.2 <| natAbs_div_le_natAbs a b)
|
||||
rwa [natAbs_of_nonneg Ha] at this
|
||||
|
||||
theorem dvd_of_emod_eq_zero {a b : Int} (H : b % a = 0) : a ∣ b :=
|
||||
⟨b / a, (mul_ediv_cancel_of_emod_eq_zero H).symm⟩
|
||||
|
||||
theorem dvd_emod_sub_self {x : Int} {m : Nat} : (m : Int) ∣ x % m - x := by
|
||||
apply dvd_of_emod_eq_zero
|
||||
simp [sub_emod]
|
||||
|
||||
theorem emod_eq_zero_of_dvd : ∀ {a b : Int}, a ∣ b → b % a = 0
|
||||
| _, _, ⟨_, rfl⟩ => mul_emod_right ..
|
||||
|
||||
theorem dvd_iff_emod_eq_zero {a b : Int} : a ∣ b ↔ b % a = 0 :=
|
||||
⟨emod_eq_zero_of_dvd, dvd_of_emod_eq_zero⟩
|
||||
|
||||
@[simp] theorem neg_mul_emod_left (a b : Int) : -(a * b) % b = 0 := by
|
||||
rw [← dvd_iff_emod_eq_zero, Int.dvd_neg]
|
||||
exact Int.dvd_mul_left a b
|
||||
@@ -637,41 +563,12 @@ theorem dvd_iff_emod_eq_zero {a b : Int} : a ∣ b ↔ b % a = 0 :=
|
||||
rw [← dvd_iff_emod_eq_zero, Int.dvd_neg]
|
||||
exact Int.dvd_mul_right a b
|
||||
|
||||
instance decidableDvd : DecidableRel (α := Int) (· ∣ ·) := fun _ _ =>
|
||||
decidable_of_decidable_of_iff (dvd_iff_emod_eq_zero ..).symm
|
||||
|
||||
theorem emod_pos_of_not_dvd {a b : Int} (h : ¬ a ∣ b) : a = 0 ∨ 0 < b % a := by
|
||||
rw [dvd_iff_emod_eq_zero] at h
|
||||
by_cases w : a = 0
|
||||
· simp_all
|
||||
· exact Or.inr (Int.lt_iff_le_and_ne.mpr ⟨emod_nonneg b w, Ne.symm h⟩)
|
||||
|
||||
protected theorem mul_ediv_assoc (a : Int) : ∀ {b c : Int}, c ∣ b → (a * b) / c = a * (b / c)
|
||||
| _, c, ⟨d, rfl⟩ =>
|
||||
if cz : c = 0 then by simp [cz, Int.mul_zero] else by
|
||||
rw [Int.mul_left_comm, Int.mul_ediv_cancel_left _ cz, Int.mul_ediv_cancel_left _ cz]
|
||||
|
||||
protected theorem mul_ediv_assoc' (b : Int) {a c : Int}
|
||||
(h : c ∣ a) : (a * b) / c = a / c * b := by
|
||||
rw [Int.mul_comm, Int.mul_ediv_assoc _ h, Int.mul_comm]
|
||||
|
||||
theorem neg_ediv_of_dvd : ∀ {a b : Int}, b ∣ a → (-a) / b = -(a / b)
|
||||
| _, b, ⟨c, rfl⟩ => by
|
||||
by_cases bz : b = 0
|
||||
· simp [bz]
|
||||
· rw [Int.neg_mul_eq_mul_neg, Int.mul_ediv_cancel_left _ bz, Int.mul_ediv_cancel_left _ bz]
|
||||
|
||||
@[simp] theorem neg_mul_ediv_cancel (a b : Int) (h : b ≠ 0) : -(a * b) / b = -a := by
|
||||
rw [neg_ediv_of_dvd (Int.dvd_mul_left a b), mul_ediv_cancel _ h]
|
||||
|
||||
@[simp] theorem neg_mul_ediv_cancel_left (a b : Int) (h : a ≠ 0) : -(a * b) / a = -b := by
|
||||
rw [neg_ediv_of_dvd (Int.dvd_mul_right a b), mul_ediv_cancel_left _ h]
|
||||
|
||||
theorem sub_ediv_of_dvd (a : Int) {b c : Int}
|
||||
(hcb : c ∣ b) : (a - b) / c = a / c - b / c := by
|
||||
rw [Int.sub_eq_add_neg, Int.sub_eq_add_neg, Int.add_ediv_of_dvd_right (Int.dvd_neg.2 hcb)]
|
||||
congr; exact Int.neg_ediv_of_dvd hcb
|
||||
|
||||
@[simp] theorem ediv_one : ∀ a : Int, a / 1 = a
|
||||
| (_:Nat) => congrArg Nat.cast (Nat.div_one _)
|
||||
| -[_+1] => congrArg negSucc (Nat.div_one _)
|
||||
@@ -705,12 +602,6 @@ theorem dvd_sub_of_emod_eq {a b c : Int} (h : a % b = c) : b ∣ a - c := by
|
||||
rw [Int.emod_emod, ← emod_sub_cancel_right c, Int.sub_self, zero_emod] at hx
|
||||
exact dvd_of_emod_eq_zero hx
|
||||
|
||||
protected theorem ediv_mul_cancel {a b : Int} (H : b ∣ a) : a / b * b = a :=
|
||||
ediv_mul_cancel_of_emod_eq_zero (emod_eq_zero_of_dvd H)
|
||||
|
||||
protected theorem mul_ediv_cancel' {a b : Int} (H : a ∣ b) : a * (b / a) = b := by
|
||||
rw [Int.mul_comm, Int.ediv_mul_cancel H]
|
||||
|
||||
protected theorem eq_mul_of_ediv_eq_right {a b c : Int}
|
||||
(H1 : b ∣ a) (H2 : a / b = c) : a = b * c := by rw [← H2, Int.mul_ediv_cancel' H1]
|
||||
|
||||
@@ -920,7 +811,7 @@ theorem ofNat_tmod (m n : Nat) : (↑(m % n) : Int) = tmod m n := rfl
|
||||
simp [tmod_def, Int.tdiv_one, Int.one_mul, Int.sub_self]
|
||||
|
||||
theorem tmod_eq_of_lt {a b : Int} (H1 : 0 ≤ a) (H2 : a < b) : tmod a b = a := by
|
||||
rw [tmod_eq_emod H1, emod_eq_of_lt H1 H2]
|
||||
rw [tmod_eq_emod_of_nonneg H1, emod_eq_of_lt H1 H2]
|
||||
|
||||
theorem tmod_lt_of_pos (a : Int) {b : Int} (H : 0 < b) : tmod a b < b :=
|
||||
match a, b, eq_succ_of_zero_lt H with
|
||||
@@ -1029,7 +920,7 @@ theorem fdiv_neg' : ∀ {a b : Int}, a < 0 → 0 < b → a.fdiv b < 0
|
||||
|
||||
@[simp] theorem mul_fdiv_cancel (a : Int) {b : Int} (H : b ≠ 0) : fdiv (a * b) b = a :=
|
||||
if b0 : 0 ≤ b then by
|
||||
rw [fdiv_eq_ediv _ b0, mul_ediv_cancel _ H]
|
||||
rw [fdiv_eq_ediv_of_nonneg _ b0, mul_ediv_cancel _ H]
|
||||
else
|
||||
match a, b, Int.not_le.1 b0 with
|
||||
| 0, _, _ => by simp [Int.zero_mul]
|
||||
@@ -1045,7 +936,7 @@ theorem fdiv_neg' : ∀ {a b : Int}, a < 0 → 0 < b → a.fdiv b < 0
|
||||
have := Int.mul_fdiv_cancel 1 H; rwa [Int.one_mul] at this
|
||||
|
||||
theorem lt_fdiv_add_one_mul_self (a : Int) {b : Int} (H : 0 < b) : a < (a.fdiv b + 1) * b :=
|
||||
Int.fdiv_eq_ediv _ (Int.le_of_lt H) ▸ lt_ediv_add_one_mul_self a H
|
||||
Int.fdiv_eq_ediv_of_nonneg _ (Int.le_of_lt H) ▸ lt_ediv_add_one_mul_self a H
|
||||
|
||||
/-! ### fmod -/
|
||||
|
||||
@@ -1056,16 +947,16 @@ theorem ofNat_fmod (m n : Nat) : ↑(m % n) = fmod m n := by
|
||||
simp [fmod_def, Int.one_mul, Int.sub_self]
|
||||
|
||||
theorem fmod_eq_of_lt {a b : Int} (H1 : 0 ≤ a) (H2 : a < b) : a.fmod b = a := by
|
||||
rw [fmod_eq_emod _ (Int.le_trans H1 (Int.le_of_lt H2)), emod_eq_of_lt H1 H2]
|
||||
rw [fmod_eq_emod_of_nonneg _ (Int.le_trans H1 (Int.le_of_lt H2)), emod_eq_of_lt H1 H2]
|
||||
|
||||
theorem fmod_nonneg {a b : Int} (ha : 0 ≤ a) (hb : 0 ≤ b) : 0 ≤ a.fmod b :=
|
||||
fmod_eq_tmod ha hb ▸ tmod_nonneg _ ha
|
||||
fmod_eq_tmod_of_nonneg ha hb ▸ tmod_nonneg _ ha
|
||||
|
||||
theorem fmod_nonneg' (a : Int) {b : Int} (hb : 0 < b) : 0 ≤ a.fmod b :=
|
||||
fmod_eq_emod _ (Int.le_of_lt hb) ▸ emod_nonneg _ (Int.ne_of_lt hb).symm
|
||||
fmod_eq_emod_of_nonneg _ (Int.le_of_lt hb) ▸ emod_nonneg _ (Int.ne_of_lt hb).symm
|
||||
|
||||
theorem fmod_lt_of_pos (a : Int) {b : Int} (H : 0 < b) : a.fmod b < b :=
|
||||
fmod_eq_emod _ (Int.le_of_lt H) ▸ emod_lt_of_pos a H
|
||||
fmod_eq_emod_of_nonneg _ (Int.le_of_lt H) ▸ emod_lt_of_pos a H
|
||||
|
||||
@[simp] theorem mul_fmod_left (a b : Int) : (a * b).fmod b = 0 :=
|
||||
if h : b = 0 then by simp [h, Int.mul_zero] else by
|
||||
@@ -1092,21 +983,10 @@ theorem fdiv_eq_ediv_of_dvd : ∀ {a b : Int}, b ∣ a → a.fdiv b = a / b
|
||||
|
||||
/-! ### bmod -/
|
||||
|
||||
@[simp] theorem bmod_emod : bmod x m % m = x % m := by
|
||||
dsimp [bmod]
|
||||
split <;> simp [Int.sub_emod]
|
||||
|
||||
@[simp]
|
||||
theorem emod_bmod_congr (x : Int) (n : Nat) : Int.bmod (x%n) n = Int.bmod x n := by
|
||||
simp [bmod, Int.emod_emod]
|
||||
|
||||
theorem bmod_def (x : Int) (m : Nat) : bmod x m =
|
||||
if (x % m) < (m + 1) / 2 then
|
||||
x % m
|
||||
else
|
||||
(x % m) - m :=
|
||||
rfl
|
||||
|
||||
theorem bdiv_add_bmod (x : Int) (m : Nat) : m * bdiv x m + bmod x m = x := by
|
||||
unfold bdiv bmod
|
||||
split
|
||||
@@ -7,7 +7,7 @@ prelude
|
||||
import Init.Data.Int.Basic
|
||||
import Init.Data.Nat.Gcd
|
||||
import Init.Data.Nat.Lcm
|
||||
import Init.Data.Int.DivModLemmas
|
||||
import Init.Data.Int.DivMod.Lemmas
|
||||
|
||||
/-!
|
||||
Definition and lemmas for gcd and lcm over Int
|
||||
|
||||
@@ -129,7 +129,16 @@ theorem subNatNat_of_le {m n : Nat} (h : n ≤ m) : subNatNat m n = ↑(m - n) :
|
||||
theorem subNatNat_of_lt {m n : Nat} (h : m < n) : subNatNat m n = -[pred (n - m) +1] :=
|
||||
subNatNat_of_sub_eq_succ <| (Nat.succ_pred_eq_of_pos (Nat.sub_pos_of_lt h)).symm
|
||||
|
||||
|
||||
@[simp] theorem subNat_eq_zero_iff {a b : Nat} : subNatNat a b = 0 ↔ a = b := by
|
||||
cases Nat.lt_or_ge a b with
|
||||
| inl h =>
|
||||
rw [subNatNat_of_lt h]
|
||||
simpa using ne_of_lt h
|
||||
| inr h =>
|
||||
rw [subNatNat_of_le h]
|
||||
norm_cast
|
||||
rw [Nat.sub_eq_iff_eq_add' h]
|
||||
simp
|
||||
|
||||
/- # Additive group properties -/
|
||||
|
||||
@@ -332,6 +341,20 @@ theorem toNat_of_nonpos : ∀ {z : Int}, z ≤ 0 → z.toNat = 0
|
||||
| 0, _ => rfl
|
||||
| -[_+1], _ => rfl
|
||||
|
||||
@[simp] theorem neg_ofNat_eq_negSucc_iff {a b : Nat} : - (a : Int) = -[b+1] ↔ a = b + 1 := by
|
||||
rw [Int.neg_eq_comm]
|
||||
rw [Int.neg_negSucc]
|
||||
norm_cast
|
||||
simp [eq_comm]
|
||||
|
||||
@[simp] theorem neg_ofNat_eq_negSucc_add_one_iff {a b : Nat} : - (a : Int) = -[b+1] + 1 ↔ a = b := by
|
||||
cases b with
|
||||
| zero => simp; norm_cast
|
||||
| succ b =>
|
||||
rw [Int.neg_eq_comm, ← Int.negSucc_sub_one, Int.sub_add_cancel, Int.neg_negSucc]
|
||||
norm_cast
|
||||
simp [eq_comm]
|
||||
|
||||
/- ## add/sub injectivity -/
|
||||
|
||||
protected theorem add_left_inj {i j : Int} (k : Int) : (i + k = j + k) ↔ i = j := by
|
||||
|
||||
@@ -5,6 +5,7 @@ Authors: Kim Morrison
|
||||
-/
|
||||
prelude
|
||||
import Init.Data.Int.Order
|
||||
import Init.Data.Int.DivMod.Lemmas
|
||||
import Init.Omega
|
||||
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1011,11 +1011,16 @@ theorem sign_eq_neg_one_iff_neg {a : Int} : sign a = -1 ↔ a < 0 :=
|
||||
exact Int.le_add_one (ofNat_nonneg _)
|
||||
| .negSucc _ => simp +decide [sign]
|
||||
|
||||
theorem mul_sign : ∀ i : Int, i * sign i = natAbs i
|
||||
@[simp] theorem mul_sign_self : ∀ i : Int, i * sign i = natAbs i
|
||||
| succ _ => Int.mul_one _
|
||||
| 0 => Int.mul_zero _
|
||||
| -[_+1] => Int.mul_neg_one _
|
||||
|
||||
@[deprecated mul_sign_self (since := "2025-02-24")] abbrev mul_sign := @mul_sign_self
|
||||
|
||||
@[simp] theorem sign_mul_self : sign i * i = natAbs i := by
|
||||
rw [Int.mul_comm, mul_sign_self]
|
||||
|
||||
/- ## natAbs -/
|
||||
|
||||
theorem natAbs_ne_zero {a : Int} : a.natAbs ≠ 0 ↔ a ≠ 0 := not_congr Int.natAbs_eq_zero
|
||||
|
||||
@@ -8,8 +8,8 @@ import Init.Data.List.Count
|
||||
import Init.Data.Subtype
|
||||
import Init.BinderNameHint
|
||||
|
||||
-- set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
-- set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
|
||||
namespace List
|
||||
|
||||
@@ -190,7 +190,7 @@ theorem length_attachWith {p : α → Prop} {l H} : length (l.attachWith p H) =
|
||||
|
||||
@[simp]
|
||||
theorem pmap_eq_nil_iff {p : α → Prop} {f : ∀ a, p a → β} {l H} : pmap f l H = [] ↔ l = [] := by
|
||||
rw [← length_eq_zero, length_pmap, length_eq_zero]
|
||||
rw [← length_eq_zero_iff, length_pmap, length_eq_zero_iff]
|
||||
|
||||
theorem pmap_ne_nil_iff {P : α → Prop} (f : (a : α) → P a → β) {xs : List α}
|
||||
(H : ∀ (a : α), a ∈ xs → P a) : xs.pmap f H ≠ [] ↔ xs ≠ [] := by
|
||||
@@ -662,6 +662,10 @@ def unattach {α : Type _} {p : α → Prop} (l : List { x // p x }) : List α :
|
||||
@[simp] theorem unattach_cons {p : α → Prop} {a : { x // p x }} {l : List { x // p x }} :
|
||||
(a :: l).unattach = a.val :: l.unattach := rfl
|
||||
|
||||
@[simp] theorem mem_unattach {p : α → Prop} {l : List { x // p x }} {a} :
|
||||
a ∈ l.unattach ↔ ∃ h : p a, ⟨a, h⟩ ∈ l := by
|
||||
simp only [unattach, mem_map, Subtype.exists, exists_and_right, exists_eq_right]
|
||||
|
||||
@[simp] theorem length_unattach {p : α → Prop} {l : List { x // p x }} :
|
||||
l.unattach.length = l.length := by
|
||||
unfold unattach
|
||||
@@ -766,6 +770,16 @@ and simplifies these to the function directly taking the value.
|
||||
simp [hf, find?_cons]
|
||||
split <;> simp [ih]
|
||||
|
||||
@[simp] theorem all_subtype {p : α → Prop} {l : List { x // p x }} {f : { x // p x } → Bool} {g : α → Bool}
|
||||
(hf : ∀ x h, f ⟨x, h⟩ = g x) :
|
||||
l.all f = l.unattach.all g := by
|
||||
simp [all_eq, hf]
|
||||
|
||||
@[simp] theorem any_subtype {p : α → Prop} {l : List { x // p x }} {f : { x // p x } → Bool} {g : α → Bool}
|
||||
(hf : ∀ x h, f ⟨x, h⟩ = g x) :
|
||||
l.any f = l.unattach.any g := by
|
||||
simp [any_eq, hf]
|
||||
|
||||
/-! ### Simp lemmas pushing `unattach` inwards. -/
|
||||
|
||||
@[simp] theorem unattach_filter {p : α → Prop} {l : List { x // p x }}
|
||||
|
||||
@@ -58,8 +58,8 @@ Further operations are defined in `Init.Data.List.BasicAux`
|
||||
-/
|
||||
|
||||
set_option linter.missingDocs true -- keep it documented
|
||||
-- set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
-- set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
|
||||
open Decidable List
|
||||
|
||||
|
||||
@@ -6,8 +6,8 @@ Author: Leonardo de Moura
|
||||
prelude
|
||||
import Init.Data.Nat.Linear
|
||||
|
||||
-- set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
-- set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
|
||||
universe u
|
||||
|
||||
|
||||
@@ -9,8 +9,8 @@ import Init.Control.Id
|
||||
import Init.Control.Lawful
|
||||
import Init.Data.List.Basic
|
||||
|
||||
-- set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
-- set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
|
||||
namespace List
|
||||
universe u v w u₁ u₂
|
||||
|
||||
@@ -10,8 +10,8 @@ import Init.Data.List.Sublist
|
||||
# Lemmas about `List.countP` and `List.count`.
|
||||
-/
|
||||
|
||||
-- set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
-- set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
|
||||
namespace List
|
||||
|
||||
@@ -87,7 +87,7 @@ theorem countP_le_length : countP p l ≤ l.length := by
|
||||
countP_pos_iff
|
||||
|
||||
@[simp] theorem countP_eq_zero {p} : countP p l = 0 ↔ ∀ a ∈ l, ¬p a := by
|
||||
simp only [countP_eq_length_filter, length_eq_zero, filter_eq_nil_iff]
|
||||
simp only [countP_eq_length_filter, length_eq_zero_iff, filter_eq_nil_iff]
|
||||
|
||||
@[simp] theorem countP_eq_length {p} : countP p l = l.length ↔ ∀ a ∈ l, p a := by
|
||||
rw [countP_eq_length_filter, filter_length_eq_length]
|
||||
|
||||
@@ -12,8 +12,8 @@ import Init.Data.List.Find
|
||||
# Lemmas about `List.eraseP`, `List.erase`, and `List.eraseIdx`.
|
||||
-/
|
||||
|
||||
-- set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
-- set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
|
||||
namespace List
|
||||
|
||||
@@ -137,7 +137,7 @@ theorem mem_of_mem_eraseP {l : List α} : a ∈ l.eraseP p → a ∈ l := (erase
|
||||
@[simp] theorem eraseP_eq_self_iff {p} {l : List α} : l.eraseP p = l ↔ ∀ a ∈ l, ¬ p a := by
|
||||
rw [← Sublist.length_eq (eraseP_sublist l), length_eraseP]
|
||||
split <;> rename_i h
|
||||
· simp only [any_eq_true, length_eq_zero] at h
|
||||
· simp only [any_eq_true, length_eq_zero_iff] at h
|
||||
constructor
|
||||
· intro; simp_all [Nat.sub_one_eq_self]
|
||||
· intro; obtain ⟨x, m, h⟩ := h; simp_all
|
||||
|
||||
@@ -6,8 +6,8 @@ Authors: François G. Dorais
|
||||
prelude
|
||||
import Init.Data.List.OfFn
|
||||
|
||||
-- set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
-- set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
|
||||
namespace List
|
||||
|
||||
|
||||
@@ -15,8 +15,8 @@ Lemmas about `List.findSome?`, `List.find?`, `List.findIdx`, `List.findIdx?`, `L
|
||||
and `List.lookup`.
|
||||
-/
|
||||
|
||||
-- set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
-- set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
|
||||
|
||||
namespace List
|
||||
@@ -514,47 +514,6 @@ private theorem findIdx?_go_eq {p : α → Bool} {xs : List α} {i : Nat} :
|
||||
(x :: xs).findIdx? p = if p x then some 0 else (xs.findIdx? p).map fun i => i + 1 := by
|
||||
simp [findIdx?, findIdx?_go_eq]
|
||||
|
||||
/-! ### findFinIdx? -/
|
||||
|
||||
@[simp] theorem findFinIdx?_nil {p : α → Bool} : findFinIdx? p [] = none := rfl
|
||||
|
||||
theorem findIdx?_go_eq_map_findFinIdx?_go_val {xs : List α} {p : α → Bool} {i : Nat} {h} :
|
||||
List.findIdx?.go p xs i =
|
||||
(List.findFinIdx?.go p l xs i h).map (·.val) := by
|
||||
unfold findIdx?.go
|
||||
unfold findFinIdx?.go
|
||||
split
|
||||
· simp_all
|
||||
· simp only
|
||||
split
|
||||
· simp
|
||||
· rw [findIdx?_go_eq_map_findFinIdx?_go_val]
|
||||
|
||||
theorem findIdx?_eq_map_findFinIdx?_val {xs : List α} {p : α → Bool} :
|
||||
xs.findIdx? p = (xs.findFinIdx? p).map (·.val) := by
|
||||
simp [findIdx?, findFinIdx?]
|
||||
rw [findIdx?_go_eq_map_findFinIdx?_go_val]
|
||||
|
||||
@[simp] theorem findFinIdx?_cons {p : α → Bool} {x : α} {xs : List α} :
|
||||
findFinIdx? p (x :: xs) = if p x then some 0 else (findFinIdx? p xs).map Fin.succ := by
|
||||
rw [← Option.map_inj_right (f := Fin.val) (fun a b => Fin.eq_of_val_eq)]
|
||||
rw [← findIdx?_eq_map_findFinIdx?_val]
|
||||
rw [findIdx?_cons]
|
||||
split
|
||||
· simp
|
||||
· rw [findIdx?_eq_map_findFinIdx?_val]
|
||||
simp [Function.comp_def]
|
||||
|
||||
@[simp] theorem findFinIdx?_subtype {p : α → Prop} {l : List { x // p x }}
|
||||
{f : { x // p x } → Bool} {g : α → Bool} (hf : ∀ x h, f ⟨x, h⟩ = g x) :
|
||||
l.findFinIdx? f = (l.unattach.findFinIdx? g).map (fun i => i.cast (by simp)) := by
|
||||
unfold unattach
|
||||
induction l with
|
||||
| nil => simp
|
||||
| cons a l ih =>
|
||||
simp [hf, findFinIdx?_cons]
|
||||
split <;> simp [ih, Function.comp_def]
|
||||
|
||||
/-! ### findIdx -/
|
||||
|
||||
theorem findIdx_cons (p : α → Bool) (b : α) (l : List α) :
|
||||
@@ -976,6 +935,71 @@ theorem findIdx_eq_getD_findIdx? {xs : List α} {p : α → Bool} :
|
||||
simp [hf, findIdx?_cons]
|
||||
split <;> simp [ih, Function.comp_def]
|
||||
|
||||
/-! ### findFinIdx? -/
|
||||
|
||||
@[simp] theorem findFinIdx?_nil {p : α → Bool} : findFinIdx? p [] = none := rfl
|
||||
|
||||
theorem findIdx?_go_eq_map_findFinIdx?_go_val {xs : List α} {p : α → Bool} {i : Nat} {h} :
|
||||
List.findIdx?.go p xs i =
|
||||
(List.findFinIdx?.go p l xs i h).map (·.val) := by
|
||||
unfold findIdx?.go
|
||||
unfold findFinIdx?.go
|
||||
split
|
||||
· simp_all
|
||||
· simp only
|
||||
split
|
||||
· simp
|
||||
· rw [findIdx?_go_eq_map_findFinIdx?_go_val]
|
||||
|
||||
theorem findIdx?_eq_map_findFinIdx?_val {xs : List α} {p : α → Bool} :
|
||||
xs.findIdx? p = (xs.findFinIdx? p).map (·.val) := by
|
||||
simp [findIdx?, findFinIdx?]
|
||||
rw [findIdx?_go_eq_map_findFinIdx?_go_val]
|
||||
|
||||
theorem findFinIdx?_eq_pmap_findIdx? {xs : List α} {p : α → Bool} :
|
||||
xs.findFinIdx? p =
|
||||
(xs.findIdx? p).pmap
|
||||
(fun i m => by simp [findIdx?_eq_some_iff_getElem] at m; exact ⟨i, m.choose⟩)
|
||||
(fun i h => h) := by
|
||||
simp [findIdx?_eq_map_findFinIdx?_val, Option.pmap_map]
|
||||
|
||||
@[simp] theorem findFinIdx?_cons {p : α → Bool} {x : α} {xs : List α} :
|
||||
findFinIdx? p (x :: xs) = if p x then some 0 else (findFinIdx? p xs).map Fin.succ := by
|
||||
rw [← Option.map_inj_right (f := Fin.val) (fun a b => Fin.eq_of_val_eq)]
|
||||
rw [← findIdx?_eq_map_findFinIdx?_val]
|
||||
rw [findIdx?_cons]
|
||||
split
|
||||
· simp
|
||||
· rw [findIdx?_eq_map_findFinIdx?_val]
|
||||
simp [Function.comp_def]
|
||||
|
||||
@[simp] theorem findFinIdx?_eq_none_iff {l : List α} {p : α → Bool} :
|
||||
l.findFinIdx? p = none ↔ ∀ x ∈ l, ¬ p x := by
|
||||
simp [findFinIdx?_eq_pmap_findIdx?]
|
||||
|
||||
@[simp]
|
||||
theorem findFinIdx?_eq_some_iff {xs : List α} {p : α → Bool} {i : Fin xs.length} :
|
||||
xs.findFinIdx? p = some i ↔
|
||||
p xs[i] ∧ ∀ j (hji : j < i), ¬p (xs[j]'(Nat.lt_trans hji i.2)) := by
|
||||
simp only [findFinIdx?_eq_pmap_findIdx?, Option.pmap_eq_some_iff, findIdx?_eq_some_iff_getElem,
|
||||
Bool.not_eq_true, Option.mem_def, exists_and_left, and_exists_self, Fin.getElem_fin]
|
||||
constructor
|
||||
· rintro ⟨a, ⟨h, w₁, w₂⟩, rfl⟩
|
||||
exact ⟨w₁, fun j hji => by simpa using w₂ j hji⟩
|
||||
· rintro ⟨h, w⟩
|
||||
exact ⟨i, ⟨i.2, h, fun j hji => w ⟨j, by omega⟩ hji⟩, rfl⟩
|
||||
|
||||
@[simp] theorem findFinIdx?_subtype {p : α → Prop} {l : List { x // p x }}
|
||||
{f : { x // p x } → Bool} {g : α → Bool} (hf : ∀ x h, f ⟨x, h⟩ = g x) :
|
||||
l.findFinIdx? f = (l.unattach.findFinIdx? g).map (fun i => i.cast (by simp)) := by
|
||||
unfold unattach
|
||||
induction l with
|
||||
| nil => simp
|
||||
| cons a l ih =>
|
||||
simp [hf, findFinIdx?_cons]
|
||||
split <;> simp [ih, Function.comp_def]
|
||||
|
||||
|
||||
/-! ### idxOf
|
||||
|
||||
The verification API for `idxOf` is still incomplete.
|
||||
@@ -1035,6 +1059,36 @@ theorem idxOf_lt_length [BEq α] [LawfulBEq α] {l : List α} (h : a ∈ l) : l.
|
||||
@[deprecated idxOf_lt_length (since := "2025-01-29")]
|
||||
abbrev indexOf_lt_length := @idxOf_lt_length
|
||||
|
||||
/-! ### finIdxOf?
|
||||
|
||||
The verification API for `finIdxOf?` is still incomplete.
|
||||
The lemmas below should be made consistent with those for `findFinIdx?` (and proved using them).
|
||||
-/
|
||||
|
||||
theorem idxOf?_eq_map_finIdxOf?_val [BEq α] {xs : List α} {a : α} :
|
||||
xs.idxOf? a = (xs.finIdxOf? a).map (·.val) := by
|
||||
simp [idxOf?, finIdxOf?, findIdx?_eq_map_findFinIdx?_val]
|
||||
|
||||
@[simp] theorem finIdxOf?_nil [BEq α] : ([] : List α).finIdxOf? a = none := rfl
|
||||
|
||||
@[simp] theorem finIdxOf?_cons [BEq α] (a : α) (xs : List α) :
|
||||
(a :: xs).finIdxOf? b =
|
||||
if a == b then some ⟨0, by simp⟩ else (xs.finIdxOf? b).map (·.succ) := by
|
||||
simp [finIdxOf?]
|
||||
|
||||
@[simp] theorem finIdxOf?_eq_none_iff [BEq α] [LawfulBEq α] {l : List α} {a : α} :
|
||||
l.finIdxOf? a = none ↔ a ∉ l := by
|
||||
simp only [finIdxOf?, findFinIdx?_eq_none_iff, beq_iff_eq]
|
||||
constructor
|
||||
· intro w m
|
||||
exact w a m rfl
|
||||
· rintro h a m rfl
|
||||
exact h m
|
||||
|
||||
@[simp] theorem finIdxOf?_eq_some_iff [BEq α] [LawfulBEq α] {l : List α} {a : α} {i : Fin l.length} :
|
||||
l.finIdxOf? a = some i ↔ l[i] = a ∧ ∀ j (_ : j < i), ¬l[j] = a := by
|
||||
simp only [finIdxOf?, findFinIdx?_eq_some_iff, beq_iff_eq]
|
||||
|
||||
/-! ### idxOf?
|
||||
|
||||
The verification API for `idxOf?` is still incomplete.
|
||||
@@ -1060,12 +1114,6 @@ theorem idxOf?_cons [BEq α] (a : α) (xs : List α) (b : α) :
|
||||
@[deprecated idxOf?_eq_none_iff (since := "2025-01-29")]
|
||||
abbrev indexOf?_eq_none_iff := @idxOf?_eq_none_iff
|
||||
|
||||
/-! ### finIdxOf? -/
|
||||
|
||||
theorem idxOf?_eq_map_finIdxOf?_val [BEq α] {xs : List α} {a : α} :
|
||||
xs.idxOf? a = (xs.finIdxOf? a).map (·.val) := by
|
||||
simp [idxOf?, finIdxOf?, findIdx?_eq_map_findFinIdx?_val]
|
||||
|
||||
/-! ### lookup -/
|
||||
|
||||
section lookup
|
||||
|
||||
@@ -16,8 +16,8 @@ If you import `Init.Data.List.Basic` but do not import this file,
|
||||
then at runtime you will get non-tail recursive versions of the following definitions.
|
||||
-/
|
||||
|
||||
-- set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
-- set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
|
||||
namespace List
|
||||
|
||||
|
||||
@@ -74,8 +74,8 @@ Also
|
||||
|
||||
-/
|
||||
|
||||
-- set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
-- set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
|
||||
namespace List
|
||||
|
||||
@@ -96,9 +96,15 @@ theorem ne_nil_of_length_eq_add_one (_ : length l = n + 1) : l ≠ [] := fun _ =
|
||||
|
||||
theorem ne_nil_of_length_pos (_ : 0 < length l) : l ≠ [] := fun _ => nomatch l
|
||||
|
||||
@[simp] theorem length_eq_zero : length l = 0 ↔ l = [] :=
|
||||
@[simp] theorem length_eq_zero_iff : length l = 0 ↔ l = [] :=
|
||||
⟨eq_nil_of_length_eq_zero, fun h => h ▸ rfl⟩
|
||||
|
||||
@[deprecated length_eq_zero_iff (since := "2025-02-24")]
|
||||
abbrev length_eq_zero := @length_eq_zero_iff
|
||||
|
||||
theorem eq_nil_iff_length_eq_zero : l = [] ↔ length l = 0 :=
|
||||
length_eq_zero_iff.symm
|
||||
|
||||
theorem length_pos_of_mem {a : α} : ∀ {l : List α}, a ∈ l → 0 < length l
|
||||
| _::_, _ => Nat.zero_lt_succ _
|
||||
|
||||
@@ -123,12 +129,21 @@ theorem exists_cons_of_length_eq_add_one :
|
||||
∀ {l : List α}, l.length = n + 1 → ∃ h t, l = h :: t
|
||||
| _::_, _ => ⟨_, _, rfl⟩
|
||||
|
||||
theorem length_pos {l : List α} : 0 < length l ↔ l ≠ [] :=
|
||||
Nat.pos_iff_ne_zero.trans (not_congr length_eq_zero)
|
||||
theorem length_pos_iff {l : List α} : 0 < length l ↔ l ≠ [] :=
|
||||
Nat.pos_iff_ne_zero.trans (not_congr length_eq_zero_iff)
|
||||
|
||||
theorem length_eq_one {l : List α} : length l = 1 ↔ ∃ a, l = [a] :=
|
||||
@[deprecated length_pos_iff (since := "2025-02-24")]
|
||||
abbrev length_pos := @length_pos_iff
|
||||
|
||||
theorem ne_nil_iff_length_pos {l : List α} : l ≠ [] ↔ 0 < length l :=
|
||||
length_pos_iff.symm
|
||||
|
||||
theorem length_eq_one_iff {l : List α} : length l = 1 ↔ ∃ a, l = [a] :=
|
||||
⟨fun h => match l, h with | [_], _ => ⟨_, rfl⟩, fun ⟨_, h⟩ => by simp [h]⟩
|
||||
|
||||
@[deprecated length_eq_one_iff (since := "2025-02-24")]
|
||||
abbrev length_eq_one := @length_eq_one_iff
|
||||
|
||||
/-! ### cons -/
|
||||
|
||||
theorem cons_ne_nil (a : α) (l : List α) : a :: l ≠ [] := nofun
|
||||
@@ -284,7 +299,7 @@ such a rewrite, with `rw [getElem_of_eq h]`.
|
||||
theorem getElem_of_eq {l l' : List α} (h : l = l') {i : Nat} (w : i < l.length) :
|
||||
l[i] = l'[i]'(h ▸ w) := by cases h; rfl
|
||||
|
||||
theorem getElem_zero {l : List α} (h : 0 < l.length) : l[0] = l.head (length_pos.mp h) :=
|
||||
theorem getElem_zero {l : List α} (h : 0 < l.length) : l[0] = l.head (length_pos_iff.mp h) :=
|
||||
match l, h with
|
||||
| _ :: _, _ => rfl
|
||||
|
||||
@@ -375,7 +390,7 @@ theorem eq_append_cons_of_mem {a : α} {xs : List α} (h : a ∈ xs) :
|
||||
theorem mem_cons_of_mem (y : α) {a : α} {l : List α} : a ∈ l → a ∈ y :: l := .tail _
|
||||
|
||||
theorem exists_mem_of_ne_nil (l : List α) (h : l ≠ []) : ∃ x, x ∈ l :=
|
||||
exists_mem_of_length_pos (length_pos.2 h)
|
||||
exists_mem_of_length_pos (length_pos_iff.2 h)
|
||||
|
||||
theorem eq_nil_iff_forall_not_mem {l : List α} : l = [] ↔ ∀ a, a ∉ l := by
|
||||
cases l <;> simp [-not_or]
|
||||
@@ -533,7 +548,7 @@ theorem isEmpty_eq_false_iff_exists_mem {xs : List α} :
|
||||
cases xs <;> simp
|
||||
|
||||
theorem isEmpty_iff_length_eq_zero {l : List α} : l.isEmpty ↔ l.length = 0 := by
|
||||
rw [isEmpty_iff, length_eq_zero]
|
||||
rw [isEmpty_iff, length_eq_zero_iff]
|
||||
|
||||
/-! ### any / all -/
|
||||
|
||||
@@ -910,13 +925,13 @@ theorem head?_eq_getElem? : ∀ l : List α, head? l = l[0]?
|
||||
| [] => rfl
|
||||
| a :: l => by simp
|
||||
|
||||
theorem head_eq_getElem (l : List α) (h : l ≠ []) : head l h = l[0]'(length_pos.mpr h) := by
|
||||
theorem head_eq_getElem (l : List α) (h : l ≠ []) : head l h = l[0]'(length_pos_iff.mpr h) := by
|
||||
cases l with
|
||||
| nil => simp at h
|
||||
| cons _ _ => simp
|
||||
|
||||
theorem getElem_zero_eq_head (l : List α) (h : 0 < l.length) :
|
||||
l[0] = head l (by simpa [length_pos] using h) := by
|
||||
l[0] = head l (by simpa [length_pos_iff] using h) := by
|
||||
cases l with
|
||||
| nil => simp at h
|
||||
| cons _ _ => simp
|
||||
@@ -1003,7 +1018,7 @@ theorem one_lt_length_of_tail_ne_nil {l : List α} (h : l.tail ≠ []) : 1 < l.l
|
||||
| nil => simp at h
|
||||
| cons _ l =>
|
||||
simp only [tail_cons, ne_eq] at h
|
||||
exact Nat.lt_add_of_pos_left (length_pos.mpr h)
|
||||
exact Nat.lt_add_of_pos_left (length_pos_iff.mpr h)
|
||||
|
||||
@[simp] theorem head_tail (l : List α) (h : l.tail ≠ []) :
|
||||
(tail l).head h = l[1]'(one_lt_length_of_tail_ne_nil h) := by
|
||||
@@ -2883,7 +2898,7 @@ theorem getLast?_replicate (a : α) (n : Nat) : (replicate n a).getLast? = if n
|
||||
-- We unfold `leftpad` and `rightpad` for verification purposes.
|
||||
attribute [simp] leftpad rightpad
|
||||
|
||||
-- `length_leftpad` is in `Init.Data.List.Nat.Basic`.
|
||||
-- `length_leftpad` and `length_rightpad` are in `Init.Data.List.Nat.Basic`.
|
||||
|
||||
theorem leftpad_prefix (n : Nat) (a : α) (l : List α) :
|
||||
replicate (n - length l) a <+: leftpad n a l := by
|
||||
@@ -3071,8 +3086,12 @@ variable [BEq α]
|
||||
@[simp] theorem replace_cons_self [LawfulBEq α] {a : α} : (a::as).replace a b = b::as := by
|
||||
simp [replace_cons]
|
||||
|
||||
@[simp] theorem replace_of_not_mem {l : List α} (h : !l.elem a) : l.replace a b = l := by
|
||||
induction l <;> simp_all [replace_cons]
|
||||
@[simp] theorem replace_of_not_mem [LawfulBEq α] {l : List α} (h : a ∉ l) : l.replace a b = l := by
|
||||
induction l with
|
||||
| nil => rfl
|
||||
| cons x xs ih =>
|
||||
simp only [replace_cons]
|
||||
split <;> simp_all
|
||||
|
||||
@[simp] theorem length_replace {l : List α} : (l.replace a b).length = l.length := by
|
||||
induction l with
|
||||
@@ -3155,7 +3174,7 @@ theorem replace_take {l : List α} {i : Nat} :
|
||||
(replicate n a).replace a b = b :: replicate (n - 1) a := by
|
||||
cases n <;> simp_all [replicate_succ, replace_cons]
|
||||
|
||||
@[simp] theorem replace_replicate_ne {a b c : α} (h : !b == a) :
|
||||
@[simp] theorem replace_replicate_ne [LawfulBEq α] {a b c : α} (h : !b == a) :
|
||||
(replicate n a).replace b c = replicate n a := by
|
||||
rw [replace_of_not_mem]
|
||||
simp_all
|
||||
@@ -3417,7 +3436,7 @@ theorem get_cons_succ {as : List α} {h : i + 1 < (a :: as).length} :
|
||||
theorem get_cons_succ' {as : List α} {i : Fin as.length} :
|
||||
(a :: as).get i.succ = as.get i := rfl
|
||||
|
||||
theorem get_mk_zero : ∀ {l : List α} (h : 0 < l.length), l.get ⟨0, h⟩ = l.head (length_pos.mp h)
|
||||
theorem get_mk_zero : ∀ {l : List α} (h : 0 < l.length), l.get ⟨0, h⟩ = l.head (length_pos_iff.mp h)
|
||||
| _::_, _ => rfl
|
||||
|
||||
set_option linter.deprecated false in
|
||||
|
||||
@@ -7,8 +7,8 @@ prelude
|
||||
import Init.Data.List.Lemmas
|
||||
import Init.Data.List.Nat.TakeDrop
|
||||
|
||||
-- set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
-- set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
|
||||
namespace List
|
||||
|
||||
|
||||
@@ -11,8 +11,8 @@ import Init.Data.List.OfFn
|
||||
import Init.Data.Fin.Lemmas
|
||||
import Init.Data.Option.Attach
|
||||
|
||||
-- set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
-- set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
|
||||
namespace List
|
||||
|
||||
|
||||
@@ -10,8 +10,8 @@ import Init.Data.List.Lemmas
|
||||
# Lemmas about `List.min?` and `List.max?.
|
||||
-/
|
||||
|
||||
-- set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
-- set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
|
||||
namespace List
|
||||
|
||||
|
||||
@@ -11,8 +11,8 @@ import Init.Data.List.Attach
|
||||
# Lemmas about `List.mapM` and `List.forM`.
|
||||
-/
|
||||
|
||||
-- set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
-- set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
|
||||
namespace List
|
||||
|
||||
|
||||
@@ -7,8 +7,8 @@ prelude
|
||||
import Init.Data.Nat.Lemmas
|
||||
import Init.Data.List.Basic
|
||||
|
||||
-- set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
-- set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
|
||||
namespace List
|
||||
|
||||
|
||||
@@ -15,8 +15,8 @@ import Init.Data.Nat.Lemmas
|
||||
In particular, `omega` is available here.
|
||||
-/
|
||||
|
||||
-- set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
-- set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
|
||||
open Nat
|
||||
|
||||
@@ -44,10 +44,42 @@ theorem tail_dropLast (l : List α) : tail (dropLast l) = dropLast (tail l) := b
|
||||
|
||||
/-! ### filter -/
|
||||
|
||||
theorem length_filter_lt_length_iff_exists {l} :
|
||||
length (filter p l) < length l ↔ ∃ x ∈ l, ¬p x := by
|
||||
@[simp]
|
||||
theorem length_filter_pos_iff {l : List α} {p : α → Bool} :
|
||||
0 < (filter p l).length ↔ ∃ x ∈ l, p x := by
|
||||
simpa [length_eq_countP_add_countP p l, countP_eq_length_filter] using
|
||||
countP_pos_iff (p := fun x => ¬p x)
|
||||
countP_pos_iff (p := p)
|
||||
|
||||
@[simp]
|
||||
theorem length_filter_lt_length_iff_exists {l} :
|
||||
(filter p l).length < l.length ↔ ∃ x ∈ l, ¬p x := by
|
||||
simp [length_eq_countP_add_countP p l, countP_eq_length_filter]
|
||||
|
||||
/-! ### filterMap -/
|
||||
|
||||
@[simp]
|
||||
theorem length_filterMap_pos_iff {xs : List α} {f : α → Option β} :
|
||||
0 < (filterMap f xs).length ↔ ∃ (x : α) (_ : x ∈ xs) (b : β), f x = some b := by
|
||||
induction xs with
|
||||
| nil => simp
|
||||
| cons x xs ih =>
|
||||
simp only [filterMap, mem_cons, exists_prop, exists_eq_or_imp]
|
||||
split
|
||||
· simp_all [ih]
|
||||
· simp_all
|
||||
|
||||
@[simp]
|
||||
theorem length_filterMap_lt_length_iff_exists {xs : List α} {f : α → Option β} :
|
||||
(filterMap f xs).length < xs.length ↔ ∃ (x : α) (_ : x ∈ xs), f x = none := by
|
||||
induction xs with
|
||||
| nil => simp
|
||||
| cons x xs ih =>
|
||||
simp only [filterMap, mem_cons, exists_prop, exists_eq_or_imp]
|
||||
split
|
||||
· simp_all only [exists_prop, length_cons, true_or, iff_true]
|
||||
have := length_filterMap_le f xs
|
||||
omega
|
||||
· simp_all
|
||||
|
||||
/-! ### reverse -/
|
||||
|
||||
@@ -63,10 +95,18 @@ theorem getElem_eq_getElem_reverse {l : List α} {i} (h : i < l.length) :
|
||||
to the larger of `n` and `l.length` -/
|
||||
-- We don't mark this as a `@[simp]` lemma since we allow `simp` to unfold `leftpad`,
|
||||
-- so the left hand side simplifies directly to `n - l.length + l.length`.
|
||||
theorem leftpad_length (n : Nat) (a : α) (l : List α) :
|
||||
theorem length_leftpad (n : Nat) (a : α) (l : List α) :
|
||||
(leftpad n a l).length = max n l.length := by
|
||||
simp only [leftpad, length_append, length_replicate, Nat.sub_add_eq_max]
|
||||
|
||||
@[deprecated length_leftpad (since := "2025-02-24")]
|
||||
abbrev leftpad_length := @length_leftpad
|
||||
|
||||
theorem length_rightpad (n : Nat) (a : α) (l : List α) :
|
||||
(rightpad n a l).length = max n l.length := by
|
||||
simp [rightpad]
|
||||
omega
|
||||
|
||||
/-! ### eraseIdx -/
|
||||
|
||||
theorem mem_eraseIdx_iff_getElem {x : α} :
|
||||
|
||||
@@ -7,8 +7,8 @@ prelude
|
||||
import Init.Data.List.Count
|
||||
import Init.Data.Nat.Lemmas
|
||||
|
||||
-- set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
-- set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
|
||||
namespace List
|
||||
|
||||
|
||||
@@ -7,8 +7,8 @@ prelude
|
||||
import Init.Data.List.Nat.TakeDrop
|
||||
import Init.Data.List.Erase
|
||||
|
||||
-- set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
-- set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
|
||||
namespace List
|
||||
|
||||
|
||||
@@ -7,8 +7,8 @@ prelude
|
||||
import Init.Data.List.Nat.Range
|
||||
import Init.Data.List.Find
|
||||
|
||||
-- set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
-- set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
|
||||
namespace List
|
||||
|
||||
|
||||
@@ -12,8 +12,8 @@ import Init.Data.List.Nat.Modify
|
||||
Proves various lemmas about `List.insertIdx`.
|
||||
-/
|
||||
|
||||
-- set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
-- set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
|
||||
open Function Nat
|
||||
|
||||
|
||||
@@ -8,8 +8,8 @@ prelude
|
||||
import Init.Data.List.Nat.TakeDrop
|
||||
import Init.Data.List.Nat.Erase
|
||||
|
||||
-- set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
-- set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
|
||||
namespace List
|
||||
|
||||
|
||||
@@ -12,8 +12,8 @@ import Init.Data.List.Pairwise
|
||||
# Lemmas about `List.Pairwise`
|
||||
-/
|
||||
|
||||
-- set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
-- set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
|
||||
namespace List
|
||||
|
||||
|
||||
@@ -7,8 +7,8 @@ prelude
|
||||
import Init.Data.List.Nat.TakeDrop
|
||||
import Init.Data.List.Perm
|
||||
|
||||
-- set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
-- set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
|
||||
namespace List
|
||||
|
||||
|
||||
@@ -14,8 +14,8 @@ import Init.Data.List.Erase
|
||||
# Lemmas about `List.range` and `List.enum`
|
||||
-/
|
||||
|
||||
-- set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
-- set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
|
||||
namespace List
|
||||
|
||||
|
||||
@@ -16,8 +16,8 @@ These are in a separate file from most of the lemmas about `List.IsSuffix`
|
||||
as they required importing more lemmas about natural numbers, and use `omega`.
|
||||
-/
|
||||
|
||||
-- set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
-- set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
|
||||
namespace List
|
||||
|
||||
@@ -156,7 +156,7 @@ theorem append_sublist_of_sublist_left {xs ys zs : List α} (h : zs <+ xs) :
|
||||
have hl' := h'.length_le
|
||||
simp only [length_append] at hl'
|
||||
have : ys.length = 0 := by omega
|
||||
simp_all only [Nat.add_zero, length_eq_zero, true_and, append_nil]
|
||||
simp_all only [Nat.add_zero, length_eq_zero_iff, true_and, append_nil]
|
||||
exact Sublist.eq_of_length_le h' hl
|
||||
· rintro ⟨rfl, rfl⟩
|
||||
simp
|
||||
@@ -169,7 +169,7 @@ theorem append_sublist_of_sublist_right {xs ys zs : List α} (h : zs <+ ys) :
|
||||
have hl' := h'.length_le
|
||||
simp only [length_append] at hl'
|
||||
have : xs.length = 0 := by omega
|
||||
simp_all only [Nat.zero_add, length_eq_zero, true_and, append_nil]
|
||||
simp_all only [Nat.zero_add, length_eq_zero_iff, true_and, append_nil]
|
||||
exact Sublist.eq_of_length_le h' hl
|
||||
· rintro ⟨rfl, rfl⟩
|
||||
simp
|
||||
|
||||
@@ -16,8 +16,8 @@ These are in a separate file from most of the list lemmas
|
||||
as they required importing more lemmas about natural numbers, and use `omega`.
|
||||
-/
|
||||
|
||||
-- set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
-- set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
|
||||
namespace List
|
||||
|
||||
@@ -115,12 +115,12 @@ theorem take_set_of_le (a : α) {i j : Nat} (l : List α) (h : j ≤ i) :
|
||||
@[deprecated take_set_of_le (since := "2025-02-04")]
|
||||
abbrev take_set_of_lt := @take_set_of_le
|
||||
|
||||
@[simp] theorem take_replicate (a : α) : ∀ i j : Nat, take i (replicate j a) = replicate (min i j) a
|
||||
@[simp] theorem take_replicate (a : α) : ∀ i n : Nat, take i (replicate n a) = replicate (min i n) a
|
||||
| n, 0 => by simp [Nat.min_zero]
|
||||
| 0, m => by simp [Nat.zero_min]
|
||||
| succ n, succ m => by simp [replicate_succ, succ_min_succ, take_replicate]
|
||||
|
||||
@[simp] theorem drop_replicate (a : α) : ∀ i j : Nat, drop i (replicate j a) = replicate (j - i) a
|
||||
@[simp] theorem drop_replicate (a : α) : ∀ i n : Nat, drop i (replicate n a) = replicate (n - i) a
|
||||
| n, 0 => by simp
|
||||
| 0, m => by simp
|
||||
| succ n, succ m => by simp [replicate_succ, succ_sub_succ, drop_replicate]
|
||||
|
||||
@@ -11,8 +11,8 @@ import Init.Data.Nat.Div.Basic
|
||||
-/
|
||||
|
||||
set_option linter.missingDocs true -- keep it documented
|
||||
-- set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
-- set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
|
||||
open Decidable List
|
||||
|
||||
|
||||
@@ -11,8 +11,8 @@ import Init.Data.Fin.Fold
|
||||
# Theorems about `List.ofFn`
|
||||
-/
|
||||
|
||||
-- set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
-- set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
|
||||
namespace List
|
||||
|
||||
|
||||
@@ -11,8 +11,8 @@ import Init.Data.List.Attach
|
||||
# Lemmas about `List.Pairwise` and `List.Nodup`.
|
||||
-/
|
||||
|
||||
-- set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
-- set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
|
||||
namespace List
|
||||
|
||||
|
||||
@@ -18,8 +18,8 @@ another.
|
||||
The notation `~` is used for permutation equivalence.
|
||||
-/
|
||||
|
||||
-- set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
-- set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
|
||||
open Nat
|
||||
|
||||
|
||||
@@ -14,8 +14,8 @@ Most of the results are deferred to `Data.Init.List.Nat.Range`, where more resul
|
||||
natural arithmetic are available.
|
||||
-/
|
||||
|
||||
-- set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
-- set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
|
||||
namespace List
|
||||
|
||||
@@ -33,7 +33,7 @@ theorem range'_succ (s n step) : range' s (n + 1) step = s :: range' (s + step)
|
||||
| _ + 1 => congrArg succ (length_range' _ _ _)
|
||||
|
||||
@[simp] theorem range'_eq_nil_iff : range' s n step = [] ↔ n = 0 := by
|
||||
rw [← length_eq_zero, length_range']
|
||||
rw [← length_eq_zero_iff, length_range']
|
||||
|
||||
@[deprecated range'_eq_nil_iff (since := "2025-01-29")] abbrev range'_eq_nil := @range'_eq_nil_iff
|
||||
|
||||
@@ -74,7 +74,7 @@ theorem mem_range' : ∀{n}, m ∈ range' s n step ↔ ∃ i < n, m = s + step *
|
||||
rw [exists_comm]; simp [Nat.mul_succ, Nat.add_assoc, Nat.add_comm]
|
||||
|
||||
theorem getElem?_range' (s step) :
|
||||
∀ {i j : Nat}, i < j → (range' s j step)[i]? = some (s + step * i)
|
||||
∀ {i n : Nat}, i < n → (range' s n step)[i]? = some (s + step * i)
|
||||
| 0, n + 1, _ => by simp [range'_succ]
|
||||
| m + 1, n + 1, h => by
|
||||
simp only [range'_succ, getElem?_cons_succ]
|
||||
@@ -147,10 +147,10 @@ theorem range_loop_range' : ∀ s n : Nat, range.loop s (range' s n) = range' 0
|
||||
theorem range_eq_range' (n : Nat) : range n = range' 0 n :=
|
||||
(range_loop_range' n 0).trans <| by rw [Nat.zero_add]
|
||||
|
||||
theorem getElem?_range {i j : Nat} (h : i < j) : (range j)[i]? = some i := by
|
||||
theorem getElem?_range {i n : Nat} (h : i < n) : (range n)[i]? = some i := by
|
||||
simp [range_eq_range', getElem?_range' _ _ h]
|
||||
|
||||
@[simp] theorem getElem_range {i : Nat} (j) (h : j < (range i).length) : (range i)[j] = j := by
|
||||
@[simp] theorem getElem_range {n : Nat} (j) (h : j < (range n).length) : (range n)[j] = j := by
|
||||
simp [range_eq_range']
|
||||
|
||||
theorem range_succ_eq_map (n : Nat) : range (n + 1) = 0 :: map succ (range n) := by
|
||||
@@ -164,7 +164,7 @@ theorem range'_eq_map_range (s n : Nat) : range' s n = map (s + ·) (range n) :=
|
||||
simp only [range_eq_range', length_range']
|
||||
|
||||
@[simp] theorem range_eq_nil {n : Nat} : range n = [] ↔ n = 0 := by
|
||||
rw [← length_eq_zero, length_range]
|
||||
rw [← length_eq_zero_iff, length_range]
|
||||
|
||||
theorem range_ne_nil {n : Nat} : range n ≠ [] ↔ n ≠ 0 := by
|
||||
cases n <;> simp
|
||||
@@ -183,9 +183,9 @@ theorem range_subset {m n : Nat} : range m ⊆ range n ↔ m ≤ n := by
|
||||
theorem range_succ (n : Nat) : range (succ n) = range n ++ [n] := by
|
||||
simp only [range_eq_range', range'_1_concat, Nat.zero_add]
|
||||
|
||||
theorem range_add (a b : Nat) : range (a + b) = range a ++ (range b).map (a + ·) := by
|
||||
theorem range_add (n m : Nat) : range (n + m) = range n ++ (range m).map (n + ·) := by
|
||||
rw [← range'_eq_map_range]
|
||||
simpa [range_eq_range', Nat.add_comm] using (range'_append_1 0 a b).symm
|
||||
simpa [range_eq_range', Nat.add_comm] using (range'_append_1 0 n m).symm
|
||||
|
||||
theorem head?_range (n : Nat) : (range n).head? = if n = 0 then none else some 0 := by
|
||||
induction n with
|
||||
|
||||
@@ -14,8 +14,8 @@ These definitions are intended for verification purposes,
|
||||
and are replaced at runtime by efficient versions in `Init.Data.List.Sort.Impl`.
|
||||
-/
|
||||
|
||||
-- set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
-- set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
|
||||
namespace List
|
||||
|
||||
|
||||
@@ -31,8 +31,8 @@ as long as such improvements are carefully validated by benchmarking,
|
||||
they can be done without changing the theory, as long as a `@[csimp]` lemma is provided.
|
||||
-/
|
||||
|
||||
-- set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
-- set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
|
||||
open List
|
||||
|
||||
|
||||
@@ -21,8 +21,8 @@ import Init.Data.Bool
|
||||
|
||||
-/
|
||||
|
||||
-- set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
-- set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
|
||||
namespace List
|
||||
|
||||
|
||||
@@ -11,8 +11,8 @@ import Init.Data.List.TakeDrop
|
||||
# Lemmas about `List.Subset`, `List.Sublist`, `List.IsPrefix`, `List.IsSuffix`, and `List.IsInfix`.
|
||||
-/
|
||||
|
||||
-- set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
-- set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
|
||||
namespace List
|
||||
|
||||
|
||||
@@ -10,8 +10,8 @@ import Init.Data.List.Lemmas
|
||||
# Lemmas about `List.take` and `List.drop`.
|
||||
-/
|
||||
|
||||
-- set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
-- set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
|
||||
namespace List
|
||||
|
||||
@@ -45,7 +45,7 @@ theorem drop_one : ∀ l : List α, drop 1 l = tail l
|
||||
_ = succ (length l) - succ i := (Nat.succ_sub_succ_eq_sub (length l) i).symm
|
||||
|
||||
theorem drop_of_length_le {l : List α} (h : l.length ≤ i) : drop i l = [] :=
|
||||
length_eq_zero.1 (length_drop .. ▸ Nat.sub_eq_zero_of_le h)
|
||||
length_eq_zero_iff.1 (length_drop .. ▸ Nat.sub_eq_zero_of_le h)
|
||||
|
||||
theorem length_lt_of_drop_ne_nil {l : List α} {i} (h : drop i l ≠ []) : i < l.length :=
|
||||
gt_of_not_le (mt drop_of_length_le h)
|
||||
|
||||
@@ -15,8 +15,8 @@ import Init.Data.Array.Lex.Basic
|
||||
We prefer to pull `List.toArray` outwards past `Array` operations.
|
||||
-/
|
||||
|
||||
-- set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
-- set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
|
||||
namespace Array
|
||||
|
||||
@@ -44,6 +44,16 @@ theorem toArray_inj {as bs : List α} (h : as.toArray = bs.toArray) : as = bs :=
|
||||
| nil => simp at h
|
||||
| cons b bs => simpa using h
|
||||
|
||||
theorem toArray_eq_iff {as : List α} {bs : Array α} : as.toArray = bs ↔ as = bs.toList := by
|
||||
cases bs
|
||||
simp
|
||||
|
||||
-- We can't make this a `@[simp]` lemma because `#[] = [].toArray` at reducible transparency,
|
||||
-- so this would loop with `toList_eq_nil_iff`
|
||||
theorem eq_toArray_iff {as : Array α} {bs : List α} : as = bs.toArray ↔ as.toList = bs := by
|
||||
cases as
|
||||
simp
|
||||
|
||||
@[simp] theorem size_toArrayAux {as : List α} {xs : Array α} :
|
||||
(as.toArrayAux xs).size = xs.size + as.length := by
|
||||
simp [size]
|
||||
@@ -77,6 +87,21 @@ theorem toArray_cons (a : α) (l : List α) : (a :: l).toArray = #[a] ++ l.toArr
|
||||
l.toArray.back = l.getLast (by simp at h; exact ne_nil_of_length_pos h) := by
|
||||
simp [back, List.getLast_eq_getElem]
|
||||
|
||||
@[simp] theorem _root_.Array.getLast!_toList [Inhabited α] (xs : Array α) :
|
||||
xs.toList.getLast! = xs.back! := by
|
||||
rcases xs with ⟨xs⟩
|
||||
simp
|
||||
|
||||
@[simp] theorem _root_.Array.getLast?_toList (xs : Array α) :
|
||||
xs.toList.getLast? = xs.back? := by
|
||||
rcases xs with ⟨xs⟩
|
||||
simp
|
||||
|
||||
@[simp] theorem _root_.Array.getLast_toList (xs : Array α) (h) :
|
||||
xs.toList.getLast h = xs.back (by simpa [ne_nil_iff_length_pos] using h) := by
|
||||
rcases xs with ⟨xs⟩
|
||||
simp
|
||||
|
||||
@[simp] theorem set_toArray (l : List α) (i : Nat) (a : α) (h : i < l.length) :
|
||||
(l.toArray.set i a) = (l.set i a).toArray := rfl
|
||||
|
||||
@@ -514,8 +539,8 @@ private theorem popWhile_toArray_aux (p : α → Bool) (l : List α) :
|
||||
|
||||
@[simp] theorem toArray_replicate (n : Nat) (v : α) : (List.replicate n v).toArray = mkArray n v := rfl
|
||||
|
||||
@[deprecated toArray_replicate (since := "2024-12-13")]
|
||||
abbrev _root_.Array.mkArray_eq_toArray_replicate := @toArray_replicate
|
||||
theorem _root_.Array.mkArray_eq_toArray_replicate : mkArray n v = (List.replicate n v).toArray := by
|
||||
simp
|
||||
|
||||
@[simp] theorem flatMap_empty {β} (f : α → Array β) : (#[] : Array α).flatMap f = #[] := rfl
|
||||
|
||||
@@ -633,4 +658,46 @@ private theorem insertIdx_loop_toArray (i : Nat) (l : List α) (j : Nat) (hj : j
|
||||
· simp only [size_toArray, Nat.not_le] at h'
|
||||
rw [List.insertIdx_of_length_lt (h := h')]
|
||||
|
||||
@[simp]
|
||||
theorem replace_toArray [BEq α] [LawfulBEq α] (l : List α) (a b : α) :
|
||||
l.toArray.replace a b = (l.replace a b).toArray := by
|
||||
rw [Array.replace]
|
||||
split <;> rename_i i h
|
||||
· simp only [finIdxOf?_toArray, finIdxOf?_eq_none_iff] at h
|
||||
rw [replace_of_not_mem]
|
||||
simpa
|
||||
· simp_all only [finIdxOf?_toArray, finIdxOf?_eq_some_iff, Fin.getElem_fin, set_toArray,
|
||||
mk.injEq]
|
||||
apply List.ext_getElem
|
||||
· simp
|
||||
· intro j h₁ h₂
|
||||
rw [List.getElem_replace, List.getElem_set]
|
||||
by_cases h₃ : j < i
|
||||
· rw [if_neg (by omega), if_neg]
|
||||
simp only [length_set] at h₁ h₃
|
||||
simpa using h.2 ⟨j, by omega⟩ h₃
|
||||
· by_cases h₃ : j = i
|
||||
· rw [if_pos (by omega), if_pos, if_neg]
|
||||
· simp only [mem_take_iff_getElem, not_exists]
|
||||
intro k hk
|
||||
simpa using h.2 ⟨k, by omega⟩ (by show k < i.1; omega)
|
||||
· subst h₃
|
||||
simpa using h.1
|
||||
· rw [if_neg (by omega)]
|
||||
split
|
||||
· rw [if_pos]
|
||||
· simp_all
|
||||
· simp only [mem_take_iff_getElem]
|
||||
simp only [length_set] at h₁
|
||||
exact ⟨i, by omega, h.1⟩
|
||||
· rfl
|
||||
|
||||
@[simp] theorem leftpad_toArray (n : Nat) (a : α) (l : List α) :
|
||||
Array.leftpad n a l.toArray = (leftpad n a l).toArray := by
|
||||
simp [leftpad, Array.leftpad, ← toArray_replicate]
|
||||
|
||||
@[simp] theorem rightpad_toArray (n : Nat) (a : α) (l : List α) :
|
||||
Array.rightpad n a l.toArray = (rightpad n a l).toArray := by
|
||||
simp [rightpad, Array.rightpad, ← toArray_replicate]
|
||||
|
||||
end List
|
||||
|
||||
@@ -6,8 +6,8 @@ Authors: Henrik Böving
|
||||
prelude
|
||||
import Init.Data.List.Basic
|
||||
|
||||
-- set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
-- set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
|
||||
/--
|
||||
Auxiliary definition for `List.toArray`.
|
||||
|
||||
@@ -11,8 +11,8 @@ import Init.Data.Function
|
||||
# Lemmas about `List.zip`, `List.zipWith`, `List.zipWithAll`, and `List.unzip`.
|
||||
-/
|
||||
|
||||
-- set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
-- set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
|
||||
namespace List
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ Authors: Kim Morrison
|
||||
prelude
|
||||
import Init.Omega
|
||||
import Init.Data.Nat.Lemmas
|
||||
import Init.Data.Nat.Simproc
|
||||
|
||||
/-!
|
||||
# Further lemmas about `Nat.div` and `Nat.mod`, with the convenience of having `omega` available.
|
||||
@@ -62,4 +63,53 @@ theorem div_add_le_right {z : Nat} (h : 0 < z) (x y : Nat) :
|
||||
x / (y + z) ≤ x / z :=
|
||||
div_le_div_left (Nat.le_add_left z y) h
|
||||
|
||||
theorem succ_div_of_dvd {a b : Nat} (h : b ∣ a + 1) :
|
||||
(a + 1) / b = a / b + 1 := by
|
||||
replace h := mod_eq_zero_of_dvd h
|
||||
cases b with
|
||||
| zero => simp at h
|
||||
| succ b =>
|
||||
by_cases h' : b ≤ a
|
||||
· rw [Nat.div_eq]
|
||||
simp only [zero_lt_succ, Nat.add_le_add_iff_right, h', and_self, ↓reduceIte,
|
||||
Nat.reduceSubDiff, Nat.add_right_cancel_iff]
|
||||
obtain ⟨_|k, h⟩ := Nat.dvd_of_mod_eq_zero h
|
||||
· simp at h
|
||||
· simp only [Nat.mul_add, Nat.add_mul, Nat.one_mul, Nat.mul_one, ← Nat.add_assoc,
|
||||
Nat.add_right_cancel_iff] at h
|
||||
subst h
|
||||
rw [Nat.add_sub_cancel, ← Nat.add_one_mul, mul_div_right _ (zero_lt_succ _), Nat.add_comm,
|
||||
Nat.add_mul_div_left _ _ (zero_lt_succ _), Nat.self_eq_add_left, div_eq_of_lt le.refl]
|
||||
· simp only [Nat.not_le] at h'
|
||||
replace h' : a + 1 < b + 1 := Nat.add_lt_add_right h' 1
|
||||
rw [Nat.mod_eq_of_lt h'] at h
|
||||
simp at h
|
||||
|
||||
theorem succ_div_of_mod_eq_zero {a b : Nat} (h : (a + 1) % b = 0) :
|
||||
(a + 1) / b = a / b + 1 := by
|
||||
rw [succ_div_of_dvd (by rwa [dvd_iff_mod_eq_zero])]
|
||||
|
||||
theorem succ_div_of_not_dvd {a b : Nat} (h : ¬ b ∣ a + 1) :
|
||||
(a + 1) / b = a / b := by
|
||||
replace h := mt dvd_of_mod_eq_zero h
|
||||
cases b with
|
||||
| zero => simp
|
||||
| succ b =>
|
||||
rw [eq_comm, Nat.div_eq_iff (by simp)]
|
||||
constructor
|
||||
· rw [Nat.div_mul_self_eq_mod_sub_self]
|
||||
have : (a + 1) % (b + 1) < b + 1 := Nat.mod_lt _ (by simp)
|
||||
omega
|
||||
· rw [Nat.div_mul_self_eq_mod_sub_self]
|
||||
omega
|
||||
|
||||
theorem succ_div_of_mod_ne_zero {a b : Nat} (h : (a + 1) % b ≠ 0) :
|
||||
(a + 1) / b = a / b := by
|
||||
rw [succ_div_of_not_dvd (by rwa [dvd_iff_mod_eq_zero])]
|
||||
|
||||
theorem succ_div {a b : Nat} : (a + 1) / b = a / b + if b ∣ a + 1 then 1 else 0 := by
|
||||
split <;> rename_i h
|
||||
· simp [succ_div_of_dvd h]
|
||||
· simp [succ_div_of_not_dvd h]
|
||||
|
||||
end Nat
|
||||
|
||||
@@ -1016,6 +1016,39 @@ theorem mul_add_mod (m x y : Nat) : (m * x + y) % m = y % m := by
|
||||
· exact (m % 0).div_zero
|
||||
· case succ n => exact Nat.div_eq_of_lt (m.mod_lt n.succ_pos)
|
||||
|
||||
theorem mod_eq_iff {a b c : Nat} :
|
||||
a % b = c ↔ (b = 0 ∧ a = c) ∨ (c < b ∧ Exists fun k => a = b * k + c) :=
|
||||
⟨fun h =>
|
||||
if w : b = 0 then
|
||||
.inl ⟨w, by simpa [w] using h⟩
|
||||
else
|
||||
.inr ⟨by subst h; exact Nat.mod_lt a (zero_lt_of_ne_zero w),
|
||||
a / b, by subst h; exact (div_add_mod a b).symm⟩,
|
||||
by
|
||||
rintro (⟨rfl, rfl⟩ | ⟨w, h, rfl⟩)
|
||||
· simp_all
|
||||
· rw [mul_add_mod, mod_eq_of_lt w]⟩
|
||||
|
||||
theorem succ_mod_succ_eq_zero_iff {a b : Nat} :
|
||||
(a + 1) % (b + 1) = 0 ↔ a % (b + 1) = b := by
|
||||
symm
|
||||
rw [mod_eq_iff, mod_eq_iff]
|
||||
simp only [add_one_ne_zero, false_and, Nat.lt_add_one, true_and, false_or, and_self, zero_lt_succ,
|
||||
Nat.add_zero]
|
||||
constructor
|
||||
· rintro ⟨k, rfl⟩
|
||||
refine ⟨k + 1, ?_⟩
|
||||
simp [Nat.add_mul, Nat.mul_add, Nat.add_assoc]
|
||||
· rintro ⟨k, h⟩
|
||||
cases k with
|
||||
| zero => simp at h
|
||||
| succ k =>
|
||||
refine ⟨k, ?_⟩
|
||||
simp only [Nat.mul_add, Nat.add_mul, Nat.one_mul, Nat.mul_one, ← Nat.add_assoc,
|
||||
Nat.add_right_cancel_iff] at h
|
||||
subst h
|
||||
simp [Nat.add_mul]
|
||||
|
||||
/-! ### Decidability of predicates -/
|
||||
|
||||
instance decidableBallLT :
|
||||
|
||||
@@ -40,3 +40,20 @@ theorem neZero_iff {n : R} : NeZero n ↔ n ≠ 0 :=
|
||||
instance {p : Prop} [Decidable p] {n m : Nat} [NeZero n] [NeZero m] :
|
||||
NeZero (if p then n else m) := by
|
||||
split <;> infer_instance
|
||||
|
||||
instance {n m : Nat} [h : NeZero n] : NeZero (n + m) where
|
||||
out :=
|
||||
match n, h, m with
|
||||
| _ + 1, _, 0
|
||||
| _ + 1, _, _ + 1 => fun h => nomatch h
|
||||
|
||||
instance {n m : Nat} [h : NeZero m] : NeZero (n + m) where
|
||||
out :=
|
||||
match m, h, n with
|
||||
| _ + 1, _, 0 => fun h => nomatch h
|
||||
| _ + 1, _, _ + 1 => fun h => nomatch h
|
||||
|
||||
instance {n m : Nat} [hn : NeZero n] [hm : NeZero m] : NeZero (n * m) where
|
||||
out :=
|
||||
match n, hn, m, hm with
|
||||
| _ + 1, _, _ + 1, _ => fun h => nomatch h
|
||||
|
||||
@@ -654,6 +654,11 @@ theorem map_pmap {p : α → Prop} (g : β → γ) (f : ∀ a, p a → β) (o H)
|
||||
Option.map g (pmap f o H) = pmap (fun a h => g (f a h)) o H := by
|
||||
cases o <;> simp
|
||||
|
||||
theorem pmap_map (o : Option α) (f : α → β) {p : β → Prop} (g : ∀ b, p b → γ) (H) :
|
||||
pmap g (o.map f) H =
|
||||
pmap (fun a h => g (f a) h) o (fun a m => H (f a) (mem_map_of_mem f m)) := by
|
||||
cases o <;> simp
|
||||
|
||||
/-! ### pelim -/
|
||||
|
||||
@[simp] theorem pelim_none : pelim none b f = b := rfl
|
||||
|
||||
@@ -7,6 +7,7 @@ prelude
|
||||
import Init.Data.SInt.Basic
|
||||
import Init.Data.SInt.Float
|
||||
import Init.Data.SInt.Float32
|
||||
import Init.Data.SInt.Lemmas
|
||||
|
||||
/-!
|
||||
This module contains the definitions and basic theory about signed fixed width integer types.
|
||||
|
||||
25
src/Init/Data/SInt/Lemmas.lean
Normal file
25
src/Init/Data/SInt/Lemmas.lean
Normal file
@@ -0,0 +1,25 @@
|
||||
/-
|
||||
Copyright (c) 2025 Lean FRO, LLC. All rights reserved.
|
||||
Released under Apache 2.0 license as described in the file LICENSE.
|
||||
Authors: Markus Himmel
|
||||
-/
|
||||
prelude
|
||||
import Init.Data.SInt.Basic
|
||||
|
||||
@[simp] theorem UInt8.toBitVec_toInt8 (x : UInt8) : x.toInt8.toBitVec = x.toBitVec := rfl
|
||||
@[simp] theorem UInt16.toBitVec_toInt16 (x : UInt16) : x.toInt16.toBitVec = x.toBitVec := rfl
|
||||
@[simp] theorem UInt32.toBitVec_toInt32 (x : UInt32) : x.toInt32.toBitVec = x.toBitVec := rfl
|
||||
@[simp] theorem UInt64.toBitVec_toInt64 (x : UInt64) : x.toInt64.toBitVec = x.toBitVec := rfl
|
||||
@[simp] theorem USize.toBitVec_toISize (x : USize) : x.toISize.toBitVec = x.toBitVec := rfl
|
||||
|
||||
@[simp] theorem Int8.ofBitVec_uInt8ToBitVec (x : UInt8) : Int8.ofBitVec x.toBitVec = x.toInt8 := rfl
|
||||
@[simp] theorem Int16.ofBitVec_uInt16ToBitVec (x : UInt16) : Int16.ofBitVec x.toBitVec = x.toInt16 := rfl
|
||||
@[simp] theorem Int32.ofBitVec_uInt32ToBitVec (x : UInt32) : Int32.ofBitVec x.toBitVec = x.toInt32 := rfl
|
||||
@[simp] theorem Int64.ofBitVec_uInt64ToBitVec (x : UInt64) : Int64.ofBitVec x.toBitVec = x.toInt64 := rfl
|
||||
@[simp] theorem ISize.ofBitVec_uSize8ToBitVec (x : USize) : ISize.ofBitVec x.toBitVec = x.toISize := rfl
|
||||
|
||||
@[simp] theorem UInt8.toUInt8_toInt8 (x : UInt8) : x.toInt8.toUInt8 = x := rfl
|
||||
@[simp] theorem UInt16.toUInt16_toInt16 (x : UInt16) : x.toInt16.toUInt16 = x := rfl
|
||||
@[simp] theorem UInt32.toUInt32_toInt32 (x : UInt32) : x.toInt32.toUInt32 = x := rfl
|
||||
@[simp] theorem UInt64.toUInt64_toInt64 (x : UInt64) : x.toInt64.toUInt64 = x := rfl
|
||||
@[simp] theorem USize.toUSize_toISize (x : USize) : x.toISize.toUSize = x := rfl
|
||||
@@ -295,11 +295,16 @@ def USize.mk (bitVec : BitVec System.Platform.numBits) : USize :=
|
||||
def USize.ofNatCore (n : Nat) (h : n < USize.size) : USize :=
|
||||
USize.ofNatLT n h
|
||||
|
||||
theorem usize_size_le : USize.size ≤ 18446744073709551616 := by
|
||||
cases usize_size_eq <;> next h => rw [h]; decide
|
||||
@[simp] theorem USize.le_size : 2 ^ 32 ≤ USize.size := by cases USize.size_eq <;> simp_all
|
||||
@[simp] theorem USize.size_le : USize.size ≤ 2 ^ 64 := by cases USize.size_eq <;> simp_all
|
||||
|
||||
theorem le_usize_size : 4294967296 ≤ USize.size := by
|
||||
cases usize_size_eq <;> next h => rw [h]; decide
|
||||
@[deprecated USize.size_le (since := "2025-02-24")]
|
||||
theorem usize_size_le : USize.size ≤ 18446744073709551616 :=
|
||||
USize.size_le
|
||||
|
||||
@[deprecated USize.le_size (since := "2025-02-24")]
|
||||
theorem le_usize_size : 4294967296 ≤ USize.size :=
|
||||
USize.le_size
|
||||
|
||||
@[extern "lean_usize_mul"]
|
||||
def USize.mul (a b : USize) : USize := ⟨a.toBitVec * b.toBitVec⟩
|
||||
@@ -326,7 +331,7 @@ This function is overridden with a native implementation.
|
||||
-/
|
||||
@[extern "lean_usize_of_nat"]
|
||||
def USize.ofNat32 (n : @& Nat) (h : n < 4294967296) : USize :=
|
||||
USize.ofNatLT n (Nat.lt_of_lt_of_le h le_usize_size)
|
||||
USize.ofNatLT n (Nat.lt_of_lt_of_le h USize.le_size)
|
||||
@[extern "lean_uint8_to_usize"]
|
||||
def UInt8.toUSize (a : UInt8) : USize :=
|
||||
USize.ofNat32 a.toBitVec.toNat (Nat.lt_trans a.toBitVec.isLt (by decide))
|
||||
@@ -351,7 +356,7 @@ This function is overridden with a native implementation.
|
||||
-/
|
||||
@[extern "lean_usize_to_uint64"]
|
||||
def USize.toUInt64 (a : USize) : UInt64 :=
|
||||
UInt64.ofNatLT a.toBitVec.toNat (Nat.lt_of_lt_of_le a.toBitVec.isLt usize_size_le)
|
||||
UInt64.ofNatLT a.toBitVec.toNat (Nat.lt_of_lt_of_le a.toBitVec.isLt USize.size_le)
|
||||
|
||||
instance : Mul USize := ⟨USize.mul⟩
|
||||
instance : Mod USize := ⟨USize.mod⟩
|
||||
|
||||
@@ -138,8 +138,16 @@ def UInt32.toUInt64 (a : UInt32) : UInt64 := ⟨⟨a.toNat, Nat.lt_trans a.toBit
|
||||
|
||||
instance UInt64.instOfNat : OfNat UInt64 n := ⟨UInt64.ofNat n⟩
|
||||
|
||||
@[deprecated usize_size_pos (since := "2024-11-24")] theorem usize_size_gt_zero : USize.size > 0 :=
|
||||
usize_size_pos
|
||||
@[deprecated USize.size_eq (since := "2025-02-24")]
|
||||
theorem usize_size_eq : USize.size = 4294967296 ∨ USize.size = 18446744073709551616 :=
|
||||
USize.size_eq
|
||||
|
||||
@[deprecated USize.size_pos (since := "2025-02-24")]
|
||||
theorem usize_size_pos : 0 < USize.size :=
|
||||
USize.size_pos
|
||||
|
||||
@[deprecated USize.size_pos (since := "2024-11-24")] theorem usize_size_gt_zero : USize.size > 0 :=
|
||||
USize.size_pos
|
||||
|
||||
/-- Converts a `USize` into the corresponding `Fin USize.size`. -/
|
||||
def USize.toFin (x : USize) : Fin USize.size := x.toBitVec.toFin
|
||||
@@ -155,7 +163,7 @@ def USize.ofNatTruncate (n : Nat) : USize :=
|
||||
if h : n < USize.size then
|
||||
USize.ofNatLT n h
|
||||
else
|
||||
USize.ofNatLT (USize.size - 1) (Nat.pred_lt (Nat.ne_zero_of_lt usize_size_pos))
|
||||
USize.ofNatLT (USize.size - 1) (Nat.pred_lt (Nat.ne_zero_of_lt USize.size_pos))
|
||||
abbrev Nat.toUSize := USize.ofNat
|
||||
@[extern "lean_usize_to_nat"]
|
||||
def USize.toNat (n : USize) : Nat := n.toBitVec.toNat
|
||||
|
||||
@@ -25,11 +25,11 @@ namespace $typeName
|
||||
@[simp, int_toBitVec] protected theorem toBitVec_shiftLeft (a b : $typeName) : (a <<< b).toBitVec = a.toBitVec <<< (b.toBitVec % $bits) := rfl
|
||||
@[simp, int_toBitVec] protected theorem toBitVec_shiftRight (a b : $typeName) : (a >>> b).toBitVec = a.toBitVec >>> (b.toBitVec % $bits) := rfl
|
||||
|
||||
@[simp] protected theorem toNat_and (a b : $typeName) : (a &&& b).toNat = a.toNat &&& b.toNat := by simp [toNat]
|
||||
@[simp] protected theorem toNat_or (a b : $typeName) : (a ||| b).toNat = a.toNat ||| b.toNat := by simp [toNat]
|
||||
@[simp] protected theorem toNat_xor (a b : $typeName) : (a ^^^ b).toNat = a.toNat ^^^ b.toNat := by simp [toNat]
|
||||
@[simp] protected theorem toNat_shiftLeft (a b : $typeName) : (a <<< b).toNat = a.toNat <<< (b.toNat % $bits) % 2 ^ $bits := by simp [toNat]
|
||||
@[simp] protected theorem toNat_shiftRight (a b : $typeName) : (a >>> b).toNat = a.toNat >>> (b.toNat % $bits) := by simp [toNat]
|
||||
@[simp] protected theorem toNat_and (a b : $typeName) : (a &&& b).toNat = a.toNat &&& b.toNat := by simp [toNat, -toNat_toBitVec]
|
||||
@[simp] protected theorem toNat_or (a b : $typeName) : (a ||| b).toNat = a.toNat ||| b.toNat := by simp [toNat, -toNat_toBitVec]
|
||||
@[simp] protected theorem toNat_xor (a b : $typeName) : (a ^^^ b).toNat = a.toNat ^^^ b.toNat := by simp [toNat, -toNat_toBitVec]
|
||||
@[simp] protected theorem toNat_shiftLeft (a b : $typeName) : (a <<< b).toNat = a.toNat <<< (b.toNat % $bits) % 2 ^ $bits := by simp [toNat, -toNat_toBitVec]
|
||||
@[simp] protected theorem toNat_shiftRight (a b : $typeName) : (a >>> b).toNat = a.toNat >>> (b.toNat % $bits) := by simp [toNat, -toNat_toBitVec]
|
||||
|
||||
open $typeName (toNat_and) in
|
||||
@[deprecated toNat_and (since := "2024-11-28")]
|
||||
@@ -37,7 +37,6 @@ protected theorem and_toNat (a b : $typeName) : (a &&& b).toNat = a.toNat &&& b.
|
||||
|
||||
end $typeName
|
||||
)
|
||||
|
||||
declare_bitwise_uint_theorems UInt8 8
|
||||
declare_bitwise_uint_theorems UInt16 16
|
||||
declare_bitwise_uint_theorems UInt32 32
|
||||
|
||||
@@ -34,15 +34,23 @@ macro "declare_uint_theorems" typeName:ident bits:term:arg : command => do
|
||||
@[deprecated toNat_ofNatLT (since := "2025-02-13")]
|
||||
theorem toNat_ofNatCore {n : Nat} {h : n < size} : (ofNatLT n h).toNat = n := BitVec.toNat_ofNatLT ..
|
||||
|
||||
@[simp] theorem toFin_val_eq_toNat (x : $typeName) : x.toFin.val = x.toNat := rfl
|
||||
@[deprecated toFin_val_eq_toNat (since := "2025-02-12")]
|
||||
@[simp] theorem toFin_val (x : $typeName) : x.toFin.val = x.toNat := rfl
|
||||
@[deprecated toFin_val (since := "2025-02-12")]
|
||||
theorem val_val_eq_toNat (x : $typeName) : x.toFin.val = x.toNat := rfl
|
||||
|
||||
@[simp] theorem toNat_toBitVec (x : $typeName) : x.toBitVec.toNat = x.toNat := rfl
|
||||
@[simp] theorem toFin_toBitVec (x : $typeName) : x.toBitVec.toFin = x.toFin := rfl
|
||||
|
||||
@[deprecated toNat_toBitVec (since := "2025-02-21")]
|
||||
theorem toNat_toBitVec_eq_toNat (x : $typeName) : x.toBitVec.toNat = x.toNat := rfl
|
||||
|
||||
@[simp] theorem ofBitVec_toBitVec_eq : ∀ (a : $typeName), ofBitVec a.toBitVec = a
|
||||
@[simp] theorem ofBitVec_toBitVec : ∀ (a : $typeName), ofBitVec a.toBitVec = a
|
||||
| ⟨_, _⟩ => rfl
|
||||
|
||||
@[deprecated ofBitVec_toBitVec (since := "2025-02-21")]
|
||||
theorem ofBitVec_toBitVec_eq : ∀ (a : $typeName), ofBitVec a.toBitVec = a :=
|
||||
ofBitVec_toBitVec
|
||||
|
||||
@[deprecated ofBitVec_toBitVec_eq (since := "2025-02-12")]
|
||||
theorem mk_toBitVec_eq : ∀ (a : $typeName), ofBitVec a.toBitVec = a
|
||||
| ⟨_, _⟩ => rfl
|
||||
@@ -241,21 +249,537 @@ declare_uint_theorems USize System.Platform.numBits
|
||||
|
||||
@[simp] theorem USize.toNat_ofNat32 {n : Nat} {h : n < 4294967296} : (ofNat32 n h).toNat = n := rfl
|
||||
|
||||
@[simp] theorem USize.toNat_toUInt32 (x : USize) : x.toUInt32.toNat = x.toNat % 2 ^ 32 := rfl
|
||||
|
||||
@[simp] theorem USize.toNat_toUInt8 (x : USize) : x.toUInt8.toNat = x.toNat % 2 ^ 8 := rfl
|
||||
@[simp] theorem USize.toNat_toUInt16 (x : USize) : x.toUInt16.toNat = x.toNat % 2 ^ 16 := rfl
|
||||
@[simp] theorem USize.toNat_toUInt32 (x : USize) : x.toUInt32.toNat = x.toNat % 2 ^ 32 := rfl
|
||||
@[simp] theorem USize.toNat_toUInt64 (x : USize) : x.toUInt64.toNat = x.toNat := rfl
|
||||
|
||||
theorem USize.toNat_ofNat_of_lt_32 {n : Nat} (h : n < 4294967296) : toNat (ofNat n) = n :=
|
||||
toNat_ofNat_of_lt (Nat.lt_of_lt_of_le h le_usize_size)
|
||||
toNat_ofNat_of_lt (Nat.lt_of_lt_of_le h USize.le_size)
|
||||
|
||||
theorem UInt32.toNat_lt_of_lt {n : UInt32} {m : Nat} (h : m < size) : n < ofNat m → n.toNat < m := by
|
||||
simp [lt_def, BitVec.lt_def, UInt32.toNat, toBitVec_eq_of_lt h]
|
||||
simp [-toNat_toBitVec, lt_def, BitVec.lt_def, UInt32.toNat, toBitVec_eq_of_lt h]
|
||||
|
||||
theorem UInt32.lt_toNat_of_lt {n : UInt32} {m : Nat} (h : m < size) : ofNat m < n → m < n.toNat := by
|
||||
simp [lt_def, BitVec.lt_def, UInt32.toNat, toBitVec_eq_of_lt h]
|
||||
simp [-toNat_toBitVec, lt_def, BitVec.lt_def, UInt32.toNat, toBitVec_eq_of_lt h]
|
||||
|
||||
theorem UInt32.toNat_le_of_le {n : UInt32} {m : Nat} (h : m < size) : n ≤ ofNat m → n.toNat ≤ m := by
|
||||
simp [le_def, BitVec.le_def, UInt32.toNat, toBitVec_eq_of_lt h]
|
||||
simp [-toNat_toBitVec, le_def, BitVec.le_def, UInt32.toNat, toBitVec_eq_of_lt h]
|
||||
|
||||
theorem UInt32.le_toNat_of_le {n : UInt32} {m : Nat} (h : m < size) : ofNat m ≤ n → m ≤ n.toNat := by
|
||||
simp [le_def, BitVec.le_def, UInt32.toNat, toBitVec_eq_of_lt h]
|
||||
simp [-toNat_toBitVec, le_def, BitVec.le_def, UInt32.toNat, toBitVec_eq_of_lt h]
|
||||
|
||||
@[simp] theorem UInt8.toNat_lt (n : UInt8) : n.toNat < 2 ^ 8 := n.toFin.isLt
|
||||
@[simp] theorem UInt16.toNat_lt (n : UInt16) : n.toNat < 2 ^ 16 := n.toFin.isLt
|
||||
@[simp] theorem UInt32.toNat_lt (n : UInt32) : n.toNat < 2 ^ 32 := n.toFin.isLt
|
||||
@[simp] theorem UInt64.toNat_lt (n : UInt64) : n.toNat < 2 ^ 64 := n.toFin.isLt
|
||||
|
||||
theorem UInt8.size_lt_usizeSize : UInt8.size < USize.size := by
|
||||
cases USize.size_eq <;> simp_all +decide
|
||||
theorem UInt8.size_le_usizeSize : UInt8.size ≤ USize.size :=
|
||||
Nat.le_of_lt UInt8.size_lt_usizeSize
|
||||
theorem UInt16.size_lt_usizeSize : UInt16.size < USize.size := by
|
||||
cases USize.size_eq <;> simp_all +decide
|
||||
theorem UInt16.size_le_usizeSize : UInt16.size ≤ USize.size :=
|
||||
Nat.le_of_lt UInt16.size_lt_usizeSize
|
||||
theorem UInt32.size_le_usizeSize : UInt32.size ≤ USize.size := by
|
||||
cases USize.size_eq <;> simp_all +decide
|
||||
theorem USize.size_eq_two_pow : USize.size = 2 ^ System.Platform.numBits := rfl
|
||||
theorem USize.toNat_lt_two_pow_numBits (n : USize) : n.toNat < 2 ^ System.Platform.numBits := n.toFin.isLt
|
||||
@[simp] theorem USize.toNat_lt (n : USize) : n.toNat < 2 ^ 64 := Nat.lt_of_lt_of_le n.toFin.isLt size_le
|
||||
|
||||
theorem UInt8.toNat_lt_usizeSize (n : UInt8) : n.toNat < USize.size :=
|
||||
Nat.lt_of_lt_of_le n.toNat_lt (by cases USize.size_eq <;> simp_all)
|
||||
theorem UInt16.toNat_lt_usizeSize (n : UInt16) : n.toNat < USize.size :=
|
||||
Nat.lt_of_lt_of_le n.toNat_lt (by cases USize.size_eq <;> simp_all)
|
||||
theorem UInt32.toNat_lt_usizeSize (n : UInt32) : n.toNat < USize.size :=
|
||||
Nat.lt_of_lt_of_le n.toNat_lt (by cases USize.size_eq <;> simp_all)
|
||||
|
||||
theorem UInt8.size_dvd_usizeSize : UInt8.size ∣ USize.size := by cases USize.size_eq <;> simp_all +decide
|
||||
theorem UInt16.size_dvd_usizeSize : UInt16.size ∣ USize.size := by cases USize.size_eq <;> simp_all +decide
|
||||
theorem UInt32.size_dvd_usizeSize : UInt32.size ∣ USize.size := by cases USize.size_eq <;> simp_all +decide
|
||||
theorem USize.size_dvd_uInt64Size : USize.size ∣ UInt64.size := by cases USize.size_eq <;> simp_all +decide
|
||||
|
||||
@[simp] theorem mod_usizeSize_uInt8Size (n : Nat) : n % USize.size % UInt8.size = n % UInt8.size :=
|
||||
Nat.mod_mod_of_dvd _ UInt8.size_dvd_usizeSize
|
||||
@[simp] theorem mod_usizeSize_uInt16Size (n : Nat) : n % USize.size % UInt16.size = n % UInt16.size :=
|
||||
Nat.mod_mod_of_dvd _ UInt16.size_dvd_usizeSize
|
||||
@[simp] theorem mod_usizeSize_uInt32Size (n : Nat) : n % USize.size % UInt32.size = n % UInt32.size :=
|
||||
Nat.mod_mod_of_dvd _ UInt32.size_dvd_usizeSize
|
||||
@[simp] theorem mod_uInt64Size_uSizeSize (n : Nat) : n % UInt64.size % USize.size = n % USize.size :=
|
||||
Nat.mod_mod_of_dvd _ USize.size_dvd_uInt64Size
|
||||
|
||||
@[simp] theorem UInt8.toNat_mod_size (n : UInt8) : n.toNat % UInt8.size = n.toNat := Nat.mod_eq_of_lt n.toNat_lt
|
||||
@[simp] theorem UInt8.toNat_mod_uInt16Size (n : UInt8) : n.toNat % UInt16.size = n.toNat := Nat.mod_eq_of_lt (Nat.lt_trans n.toNat_lt (by decide))
|
||||
@[simp] theorem UInt8.toNat_mod_uInt32Size (n : UInt8) : n.toNat % UInt32.size = n.toNat := Nat.mod_eq_of_lt (Nat.lt_trans n.toNat_lt (by decide))
|
||||
@[simp] theorem UInt8.toNat_mod_uInt64Size (n : UInt8) : n.toNat % UInt64.size = n.toNat := Nat.mod_eq_of_lt (Nat.lt_trans n.toNat_lt (by decide))
|
||||
@[simp] theorem UInt8.toNat_mod_uSizeSize (n : UInt8) : n.toNat % USize.size = n.toNat := Nat.mod_eq_of_lt n.toNat_lt_usizeSize
|
||||
|
||||
@[simp] theorem UInt16.toNat_mod_size (n : UInt16) : n.toNat % UInt16.size = n.toNat := Nat.mod_eq_of_lt n.toNat_lt
|
||||
@[simp] theorem UInt16.toNat_mod_uInt32Size (n : UInt16) : n.toNat % UInt32.size = n.toNat := Nat.mod_eq_of_lt (Nat.lt_trans n.toNat_lt (by decide))
|
||||
@[simp] theorem UInt16.toNat_mod_uInt64Size (n : UInt16) : n.toNat % UInt64.size = n.toNat := Nat.mod_eq_of_lt (Nat.lt_trans n.toNat_lt (by decide))
|
||||
@[simp] theorem UInt16.toNat_mod_uSizeSize (n : UInt16) : n.toNat % USize.size = n.toNat := Nat.mod_eq_of_lt n.toNat_lt_usizeSize
|
||||
|
||||
@[simp] theorem UInt32.toNat_mod_size (n : UInt32) : n.toNat % UInt32.size = n.toNat := Nat.mod_eq_of_lt n.toNat_lt
|
||||
@[simp] theorem UInt32.toNat_mod_uInt64Size (n : UInt32) : n.toNat % UInt64.size = n.toNat := Nat.mod_eq_of_lt (Nat.lt_trans n.toNat_lt (by decide))
|
||||
@[simp] theorem UInt32.toNat_mod_uSizeSize (n : UInt32) : n.toNat % USize.size = n.toNat := Nat.mod_eq_of_lt n.toNat_lt_usizeSize
|
||||
|
||||
@[simp] theorem UInt64.toNat_mod_size (n : UInt64) : n.toNat % UInt64.size = n.toNat := Nat.mod_eq_of_lt n.toNat_lt
|
||||
|
||||
@[simp] theorem USize.toNat_mod_size (n : USize) : n.toNat % USize.size = n.toNat := Nat.mod_eq_of_lt n.toNat_lt_size
|
||||
@[simp] theorem USize.toNat_mod_uInt64Size (n : USize) : n.toNat % UInt64.size = n.toNat := Nat.mod_eq_of_lt n.toNat_lt
|
||||
|
||||
@[simp] theorem UInt8.toUInt16_mod_256 (n : UInt8) : n.toUInt16 % 256 = n.toUInt16 := UInt16.toNat.inj (by simp)
|
||||
@[simp] theorem UInt8.toUInt32_mod_256 (n : UInt8) : n.toUInt32 % 256 = n.toUInt32 := UInt32.toNat.inj (by simp)
|
||||
@[simp] theorem UInt8.toUInt64_mod_256 (n : UInt8) : n.toUInt64 % 256 = n.toUInt64 := UInt64.toNat.inj (by simp)
|
||||
@[simp] theorem UInt8.toUSize_mod_256 (n : UInt8) : n.toUSize % 256 = n.toUSize := USize.toNat.inj (by simp)
|
||||
|
||||
@[simp] theorem UInt16.toUInt32_mod_65536 (n : UInt16) : n.toUInt32 % 65536 = n.toUInt32 := UInt32.toNat.inj (by simp)
|
||||
@[simp] theorem UInt16.toUInt64_mod_65536 (n : UInt16) : n.toUInt64 % 65536 = n.toUInt64 := UInt64.toNat.inj (by simp)
|
||||
@[simp] theorem UInt16.toUSize_mod_65536 (n : UInt16) : n.toUSize % 65536 = n.toUSize := USize.toNat.inj (by simp)
|
||||
|
||||
@[simp] theorem UInt32.toUInt64_mod_4294967296 (n : UInt32) : n.toUInt64 % 4294967296 = n.toUInt64 := UInt64.toNat.inj (by simp)
|
||||
|
||||
@[simp] theorem Fin.mk_uInt8ToNat (n : UInt8) : Fin.mk n.toNat n.toFin.isLt = n.toFin := rfl
|
||||
@[simp] theorem Fin.mk_uInt16ToNat (n : UInt16) : Fin.mk n.toNat n.toFin.isLt = n.toFin := rfl
|
||||
@[simp] theorem Fin.mk_uInt32ToNat (n : UInt32) : Fin.mk n.toNat n.toFin.isLt = n.toFin := rfl
|
||||
@[simp] theorem Fin.mk_uInt64ToNat (n : UInt64) : Fin.mk n.toNat n.toFin.isLt = n.toFin := rfl
|
||||
@[simp] theorem Fin.mk_uSizeToNat (n : USize) : Fin.mk n.toNat n.toFin.isLt = n.toFin := rfl
|
||||
|
||||
@[simp] theorem BitVec.ofNatLT_uInt8ToNat (n : UInt8) : BitVec.ofNatLT n.toNat n.toFin.isLt = n.toBitVec := rfl
|
||||
@[simp] theorem BitVec.ofNatLT_uInt16ToNat (n : UInt16) : BitVec.ofNatLT n.toNat n.toFin.isLt = n.toBitVec := rfl
|
||||
@[simp] theorem BitVec.ofNatLT_uInt32ToNat (n : UInt32) : BitVec.ofNatLT n.toNat n.toFin.isLt = n.toBitVec := rfl
|
||||
@[simp] theorem BitVec.ofNatLT_uInt64ToNat (n : UInt64) : BitVec.ofNatLT n.toNat n.toFin.isLt = n.toBitVec := rfl
|
||||
@[simp] theorem BitVec.ofNatLT_uSizeToNat (n : USize) : BitVec.ofNatLT n.toNat n.toFin.isLt = n.toBitVec := rfl
|
||||
|
||||
@[simp] theorem BitVec.ofFin_uInt8ToFin (n : UInt8) : BitVec.ofFin n.toFin = n.toBitVec := rfl
|
||||
@[simp] theorem BitVec.ofFin_uInt16ToFin (n : UInt16) : BitVec.ofFin n.toFin = n.toBitVec := rfl
|
||||
@[simp] theorem BitVec.ofFin_uInt32ToFin (n : UInt32) : BitVec.ofFin n.toFin = n.toBitVec := rfl
|
||||
@[simp] theorem BitVec.ofFin_uInt64ToFin (n : UInt64) : BitVec.ofFin n.toFin = n.toBitVec := rfl
|
||||
@[simp] theorem BitVec.ofFin_uSizeToFin (n : USize) : BitVec.ofFin n.toFin = n.toBitVec := rfl
|
||||
|
||||
@[simp] theorem UInt8.toFin_toUInt16 (n : UInt8) : n.toUInt16.toFin = n.toFin.castLE (by decide) := rfl
|
||||
@[simp] theorem UInt8.toFin_toUInt32 (n : UInt8) : n.toUInt32.toFin = n.toFin.castLE (by decide) := rfl
|
||||
@[simp] theorem UInt8.toFin_toUInt64 (n : UInt8) : n.toUInt64.toFin = n.toFin.castLE (by decide) := rfl
|
||||
@[simp] theorem UInt8.toFin_toUSize (n : UInt8) :
|
||||
n.toUSize.toFin = n.toFin.castLE size_le_usizeSize := rfl
|
||||
|
||||
@[simp] theorem UInt16.toFin_toUInt32 (n : UInt16) : n.toUInt32.toFin = n.toFin.castLE (by decide) := rfl
|
||||
@[simp] theorem UInt16.toFin_toUInt64 (n : UInt16) : n.toUInt64.toFin = n.toFin.castLE (by decide) := rfl
|
||||
@[simp] theorem UInt16.toFin_toUSize (n : UInt16) :
|
||||
n.toUSize.toFin = n.toFin.castLE size_le_usizeSize := rfl
|
||||
|
||||
@[simp] theorem UInt32.toFin_toUInt64 (n : UInt32) : n.toUInt64.toFin = n.toFin.castLE (by decide) := rfl
|
||||
@[simp] theorem UInt32.toFin_toUSize (n : UInt32) :
|
||||
n.toUSize.toFin = n.toFin.castLE size_le_usizeSize := rfl
|
||||
|
||||
@[simp] theorem USize.toFin_toUInt64 (n : USize) : n.toUInt64.toFin = n.toFin.castLE size_le_usizeSize := rfl
|
||||
|
||||
@[simp] theorem UInt16.toBitVec_toUInt8 (n : UInt16) : n.toUInt8.toBitVec = n.toBitVec.setWidth 8 := rfl
|
||||
@[simp] theorem UInt32.toBitVec_toUInt8 (n : UInt32) : n.toUInt8.toBitVec = n.toBitVec.setWidth 8 := rfl
|
||||
@[simp] theorem UInt64.toBitVec_toUInt8 (n : UInt64) : n.toUInt8.toBitVec = n.toBitVec.setWidth 8 := rfl
|
||||
@[simp] theorem USize.toBitVec_toUInt8 (n : USize) : n.toUInt8.toBitVec = n.toBitVec.setWidth 8 := BitVec.eq_of_toNat_eq (by simp)
|
||||
|
||||
@[simp] theorem UInt8.toBitVec_toUInt16 (n : UInt8) : n.toUInt16.toBitVec = n.toBitVec.setWidth 16 := rfl
|
||||
@[simp] theorem UInt32.toBitVec_toUInt16 (n : UInt32) : n.toUInt16.toBitVec = n.toBitVec.setWidth 16 := rfl
|
||||
@[simp] theorem UInt64.toBitVec_toUInt16 (n : UInt64) : n.toUInt16.toBitVec = n.toBitVec.setWidth 16 := rfl
|
||||
@[simp] theorem USize.toBitVec_toUInt16 (n : USize) : n.toUInt16.toBitVec = n.toBitVec.setWidth 16 := BitVec.eq_of_toNat_eq (by simp)
|
||||
|
||||
@[simp] theorem UInt8.toBitVec_toUInt32 (n : UInt8) : n.toUInt32.toBitVec = n.toBitVec.setWidth 32 := rfl
|
||||
@[simp] theorem UInt16.toBitVec_toUInt32 (n : UInt16) : n.toUInt32.toBitVec = n.toBitVec.setWidth 32 := rfl
|
||||
@[simp] theorem UInt64.toBitVec_toUInt32 (n : UInt64) : n.toUInt32.toBitVec = n.toBitVec.setWidth 32 := rfl
|
||||
@[simp] theorem USize.toBitVec_toUInt32 (n : USize) : n.toUInt32.toBitVec = n.toBitVec.setWidth 32 := BitVec.eq_of_toNat_eq (by simp)
|
||||
|
||||
@[simp] theorem UInt8.toBitVec_toUInt64 (n : UInt8) : n.toUInt64.toBitVec = n.toBitVec.setWidth 64 := rfl
|
||||
@[simp] theorem UInt16.toBitVec_toUInt64 (n : UInt16) : n.toUInt64.toBitVec = n.toBitVec.setWidth 64 := rfl
|
||||
@[simp] theorem UInt32.toBitVec_toUInt64 (n : UInt32) : n.toUInt64.toBitVec = n.toBitVec.setWidth 64 := rfl
|
||||
@[simp] theorem USize.toBitVec_toUInt64 (n : USize) : n.toUInt64.toBitVec = n.toBitVec.setWidth 64 :=
|
||||
BitVec.eq_of_toNat_eq (by simp)
|
||||
|
||||
@[simp] theorem UInt8.toBitVec_toUSize (n : UInt8) : n.toUSize.toBitVec = n.toBitVec.setWidth System.Platform.numBits :=
|
||||
BitVec.eq_of_toNat_eq (by simp)
|
||||
@[simp] theorem UInt16.toBitVec_toUSize (n : UInt16) : n.toUSize.toBitVec = n.toBitVec.setWidth System.Platform.numBits :=
|
||||
BitVec.eq_of_toNat_eq (by simp)
|
||||
@[simp] theorem UInt32.toBitVec_toUSize (n : UInt32) : n.toUSize.toBitVec = n.toBitVec.setWidth System.Platform.numBits :=
|
||||
BitVec.eq_of_toNat_eq (by simp)
|
||||
@[simp] theorem UInt64.toBitVec_toUSize (n : UInt64) : n.toUSize.toBitVec = n.toBitVec.setWidth System.Platform.numBits :=
|
||||
BitVec.eq_of_toNat_eq (by simp)
|
||||
|
||||
@[simp] theorem UInt8.ofNatLT_toNat (n : UInt8) : UInt8.ofNatLT n.toNat n.toNat_lt = n := rfl
|
||||
@[simp] theorem UInt16.ofNatLT_uInt8ToNat (n : UInt8) : UInt16.ofNatLT n.toNat (Nat.lt_trans n.toNat_lt (by decide)) = n.toUInt16 := rfl
|
||||
@[simp] theorem UInt32.ofNatLT_uInt8ToNat (n : UInt8) : UInt32.ofNatLT n.toNat (Nat.lt_trans n.toNat_lt (by decide)) = n.toUInt32 := rfl
|
||||
@[simp] theorem UInt64.ofNatLT_uInt8ToNat (n : UInt8) : UInt64.ofNatLT n.toNat (Nat.lt_trans n.toNat_lt (by decide)) = n.toUInt64 := rfl
|
||||
@[simp] theorem USize.ofNatLT_uInt8ToNat (n : UInt8) : USize.ofNatLT n.toNat n.toNat_lt_usizeSize = n.toUSize := rfl
|
||||
|
||||
@[simp] theorem UInt16.ofNatLT_toNat (n : UInt16) : UInt16.ofNatLT n.toNat n.toNat_lt = n := rfl
|
||||
@[simp] theorem UInt32.ofNatLT_uInt16ToNat (n : UInt16) : UInt32.ofNatLT n.toNat (Nat.lt_trans n.toNat_lt (by decide)) = n.toUInt32 := rfl
|
||||
@[simp] theorem UInt64.ofNatLT_uInt16ToNat (n : UInt16) : UInt64.ofNatLT n.toNat (Nat.lt_trans n.toNat_lt (by decide)) = n.toUInt64 := rfl
|
||||
@[simp] theorem USize.ofNatLT_uInt16ToNat (n : UInt16) : USize.ofNatLT n.toNat n.toNat_lt_usizeSize = n.toUSize := rfl
|
||||
|
||||
@[simp] theorem UInt32.ofNatLT_toNat (n : UInt32) : UInt32.ofNatLT n.toNat n.toNat_lt = n := rfl
|
||||
@[simp] theorem UInt64.ofNatLT_uInt32ToNat (n : UInt32) : UInt64.ofNatLT n.toNat (Nat.lt_trans n.toNat_lt (by decide)) = n.toUInt64 := rfl
|
||||
@[simp] theorem USize.ofNatLT_uInt32ToNat (n : UInt32) : USize.ofNatLT n.toNat n.toNat_lt_usizeSize = n.toUSize := rfl
|
||||
|
||||
@[simp] theorem UInt64.ofNatLT_toNat (n : UInt64) : UInt64.ofNatLT n.toNat n.toNat_lt = n := rfl
|
||||
|
||||
@[simp] theorem USize.ofNatLT_toNat (n : USize) : USize.ofNatLT n.toNat n.toNat_lt_size = n := rfl
|
||||
@[simp] theorem UInt64.ofNatLT_uSizeToNat (n : USize) : UInt64.ofNatLT n.toNat n.toNat_lt = n.toUInt64 := rfl
|
||||
|
||||
-- We are not making these into `simp` lemmas because they lose the information stored in `h`. ·
|
||||
theorem UInt8.ofNatLT_uInt16ToNat (n : UInt16) (h) : UInt8.ofNatLT n.toNat h = n.toUInt8 :=
|
||||
UInt8.toNat.inj (by simp [Nat.mod_eq_of_lt h])
|
||||
theorem UInt8.ofNatLT_uInt32ToNat (n : UInt32) (h) : UInt8.ofNatLT n.toNat h = n.toUInt8 :=
|
||||
UInt8.toNat.inj (by simp [Nat.mod_eq_of_lt h])
|
||||
theorem UInt8.ofNatLT_uInt64ToNat (n : UInt64) (h) : UInt8.ofNatLT n.toNat h = n.toUInt8 :=
|
||||
UInt8.toNat.inj (by simp [Nat.mod_eq_of_lt h])
|
||||
theorem UInt8.ofNatLT_uSizeToNat (n : USize) (h) : UInt8.ofNatLT n.toNat h = n.toUInt8 :=
|
||||
UInt8.toNat.inj (by simp [Nat.mod_eq_of_lt h])
|
||||
theorem UInt16.ofNatLT_uInt32ToNat (n : UInt32) (h) : UInt16.ofNatLT n.toNat h = n.toUInt16 :=
|
||||
UInt16.toNat.inj (by simp [Nat.mod_eq_of_lt h])
|
||||
theorem UInt16.ofNatLT_uInt64ToNat (n : UInt64) (h) : UInt16.ofNatLT n.toNat h = n.toUInt16 :=
|
||||
UInt16.toNat.inj (by simp [Nat.mod_eq_of_lt h])
|
||||
theorem UInt16.ofNatLT_uSizeToNat (n : USize) (h) : UInt16.ofNatLT n.toNat h = n.toUInt16 :=
|
||||
UInt16.toNat.inj (by simp [Nat.mod_eq_of_lt h])
|
||||
theorem UInt32.ofNatLT_uInt64ToNat (n : UInt64) (h) : UInt32.ofNatLT n.toNat h = n.toUInt32 :=
|
||||
UInt32.toNat.inj (by simp [Nat.mod_eq_of_lt h])
|
||||
theorem UInt32.ofNatLT_uSizeToNat (n : USize) (h) : UInt32.ofNatLT n.toNat h = n.toUInt32 :=
|
||||
UInt32.toNat.inj (by simp [Nat.mod_eq_of_lt h])
|
||||
theorem USize.ofNatLT_uInt64ToNat (n : UInt64) (h) : USize.ofNatLT n.toNat h = n.toUSize :=
|
||||
USize.toNat.inj (by simp [Nat.mod_eq_of_lt h])
|
||||
|
||||
@[simp] theorem UInt8.ofFin_toFin (n : UInt8) : UInt8.ofFin n.toFin = n := rfl
|
||||
@[simp] theorem UInt16.ofFin_toFin (n : UInt16) : UInt16.ofFin n.toFin = n := rfl
|
||||
@[simp] theorem UInt32.ofFin_toFin (n : UInt32) : UInt32.ofFin n.toFin = n := rfl
|
||||
@[simp] theorem UInt64.ofFin_toFin (n : UInt64) : UInt64.ofFin n.toFin = n := rfl
|
||||
@[simp] theorem USize.ofFin_toFin (n : USize) : USize.ofFin n.toFin = n := rfl
|
||||
|
||||
@[simp] theorem UInt16.ofFin_uint8ToFin (n : UInt8) : UInt16.ofFin (n.toFin.castLE (by decide)) = n.toUInt16 := rfl
|
||||
|
||||
@[simp] theorem UInt32.ofFin_uint8ToFin (n : UInt8) : UInt32.ofFin (n.toFin.castLE (by decide)) = n.toUInt32 := rfl
|
||||
@[simp] theorem UInt32.ofFin_uint16ToFin (n : UInt16) : UInt32.ofFin (n.toFin.castLE (by decide)) = n.toUInt32 := rfl
|
||||
|
||||
@[simp] theorem UInt64.ofFin_uint8ToFin (n : UInt8) : UInt64.ofFin (n.toFin.castLE (by decide)) = n.toUInt64 := rfl
|
||||
@[simp] theorem UInt64.ofFin_uint16ToFin (n : UInt16) : UInt64.ofFin (n.toFin.castLE (by decide)) = n.toUInt64 := rfl
|
||||
@[simp] theorem UInt64.ofFin_uint32ToFin (n : UInt32) : UInt64.ofFin (n.toFin.castLE (by decide)) = n.toUInt64 := rfl
|
||||
|
||||
@[simp] theorem USize.ofFin_uint8ToFin (n : UInt8) : USize.ofFin (n.toFin.castLE UInt8.size_le_usizeSize) = n.toUSize := rfl
|
||||
@[simp] theorem USize.ofFin_uint16ToFin (n : UInt16) : USize.ofFin (n.toFin.castLE UInt16.size_le_usizeSize) = n.toUSize := rfl
|
||||
@[simp] theorem USize.ofFin_uint32ToFin (n : UInt32) : USize.ofFin (n.toFin.castLE UInt32.size_le_usizeSize) = n.toUSize := rfl
|
||||
|
||||
@[simp] theorem Nat.toUInt8_eq {n : Nat} : n.toUInt8 = UInt8.ofNat n := rfl
|
||||
@[simp] theorem Nat.toUInt16_eq {n : Nat} : n.toUInt16 = UInt16.ofNat n := rfl
|
||||
@[simp] theorem Nat.toUInt32_eq {n : Nat} : n.toUInt32 = UInt32.ofNat n := rfl
|
||||
@[simp] theorem Nat.toUInt64_eq {n : Nat} : n.toUInt64 = UInt64.ofNat n := rfl
|
||||
@[simp] theorem Nat.toUSize_eq {n : Nat} : n.toUSize = USize.ofNat n := rfl
|
||||
|
||||
@[simp] theorem UInt8.ofBitVec_uInt16ToBitVec (n : UInt16) :
|
||||
UInt8.ofBitVec (n.toBitVec.setWidth 8) = n.toUInt8 := rfl
|
||||
@[simp] theorem UInt8.ofBitVec_uInt32ToBitVec (n : UInt32) :
|
||||
UInt8.ofBitVec (n.toBitVec.setWidth 8) = n.toUInt8 := rfl
|
||||
@[simp] theorem UInt8.ofBitVec_uInt64ToBitVec (n : UInt64) :
|
||||
UInt8.ofBitVec (n.toBitVec.setWidth 8) = n.toUInt8 := rfl
|
||||
@[simp] theorem UInt8.ofBitVec_uSizeToBitVec (n : USize) :
|
||||
UInt8.ofBitVec (n.toBitVec.setWidth 8) = n.toUInt8 := UInt8.toNat.inj (by simp)
|
||||
|
||||
@[simp] theorem UInt16.ofBitVec_uInt8ToBitVec (n : UInt8) :
|
||||
UInt16.ofBitVec (n.toBitVec.setWidth 16) = n.toUInt16 := rfl
|
||||
@[simp] theorem UInt16.ofBitVec_uInt32ToBitVec (n : UInt32) :
|
||||
UInt16.ofBitVec (n.toBitVec.setWidth 16) = n.toUInt16 := rfl
|
||||
@[simp] theorem UInt16.ofBitVec_uInt64ToBitVec (n : UInt64) :
|
||||
UInt16.ofBitVec (n.toBitVec.setWidth 16) = n.toUInt16 := rfl
|
||||
@[simp] theorem UInt16.ofBitVec_uSizeToBitVec (n : USize) :
|
||||
UInt16.ofBitVec (n.toBitVec.setWidth 16) = n.toUInt16 := UInt16.toNat.inj (by simp)
|
||||
|
||||
@[simp] theorem UInt32.ofBitVec_uInt8ToBitVec (n : UInt8) :
|
||||
UInt32.ofBitVec (n.toBitVec.setWidth 32) = n.toUInt32 := rfl
|
||||
@[simp] theorem UInt32.ofBitVec_uInt16ToBitVec (n : UInt16) :
|
||||
UInt32.ofBitVec (n.toBitVec.setWidth 32) = n.toUInt32 := rfl
|
||||
@[simp] theorem UInt32.ofBitVec_uInt64ToBitVec (n : UInt64) :
|
||||
UInt32.ofBitVec (n.toBitVec.setWidth 32) = n.toUInt32 := rfl
|
||||
@[simp] theorem UInt32.ofBitVec_uSizeToBitVec (n : USize) :
|
||||
UInt32.ofBitVec (n.toBitVec.setWidth 32) = n.toUInt32 := UInt32.toNat.inj (by simp)
|
||||
|
||||
@[simp] theorem UInt64.ofBitVec_uInt8ToBitVec (n : UInt8) :
|
||||
UInt64.ofBitVec (n.toBitVec.setWidth 64) = n.toUInt64 := rfl
|
||||
@[simp] theorem UInt64.ofBitVec_uInt16ToBitVec (n : UInt16) :
|
||||
UInt64.ofBitVec (n.toBitVec.setWidth 64) = n.toUInt64 := rfl
|
||||
@[simp] theorem UInt64.ofBitVec_uInt32ToBitVec (n : UInt32) :
|
||||
UInt64.ofBitVec (n.toBitVec.setWidth 64) = n.toUInt64 := rfl
|
||||
@[simp] theorem UInt64.ofBitVec_uSizeToBitVec (n : USize) :
|
||||
UInt64.ofBitVec (n.toBitVec.setWidth 64) = n.toUInt64 :=
|
||||
UInt64.toNat.inj (by simp)
|
||||
|
||||
@[simp] theorem USize.ofBitVec_uInt8ToBitVec (n : UInt8) :
|
||||
USize.ofBitVec (n.toBitVec.setWidth System.Platform.numBits) = n.toUSize :=
|
||||
USize.toNat.inj (by simp)
|
||||
@[simp] theorem USize.ofBitVec_uInt16ToBitVec (n : UInt16) :
|
||||
USize.ofBitVec (n.toBitVec.setWidth System.Platform.numBits) = n.toUSize :=
|
||||
USize.toNat.inj (by simp)
|
||||
@[simp] theorem USize.ofBitVec_uInt32ToBitVec (n : UInt32) :
|
||||
USize.ofBitVec (n.toBitVec.setWidth System.Platform.numBits) = n.toUSize :=
|
||||
USize.toNat.inj (by simp)
|
||||
@[simp] theorem USize.ofBitVec_uInt64ToBitVec (n : UInt64) :
|
||||
USize.ofBitVec (n.toBitVec.setWidth System.Platform.numBits) = n.toUSize :=
|
||||
USize.toNat.inj (by simp)
|
||||
|
||||
@[simp] theorem UInt8.ofNat_uInt16ToNat (n : UInt16) : UInt8.ofNat n.toNat = n.toUInt8 := rfl
|
||||
@[simp] theorem UInt8.ofNat_uInt32ToNat (n : UInt32) : UInt8.ofNat n.toNat = n.toUInt8 := rfl
|
||||
@[simp] theorem UInt8.ofNat_uInt64ToNat (n : UInt64) : UInt8.ofNat n.toNat = n.toUInt8 := rfl
|
||||
@[simp] theorem UInt8.ofNat_uSizeToNat (n : USize) : UInt8.ofNat n.toNat = n.toUInt8 := rfl
|
||||
|
||||
@[simp] theorem UInt16.ofNat_uInt8ToNat (n : UInt8) : UInt16.ofNat n.toNat = n.toUInt16 :=
|
||||
UInt16.toNat.inj (by simp)
|
||||
@[simp] theorem UInt16.ofNat_uInt32ToNat (n : UInt32) : UInt16.ofNat n.toNat = n.toUInt16 := rfl
|
||||
@[simp] theorem UInt16.ofNat_uInt64ToNat (n : UInt64) : UInt16.ofNat n.toNat = n.toUInt16 := rfl
|
||||
@[simp] theorem UInt16.ofNat_uSizeToNat (n : USize) : UInt16.ofNat n.toNat = n.toUInt16 := rfl
|
||||
|
||||
@[simp] theorem UInt32.ofNat_uInt8ToNat (n : UInt8) : UInt32.ofNat n.toNat = n.toUInt32 :=
|
||||
UInt32.toNat.inj (by simp)
|
||||
@[simp] theorem UInt32.ofNat_uInt16ToNat (n : UInt16) : UInt32.ofNat n.toNat = n.toUInt32 :=
|
||||
UInt32.toNat.inj (by simp)
|
||||
@[simp] theorem UInt32.ofNat_uInt64ToNat (n : UInt64) : UInt32.ofNat n.toNat = n.toUInt32 := rfl
|
||||
@[simp] theorem UInt32.ofNat_uSizeToNat (n : USize) : UInt32.ofNat n.toNat = n.toUInt32 := rfl
|
||||
|
||||
@[simp] theorem UInt64.ofNat_uInt8ToNat (n : UInt8) : UInt64.ofNat n.toNat = n.toUInt64 :=
|
||||
UInt64.toNat.inj (by simp)
|
||||
@[simp] theorem UInt64.ofNat_uInt16ToNat (n : UInt16) : UInt64.ofNat n.toNat = n.toUInt64 :=
|
||||
UInt64.toNat.inj (by simp)
|
||||
@[simp] theorem UInt64.ofNat_uInt32ToNat (n : UInt32) : UInt64.ofNat n.toNat = n.toUInt64 :=
|
||||
UInt64.toNat.inj (by simp)
|
||||
@[simp] theorem UInt64.ofNat_uSizeToNat (n : USize) : UInt64.ofNat n.toNat = n.toUInt64 :=
|
||||
UInt64.toNat.inj (by simp)
|
||||
|
||||
@[simp] theorem USize.ofNat_uInt8ToNat (n : UInt8) : USize.ofNat n.toNat = n.toUSize :=
|
||||
USize.toNat.inj (by simp)
|
||||
@[simp] theorem USize.ofNat_uInt16ToNat (n : UInt16) : USize.ofNat n.toNat = n.toUSize :=
|
||||
USize.toNat.inj (by simp)
|
||||
@[simp] theorem USize.ofNat_uInt32ToNat (n : UInt32) : USize.ofNat n.toNat = n.toUSize :=
|
||||
USize.toNat.inj (by simp)
|
||||
@[simp] theorem USize.ofNat_uInt64ToNat (n : UInt64) : USize.ofNat n.toNat = n.toUSize :=
|
||||
USize.toNat.inj (by simp)
|
||||
|
||||
theorem UInt8.ofNatLT_eq_ofNat (n : Nat) {h} : UInt8.ofNatLT n h = UInt8.ofNat n :=
|
||||
UInt8.toNat.inj (by simp [Nat.mod_eq_of_lt h])
|
||||
theorem UInt16.ofNatLT_eq_ofNat (n : Nat) {h} : UInt16.ofNatLT n h = UInt16.ofNat n :=
|
||||
UInt16.toNat.inj (by simp [Nat.mod_eq_of_lt h])
|
||||
theorem UInt32.ofNatLT_eq_ofNat (n : Nat) {h} : UInt32.ofNatLT n h = UInt32.ofNat n :=
|
||||
UInt32.toNat.inj (by simp [Nat.mod_eq_of_lt h])
|
||||
theorem UInt64.ofNatLT_eq_ofNat (n : Nat) {h} : UInt64.ofNatLT n h = UInt64.ofNat n :=
|
||||
UInt64.toNat.inj (by simp [Nat.mod_eq_of_lt h])
|
||||
theorem USize.ofNatLT_eq_ofNat (n : Nat) {h} : USize.ofNatLT n h = USize.ofNat n :=
|
||||
USize.toNat.inj (by simp [Nat.mod_eq_of_lt h])
|
||||
|
||||
theorem UInt8.ofNatTruncate_eq_ofNat (n : Nat) (hn : n < UInt8.size) :
|
||||
UInt8.ofNatTruncate n = UInt8.ofNat n := by
|
||||
simp [ofNatTruncate, hn, UInt8.ofNatLT_eq_ofNat]
|
||||
theorem UInt16.ofNatTruncate_eq_ofNat (n : Nat) (hn : n < UInt16.size) :
|
||||
UInt16.ofNatTruncate n = UInt16.ofNat n := by
|
||||
simp [ofNatTruncate, hn, UInt16.ofNatLT_eq_ofNat]
|
||||
theorem UInt32.ofNatTruncate_eq_ofNat (n : Nat) (hn : n < UInt32.size) :
|
||||
UInt32.ofNatTruncate n = UInt32.ofNat n := by
|
||||
simp [ofNatTruncate, hn, UInt32.ofNatLT_eq_ofNat]
|
||||
theorem UInt64.ofNatTruncate_eq_ofNat (n : Nat) (hn : n < UInt64.size) :
|
||||
UInt64.ofNatTruncate n = UInt64.ofNat n := by
|
||||
simp [ofNatTruncate, hn, UInt64.ofNatLT_eq_ofNat]
|
||||
theorem USize.ofNatTruncate_eq_ofNat (n : Nat) (hn : n < USize.size) :
|
||||
USize.ofNatTruncate n = USize.ofNat n := by
|
||||
simp [ofNatTruncate, hn, USize.ofNatLT_eq_ofNat]
|
||||
|
||||
@[simp] theorem UInt8.ofNatTruncate_toNat (n : UInt8) : UInt8.ofNatTruncate n.toNat = n := by
|
||||
rw [UInt8.ofNatTruncate_eq_ofNat] <;> simp [n.toNat_lt]
|
||||
|
||||
@[simp] theorem UInt16.ofNatTruncate_uInt8ToNat (n : UInt8) : UInt16.ofNatTruncate n.toNat = n.toUInt16 := by
|
||||
rw [UInt16.ofNatTruncate_eq_ofNat, ofNat_uInt8ToNat]
|
||||
exact Nat.lt_trans (n.toNat_lt) (by decide)
|
||||
@[simp] theorem UInt16.ofNatTruncate_toNat (n : UInt16) : UInt16.ofNatTruncate n.toNat = n := by
|
||||
rw [UInt16.ofNatTruncate_eq_ofNat] <;> simp [n.toNat_lt]
|
||||
|
||||
@[simp] theorem UInt32.ofNatTruncate_uInt8ToNat (n : UInt8) : UInt32.ofNatTruncate n.toNat = n.toUInt32 := by
|
||||
rw [UInt32.ofNatTruncate_eq_ofNat, ofNat_uInt8ToNat]
|
||||
exact Nat.lt_trans (n.toNat_lt) (by decide)
|
||||
@[simp] theorem UInt32.ofNatTruncate_uInt16ToNat (n : UInt16) : UInt32.ofNatTruncate n.toNat = n.toUInt32 := by
|
||||
rw [UInt32.ofNatTruncate_eq_ofNat, ofNat_uInt16ToNat]
|
||||
exact Nat.lt_trans (n.toNat_lt) (by decide)
|
||||
@[simp] theorem UInt32.ofNatTruncate_toNat (n : UInt32) : UInt32.ofNatTruncate n.toNat = n := by
|
||||
rw [UInt32.ofNatTruncate_eq_ofNat] <;> simp [n.toNat_lt]
|
||||
|
||||
@[simp] theorem UInt64.ofNatTruncate_uInt8ToNat (n : UInt8) : UInt64.ofNatTruncate n.toNat = n.toUInt64 := by
|
||||
rw [UInt64.ofNatTruncate_eq_ofNat, ofNat_uInt8ToNat]
|
||||
exact Nat.lt_trans (n.toNat_lt) (by decide)
|
||||
@[simp] theorem UInt64.ofNatTruncate_uInt16ToNat (n : UInt16) : UInt64.ofNatTruncate n.toNat = n.toUInt64 := by
|
||||
rw [UInt64.ofNatTruncate_eq_ofNat, ofNat_uInt16ToNat]
|
||||
exact Nat.lt_trans (n.toNat_lt) (by decide)
|
||||
@[simp] theorem UInt64.ofNatTruncate_uInt32ToNat (n : UInt32) : UInt64.ofNatTruncate n.toNat = n.toUInt64 := by
|
||||
rw [UInt64.ofNatTruncate_eq_ofNat, ofNat_uInt32ToNat]
|
||||
exact Nat.lt_trans (n.toNat_lt) (by decide)
|
||||
@[simp] theorem UInt64.ofNatTruncate_toNat (n : UInt64) : UInt64.ofNatTruncate n.toNat = n := by
|
||||
rw [UInt64.ofNatTruncate_eq_ofNat] <;> simp [n.toNat_lt]
|
||||
@[simp] theorem UInt64.ofNatTruncate_uSizeToNat (n : USize) : UInt64.ofNatTruncate n.toNat = n.toUInt64 := by
|
||||
rw [UInt64.ofNatTruncate_eq_ofNat, ofNat_uSizeToNat]
|
||||
exact n.toNat_lt
|
||||
|
||||
@[simp] theorem USize.ofNatTruncate_uInt8ToNat (n : UInt8) : USize.ofNatTruncate n.toNat = n.toUSize := by
|
||||
rw [USize.ofNatTruncate_eq_ofNat, ofNat_uInt8ToNat]
|
||||
exact n.toNat_lt_usizeSize
|
||||
@[simp] theorem USize.ofNatTruncate_uInt16ToNat (n : UInt16) : USize.ofNatTruncate n.toNat = n.toUSize := by
|
||||
rw [USize.ofNatTruncate_eq_ofNat, ofNat_uInt16ToNat]
|
||||
exact n.toNat_lt_usizeSize
|
||||
@[simp] theorem USize.ofNatTruncate_uInt32ToNat (n : UInt32) : USize.ofNatTruncate n.toNat = n.toUSize := by
|
||||
rw [USize.ofNatTruncate_eq_ofNat, ofNat_uInt32ToNat]
|
||||
exact n.toNat_lt_usizeSize
|
||||
@[simp] theorem USize.ofNatTruncate_toNat (n : USize) : USize.ofNatTruncate n.toNat = n := by
|
||||
rw [USize.ofNatTruncate_eq_ofNat] <;> simp [n.toNat_lt_size]
|
||||
|
||||
@[simp] theorem UInt8.toUInt8_toUInt16 (n : UInt8) : n.toUInt16.toUInt8 = n :=
|
||||
UInt8.toNat.inj (by simp)
|
||||
@[simp] theorem UInt8.toUInt8_toUInt32 (n : UInt8) : n.toUInt32.toUInt8 = n :=
|
||||
UInt8.toNat.inj (by simp)
|
||||
@[simp] theorem UInt8.toUInt8_toUInt64 (n : UInt8) : n.toUInt64.toUInt8 = n :=
|
||||
UInt8.toNat.inj (by simp)
|
||||
@[simp] theorem UInt8.toUInt8_toUSize (n : UInt8) : n.toUSize.toUInt8 = n :=
|
||||
UInt8.toNat.inj (by simp)
|
||||
|
||||
@[simp] theorem UInt8.toUInt16_toUInt32 (n : UInt8) : n.toUInt32.toUInt16 = n.toUInt16 :=
|
||||
UInt16.toNat.inj (by simp)
|
||||
@[simp] theorem UInt8.toUInt16_toUInt64 (n : UInt8) : n.toUInt64.toUInt16 = n.toUInt16 :=
|
||||
UInt16.toNat.inj (by simp)
|
||||
@[simp] theorem UInt8.toUInt16_toUSize (n : UInt8) : n.toUSize.toUInt16 = n.toUInt16 :=
|
||||
UInt16.toNat.inj (by simp)
|
||||
|
||||
@[simp] theorem UInt8.toUInt32_toUInt16 (n : UInt8) : n.toUInt16.toUInt32 = n.toUInt32 := rfl
|
||||
@[simp] theorem UInt8.toUInt32_toUInt64 (n : UInt8) : n.toUInt64.toUInt32 = n.toUInt32 :=
|
||||
UInt32.toNat.inj (by simp)
|
||||
@[simp] theorem UInt8.toUInt32_toUSize (n : UInt8) : n.toUSize.toUInt32 = n.toUInt32 :=
|
||||
UInt32.toNat.inj (by simp)
|
||||
|
||||
@[simp] theorem UInt8.toUInt64_toUInt16 (n : UInt8) : n.toUInt16.toUInt64 = n.toUInt64 := rfl
|
||||
@[simp] theorem UInt8.toUInt64_toUInt32 (n : UInt8) : n.toUInt32.toUInt64 = n.toUInt64 := rfl
|
||||
@[simp] theorem UInt8.toUInt64_toUSize (n : UInt8) : n.toUSize.toUInt64 = n.toUInt64 := rfl
|
||||
|
||||
@[simp] theorem UInt8.toUSize_toUInt16 (n : UInt8) : n.toUInt16.toUSize = n.toUSize := rfl
|
||||
@[simp] theorem UInt8.toUSize_toUInt32 (n : UInt8) : n.toUInt32.toUSize = n.toUSize := rfl
|
||||
@[simp] theorem UInt8.toUSize_toUInt64 (n : UInt8) : n.toUInt64.toUSize = n.toUSize :=
|
||||
USize.toNat.inj (by simp)
|
||||
|
||||
@[simp] theorem UInt16.toUInt8_toUInt32 (n : UInt16) : n.toUInt32.toUInt8 = n.toUInt8 := rfl
|
||||
@[simp] theorem UInt16.toUInt8_toUInt64 (n : UInt16) : n.toUInt64.toUInt8 = n.toUInt8 := rfl
|
||||
@[simp] theorem UInt16.toUInt8_toUSize (n : UInt16) : n.toUSize.toUInt8 = n.toUInt8 := rfl
|
||||
|
||||
@[simp] theorem UInt16.toUInt16_toUInt8 (n : UInt16) : n.toUInt8.toUInt16 = n % 256 := rfl
|
||||
@[simp] theorem UInt16.toUInt16_toUInt32 (n : UInt16) : n.toUInt32.toUInt16 = n :=
|
||||
UInt16.toNat.inj (by simp)
|
||||
@[simp] theorem UInt16.toUInt16_toUInt64 (n : UInt16) : n.toUInt64.toUInt16 = n :=
|
||||
UInt16.toNat.inj (by simp)
|
||||
@[simp] theorem UInt16.toUInt16_toUSize (n : UInt16) : n.toUSize.toUInt16 = n :=
|
||||
UInt16.toNat.inj (by simp)
|
||||
|
||||
@[simp] theorem UInt16.toUInt32_toUInt8 (n : UInt16) : n.toUInt8.toUInt32 = n.toUInt32 % 256 := rfl
|
||||
@[simp] theorem UInt16.toUInt32_toUInt64 (n : UInt16) : n.toUInt64.toUInt32 = n.toUInt32 :=
|
||||
UInt32.toNat.inj (by simp)
|
||||
@[simp] theorem UInt16.toUInt32_toUSize (n : UInt16) : n.toUSize.toUInt32 = n.toUInt32 :=
|
||||
UInt32.toNat.inj (by simp)
|
||||
|
||||
@[simp] theorem UInt16.toUInt64_toUInt8 (n : UInt16) : n.toUInt8.toUInt64 = n.toUInt64 % 256 := rfl
|
||||
@[simp] theorem UInt16.toUInt64_toUInt32 (n : UInt16) : n.toUInt32.toUInt64 = n.toUInt64 := rfl
|
||||
@[simp] theorem UInt16.toUInt64_toUSize (n : UInt16) : n.toUSize.toUInt64 = n.toUInt64 := rfl
|
||||
|
||||
@[simp] theorem UInt16.toUSize_toUInt8 (n : UInt16) : n.toUInt8.toUSize = n.toUSize % 256 :=
|
||||
USize.toNat.inj (by simp)
|
||||
@[simp] theorem UInt16.toUSize_toUInt32 (n : UInt16) : n.toUInt32.toUSize = n.toUSize :=
|
||||
USize.toNat.inj (by simp)
|
||||
@[simp] theorem UInt16.toUSize_toUInt64 (n : UInt16) : n.toUInt64.toUSize = n.toUSize :=
|
||||
USize.toNat.inj (by simp)
|
||||
|
||||
@[simp] theorem UInt32.toUInt8_toUInt16 (n : UInt32) : n.toUInt16.toUInt8 = n.toUInt8 :=
|
||||
UInt8.toNat.inj (by simp)
|
||||
@[simp] theorem UInt32.toUInt8_toUInt64 (n : UInt32) : n.toUInt64.toUInt8 = n.toUInt8 := rfl
|
||||
@[simp] theorem UInt32.toUInt8_toUSize (n : UInt32) : n.toUSize.toUInt8 = n.toUInt8 := rfl
|
||||
|
||||
@[simp] theorem UInt32.toUInt16_toUInt8 (n : UInt32) : n.toUInt8.toUInt16 = n.toUInt16 % 256 :=
|
||||
UInt16.toNat.inj (by simp)
|
||||
@[simp] theorem UInt32.toUInt16_toUInt64 (n : UInt32) : n.toUInt64.toUInt16 = n.toUInt16 := rfl
|
||||
@[simp] theorem UInt32.toUInt16_toUSize (n : UInt32) : n.toUSize.toUInt16 = n.toUInt16 := rfl
|
||||
|
||||
@[simp] theorem UInt32.toUInt32_toUInt8 (n : UInt32) : n.toUInt8.toUInt32 = n % 256 := rfl
|
||||
@[simp] theorem UInt32.toUInt32_toUInt16 (n : UInt32) : n.toUInt16.toUInt32 = n % 65536 := rfl
|
||||
@[simp] theorem UInt32.toUInt32_toUInt64 (n : UInt32) : n.toUInt64.toUInt32 = n :=
|
||||
UInt32.toNat.inj (by simp)
|
||||
@[simp] theorem UInt32.toUInt32_toUSize (n : UInt32) : n.toUSize.toUInt32 = n :=
|
||||
UInt32.toNat.inj (by simp)
|
||||
|
||||
@[simp] theorem UInt32.toUInt64_toUInt8 (n : UInt32) : n.toUInt8.toUInt64 = n.toUInt64 % 256 := rfl
|
||||
@[simp] theorem UInt32.toUInt64_toUInt16 (n : UInt32) : n.toUInt16.toUInt64 = n.toUInt64 % 65536 := rfl
|
||||
@[simp] theorem UInt32.toUInt64_toUSize (n : UInt32) : n.toUSize.toUInt64 = n.toUInt64 := rfl
|
||||
|
||||
@[simp] theorem UInt32.toUSize_toUInt8 (n : UInt32) : n.toUInt8.toUSize = n.toUSize % 256 :=
|
||||
USize.toNat.inj (by simp)
|
||||
@[simp] theorem UInt32.toUSize_toUInt16 (n : UInt32) : n.toUInt16.toUSize = n.toUSize % 65536 :=
|
||||
USize.toNat.inj (by simp)
|
||||
@[simp] theorem UInt32.toUSize_toUInt64 (n : UInt32) : n.toUInt64.toUSize = n.toUSize :=
|
||||
USize.toNat.inj (by simp)
|
||||
|
||||
@[simp] theorem UInt64.toUInt8_toUInt16 (n : UInt64) : n.toUInt16.toUInt8 = n.toUInt8 :=
|
||||
UInt8.toNat.inj (by simp)
|
||||
@[simp] theorem UInt64.toUInt8_toUInt32 (n : UInt64) : n.toUInt32.toUInt8 = n.toUInt8 :=
|
||||
UInt8.toNat.inj (by simp)
|
||||
@[simp] theorem UInt64.toUInt8_toUSize (n : UInt64) : n.toUSize.toUInt8 = n.toUInt8 :=
|
||||
UInt8.toNat.inj (by simp)
|
||||
|
||||
@[simp] theorem UInt64.toUInt16_toUInt8 (n : UInt64) : n.toUInt8.toUInt16 = n.toUInt16 % 256 :=
|
||||
UInt16.toNat.inj (by simp)
|
||||
@[simp] theorem UInt64.toUInt16_toUInt32 (n : UInt64) : n.toUInt32.toUInt16 = n.toUInt16 :=
|
||||
UInt16.toNat.inj (by simp)
|
||||
@[simp] theorem UInt64.toUInt16_toUSize (n : UInt64) : n.toUSize.toUInt16 = n.toUInt16 :=
|
||||
UInt16.toNat.inj (by simp)
|
||||
|
||||
@[simp] theorem UInt64.toUInt32_toUInt8 (n : UInt64) : n.toUInt8.toUInt32 = n.toUInt32 % 256 :=
|
||||
UInt32.toNat.inj (by simp)
|
||||
@[simp] theorem UInt64.toUInt32_toUInt16 (n : UInt64) : n.toUInt16.toUInt32 = n.toUInt32 % 65536 :=
|
||||
UInt32.toNat.inj (by simp)
|
||||
@[simp] theorem UInt64.toUInt32_toUSize (n : UInt64) : n.toUSize.toUInt32 = n.toUInt32 :=
|
||||
UInt32.toNat.inj (by simp)
|
||||
|
||||
@[simp] theorem UInt64.toUInt64_toUInt8 (n : UInt64) : n.toUInt8.toUInt64 = n % 256 := rfl
|
||||
@[simp] theorem UInt64.toUInt64_toUInt16 (n : UInt64) : n.toUInt16.toUInt64 = n % 65536 := rfl
|
||||
@[simp] theorem UInt64.toUInt64_toUInt32 (n : UInt64) : n.toUInt32.toUInt64 = n % 4294967296 := rfl
|
||||
|
||||
@[simp] theorem UInt64.toUSize_toUInt8 (n : UInt64) : n.toUInt8.toUSize = n.toUSize % 256 :=
|
||||
USize.toNat.inj (by simp)
|
||||
@[simp] theorem UInt64.toUSize_toUInt16 (n : UInt64) : n.toUInt16.toUSize = n.toUSize % 65536 :=
|
||||
USize.toNat.inj (by simp)
|
||||
|
||||
@[simp] theorem USize.toUInt8_toUInt16 (n : USize) : n.toUInt16.toUInt8 = n.toUInt8 :=
|
||||
UInt8.toNat.inj (by simp)
|
||||
@[simp] theorem USize.toUInt8_toUInt32 (n : USize) : n.toUInt32.toUInt8 = n.toUInt8 :=
|
||||
UInt8.toNat.inj (by simp)
|
||||
@[simp] theorem USize.toUInt8_toUInt64 (n : USize) : n.toUInt64.toUInt8 = n.toUInt8 := rfl
|
||||
|
||||
@[simp] theorem USize.toUInt16_toUInt8 (n : USize) : n.toUInt8.toUInt16 = n.toUInt16 % 256 :=
|
||||
UInt16.toNat.inj (by simp)
|
||||
@[simp] theorem USize.toUInt16_toUInt32 (n : USize) : n.toUInt32.toUInt16 = n.toUInt16 :=
|
||||
UInt16.toNat.inj (by simp)
|
||||
@[simp] theorem USize.toUInt16_toUInt64 (n : USize) : n.toUInt64.toUInt16 = n.toUInt16 := rfl
|
||||
|
||||
@[simp] theorem USize.toUInt64_toUInt8 (n : USize) : n.toUInt8.toUInt64 = n.toUInt64 % 256 := rfl
|
||||
@[simp] theorem USize.toUInt64_toUInt16 (n : USize) : n.toUInt16.toUInt64 = n.toUInt64 % 65536 := rfl
|
||||
|
||||
@[simp] theorem USize.toUInt32_toUInt8 (n : USize) : n.toUInt8.toUInt32 = n.toUInt32 % 256 :=
|
||||
UInt32.toNat.inj (by simp)
|
||||
@[simp] theorem USize.toUInt32_toUInt16 (n : USize) : n.toUInt16.toUInt32 = n.toUInt32 % 65536 :=
|
||||
UInt32.toNat.inj (by simp)
|
||||
@[simp] theorem USize.toUInt32_toUInt64 (n : USize) : n.toUInt64.toUInt32 = n.toUInt32 :=
|
||||
UInt32.toNat.inj (by simp)
|
||||
|
||||
@[simp] theorem USize.toUSize_toUInt8 (n : USize) : n.toUInt8.toUSize = n % 256 :=
|
||||
USize.toNat.inj (by simp)
|
||||
@[simp] theorem USize.toUSize_toUInt16 (n : USize) : n.toUInt16.toUSize = n % 65536 :=
|
||||
USize.toNat.inj (by simp)
|
||||
@[simp] theorem USize.toUSize_toUInt64 (n : USize) : n.toUInt64.toUSize = n :=
|
||||
USize.toNat.inj (by simp)
|
||||
|
||||
-- Note: we are currently missing the following four results for which there does not seem to
|
||||
-- be a good candidate for the RHS:
|
||||
-- @[simp] theorem UInt64.toUInt64_toUSize (n : UInt64) : n.toUSize.toUInt64 = ? :=
|
||||
-- @[simp] theorem UInt64.toUSize_toUInt32 (n : UInt64) : n.toUInt32.toUSize = ? :=
|
||||
-- @[simp] theorem USize.toUInt64_toUInt32 (n : USize) : n.toUInt32.toUInt64 = ? :=
|
||||
-- @[simp] theorem USize.toUSize_toUInt32 (n : USize) : n.toInt32.toUSize = ? :=
|
||||
|
||||
@@ -473,6 +473,10 @@ def unattach {α : Type _} {p : α → Prop} (xs : Vector { x // p x } n) : Vect
|
||||
(xs.push a).unattach = xs.unattach.push a.1 := by
|
||||
simp only [unattach, Vector.map_push]
|
||||
|
||||
@[simp] theorem mem_unattach {p : α → Prop} {xs : Vector { x // p x } n} {a} :
|
||||
a ∈ xs.unattach ↔ ∃ h : p a, ⟨a, h⟩ ∈ xs := by
|
||||
simp only [unattach, mem_map, Subtype.exists, exists_and_right, exists_eq_right]
|
||||
|
||||
@[simp] theorem unattach_mk {p : α → Prop} {xs : Array { x // p x }} {h : xs.size = n} :
|
||||
(mk xs h).unattach = mk xs.unattach (by simpa using h) := by
|
||||
simp [unattach]
|
||||
@@ -552,6 +556,18 @@ and simplifies these to the function directly taking the value.
|
||||
simp
|
||||
rw [Array.find?_subtype hf]
|
||||
|
||||
@[simp] theorem all_subtype {p : α → Prop} {xs : Vector { x // p x } n} {f : { x // p x } → Bool} {g : α → Bool}
|
||||
(hf : ∀ x h, f ⟨x, h⟩ = g x) :
|
||||
xs.all f = xs.unattach.all g := by
|
||||
rcases xs with ⟨xs, rfl⟩
|
||||
simp [hf]
|
||||
|
||||
@[simp] theorem any_subtype {p : α → Prop} {xs : Vector { x // p x } n} {f : { x // p x } → Bool} {g : α → Bool}
|
||||
(hf : ∀ x h, f ⟨x, h⟩ = g x) :
|
||||
xs.any f = xs.unattach.any g := by
|
||||
rcases xs with ⟨xs, rfl⟩
|
||||
simp [hf]
|
||||
|
||||
/-! ### Simp lemmas pushing `unattach` inwards. -/
|
||||
|
||||
@[simp] theorem unattach_reverse {p : α → Prop} {xs : Vector { x // p x } n} :
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user