Compare commits

..

47 Commits

Author SHA1 Message Date
Kim Morrison
26268136dc doc-string 2025-06-21 14:37:50 +10:00
Kim Morrison
98c220ea8d cleanup 2025-06-21 14:24:00 +10:00
Kim Morrison
b277f3a402 yay 2025-06-21 14:18:55 +10:00
Kim Morrison
7563199ccc fix merge 2025-06-21 13:26:10 +10:00
Kim Morrison
42882ce465 merge grind_no_nat_div 2025-06-21 13:17:04 +10:00
Kim Morrison
f20d0e4532 merge master 2025-06-21 13:14:25 +10:00
Leonardo de Moura
9ece4e463a refactor: NoNatZeroDivisors (#8909)
This PR refactors the `NoNatZeroDivisors` to make sure it will work with
the new `Semiring` support.
2025-06-21 03:01:05 +00:00
Sebastian Ullrich
c38c0898a3 chore: allow module in tests (#8881)
This PR adjusts the test scripts and adds a simple test-only lakefile so
that `experimental.module` is set both when editing and running tests.
2025-06-21 02:49:22 +00:00
Leonardo de Moura
070e622f05 refactor: NoNatZeroDivisors
This PR refactors the `NoNatZeroDivisors` to make sure it will work
with the new `Semiring` support.
2025-06-21 11:47:35 +09:00
Leonardo de Moura
12a8f1b5f8 chore: remove staging workarounds (#8908) 2025-06-21 02:38:09 +00:00
Lean stage0 autoupdater
7050dc6d38 chore: update stage0 2025-06-21 01:59:13 +00:00
Kim Morrison
376ae32c7c feat: fix pretty printing of grind attributes (#8892)
This PR corrects the pretty printing of `grind` modifiers. Previously
`@[grind →]` was being pretty printed as `@[grind→ ]` (Space on the
right of the symbol, rather than left.) This fixes the pretty printing
of attributes, and preserves the presence of spaces after the symbol in
the output of `grind?`.

---------

Co-authored-by: Leonardo de Moura <leomoura@amazon.com>
2025-06-21 00:50:25 +00:00
Cameron Zwarich
0c44aab811 chore: add a test for #4716, which is fixed by the new compiler (#8907) 2025-06-20 23:43:25 +00:00
Kim Morrison
a5eeed4f2c chore: a few missing grind typeclass docstrings (#8906) 2025-06-20 23:35:58 +00:00
Joachim Breitner
be80a23281 chore: remove unused simp args (#8905)
This PR uses the linter from
https://github.com/leanprover/lean4/pull/8901 to clean up simp
arguments.
2025-06-20 22:34:30 +00:00
Sebastian Ullrich
92ac564f3c fix: make mkHCongrWithArityForConst? compatible with parallelism (#8899)
This PR ensures the helper is compatible with using `grind` in
asynchronous proofs
2025-06-20 21:55:14 +00:00
Cameron Zwarich
0fcb6495d6 chore: add a test for #6957, fixed by the new compiler (#8904) 2025-06-20 21:44:09 +00:00
Lean stage0 autoupdater
e7c8baaef5 chore: update stage0 2025-06-20 18:52:57 +00:00
Cameron Zwarich
8d8c73416a chore: add a test for #2602, which was fixed by the new compiler (#8902) 2025-06-20 17:37:19 +00:00
Sebastian Graf
cf527e05bd feat: where ... finally section to assign leftover goals (#8723)
This PR implements a `finally` section following a (potentially empty)
`where` block. `where ... finally` opens a tactic sequence block in
which the goals are the unassigned metavariables from the definition
body and its auxiliary definitions that arise from use of `let rec` and
`where`.

This can be useful for discharging multiple proof obligations in the
definition body by a single invocation of a tactic such as `all_goals`:
```lean
example (i j : Nat) (xs : Array Nat) (hi : i < xs.size) (hj: j < xs.size) :=
  match i with
  | 0 => x
  | _ => xs[i]'?_ + xs[j]'?_
where x := 13
finally all_goals assumption
```

---------

Co-authored-by: Sebastian Graf <sg@lean-fro.org>
2025-06-20 15:51:28 +00:00
Sebastian Graf
61ee83f73b feat: Upstream MPL.SPred.* from mpl (#8745)
This PR adds a logic of stateful predicates `SPred` to `Std.Do` in order
to support reasoning about monadic programs. It comes with a dedicated
proof mode the tactics of which are accessible by importing
`Std.Tactic.Do`.

Co-authored-by: Sebastian Graf <sg@lean-fro.org>
2025-06-20 15:13:40 +00:00
Cameron Zwarich
26b7e49c05 chore: update stage0 2025-06-20 17:29:10 +02:00
Cameron Zwarich
466c9b56ba chore: add new tests for noncomputable 2025-06-20 17:29:10 +02:00
Cameron Zwarich
00474e17ff chore: add an extra test case to lean/run/noncomp.lean 2025-06-20 17:29:10 +02:00
Cameron Zwarich
891a2c6590 chore: reenable subset of new-compiler tests and delete others 2025-06-20 17:29:10 +02:00
Cameron Zwarich
d489c6196c chore: update expected test outputs
This makes it easier to distinguish tests that are actually
failing while we work on the new codegen.
2025-06-20 17:29:10 +02:00
Cameron Zwarich
6703af1ea0 chore: rename closed term suffix from _closedTerm to _closed
The longer name was chosen to avoid clashes with the old compiler.
2025-06-20 17:29:10 +02:00
Cameron Zwarich
7f8ccd8425 feat: enable the new compiler 2025-06-20 17:29:10 +02:00
Kim Morrison
4ce18249d3 Merge branch 'IntModule_refactor' of github.com:leanprover/lean4 into IntModule_refactor 2025-06-20 18:14:31 +10:00
Kim Morrison
1e69d88d6f merge master 2025-06-20 16:36:29 +10:00
Kim Morrison
c5ca9aa87c merge documentation PR 2025-06-20 13:56:09 +10:00
Kim Morrison
28f89c0567 feat: add doc-string to grind algebra typeclasses 2025-06-20 13:42:29 +10:00
Kim Morrison
e6b5c45e04 Merge remote-tracking branch 'origin/master' into IntModule_refactor 2025-06-20 09:36:45 +10:00
Kim Morrison
3710e4f176 fix 2025-06-19 21:05:15 +10:00
Kim Morrison
ec9865dbd5 fix proof 2025-06-19 18:41:44 +10:00
Kim Morrison
a2b03b3efd merge master 2025-06-19 17:23:32 +10:00
Kim Morrison
42eb3bb4b5 fix 2025-06-19 09:57:30 +10:00
Kim Morrison
f3f932ae8c oops 2025-06-19 09:52:53 +10:00
Kim Morrison
6c6a058beb fix 2025-06-19 09:39:05 +10:00
Kim Morrison
04113f2be5 Merge remote-tracking branch 'origin/master' into IntModule_refactor 2025-06-19 09:35:37 +10:00
Kim Morrison
2b393a3b88 no_int_zero_divisors 2025-06-19 09:35:28 +10:00
Kim Morrison
e1ecc150e3 rfl 2025-06-18 18:22:49 +10:00
Kim Morrison
76fcd276c6 merge master 2025-06-18 18:20:30 +10:00
Kim Morrison
705769f466 hrmm 2025-06-18 15:25:02 +10:00
Kim Morrison
cd346a360e more 2025-06-18 15:09:37 +10:00
Kim Morrison
cfa38b055b chore: refactor of Lean.Grind.IntModule.IsOrdered 2025-06-18 14:23:28 +10:00
Kim Morrison
e9086533ed step1 2025-06-18 14:09:18 +10:00
1647 changed files with 4514 additions and 1114 deletions

1
.gitignore vendored
View File

@@ -6,7 +6,6 @@
lake-manifest.json
/build
/src/lakefile.toml
/tests/lakefile.toml
/lakefile.toml
GPATH
GRTAGS

View File

@@ -45,7 +45,7 @@ theorem em (p : Prop) : p ¬p :=
| Or.inr h, _ => Or.inr h
| _, Or.inr h => Or.inr h
| Or.inl hut, Or.inl hvf =>
have hne : u v := by simp [hvf, hut, true_ne_false]
have hne : u v := by simp [hvf, hut]
Or.inl hne
have p_implies_uv : p u = v :=
fun hp =>

View File

@@ -50,7 +50,7 @@ attribute [simp] id_map
(comp_map _ _ _).symm
theorem Functor.map_unit [Functor f] [LawfulFunctor f] {a : f PUnit} : (fun _ => PUnit.unit) <$> a = a := by
simp [map]
simp
/--
An applicative functor satisfies the laws of an applicative functor.

View File

@@ -67,7 +67,7 @@ protected theorem seqLeft_eq {α β ε : Type u} {m : Type u → Type v} [Monad
| Except.error _ => simp
| Except.ok _ =>
simp [bind_pure_comp]; apply bind_congr; intro b;
cases b <;> simp [comp, Except.map, const]
cases b <;> simp [Except.map, const]
protected theorem seqRight_eq [Monad m] [LawfulMonad m] (x : ExceptT ε m α) (y : ExceptT ε m β) : x *> y = const α id <$> x <*> y := by
change (x >>= fun _ => y) = (const α id <$> x) >>= fun f => f <$> y

View File

@@ -209,7 +209,7 @@ theorem Context.evalList_sort_congr
induction c generalizing a b with
| nil => simp [sort.loop, h₂]
| cons c _ ih =>
simp [sort.loop]; apply ih; simp [evalList_insert ctx h, evalList]
simp [sort.loop]; apply ih; simp [evalList_insert ctx h]
cases a with
| nil => apply absurd h₃; simp
| cons a as =>
@@ -282,7 +282,7 @@ theorem Context.toList_nonEmpty (e : Expr) : e.toList ≠ [] := by
simp [Expr.toList]
cases h : l.toList with
| nil => contradiction
| cons => simp [List.append]
| cons => simp
theorem Context.unwrap_isNeutral
{ctx : Context α}
@@ -328,13 +328,13 @@ theorem Context.eval_toList (ctx : Context α) (e : Expr) : evalList α ctx e.to
induction e with
| var x => rfl
| op l r ih₁ ih₂ =>
simp [evalList, Expr.toList, eval, ih₁, ih₂]
simp [Expr.toList, eval, ih₁, ih₂]
apply evalList_append <;> apply toList_nonEmpty
theorem Context.eval_norm (ctx : Context α) (e : Expr) : evalList α ctx (norm ctx e) = eval α ctx e := by
simp [norm]
cases h₁ : ContextInformation.isIdem ctx <;> cases h₂ : ContextInformation.isComm ctx <;>
simp_all [evalList_removeNeutrals, eval_toList, toList_nonEmpty, evalList_mergeIdem, evalList_sort]
simp_all [evalList_removeNeutrals, eval_toList, evalList_mergeIdem, evalList_sort]
theorem Context.eq_of_norm (ctx : Context α) (a b : Expr) (h : norm ctx a == norm ctx b) : eval α ctx a = eval α ctx b := by
have h := congrArg (evalList α ctx) (eq_of_beq h)

View File

@@ -155,7 +155,7 @@ theorem attachWith_congr {xs ys : Array α} (w : xs = ys) {P : α → Prop} {H :
(xs.push a).attachWith P H =
(xs.attachWith P (fun x h => by simp at H; exact H x (.inl h))).push a, H a (by simp) := by
cases xs
simp [attachWith_congr (List.push_toArray _ _)]
simp
theorem pmap_eq_map_attach {p : α Prop} {f : a, p a β} {xs : Array α} (H) :
pmap f xs H = xs.attach.map fun x => f x.1 (H _ x.2) := by
@@ -342,7 +342,7 @@ theorem foldl_attach {xs : Array α} {f : β → α → β} {b : β} :
xs.attach.foldl (fun acc t => f acc t.1) b = xs.foldl f b := by
rcases xs with xs
simp only [List.attach_toArray, List.attachWith_mem_toArray, List.size_toArray,
List.length_pmap, List.foldl_toArray', mem_toArray, List.foldl_subtype]
List.foldl_toArray', mem_toArray, List.foldl_subtype]
congr
ext
simpa using fun a => List.mem_of_getElem? a
@@ -361,7 +361,7 @@ theorem foldr_attach {xs : Array α} {f : α → β → β} {b : β} :
xs.attach.foldr (fun t acc => f t.1 acc) b = xs.foldr f b := by
rcases xs with xs
simp only [List.attach_toArray, List.attachWith_mem_toArray, List.size_toArray,
List.length_pmap, List.foldr_toArray', mem_toArray, List.foldr_subtype]
List.foldr_toArray', mem_toArray, List.foldr_subtype]
congr
ext
simpa using fun a => List.mem_of_getElem? a
@@ -470,7 +470,7 @@ theorem pmap_append' {p : α → Prop} {f : ∀ a : α, p a → β} {xs ys : Arr
{H : (a : α), a xs ++ ys P a} :
(xs ++ ys).attachWith P H = xs.attachWith P (fun a h => H a (mem_append_left ys h)) ++
ys.attachWith P (fun a h => H a (mem_append_right xs h)) := by
simp [attachWith, attach_append, map_pmap, pmap_append]
simp [attachWith]
@[simp, grind =] theorem pmap_reverse {P : α Prop} {f : (a : α) P a β} {xs : Array α}
(H : (a : α), a xs.reverse P a) :
@@ -703,7 +703,7 @@ and simplifies these to the function directly taking the value.
{f : { x // p x } Array β} {g : α Array β} (hf : x h, f x, h = g x) :
(xs.flatMap f) = xs.unattach.flatMap g := by
cases xs
simp only [List.size_toArray, List.flatMap_toArray, List.unattach_toArray, List.length_unattach,
simp only [List.flatMap_toArray, List.unattach_toArray,
mk.injEq]
rw [List.flatMap_subtype]
simp [hf]

View File

@@ -1788,7 +1788,7 @@ decreasing_by simp_wf; exact Nat.sub_succ_lt_self _ _ h
induction xs, i, h using Array.eraseIdx.induct with
| @case1 xs i h h' xs' ih =>
unfold eraseIdx
simp +zetaDelta [h', xs', ih]
simp +zetaDelta [h', ih]
| case2 xs i h h' =>
unfold eraseIdx
simp [h']

View File

@@ -119,13 +119,13 @@ abbrev pop_toList := @Array.toList_pop
@[simp] theorem toList_empty : (#[] : Array α).toList = [] := rfl
@[simp, grind =] theorem append_empty {xs : Array α} : xs ++ #[] = xs := by
apply ext'; simp only [toList_append, toList_empty, List.append_nil]
apply ext'; simp only [toList_append, List.append_nil]
@[deprecated append_empty (since := "2025-01-13")]
abbrev append_nil := @append_empty
@[simp, grind =] theorem empty_append {xs : Array α} : #[] ++ xs = xs := by
apply ext'; simp only [toList_append, toList_empty, List.nil_append]
apply ext'; simp only [toList_append, List.nil_append]
@[deprecated empty_append (since := "2025-01-13")]
abbrev nil_append := @empty_append

View File

@@ -223,7 +223,7 @@ theorem boole_getElem_le_count {xs : Array α} {i : Nat} {a : α} (h : i < xs.si
@[grind =]
theorem count_set {xs : Array α} {i : Nat} {a b : α} (h : i < xs.size) :
(xs.set i a).count b = xs.count b - (if xs[i] == b then 1 else 0) + (if a == b then 1 else 0) := by
simp [count_eq_countP, countP_set, h]
simp [count_eq_countP, countP_set]
variable [LawfulBEq α]
@@ -231,7 +231,7 @@ variable [LawfulBEq α]
simp [count_push]
@[simp] theorem count_push_of_ne {xs : Array α} (h : b a) : count a (xs.push b) = count a xs := by
simp_all [count_push, h]
simp_all [count_push]
theorem count_singleton_self {a : α} : count a #[a] = 1 := by simp
@@ -292,17 +292,17 @@ abbrev mkArray_count_eq_of_count_eq_size := @replicate_count_eq_of_count_eq_size
theorem count_le_count_map [BEq β] [LawfulBEq β] {xs : Array α} {f : α β} {x : α} :
count x xs count (f x) (map f xs) := by
rcases xs with xs
simp [List.count_le_count_map, countP_map]
simp [List.count_le_count_map]
theorem count_filterMap {α} [BEq β] {b : β} {f : α Option β} {xs : Array α} :
count b (filterMap f xs) = countP (fun a => f a == some b) xs := by
rcases xs with xs
simp [List.count_filterMap, countP_filterMap]
simp [List.count_filterMap]
theorem count_flatMap {α} [BEq β] {xs : Array α} {f : α Array β} {x : β} :
count x (xs.flatMap f) = sum (map (count x f) xs) := by
rcases xs with xs
simp [List.count_flatMap, countP_flatMap, Function.comp_def]
simp [List.count_flatMap, Function.comp_def]
theorem countP_replace {a b : α} {xs : Array α} {p : α Bool} :
(xs.replace a b).countP p =

View File

@@ -23,7 +23,7 @@ private theorem rel_of_isEqvAux
induction i with
| zero => contradiction
| succ i ih =>
simp only [Array.isEqvAux, Bool.and_eq_true, decide_eq_true_eq] at heqv
simp only [Array.isEqvAux, Bool.and_eq_true] at heqv
by_cases hj' : j < i
next =>
exact ih _ heqv.right hj'

View File

@@ -206,7 +206,7 @@ theorem erase_eq_eraseP [LawfulBEq α] (a : α) (xs : Array α) : xs.erase a = x
theorem erase_ne_empty_iff [LawfulBEq α] {xs : Array α} {a : α} :
xs.erase a #[] xs #[] xs #[a] := by
rcases xs with xs
simp [List.erase_ne_nil_iff]
simp
theorem exists_erase_eq [LawfulBEq α] {a : α} {xs : Array α} (h : a xs) :
ys zs, a ys xs = ys.push a ++ zs xs.erase a = ys ++ zs := by
@@ -306,7 +306,7 @@ theorem erase_eq_iff [LawfulBEq α] {a : α} {xs : Array α} :
@[simp] theorem erase_replicate_self [LawfulBEq α] {a : α} :
(replicate n a).erase a = replicate (n - 1) a := by
simp only [ List.toArray_replicate, List.erase_toArray]
simp [List.erase_replicate]
simp
@[deprecated erase_replicate_self (since := "2025-03-18")]
abbrev erase_mkArray_self := @erase_replicate_self
@@ -352,7 +352,7 @@ theorem getElem?_eraseIdx_of_lt {xs : Array α} {i : Nat} (h : i < xs.size) {j :
theorem getElem?_eraseIdx_of_ge {xs : Array α} {i : Nat} (h : i < xs.size) {j : Nat} (h' : i j) :
(xs.eraseIdx i)[j]? = xs[j + 1]? := by
rw [getElem?_eraseIdx]
simp only [dite_eq_ite, ite_eq_right_iff]
simp only [ite_eq_right_iff]
intro h'
omega

View File

@@ -29,7 +29,7 @@ namespace Array
· simp
omega
· simp only [size_extract] at h₁ h₂
simp [h]
simp
theorem size_extract_le {as : Array α} {i j : Nat} :
(as.extract i j).size j - i := by
@@ -162,7 +162,7 @@ theorem extract_sub_one {as : Array α} {i j : Nat} (h : j < as.size) :
@[simp]
theorem getElem?_extract_of_lt {as : Array α} {i j k : Nat} (h : k < min j as.size - i) :
(as.extract i j)[k]? = some (as[i + k]'(by omega)) := by
simp [getElem?_extract, h]
simp [h]
theorem getElem?_extract_of_succ {as : Array α} {j : Nat} :
(as.extract 0 (j + 1))[j]? = as[j]? := by

View File

@@ -81,7 +81,7 @@ theorem find?_eq_findSome?_guard {xs : Array α} : find? p xs = findSome? (Optio
@[simp, grind =] theorem getElem_zero_filterMap {f : α Option β} {xs : Array α} (h) :
(xs.filterMap f)[0] = (xs.findSome? f).get (by cases xs; simpa [List.length_filterMap_eq_countP] using h) := by
cases xs; simp [ List.head_eq_getElem, getElem?_zero_filterMap]
cases xs; simp [ getElem?_zero_filterMap]
@[simp, grind =] theorem back?_filterMap {f : α Option β} {xs : Array α} : (xs.filterMap f).back? = xs.findSomeRev? f := by
cases xs; simp
@@ -122,7 +122,7 @@ theorem getElem_zero_flatten.proof {xss : Array (Array α)} (h : 0 < xss.flatten
theorem getElem_zero_flatten {xss : Array (Array α)} (h) :
(flatten xss)[0] = (xss.findSome? fun xs => xs[0]?).get (getElem_zero_flatten.proof h) := by
have t := getElem?_zero_flatten xss
simp [getElem?_eq_getElem, h] at t
simp at t
simp [ t]
@[grind =]
@@ -308,7 +308,7 @@ abbrev find?_flatten_eq_some := @find?_flatten_eq_some_iff
@[simp, grind =] theorem find?_flatMap {xs : Array α} {f : α Array β} {p : β Bool} :
(xs.flatMap f).find? p = xs.findSome? (fun x => (f x).find? p) := by
cases xs
simp [List.find?_flatMap, Array.flatMap_toArray]
simp [List.find?_flatMap]
theorem find?_flatMap_eq_none_iff {xs : Array α} {f : α Array β} {p : β Bool} :
(xs.flatMap f).find? p = none x xs, y f x, !p y := by
@@ -348,7 +348,7 @@ abbrev find?_mkArray_of_neg := @find?_replicate_of_neg
-- This isn't a `@[simp]` lemma since there is already a lemma for `l.find? p = none` for any `l`.
theorem find?_replicate_eq_none_iff {n : Nat} {a : α} {p : α Bool} :
(replicate n a).find? p = none n = 0 !p a := by
simp [ List.toArray_replicate, List.find?_replicate_eq_none_iff, Classical.or_iff_not_imp_left]
simp [ List.toArray_replicate, Classical.or_iff_not_imp_left]
@[deprecated find?_replicate_eq_none_iff (since := "2025-03-18")]
abbrev find?_mkArray_eq_none_iff := @find?_replicate_eq_none_iff
@@ -488,7 +488,7 @@ theorem findIdx_push {xs : Array α} {a : α} {p : α → Bool} :
simp only [push_eq_append, findIdx_append]
split <;> rename_i h
· rfl
· simp [findIdx_singleton, Nat.add_comm]
· simp [Nat.add_comm]
theorem findIdx_le_findIdx {xs : Array α} {p q : α Bool} (h : x xs, p x q x) : xs.findIdx q xs.findIdx p := by
rcases xs with xs
@@ -553,7 +553,7 @@ theorem findIdx?_eq_some_of_exists {xs : Array α} {p : α → Bool} (h : ∃ x,
theorem findIdx?_eq_none_iff_findIdx_eq {xs : Array α} {p : α Bool} :
xs.findIdx? p = none xs.findIdx p = xs.size := by
rcases xs with xs
simp [List.findIdx?_eq_none_iff_findIdx_eq]
simp
theorem findIdx?_eq_guard_findIdx_lt {xs : Array α} {p : α Bool} :
xs.findIdx? p = Option.guard (fun i => i < xs.size) (xs.findIdx p) := by
@@ -798,7 +798,7 @@ The lemmas below should be made consistent with those for `findFinIdx?` (and pro
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 [idxOf?, finIdxOf?]
@[grind =] theorem finIdxOf?_empty [BEq α] : (#[] : Array α).finIdxOf? a = none := by simp

View File

@@ -109,19 +109,19 @@ theorem getElem_insertIdx {xs : Array α} {x : α} {i k : Nat} (w : i ≤ xs.siz
else
xs[k-1]'(by simp [size_insertIdx] at h; omega) := by
cases xs
simp [List.getElem_insertIdx, w]
simp [List.getElem_insertIdx]
theorem getElem_insertIdx_of_lt {xs : Array α} {x : α} {i k : Nat} (w : i xs.size) (h : k < i) :
(xs.insertIdx i x)[k]'(by simp; omega) = xs[k] := by
simp [getElem_insertIdx, w, h]
simp [getElem_insertIdx, h]
theorem getElem_insertIdx_self {xs : Array α} {x : α} {i : Nat} (w : i xs.size) :
(xs.insertIdx i x)[i]'(by simp; omega) = x := by
simp [getElem_insertIdx, w]
simp [getElem_insertIdx]
theorem getElem_insertIdx_of_gt {xs : Array α} {x : α} {i k : Nat} (w : k xs.size) (h : k > i) :
(xs.insertIdx i x)[k]'(by simp; omega) = xs[k - 1]'(by omega) := by
simp [getElem_insertIdx, w, h]
simp [getElem_insertIdx]
rw [dif_neg (by omega), dif_neg (by omega)]
@[grind =]
@@ -135,7 +135,7 @@ theorem getElem?_insertIdx {xs : Array α} {x : α} {i k : Nat} (h : i ≤ xs.si
else
xs[k-1]? := by
cases xs
simp [List.getElem?_insertIdx, h]
simp [List.getElem?_insertIdx]
theorem getElem?_insertIdx_of_lt {xs : Array α} {x : α} {i k : Nat} (w : i xs.size) (h : k < i) :
(xs.insertIdx i x)[k]? = xs[k]? := by

View File

@@ -125,7 +125,7 @@ theorem none_eq_getElem?_iff {xs : Array α} {i : Nat} : none = xs[i]? ↔ xs.si
simp
theorem getElem?_eq_none {xs : Array α} (h : xs.size i) : xs[i]? = none := by
simp [getElem?_eq_none_iff, h]
simp [h]
grind_pattern Array.getElem?_eq_none => xs.size i, xs[i]?
@@ -154,16 +154,16 @@ theorem getElem_eq_iff {xs : Array α} {i : Nat} {h : i < xs.size} : xs[i] = x
exact fun w => h, w, fun h => h.2
theorem getElem_eq_getElem?_get {xs : Array α} {i : Nat} (h : i < xs.size) :
xs[i] = xs[i]?.get (by simp [getElem?_eq_getElem, h]) := by
simp [getElem_eq_iff]
xs[i] = xs[i]?.get (by simp [h]) := by
simp
theorem getD_getElem? {xs : Array α} {i : Nat} {d : α} :
xs[i]?.getD d = if p : i < xs.size then xs[i]'p else d := by
if h : i < xs.size then
simp [h, getElem?_def]
simp [h]
else
have p : i xs.size := Nat.le_of_not_gt h
simp [getElem?_eq_none p, h]
simp [h]
@[simp] theorem getElem?_empty {i : Nat} : (#[] : Array α)[i]? = none := rfl
@@ -175,14 +175,14 @@ theorem getElem_push_lt {xs : Array α} {x : α} {i : Nat} (h : i < xs.size) :
@[simp] theorem getElem_push_eq {xs : Array α} {x : α} : (xs.push x)[xs.size] = x := by
simp only [push, getElem_toList, List.concat_eq_append]
rw [List.getElem_append_right] <;> simp [ getElem_toList, Nat.zero_lt_one]
rw [List.getElem_append_right] <;> simp
@[grind =] theorem getElem_push {xs : Array α} {x : α} {i : Nat} (h : i < (xs.push x).size) :
(xs.push x)[i] = if h : i < xs.size then xs[i] else x := by
by_cases h' : i < xs.size
· simp [getElem_push_lt, h']
· simp at h
simp [getElem_push_lt, Nat.le_antisymm (Nat.le_of_lt_succ h) (Nat.ge_of_not_lt h')]
simp [Nat.le_antisymm (Nat.le_of_lt_succ h) (Nat.ge_of_not_lt h')]
@[grind =] theorem getElem?_push {xs : Array α} {x} : (xs.push x)[i]? = if i = xs.size then some x else xs[i]? := by
simp [getElem?_def, getElem_push]
@@ -906,7 +906,7 @@ theorem all_push [BEq α] {xs : Array α} {a : α} {p : α → Bool} :
abbrev getElem_set_eq := @getElem_set_self
@[simp] theorem getElem?_set_self {xs : Array α} {i : Nat} (h : i < xs.size) {v : α} :
(xs.set i v)[i]? = some v := by simp [getElem?_eq_getElem, h]
(xs.set i v)[i]? = some v := by simp [h]
@[deprecated getElem?_set_self (since := "2024-12-11")]
abbrev getElem?_set_eq := @getElem?_set_self
@@ -918,7 +918,7 @@ abbrev getElem?_set_eq := @getElem?_set_self
@[simp] theorem getElem?_set_ne {xs : Array α} {i : Nat} (h : i < xs.size) {v : α} {j : Nat}
(ne : i j) : (xs.set i v)[j]? = xs[j]? := by
by_cases h : j < xs.size <;> simp [getElem?_eq_getElem, getElem?_eq_none, Nat.ge_of_not_lt, ne, h]
by_cases h : j < xs.size <;> simp [ne, h]
@[grind] theorem getElem_set {xs : Array α} {i : Nat} (h' : i < xs.size) {v : α} {j : Nat}
(h : j < (xs.set i v).size) :
@@ -1044,7 +1044,7 @@ theorem getElem?_setIfInBounds_self {xs : Array α} {i : Nat} {a : α} :
@[simp]
theorem getElem?_setIfInBounds_self_of_lt {xs : Array α} {i : Nat} {a : α} (h : i < xs.size) :
(xs.setIfInBounds i a)[i]? = some a := by
simp [getElem?_setIfInBounds, h]
simp [h]
@[deprecated getElem?_setIfInBounds_self (since := "2024-12-11")]
abbrev getElem?_setIfInBounds_eq := @getElem?_setIfInBounds_self
@@ -1088,7 +1088,7 @@ theorem mem_or_eq_of_mem_setIfInBounds
@[simp] theorem getD_getElem?_setIfInBounds {xs : Array α} {i : Nat} {v d : α} :
(xs.setIfInBounds i v)[i]?.getD d = if i < xs.size then v else d := by
by_cases h : i < xs.size <;>
simp [setIfInBounds, Nat.not_lt_of_le, h, getD_getElem?]
simp [setIfInBounds, h, ]
@[simp, grind =] theorem toList_setIfInBounds {xs : Array α} {i : Nat} {x : α} :
(xs.setIfInBounds i x).toList = xs.toList.set i x := by
@@ -1200,7 +1200,7 @@ where
mapM.map f xs i bs = (xs.toList.drop i).foldlM (fun bs a => bs.push <$> f a) bs := by
unfold mapM.map; split
· rw [ List.getElem_cons_drop_succ_eq_drop _]
simp only [aux (i + 1), map_eq_pure_bind, length_toList, List.foldlM_cons, bind_assoc,
simp only [aux (i + 1), map_eq_pure_bind, List.foldlM_cons, bind_assoc,
pure_bind]
rfl
· rw [List.drop_of_length_le (Nat.ge_of_not_lt _)]; rfl
@@ -1755,7 +1755,7 @@ theorem forall_mem_filterMap {f : α → Option β} {xs : Array α} {P : β →
theorem map_filterMap_of_inv {f : α Option β} {g : β α} (H : x : α, (f x).map g = some x) {xs : Array α} :
map g (filterMap f xs) = xs := by
simp only [map_filterMap, H, filterMap_some, id]
simp only [map_filterMap, H, filterMap_some]
@[grind ]
theorem forall_none_of_filterMap_eq_empty (h : filterMap f xs = #[]) : x xs, f x = none := by
@@ -1894,7 +1894,7 @@ theorem getElem?_append_left {xs ys : Array α} {i : Nat} (hn : i < xs.size) :
(xs ++ ys)[i]? = xs[i]? := by
have hn' : i < (xs ++ ys).size := Nat.lt_of_lt_of_le hn <|
size_append .. Nat.le_add_right ..
simp_all [getElem?_eq_getElem, getElem_append]
simp_all
theorem getElem?_append_right {xs ys : Array α} {i : Nat} (h : xs.size i) :
(xs ++ ys)[i]? = ys[i - xs.size]? := by
@@ -2025,7 +2025,7 @@ theorem append_eq_singleton_iff {xs ys : Array α} {x : α} :
xs ++ ys = #[x] (xs = #[] ys = #[x]) (xs = #[x] ys = #[]) := by
rcases xs with xs
rcases ys with ys
simp only [List.append_toArray, mk.injEq, List.append_eq_singleton_iff, toArray_eq_append_iff]
simp only [List.append_toArray, mk.injEq, List.append_eq_singleton_iff]
theorem singleton_eq_append_iff {xs ys : Array α} {x : α} :
#[x] = xs ++ ys (xs = #[] ys = #[x]) (xs = #[x] ys = #[]) := by
@@ -2351,7 +2351,7 @@ theorem flatMap_toArray {β} {f : α → Array β} {as : List α} :
theorem size_flatMap {xs : Array α} {f : α Array β} :
(xs.flatMap f).size = sum (map (fun a => (f a).size) xs) := by
rcases xs with l
simp [Function.comp_def]
simp
@[simp, grind] theorem mem_flatMap {f : α Array β} {b} {xs : Array α} : b xs.flatMap f a, a xs b f a := by
simp [flatMap_def, mem_flatten]
@@ -2569,7 +2569,7 @@ abbrev map_mkArray := @map_replicate
@[grind] theorem filter_replicate (w : stop = n) :
(replicate n a).filter p 0 stop = if p a then replicate n a else #[] := by
apply Array.ext'
simp only [w, toList_filter', toList_replicate, List.filter_replicate]
simp only [w]
split <;> simp_all
@[deprecated filter_replicate (since := "2025-03-18")]
@@ -2609,7 +2609,7 @@ abbrev filterMap_mkArray_of_some := @filterMap_replicate_of_some
@[simp] theorem filterMap_replicate_of_isSome {f : α Option β} (h : (f a).isSome) :
(replicate n a).filterMap f = replicate n (Option.get _ h) := by
match w : f a, h with
| some b, _ => simp [filterMap_replicate, h, w]
| some b, _ => simp [filterMap_replicate, w]
@[deprecated filterMap_replicate_of_isSome (since := "2025-03-18")]
abbrev filterMap_mkArray_of_isSome := @filterMap_replicate_of_isSome
@@ -2644,7 +2644,7 @@ abbrev flatten_mkArray_replicate := @flatten_replicate_replicate
theorem flatMap_replicate {f : α Array β} : (replicate n a).flatMap f = (replicate n (f a)).flatten := by
rw [ toList_inj]
simp [flatMap_toList, List.flatMap_replicate]
simp [List.flatMap_replicate]
@[deprecated flatMap_replicate (since := "2025-03-18")]
abbrev flatMap_mkArray := @flatMap_replicate
@@ -4142,7 +4142,7 @@ theorem getElem_modify_of_ne {xs : Array α} {i : Nat} (h : i ≠ j)
@[simp] theorem getElem_swap_right {xs : Array α} {i j : Nat} {hi hj} :
(xs.swap i j hi hj)[j]'(by simpa using hj) = xs[i] := by
simp [swap_def, getElem_set]
simp [swap_def]
@[simp] theorem getElem_swap_left {xs : Array α} {i j : Nat} {hi hj} :
(xs.swap i j hi hj)[i]'(by simpa using hi) = xs[j] := by
@@ -4439,7 +4439,7 @@ theorem size_uset {xs : Array α} {v : α} {i : USize} (h : i.toNat < xs.size) :
@[simp] theorem getD_eq_getD_getElem? {xs : Array α} {i : Nat} {d : α} :
xs.getD i d = xs[i]?.getD d := by
simp only [getD]; split <;> simp [getD_getElem?, *]
simp only [getD]; split <;> simp [*]
theorem getElem!_eq_getD [Inhabited α] {xs : Array α} {i} : xs[i]! = xs.getD i default := by
rfl
@@ -4467,13 +4467,13 @@ theorem getElem?_size_le {xs : Array α} {i : Nat} (h : xs.size ≤ i) : xs[i]?
simp [getElem?_neg, h]
theorem getElem_mem_toList {xs : Array α} {i : Nat} (h : i < xs.size) : xs[i] xs.toList := by
simp only [ getElem_toList, List.getElem_mem, ugetElem_eq_getElem]
simp only [ getElem_toList, List.getElem_mem]
theorem back!_eq_back? [Inhabited α] {xs : Array α} : xs.back! = xs.back?.getD default := by
simp [back!, back?, getElem!_def, Option.getD]; rfl
@[simp, grind] theorem back?_push {xs : Array α} {x : α} : (xs.push x).back? = some x := by
simp [back?, getElem?_toList]
simp [back?]
@[simp] theorem back!_push [Inhabited α] {xs : Array α} {x : α} : (xs.push x).back! = x := by
simp [back!_eq_back?]
@@ -4622,7 +4622,7 @@ theorem uset_toArray {l : List α} {i : USize} {a : α} {h : i.toNat < l.toArray
@[simp, grind =] theorem flatten_toArray {L : List (List α)} :
(L.toArray.map List.toArray).flatten = L.flatten.toArray := by
apply ext'
simp [Function.comp_def]
simp
end List
@@ -4714,7 +4714,7 @@ namespace List
intro h'
specialize ih (by omega)
have : as.length - (i + 1) + 1 = as.length - i := by omega
simp_all [ih]
simp_all
· simp only [size_toArray, Nat.not_lt] at h
have : as.length = 0 := by omega
simp_all
@@ -4741,7 +4741,7 @@ theorem get?_eq_getElem? (xs : Array α) (i : Nat) : xs.get? i = xs[i]? := rfl
@[deprecated getElem?_eq_none (since := "2024-12-11")]
theorem getElem?_len_le (xs : Array α) {i : Nat} (h : xs.size i) : xs[i]? = none := by
simp [getElem?_eq_none, h]
simp [h]
@[deprecated getD_getElem? (since := "2024-12-11")] abbrev getD_get? := @getD_getElem?
@@ -4756,7 +4756,7 @@ set_option linter.deprecated false in
theorem get!_eq_getD_getElem? [Inhabited α] (xs : Array α) (i : Nat) :
xs.get! i = xs[i]?.getD default := by
by_cases p : i < xs.size <;>
simp [get!, getElem!_eq_getD, getD_eq_getD_getElem?, getD_getElem?, p]
simp [get!, getD_eq_getD_getElem?, p]
set_option linter.deprecated false in
@[deprecated get!_eq_getD_getElem? (since := "2025-02-12")] abbrev get!_eq_getElem? := @get!_eq_getD_getElem?

View File

@@ -162,7 +162,7 @@ instance [DecidableEq α] [LT α] [DecidableLT α]
{xs ys : Array α} : lex xs ys = false ys xs := by
cases xs
cases ys
simp [List.not_lt_iff_ge]
simp
instance [DecidableEq α] [LT α] [DecidableLT α] : DecidableLT (Array α) :=
fun xs ys => decidable_of_iff (lex xs ys = true) lex_eq_true_iff_lt

View File

@@ -135,7 +135,7 @@ abbrev getElem_zipWithIndex := @getElem_zipIdx
@[simp, grind =] theorem zipIdx_toArray {l : List α} {k : Nat} :
l.toArray.zipIdx k = (l.zipIdx k).toArray := by
ext i hi₁ hi₂ <;> simp [Nat.add_comm]
ext i hi₁ hi₂ <;> simp
@[deprecated zipIdx_toArray (since := "2025-01-21")]
abbrev zipWithIndex_toArray := @zipIdx_toArray

View File

@@ -59,7 +59,7 @@ theorem mapM_eq_foldlM_push [Monad m] [LawfulMonad m] {f : α → m β} {xs : Ar
rcases xs with xs
simp only [List.mapM_toArray, bind_pure_comp, List.size_toArray, List.foldlM_toArray']
rw [List.mapM_eq_reverse_foldlM_cons]
simp only [bind_pure_comp, Functor.map_map]
simp only [Functor.map_map]
suffices (l), (fun l' => l'.reverse.toArray) <$> List.foldlM (fun acc a => (fun a => a :: acc) <$> f a) l xs =
List.foldlM (fun acc a => acc.push <$> f a) l.reverse.toArray xs by
exact this []
@@ -234,14 +234,14 @@ theorem forIn_eq_foldlM [Monad m] [LawfulMonad m]
forIn xs init (fun a b => (fun c => .yield (g a b c)) <$> f a b) =
xs.foldlM (fun b a => g a b <$> f a b) init := by
rcases xs with xs
simp [List.foldlM_map]
simp
@[simp] theorem forIn_pure_yield_eq_foldl [Monad m] [LawfulMonad m]
{xs : Array α} (f : α β β) (init : β) :
forIn xs init (fun a b => pure (.yield (f a b))) =
pure (f := m) (xs.foldl (fun b a => f a b) init) := by
rcases xs with xs
simp [List.forIn_pure_yield_eq_foldl, List.foldl_map]
simp [List.forIn_pure_yield_eq_foldl]
theorem idRun_forIn_yield_eq_foldl
{xs : Array α} (f : α β Id β) (init : β) :

View File

@@ -219,7 +219,7 @@ theorem getElem?_zipIdx {xs : Array α} {i j} : (zipIdx xs i)[j]? = xs[j]?.map f
theorem map_snd_add_zipIdx_eq_zipIdx {xs : Array α} {n k : Nat} :
map (Prod.map id (· + n)) (zipIdx xs k) = zipIdx xs (n + k) :=
ext_getElem? fun i by simp [(· ·), Nat.add_comm, Nat.add_left_comm]; rfl
ext_getElem? fun i by simp [Nat.add_comm, Nat.add_left_comm]; rfl
-- Arguments are explicit for parity with `zipIdx_map_fst`.
@[simp]

View File

@@ -240,7 +240,7 @@ theorem toNat_add_of_and_eq_zero {x y : BitVec w} (h : x &&& y = 0#w) :
simp only [decide_eq_true_eq] at this
omega
rw [ carry_width]
simp [not_eq_true, carry_of_and_eq_zero h]
simp [carry_of_and_eq_zero h]
/-- Carry function for bitwise addition. -/
def adcb (x y c : Bool) : Bool × Bool := (atLeastTwo x y c, x ^^ (y ^^ c))
@@ -254,7 +254,7 @@ theorem getLsbD_add_add_bool {i : Nat} (i_lt : i < w) (x y : BitVec w) (c : Bool
(getLsbD x i ^^ (getLsbD y i ^^ carry i x y c)) := by
let x, x_lt := x
let y, y_lt := y
simp only [getLsbD, toNat_add, toNat_setWidth, i_lt, toNat_ofFin, toNat_ofBool,
simp only [getLsbD, toNat_add, toNat_setWidth, toNat_ofFin, toNat_ofBool,
Nat.mod_add_mod, Nat.add_mod_mod]
apply Eq.trans
rw [ Nat.div_add_mod x (2^i), Nat.div_add_mod y (2^i)]
@@ -297,7 +297,7 @@ theorem adc_spec (x y : BitVec w) (c : Bool) :
simp [carry, Nat.mod_one]
cases c <;> rfl
case step =>
simp [adcb, Prod.mk.injEq, carry_succ, getElem_add_add_bool]
simp [adcb, carry_succ, getElem_add_add_bool]
theorem add_eq_adc (w : Nat) (x y : BitVec w) : x + y = (adc x y false).snd := by
simp [adc_spec]
@@ -314,7 +314,7 @@ theorem msb_add {w : Nat} {x y: BitVec w} :
Bool.xor x.msb (Bool.xor y.msb (carry (w - 1) x y false)) := by
simp only [BitVec.msb, BitVec.getMsbD]
by_cases h : w 0
· simp [h, show w = 0 by omega]
· simp [show w = 0 by omega]
· rw [getLsbD_add (x := x)]
simp [show w > 0 by omega]
omega
@@ -334,15 +334,15 @@ theorem add_eq_or_of_and_eq_zero {w : Nat} (x y : BitVec w)
(h : x &&& y = 0#w) : x + y = x ||| y := by
rw [add_eq_adc, adc, iunfoldr_replace (fun _ => false) (x ||| y)]
· rfl
· simp only [adcb, atLeastTwo, Bool.and_false, Bool.or_false, bne_false, getLsbD_or,
· simp only [adcb, atLeastTwo, Bool.and_false, Bool.or_false, bne_false,
Prod.mk.injEq, and_eq_false_imp]
intros i
replace h : (x &&& y).getLsbD i = (0#w).getLsbD i := by rw [h]
simp only [getLsbD_and, getLsbD_zero, and_eq_false_imp] at h
constructor
· intros hx
simp_all [hx]
· by_cases hx : x.getLsbD i <;> simp_all [hx]
simp_all
· by_cases hx : x.getLsbD i <;> simp_all
/-! ### Sub-/
@@ -379,7 +379,7 @@ theorem bit_not_add_self (x : BitVec w) :
simp only [add_eq_adc]
apply iunfoldr_replace_snd (fun _ => false) (-1) false rfl
intro i; simp only [adcb, Fin.is_lt, getLsbD_eq_getElem, atLeastTwo_false_right, bne_false,
ofNat_eq_ofNat, Fin.getElem_fin, Prod.mk.injEq, and_eq_false_imp]
ofNat_eq_ofNat, Prod.mk.injEq, and_eq_false_imp]
rw [iunfoldr_replace_snd (fun _ => ()) (((iunfoldr (fun i c => (c, !(x[i.val])))) ()).snd)]
<;> simp [bit_not_testBit, neg_one_eq_allOnes, getElem_allOnes]
@@ -411,7 +411,7 @@ theorem getLsbD_neg {i : Nat} {x : BitVec w} :
· rw [getLsbD_add hi]
have : 0 < w := by omega
simp only [getLsbD_not, hi, decide_true, Bool.true_and, getLsbD_one, this, not_bne,
_root_.true_and, not_eq_eq_eq_not]
not_eq_eq_eq_not]
cases i with
| zero =>
have carry_zero : carry 0 ?x ?y false = false := by
@@ -426,7 +426,7 @@ theorem getLsbD_neg {i : Nat} {x : BitVec w} :
· rintro h j hj; exact And.right <| h j (by omega)
· rintro h j hj; exact by omega, h j (by omega)
· have h_ge : w i := by omega
simp [getLsbD_of_ge _ _ h_ge, h_ge, hi]
simp [h_ge, hi]
theorem getElem_neg {i : Nat} {x : BitVec w} (h : i < w) :
(-x)[i] = (x[i] ^^ decide ( j < i, x.getLsbD j = true)) := by
@@ -435,7 +435,7 @@ theorem getElem_neg {i : Nat} {x : BitVec w} (h : i < w) :
theorem getMsbD_neg {i : Nat} {x : BitVec w} :
getMsbD (-x) i =
(getMsbD x i ^^ decide ( j < w, i < j getMsbD x j = true)) := by
simp only [getMsbD, getLsbD_neg, Bool.decide_and, Bool.and_eq_true, decide_eq_true_eq]
simp only [getMsbD, getLsbD_neg, Bool.and_eq_true, decide_eq_true_eq]
by_cases hi : i < w
case neg =>
simp [hi]; omega
@@ -524,7 +524,7 @@ theorem msb_neg {w : Nat} {x : BitVec w} :
theorem msb_abs {w : Nat} {x : BitVec w} :
x.abs.msb = (decide (x = intMin w) && decide (0 < w)) := by
simp only [BitVec.abs, getMsbD_neg, ne_eq, decide_not, Bool.not_bne]
simp only [BitVec.abs]
by_cases h₀ : 0 < w
· by_cases h₁ : x = intMin w
· simp [h₁, msb_intMin]
@@ -611,7 +611,7 @@ theorem setWidth_setWidth_succ_eq_setWidth_setWidth_add_twoPow (x : BitVec w) (i
getElem_twoPow]
by_cases hik : i = k
· subst hik
simp [h]
simp
· by_cases hik' : k < (i + 1)
· have hik'' : k < i := by omega
simp [hik', hik'']
@@ -620,8 +620,8 @@ theorem setWidth_setWidth_succ_eq_setWidth_setWidth_add_twoPow (x : BitVec w) (i
simp [hik', hik'']
omega
· ext k
simp only [and_twoPow, getLsbD_and, getLsbD_setWidth, Fin.is_lt, decide_true, Bool.true_and,
getLsbD_zero, and_eq_false_imp, and_eq_true, decide_eq_true_eq, and_imp]
simp only [and_twoPow,
]
by_cases hi : x.getLsbD i <;> simp [hi] <;> omega
/--
@@ -778,7 +778,7 @@ private theorem Nat.div_add_eq_left_of_lt {x y z : Nat} (hx : z x) (hy : y <
· apply Nat.le_trans
· exact div_mul_le_self x z
· omega
· simp only [succ_eq_add_one, Nat.add_mul, Nat.one_mul]
· simp only [Nat.add_mul, Nat.one_mul]
apply Nat.add_lt_add_of_le_of_lt
· apply Nat.le_of_eq
exact (Nat.div_eq_iff_eq_mul_left hz hx).mp rfl
@@ -891,10 +891,10 @@ def DivModState.lawful_init {w : Nat} (args : DivModArgs w) (hd : 0#w < args.d)
hwrn := by simp only; omega,
hdPos := by assumption
hrLtDivisor := by simp [BitVec.lt_def] at hd ; assumption
hrWidth := by simp [DivModState.init],
hqWidth := by simp [DivModState.init],
hrWidth := by simp,
hqWidth := by simp,
hdiv := by
simp only [DivModState.init, toNat_ofNat, zero_mod, Nat.mul_zero, Nat.add_zero];
simp only [toNat_ofNat, zero_mod, Nat.mul_zero, Nat.add_zero];
rw [Nat.shiftRight_eq_div_pow]
apply Nat.div_eq_of_lt args.n.isLt
}
@@ -922,7 +922,7 @@ theorem DivModState.umod_eq_of_lawful {qr : DivModState w}
n % d = qr.r := by
apply umod_eq_of_mul_add_toNat h.hrLtDivisor
have hdiv := h.hdiv
simp only [shiftRight_zero] at hdiv
simp only at hdiv
simp only [h_final] at *
exact hdiv.symm
@@ -1000,7 +1000,7 @@ obeys the division equation. -/
theorem lawful_divSubtractShift (qr : DivModState w) (h : qr.Poised args) :
DivModState.Lawful args (divSubtractShift args qr) := by
rcases args with n, d
simp only [divSubtractShift, decide_eq_true_eq]
simp only [divSubtractShift]
-- We add these hypotheses for `omega` to find them later.
have hrwn, hd, hrd, hr, hn, hrnd, hwn_lt := h
have : d.toNat * (qr.q.toNat * 2) = d.toNat * qr.q.toNat * 2 := by rw [Nat.mul_assoc]
@@ -1137,7 +1137,7 @@ theorem getLsbD_udiv (n d : BitVec w) (hy : 0#w < d) (i : Nat) :
theorem getMsbD_udiv (n d : BitVec w) (hd : 0#w < d) (i : Nat) :
(n / d).getMsbD i = (decide (i < w) && (divRec w {n, d} (DivModState.init w)).q.getMsbD i) := by
simp [getMsbD_eq_getLsbD, getLsbD_udiv, udiv_eq_divRec (by assumption)]
simp [getMsbD_eq_getLsbD, udiv_eq_divRec (by assumption)]
/- ### Arithmetic shift right (sshiftRight) recurrence -/
@@ -1304,7 +1304,7 @@ theorem negOverflow_eq {w : Nat} (x : BitVec w) :
(negOverflow x) = (decide (0 < w) && (x == intMin w)) := by
simp only [negOverflow]
rcases w with _|w
· simp [toInt_of_zero_length, Int.min_eq_right]
· simp [toInt_of_zero_length]
· suffices - 2 ^ w = (intMin (w + 1)).toInt by simp [beq_eq_decide_eq, toInt_inj, this]
simp only [toInt_intMin, Nat.add_one_sub_one, Int.natCast_emod, Int.neg_inj]
rw_mod_cast [Nat.mod_eq_of_lt (by simp [Nat.pow_lt_pow_succ])]
@@ -1346,7 +1346,7 @@ theorem umulOverflow_eq {w : Nat} (x y : BitVec w) :
(0 < w && BitVec.twoPow (w * 2) w x.zeroExtend (w * 2) * y.zeroExtend (w * 2)) := by
simp only [umulOverflow, toNat_twoPow, le_def, toNat_mul, toNat_setWidth, mod_mul_mod]
rcases w with _|w
· simp [of_length_zero, toInt_zero, mul_mod_mod]
· simp [of_length_zero]
· simp only [ge_iff_le, show 0 < w + 1 by omega, decide_true, mul_mod_mod, Bool.true_and,
decide_eq_decide]
rw [Nat.mod_eq_of_lt BitVec.toNat_mul_toNat_lt, Nat.mod_eq_of_lt]
@@ -1582,11 +1582,11 @@ theorem toInt_sdiv_of_ne_or_ne (a b : BitVec w) (h : a ≠ intMin w b ≠ -1
have := Nat.two_pow_pos (w - 1)
by_cases hbintMin : b = intMin w
· simp only [ne_eq, Decidable.not_not] at hbintMin
· simp only at hbintMin
subst hbintMin
have toIntA_lt := @BitVec.toInt_lt w a; norm_cast at toIntA_lt
have le_toIntA := @BitVec.le_toInt w a; norm_cast at le_toIntA
simp only [sdiv_intMin, h, reduceIte, toInt_zero, toInt_intMin, wpos,
simp only [sdiv_intMin, toInt_intMin, wpos,
Nat.two_pow_pred_mod_two_pow, Int.tdiv_neg]
· by_cases ha_intMin : a = intMin w
· simp only [ha_intMin, reduceIte, show 1 < w by omega, toInt_one, toInt_intMin, wpos,
@@ -1763,7 +1763,7 @@ theorem msb_umod_of_le_of_ne_zero_of_le {x y : BitVec w}
theorem toInt_srem (x y : BitVec w) : (x.srem y).toInt = x.toInt.tmod y.toInt := by
rw [srem_eq]
by_cases hyz : y = 0#w
· simp only [hyz, ofNat_eq_ofNat, msb_zero, umod_zero, neg_zero, neg_neg, toInt_zero, Int.tmod_zero]
· simp only [hyz, msb_zero, umod_zero, neg_zero, neg_neg, toInt_zero, Int.tmod_zero]
cases x.msb <;> rfl
cases h : x.msb
· cases h' : y.msb
@@ -1842,7 +1842,7 @@ theorem toInt_umod_neg_add {x y : BitVec w} (hymsb : y.msb = true) (hxmsb : x.ms
have hylt : (-y).toNat 2 ^ (w) := toNat_neg_lt_of_msb y hymsb
have hmodlt := Nat.mod_lt x.toNat (y := (-y).toNat)
(by rw [toNat_neg, Nat.mod_eq_of_lt (by omega)]; omega)
simp only [hdvd, reduceIte, toInt_add, hxnonneg, show ¬0 y.toInt by omega]
simp only [toInt_add]
rw [toInt_umod, toInt_eq_neg_toNat_neg_of_msb_true hymsb, Int.bmod_add_bmod,
Int.bmod_eq_of_le (by omega) (by omega),
toInt_eq_toNat_of_msb hxmsb, Int.emod_neg]
@@ -1857,7 +1857,7 @@ theorem toInt_sub_neg_umod {x y : BitVec w} (hxmsb : x.msb = true) (hymsb : y.ms
· subst hyzero; simp
· simp only [toNat_eq, toNat_ofNat, zero_mod] at hyzero
have hypos : 0 < y.toNat := by omega
simp only [reduceIte, toInt_sub, toInt_eq_toNat_of_msb hymsb, toInt_umod,
simp only [toInt_sub, toInt_eq_toNat_of_msb hymsb, toInt_umod,
Int.sub_bmod_bmod, toInt_eq_neg_toNat_neg_of_msb_true hxmsb, Int.neg_emod]
have hmodlt := Nat.mod_lt (x := (-x).toNat) (y := y.toNat) hypos
rw [Int.bmod_eq_of_le (by omega) (by omega)]
@@ -1895,7 +1895,7 @@ theorem toInt_smod {x y : BitVec w} :
· simp [show ¬-x % y = 0#(w + 1) by simp_all, toInt_sub_neg_umod hxmsb hymsb hx_dvd_y]
· rw [Int.neg_inj, neg_toInt_neg_umod_eq_of_msb_true_msb_true hxmsb hymsb]
simp [BitVec.toInt_eq_neg_toNat_neg_of_msb_true, hxmsb, hymsb,
Int.fmod_eq_emod_of_nonneg _, show 0 (-y).toNat by omega]
Int.fmod_eq_emod_of_nonneg _]
/-! ### Lemmas that use bit blasting circuits -/
@@ -1929,7 +1929,7 @@ theorem carry_extractLsb'_eq_carry {w i len : Nat} (hi : i < len)
{x y : BitVec w} {b : Bool}:
(carry i (extractLsb' 0 len x) (extractLsb' 0 len y) b)
= (carry i x y b) := by
simp only [carry, extractLsb'_toNat, shiftRight_zero, toNat_false, Nat.add_zero, ge_iff_le,
simp only [carry, extractLsb'_toNat, shiftRight_zero, ge_iff_le,
decide_eq_decide]
have : 2 ^ i 2^len := by
apply Nat.pow_dvd_pow

View File

@@ -64,14 +64,14 @@ theorem eq_of_getLsbD_eq {x y : BitVec w}
theorem getElem_cons {b : Bool} {n} {x : BitVec n} {i : Nat} (h : i < n + 1) :
(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]
simp only [getElem_eq_testBit_toNat, toNat_cons, Nat.testBit_or]
rw [Nat.testBit_shiftLeft]
rcases Nat.lt_trichotomy i n with i_lt_n | i_eq_n | n_lt_i
· have p1 : ¬(n i) := by omega
have p2 : i n := by omega
simp [p1, p2]
· simp only [i_eq_n, ge_iff_le, Nat.le_refl, decide_true, Nat.sub_self, Nat.testBit_zero,
Bool.true_and, testBit_toNat, getLsbD_of_ge, Bool.or_false, reduceIte]
Bool.true_and, testBit_toNat, getLsbD_of_ge, Bool.or_false]
cases b <;> trivial
· have p1 : i n := by omega
have p2 : i - n 0 := by omega

View File

@@ -82,9 +82,9 @@ theorem iunfoldr_getLsbD' {f : Fin w → αα × Bool} (state : Nat → α)
simp only [getLsbD_cons]
have hj2 : j.val w := by simp
cases (Nat.lt_or_eq_of_le (Nat.lt_succ.mp i.isLt)) with
| inl h3 => simp [if_neg, (Nat.ne_of_lt h3)]
| inl h3 => simp [(Nat.ne_of_lt h3)]
exact (ih hj2).1 i.val, h3
| inr h3 => simp [h3, if_pos]
| inr h3 => simp [h3]
cases (Nat.eq_zero_or_pos j.val) with
| inl hj3 => congr
rw [ (ih hj2).2]

View File

@@ -96,8 +96,8 @@ theorem getElem_eq_iff {l : BitVec w} {n : Nat} {h : n < w} : l[n] = x ↔ l[n]?
exact fun w => h, w, fun h => h.2
theorem getElem_eq_getElem? (l : BitVec w) (i : Nat) (h : i < w) :
l[i] = l[i]?.get (by simp [getElem?_eq_getElem, h]) := by
simp [getElem_eq_iff]
l[i] = l[i]?.get (by simp [h]) := by
simp
theorem getLsbD_eq_getElem?_getD {x : BitVec w} {i : Nat} :
x.getLsbD i = x[i]?.getD false := by
@@ -164,7 +164,7 @@ theorem getMsb'_eq_getLsb' (x : BitVec w) (i : Nat) : x.getMsbD i = (decide (i <
theorem getLsbD_eq_getMsbD (x : BitVec w) (i : Nat) : x.getLsbD i = (decide (i < w) && x.getMsbD (w - 1 - i)) := by
rw [getMsbD]
by_cases h₁ : i < w <;> by_cases h₂ : w - 1 - i < w <;>
simp only [h₁, h₂] <;> simp only [decide_true, decide_false, Bool.false_and, Bool.and_false, Bool.true_and, Bool.and_true]
simp only [h₁, h₂] <;> simp only [decide_true, decide_false, Bool.false_and, Bool.and_false, Bool.true_and]
· congr
omega
all_goals
@@ -274,9 +274,9 @@ theorem toNat_of_zero_length (h : w = 0) (x : BitVec w) : x.toNat = 0 := by
theorem toInt_of_zero_length (h : w = 0) (x : BitVec w) : x.toInt = 0 := by
subst h; simp [toInt_zero_length]
theorem getLsbD_of_zero_length (h : w = 0) (x : BitVec w) : x.getLsbD i = false := by
subst h; simp [getLsbD_zero_length]
subst h; simp
theorem getMsbD_of_zero_length (h : w = 0) (x : BitVec w) : x.getMsbD i = false := by
subst h; simp [getMsbD_zero_length]
subst h; simp
theorem msb_of_zero_length (h : w = 0) (x : BitVec w) : x.msb = false := by
subst h; simp [msb_zero_length]
theorem eq_of_zero_length (h : w = 0) {x y : BitVec w} : x = y := by
@@ -287,7 +287,7 @@ theorem length_pos_of_ne {x y : BitVec w} (h : x ≠ y) : 0 < w :=
theorem ofFin_ofNat (n : Nat) :
ofFin (no_index (OfNat.ofNat n : Fin (2^w))) = OfNat.ofNat n := by
simp only [OfNat.ofNat, Fin.ofNat, BitVec.ofNat, Nat.and_two_pow_sub_one_eq_mod]
simp only [OfNat.ofNat, Fin.ofNat, BitVec.ofNat]
@[simp] theorem ofFin_neg {x : Fin (2 ^ w)} : ofFin (-x) = -(ofFin x) := by
rfl
@@ -305,7 +305,7 @@ theorem toFin_inj {x y : BitVec w} : x.toFin = y.toFin ↔ x = y := by
exact @eq_of_toFin_eq w x y
case mpr =>
intro h
simp [toFin, h]
simp [h]
theorem toFin_zero : toFin (0 : BitVec w) = 0 := rfl
theorem toFin_one : toFin (1 : BitVec w) = 1 := by
@@ -394,7 +394,7 @@ theorem getLsbD_ofNat (n : Nat) (x : Nat) (i : Nat) :
<;> simp [h, Nat.testBit_eq_decide_div_mod_eq, Nat.div_eq_of_lt]
@[simp] theorem getElem_one (h : i < w) : (1#w)[i] = decide (i = 0) := by
simp [ getLsbD_eq_getElem, getLsbD_one, h, show 0 < w by omega]
simp [ getLsbD_eq_getElem, getLsbD_one, show 0 < w by omega]
/-- The msb at index `w-1` is the least significant bit, and is true when the width is nonzero. -/
@[simp] theorem getMsbD_one : (1#w).getMsbD i = (decide (i = w - 1) && decide (0 < w)) := by
@@ -428,7 +428,7 @@ theorem getLsbD_ofNat (n : Nat) (x : Nat) (i : Nat) :
@[simp] theorem sub_sub_toNat_cancel {x : BitVec w} :
2 ^ w - (2 ^ w - x.toNat) = x.toNat := by
simp [Nat.sub_sub_eq_min, Nat.min_eq_right]
simp [Nat.sub_sub_eq_min]
omega
@[simp] theorem sub_add_bmod_cancel {x y : BitVec w} :
@@ -703,18 +703,18 @@ theorem toInt_one (h : 1 < w) : (1#w : BitVec w).toInt = 1 := by
@[simp] theorem sub_toNat_mod_cancel_of_msb_true {x : BitVec w} (h : x.msb = true) :
(2 ^ w - x.toNat) % 2 ^ w = 2 ^ w - x.toNat := by
simp only [msb_eq_decide, ge_iff_le, decide_eq_true_eq] at h
simp only [msb_eq_decide, decide_eq_true_eq] at h
have := Nat.two_pow_pos (w-1)
exact sub_toNat_mod_cancel_of_toNat (by omega)
theorem toNat_lt_of_msb_false {w : Nat} {x : BitVec w} (h : x.msb = false) : x.toNat < 2 ^ (w - 1) := by
have rt := @msb_eq_decide w x
simp only [ge_iff_le, false_eq_decide_iff, Nat.not_le, h] at rt
simp only [false_eq_decide_iff, Nat.not_le, h] at rt
omega
theorem le_toNat_of_msb_true {w : Nat} {x : BitVec w} (h : x.msb = true) : 2 ^ (w - 1) x.toNat := by
have rt := @msb_eq_decide w x
simp only [h, ge_iff_le, true_eq_decide_iff] at rt
simp only [h, true_eq_decide_iff] at rt
omega
/--
@@ -913,7 +913,7 @@ theorem getElem?_setWidth (m : Nat) (x : BitVec n) (i : Nat) :
@[simp] theorem getMsbD_setWidth' (ge : m n) (x : BitVec n) (i : Nat) :
getMsbD (setWidth' ge x) i = (decide (m - n i) && getMsbD x (i + n - m)) := by
simp only [getMsbD, getLsbD_setWidth', gt_iff_lt]
simp only [getMsbD, getLsbD_setWidth']
by_cases h₁ : decide (i < m) <;> by_cases h₂ : decide (m - n i) <;> by_cases h₃ : decide (i + n - m < n) <;>
by_cases h₄ : n - 1 - (i + n - m) = m - 1 - i
all_goals
@@ -933,8 +933,8 @@ theorem getElem?_setWidth (m : Nat) (x : BitVec n) (i : Nat) :
unfold setWidth
by_cases h : n m <;> simp only [h]
· by_cases h' : m - n i
<;> simp [h', show i - (m - n) = i + n - m by omega]
· simp only [show m - n = 0 by omega, getMsbD, getLsbD_setWidth]
<;> simp [h']
· simp only [show m - n = 0 by omega, getMsbD]
by_cases h' : i < m
· simp [show m - 1 - i < m by omega, show i + n - m < n by omega,
show n - 1 - (i + n - m) = m - 1 - i by omega]
@@ -972,7 +972,7 @@ theorem setWidth'_eq {x : BitVec w} (h : w ≤ v) : x.setWidth' h = x.setWidth v
@[simp] theorem setWidth_setWidth_of_le (x : BitVec w) (h : k l) :
(x.setWidth l).setWidth k = x.setWidth k := by
ext i
simp [getElem_setWidth, Fin.is_lt, decide_true, Bool.true_and]
simp [getElem_setWidth]
omega
@[simp] theorem setWidth_cast {x : BitVec w} {h : w = v} : (x.cast h).setWidth k = x.setWidth k := by
@@ -995,14 +995,14 @@ theorem setWidth_one_eq_ofBool_getLsb_zero (x : BitVec w) :
x.setWidth 1 = BitVec.ofBool (x.getLsbD 0) := by
ext i h
simp at h
simp [getLsbD_setWidth, h]
simp [h]
/-- Zero extending `1#v` to `1#w` equals `1#w` when `v > 0`. -/
theorem setWidth_ofNat_one_eq_ofNat_one_of_lt {v w : Nat} (hv : 0 < v) :
(BitVec.ofNat v 1).setWidth w = BitVec.ofNat w 1 := by
ext i h
simp only [getElem_setWidth, h, decide_true, getLsbD_ofNat, Bool.true_and,
Bool.and_eq_right_iff_imp, decide_eq_true_eq]
simp only [getElem_setWidth, getLsbD_ofNat,
]
have hv := (@Nat.testBit_one_eq_true_iff_self_eq_zero i)
by_cases h : Nat.testBit 1 i = true <;> simp_all
@@ -1078,15 +1078,15 @@ protected theorem extractLsb_ofNat (x n : Nat) (hi lo : Nat) :
@[simp] theorem toInt_extractLsb {hi lo : Nat} {x : BitVec n} :
(extractLsb hi lo x).toInt = ((x.toNat >>> lo) : Int).bmod (2 ^ (hi - lo + 1)) := by
simp [extractLsb, toInt_ofNat]
simp [extractLsb]
@[simp] theorem toFin_extractLsb' {s m : Nat} {x : BitVec n} :
(extractLsb' s m x).toFin = Fin.ofNat (2 ^ m) (x.toNat >>> s) := by
simp [extractLsb', toInt_ofNat]
simp [extractLsb']
@[simp] theorem toFin_extractLsb {hi lo : Nat} {x : BitVec n} :
(extractLsb hi lo x).toFin = Fin.ofNat (2 ^ (hi - lo + 1)) (x.toNat >>> lo) := by
simp [extractLsb, toInt_ofNat]
simp [extractLsb]
@[simp] theorem getElem_extractLsb' {start len : Nat} {x : BitVec n} {i : Nat} (h : i < len) :
(extractLsb' start len x)[i] = x.getLsbD (start+i) := by
@@ -1094,7 +1094,7 @@ protected theorem extractLsb_ofNat (x n : Nat) (hi lo : Nat) :
@[simp] theorem getLsbD_extractLsb' (start len : Nat) (x : BitVec n) (i : Nat) :
(extractLsb' start len x).getLsbD i = (i < len && x.getLsbD (start+i)) := by
simp [getLsbD, Nat.lt_succ]
simp [getLsbD]
/--
Get the most significant bit after `extractLsb'`. With `extractLsb'`, we extract
@@ -1272,9 +1272,9 @@ theorem extractLsb'_eq_zero {x : BitVec w} {start : Nat} :
@[simp] theorem ofFin_add_rev (x : Fin (2^n)) : ofFin (x + x.rev) = allOnes n := by
ext
simp only [Fin.rev, getElem_ofFin, getElem_allOnes, Fin.is_lt, decide_true]
simp only [Fin.rev, getElem_ofFin, getElem_allOnes]
rw [Fin.add_def]
simp only [Nat.testBit_mod_two_pow, Fin.is_lt, decide_true, Bool.true_and]
simp only [Nat.testBit_mod_two_pow]
have h : (x : Nat) + (2 ^ n - (x + 1)) = 2 ^ n - 1 := by omega
rw [h, Nat.testBit_two_pow_sub_one]
simp
@@ -1318,7 +1318,7 @@ theorem msb_allOnes (hw : 0 < w) : (allOnes w).msb = true := by
@[simp] theorem setWidth_or {x y : BitVec w} :
(x ||| y).setWidth k = x.setWidth k ||| y.setWidth k := by
ext i h
simp [h]
simp
theorem or_assoc (x y z : BitVec w) :
x ||| y ||| z = x ||| (y ||| z) := by
@@ -1352,11 +1352,11 @@ instance : Std.LawfulCommIdentity (α := BitVec n) (· ||| · ) (0#n) where
@[simp] theorem or_allOnes {x : BitVec w} : x ||| allOnes w = allOnes w := by
ext i h
simp [h]
simp
@[simp] theorem allOnes_or {x : BitVec w} : allOnes w ||| x = allOnes w := by
ext i h
simp [h]
simp
@[simp]
theorem or_eq_zero_iff {x y : BitVec w} : (x ||| y) = 0#w x = 0#w y = 0#w := by
@@ -1374,12 +1374,12 @@ theorem or_eq_zero_iff {x y : BitVec w} : (x ||| y) = 0#w ↔ x = 0#w ∧ y = 0#
theorem extractLsb'_or {x y : BitVec w} {start len : Nat} :
(x ||| y).extractLsb' start len = (x.extractLsb' start len) ||| (y.extractLsb' start len) := by
ext i hi
simp [hi]
simp
theorem extractLsb_or {x : BitVec w} {hi lo : Nat} :
(x ||| y).extractLsb lo hi = (x.extractLsb lo hi) ||| (y.extractLsb lo hi) := by
ext k hk
simp [hk, show k lo - hi by omega]
simp
@[simp] theorem ofNat_or {x y : Nat} : BitVec.ofNat w (x ||| y) = BitVec.ofNat w x ||| BitVec.ofNat w y :=
eq_of_toNat_eq (by simp [Nat.or_mod_two_pow])
@@ -1417,7 +1417,7 @@ theorem extractLsb_or {x : BitVec w} {hi lo : Nat} :
@[simp] theorem setWidth_and {x y : BitVec w} :
(x &&& y).setWidth k = x.setWidth k &&& y.setWidth k := by
ext i h
simp [h]
simp
theorem and_assoc (x y z : BitVec w) :
x &&& y &&& z = x &&& (y &&& z) := by
@@ -1448,14 +1448,14 @@ instance : Std.IdempotentOp (α := BitVec n) (· &&& · ) where
@[simp] theorem and_allOnes {x : BitVec w} : x &&& allOnes w = x := by
ext i h
simp [h]
simp
instance : Std.LawfulCommIdentity (α := BitVec n) (· &&& · ) (allOnes n) where
right_id _ := BitVec.and_allOnes
@[simp] theorem allOnes_and {x : BitVec w} : allOnes w &&& x = x := by
ext i h
simp [h]
simp
@[simp]
theorem and_eq_allOnes_iff {x y : BitVec w} :
@@ -1467,19 +1467,19 @@ theorem and_eq_allOnes_iff {x y : BitVec w} :
· ext i ih
have := BitVec.eq_of_getElem_eq_iff.mp h i ih
simp only [getElem_and, getElem_allOnes, Bool.and_eq_true] at this
simp [this, ih]
simp [this]
· intro h
simp [h]
theorem extractLsb'_and {x y : BitVec w} {start len : Nat} :
(x &&& y).extractLsb' start len = (x.extractLsb' start len) &&& (y.extractLsb' start len) := by
ext i hi
simp [hi]
simp
theorem extractLsb_and {x : BitVec w} {hi lo : Nat} :
(x &&& y).extractLsb lo hi = (x.extractLsb lo hi) &&& (y.extractLsb lo hi) := by
ext k hk
simp [hk, show k lo - hi by omega]
simp
@[simp] theorem ofNat_and {x y : Nat} : BitVec.ofNat w (x &&& y) = BitVec.ofNat w x &&& BitVec.ofNat w y :=
eq_of_toNat_eq (by simp [Nat.and_mod_two_pow])
@@ -1520,12 +1520,12 @@ theorem extractLsb_and {x : BitVec w} {hi lo : Nat} :
@[simp] theorem setWidth_xor {x y : BitVec w} :
(x ^^^ y).setWidth k = x.setWidth k ^^^ y.setWidth k := by
ext i h
simp [h]
simp
theorem xor_assoc (x y z : BitVec w) :
x ^^^ y ^^^ z = x ^^^ (y ^^^ z) := by
ext i
simp [Bool.xor_assoc]
simp
instance : Std.Associative (fun (x y : BitVec w) => x ^^^ y) := BitVec.xor_assoc
theorem xor_comm (x y : BitVec w) :
@@ -1577,12 +1577,12 @@ theorem xor_eq_zero_iff {x y : BitVec w} : (x ^^^ y = 0#w) ↔ x = y := by
theorem extractLsb'_xor {x y : BitVec w} {start len : Nat} :
(x ^^^ y).extractLsb' start len = (x.extractLsb' start len) ^^^ (y.extractLsb' start len) := by
ext i hi
simp [hi]
simp
theorem extractLsb_xor {x : BitVec w} {hi lo : Nat} :
(x ^^^ y).extractLsb lo hi = (x.extractLsb lo hi) ^^^ (y.extractLsb lo hi) := by
ext k hk
simp [hk, show k lo - hi by omega]
simp
@[simp] theorem ofNat_xor {x y : Nat} : BitVec.ofNat w (x ^^^ y) = BitVec.ofNat w x ^^^ BitVec.ofNat w y :=
eq_of_toNat_eq (by simp [Nat.xor_mod_two_pow])
@@ -1655,7 +1655,7 @@ theorem not_def {x : BitVec v} : ~~~x = allOnes v ^^^ x := rfl
@[simp] theorem setWidth_not {x : BitVec w} (_ : k w) :
(~~~x).setWidth k = ~~~(x.setWidth k) := by
ext i h
simp [h]
simp
omega
@[simp] theorem not_zero : ~~~(0#n) = allOnes n := by
@@ -1668,16 +1668,16 @@ theorem not_def {x : BitVec v} : ~~~x = allOnes v ^^^ x := rfl
@[simp] theorem xor_allOnes {x : BitVec w} : x ^^^ allOnes w = ~~~ x := by
ext i h
simp [h]
simp
@[simp] theorem allOnes_xor {x : BitVec w} : allOnes w ^^^ x = ~~~ x := by
ext i h
simp [h]
simp
@[simp]
theorem not_not {b : BitVec w} : ~~~(~~~b) = b := by
ext i h
simp [h]
simp
@[simp]
protected theorem not_inj {x y : BitVec w} : ~~~x = ~~~y x = y :=
@@ -1721,7 +1721,7 @@ which makes the operation not commute.
theorem extractLsb'_not_of_lt {x : BitVec w} {start len : Nat} (h : start + len < w) :
(~~~ x).extractLsb' start len = ~~~ (x.extractLsb' start len) := by
ext i hi
simp [hi]
simp
omega
/--
@@ -1734,7 +1734,7 @@ we need the range [lo:hi] to be a valid closed interval inside the bitvector:
theorem extractLsb_not_of_lt {x : BitVec w} {hi lo : Nat} (hlo : lo hi) (hhi : hi < w) :
(~~~ x).extractLsb hi lo = ~~~ (x.extractLsb hi lo) := by
ext k hk
simp [hk, show k hi - lo by omega]
simp
omega
@[simp]
@@ -1767,19 +1767,19 @@ theorem not_xor_right {x y : BitVec w} : ~~~ (x ^^^ y) = x ^^^ ~~~ y := by
@[simp] theorem not_cast {x : BitVec w} (h : w = w') : ~~~(x.cast h) = (~~~x).cast h := by
ext
simp_all [lt_of_getLsbD]
simp_all
@[simp] theorem and_cast {x y : BitVec w} (h : w = w') : x.cast h &&& y.cast h = (x &&& y).cast h := by
ext
simp_all [lt_of_getLsbD]
simp_all
@[simp] theorem or_cast {x y : BitVec w} (h : w = w') : x.cast h ||| y.cast h = (x ||| y).cast h := by
ext
simp_all [lt_of_getLsbD]
simp_all
@[simp] theorem xor_cast {x y : BitVec w} (h : w = w') : x.cast h ^^^ y.cast h = (x ^^^ y).cast h := by
ext
simp_all [lt_of_getLsbD]
simp_all
/-! ### shiftLeft -/
@@ -1823,19 +1823,19 @@ theorem zero_shiftLeft (n : Nat) : 0#w <<< n = 0#w := by
theorem shiftLeft_xor_distrib (x y : BitVec w) (n : Nat) :
(x ^^^ y) <<< n = (x <<< n) ^^^ (y <<< n) := by
ext i h
simp only [getElem_shiftLeft, h, decide_true, Bool.true_and, getLsbD_xor]
simp only [getElem_shiftLeft]
by_cases h' : i < n <;> simp [h']
theorem shiftLeft_and_distrib (x y : BitVec w) (n : Nat) :
(x &&& y) <<< n = (x <<< n) &&& (y <<< n) := by
ext i h
simp only [getElem_shiftLeft, h, decide_true, Bool.true_and, getLsbD_and]
simp only [getElem_shiftLeft]
by_cases h' : i < n <;> simp [h']
theorem shiftLeft_or_distrib (x y : BitVec w) (n : Nat) :
(x ||| y) <<< n = (x <<< n) ||| (y <<< n) := by
ext i h
simp only [getElem_shiftLeft, h, decide_true, Bool.true_and, getLsbD_or]
simp only [getElem_shiftLeft]
by_cases h' : i < n <;> simp [h']
@[simp] theorem getMsbD_shiftLeft (x : BitVec w) (i) :
@@ -1847,7 +1847,7 @@ theorem shiftLeft_or_distrib (x y : BitVec w) (n : Nat) :
simp only [t]
simp only [decide_true, Nat.sub_sub, Bool.true_and, Nat.add_assoc]
by_cases h₁ : k < w <;> by_cases h₂ : w - (1 + k) < i <;> by_cases h₃ : k + i < w
<;> simp only [h₁, h₂, h₃, decide_false, h₂, decide_true, Bool.not_true, Bool.false_and, Bool.and_self,
<;> simp only [h₁, h₃, decide_false, h₂, decide_true, Bool.not_true, Bool.false_and, Bool.and_self,
Bool.true_and, Bool.false_eq, Bool.false_and, Bool.not_false]
<;> (first | apply getLsbD_of_ge | apply Eq.symm; apply getLsbD_of_ge)
<;> omega
@@ -1923,9 +1923,9 @@ theorem toFin_shiftLeftZeroExtend {x : BitVec w} :
@[simp] theorem getElem_shiftLeftZeroExtend {x : BitVec m} {n : Nat} (h : i < m + n) :
(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]
simp only [getElem_eq_testBit_toNat]
cases h₁ : decide (i < n) <;> cases h₂ : decide (i - n < m + n)
<;> simp_all [h]
<;> simp_all
<;> omega
@[simp] theorem getLsbD_shiftLeftZeroExtend (x : BitVec m) (n : Nat) :
@@ -1994,7 +1994,7 @@ theorem getElem_shiftLeft' {x : BitVec w₁} {y : BitVec w₂} {i : Nat} (h : i
@[simp] theorem shiftLeft_eq_zero {x : BitVec w} {n : Nat} (hn : w n) : x <<< n = 0#w := by
ext i hi
simp [hn, hi]
simp
omega
theorem shiftLeft_ofNat_eq {x : BitVec w} {k : Nat} : x <<< (BitVec.ofNat w k) = x <<< (k % 2^w) := rfl
@@ -2121,7 +2121,7 @@ theorem msb_ushiftRight {x : BitVec w} {n : Nat} :
case zero =>
simp
case succ nn ih =>
simp [BitVec.ushiftRight_eq, getMsbD_ushiftRight, BitVec.msb, ih, show nn + 1 > 0 by omega]
simp [getMsbD_ushiftRight, BitVec.msb, show nn + 1 > 0 by omega]
@[simp] theorem setWidth_ushiftRight {x : BitVec w} {y : Nat} (hi : w i) :
(x >>> y).setWidth i = x.setWidth i >>> y := by
@@ -2157,7 +2157,7 @@ theorem sshiftRight_eq_of_msb_false {x : BitVec w} {s : Nat} (h : x.msb = false)
apply BitVec.eq_of_toNat_eq
rw [BitVec.sshiftRight_eq, BitVec.toInt_eq_toNat_cond]
have hxbound : 2 * x.toNat < 2 ^ w := BitVec.msb_eq_false_iff_two_mul_lt.mp h
simp only [hxbound, reduceIte, Int.natCast_shiftRight, Int.ofNat_eq_coe, ofInt_natCast,
simp only [hxbound, reduceIte, Int.natCast_shiftRight, ofInt_natCast,
toNat_ofNat, toNat_ushiftRight]
replace hxbound : x.toNat >>> s < 2 ^ w := by
rw [Nat.shiftRight_eq_div_pow]
@@ -2259,7 +2259,7 @@ theorem msb_sshiftRight {n : Nat} {x : BitVec w} :
@[simp] theorem zero_sshiftRight {n : Nat} : (0#w).sshiftRight n = 0#w := by
ext i h
simp [getElem_sshiftRight, h]
simp [getElem_sshiftRight]
theorem sshiftRight_add {x : BitVec w} {m n : Nat} :
x.sshiftRight (m + n) = (x.sshiftRight m).sshiftRight n := by
@@ -2271,17 +2271,17 @@ theorem sshiftRight_add {x : BitVec w} {m n : Nat} :
by_cases h₃ : m + (n + i) < w
· simp [h₃]
omega
· simp [h₃, msb_sshiftRight]
· simp [h₃]
theorem not_sshiftRight {b : BitVec w} :
~~~b.sshiftRight n = (~~~b).sshiftRight n := by
ext i
simp only [getElem_not, Fin.is_lt, decide_true, getElem_sshiftRight, Bool.not_and, Bool.not_not,
Bool.true_and, msb_not]
simp only [getElem_not, getElem_sshiftRight,
msb_not]
by_cases h : w i
<;> by_cases h' : n + i < w
<;> by_cases h'' : 0 < w
<;> simp [h, h', h'']
<;> simp [h', h'']
<;> omega
@[simp]
@@ -2427,7 +2427,7 @@ 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] = (if h : y.toNat + i < w then x[y.toNat + i] else x.msb) := by
simp [show ¬ w i by omega, getElem_sshiftRight]
simp [getElem_sshiftRight]
theorem getMsbD_sshiftRight' {x y: BitVec w} {i : Nat} :
(x.sshiftRight y.toNat).getMsbD i =
@@ -2453,10 +2453,10 @@ theorem signExtend_eq_setWidth_of_msb_false {x : BitVec w} {v : Nat} (hmsb : x.m
x.signExtend v = x.setWidth v := by
ext i
by_cases hv : i < v
· simp only [signExtend, getLsbD, getElem_setWidth, hv, decide_true, Bool.true_and, toNat_ofInt,
· simp only [signExtend, getLsbD, getElem_setWidth,
BitVec.toInt_eq_msb_cond, hmsb, reduceIte, reduceCtorEq]
simp [BitVec.testBit_toNat]
· simp only [getElem_setWidth, hv, decide_false, Bool.false_and]
· simp only [getElem_setWidth]
omega
/--
@@ -2470,7 +2470,7 @@ theorem signExtend_eq_not_setWidth_not_of_msb_true {x : BitVec w} {v : Nat} (hms
toNat_setWidth, hmsb, reduceIte]
norm_cast
rw [Int.ofNat_sub_ofNat_of_lt, Int.negSucc_emod]
simp only [Int.natAbs_natCast, Nat.succ_eq_add_one]
simp only [Int.natAbs_natCast]
rw [Int.subNatNat_of_le]
· rw [Int.toNat_natCast, Nat.add_comm, Nat.sub_add_eq]
· apply Nat.le_trans
@@ -2539,7 +2539,7 @@ private theorem toNat_signExtend_of_le (x : BitVec w) {v : Nat} (hv : w ≤ v) :
rcases hi with hi | hi | hi
· simp [hi]; omega
· simp [hi]; omega
· simp [hi, show ¬ (i < w + k) by omega, show ¬ (i < w) by omega]
· simp [show ¬ (i < w + k) by omega, show ¬ (i < w) by omega]
omega
· simp only [hx, Bool.if_false_right,
Bool.false_eq_true, reduceIte, Nat.zero_add, testBit_toNat]
@@ -2547,7 +2547,7 @@ private theorem toNat_signExtend_of_le (x : BitVec w) {v : Nat} (hv : w ≤ v) :
rcases hi with hi | hi | hi
· simp [hi]; omega
· simp [hi]
· simp [hi, show ¬ (i < w + k) by omega, show ¬ (i < w) by omega, getLsbD_of_ge x i (by omega)]
· simp [show ¬ (i < w + k) by omega, show ¬ (i < w) by omega, getLsbD_of_ge x i (by omega)]
/-- Sign extending to a larger bitwidth depends on the msb.
If the msb is false, then the result equals the original value.
@@ -2576,10 +2576,10 @@ where
simp only [toInt_eq_msb_cond, toNat_signExtend]
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]
simp [getElem_signExtend]
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.natCast_emod, Int.natCast_mul]
simp only [this, toNat_setWidth, Int.natCast_add, Int.natCast_emod]
by_cases h : x.msb
<;> norm_cast
<;> simp [h, Nat.mod_eq_of_lt (Nat.lt_of_lt_of_le x.isLt H), -Int.natCast_pow]
@@ -2666,14 +2666,14 @@ theorem getLsbD_append {x : BitVec n} {y : BitVec m} :
simp only [append_def, getLsbD_or, getLsbD_shiftLeftZeroExtend, getLsbD_setWidth']
by_cases h : i < m
· simp [h]
· simp_all [h]
· simp_all
theorem getElem_append {x : BitVec n} {y : BitVec m} (h : i < n + m) :
(x ++ y)[i] = if h : i < m then y[i] else x[i - m] := by
simp only [append_def]
by_cases h' : i < m
· simp [h']
· simp [h', show m i by omega, show i - m < n by omega]
· simp [h', show m i by omega]
@[simp] theorem getMsbD_append {x : BitVec n} {y : BitVec m} :
getMsbD (x ++ y) i = if n i then getMsbD y (i - n) else getMsbD x i := by
@@ -2697,7 +2697,7 @@ theorem msb_append {x : BitVec w} {y : BitVec v} :
@[simp] theorem append_zero_width (x : BitVec w) (y : BitVec 0) : x ++ y = x := by
ext i ih
rw [getElem_append] -- Why does this not work with `simp [getElem_append]`?
simp [show i < w by omega]
simp
theorem toInt_append {x : BitVec n} {y : BitVec m} :
(x ++ y).toInt = if n == 0 then y.toInt else (2 ^ m) * x.toInt + y.toNat := by
@@ -2783,9 +2783,9 @@ theorem toNat_shiftLeft_or_toNat_lt_two_pow_add {m n : Nat} (x : BitVec m) (y :
theorem setWidth_append {x : BitVec w} {y : BitVec v} :
(x ++ y).setWidth k = if h : k v then y.setWidth k else (x.setWidth (k - v) ++ y).cast (by omega) := by
ext i h
simp only [getElem_setWidth, h, getLsbD_append, getElem_append]
simp only [getElem_setWidth, getLsbD_append]
split <;> rename_i h₁ <;> split <;> rename_i h₂
· simp [h]
· simp
· simp [getElem_append, h₁]
· omega
· simp [getElem_append, h₁]
@@ -2804,7 +2804,7 @@ theorem setWidth_append {x : BitVec w} {y : BitVec v} :
@[simp] theorem not_append {x : BitVec w} {y : BitVec v} : ~~~ (x ++ y) = (~~~ x) ++ (~~~ y) := by
ext i
simp only [getElem_not, getElem_append, cond_eq_if]
simp only [getElem_not, getElem_append]
split
· simp_all
· simp_all
@@ -2861,7 +2861,7 @@ theorem setWidth_eq_append_extractLsb' {v : Nat} {x : BitVec v} {w : Nat} :
ext i hi
simp only [getElem_cast, getElem_append]
by_cases hiv : i < v
· simp [hi]
· simp
omega
· simp [getLsbD_of_ge x i (by omega)]
@@ -2884,7 +2884,7 @@ theorem setWidth_eq_extractLsb' {v : Nat} {x : BitVec v} {w : Nat} (h : w ≤ v)
ext i hi
simp only [getElem_cast, getElem_append]
by_cases hiv : i < v
· simp [hi]
· simp
omega
· simp [getLsbD_of_ge x i (by omega)]
@@ -2900,7 +2900,7 @@ 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, getElem_zero, getElem_extractLsb',
Nat.zero_add, Bool.if_false_left]
Nat.zero_add]
by_cases hi' : i < n
· simp [hi']
· simp [hi', show i - n < w by omega]
@@ -2993,7 +2993,7 @@ theorem extractLsb'_append_eq_ite {v w} {xhi : BitVec v} {xlo : BitVec w} {start
simp only [getElem_extractLsb', getLsbD_append, getElem_cast,
getElem_append, dite_eq_ite]
by_cases hi₂ : start + i < w
· simp [hi₂, show i < min len w by omega, show i < w - start by omega]
· simp [hi₂, show i < w - start by omega]
· simp [hi₂, reduceIte, show ¬i < w - start by omega,
show start + i - w = start - w + (i - (w - start)) by omega]
· simp only [hstart, reduceDIte]
@@ -3020,7 +3020,7 @@ the bits from `xhi` when `start` is outside `xlo`.
theorem extractLsb'_append_eq_of_le {v w} {xhi : BitVec v} {xlo : BitVec w}
{start len : Nat} (h : w start) :
extractLsb' start len (xhi ++ xlo) = extractLsb' (start - w) len xhi := by
simp [extractLsb'_append_eq_ite, h, show ¬ start < w by omega]
simp [extractLsb'_append_eq_ite, show ¬ start < w by omega]
/-! ### rev -/
@@ -3057,7 +3057,7 @@ theorem getLsbD_cons (b : Bool) {n} (x : BitVec n) (i : Nat) :
· have p1 : ¬(n i) := by omega
have p2 : i n := by omega
simp [p1, p2]
· simp only [i_eq_n, ge_iff_le, Nat.le_refl, decide_true, Nat.sub_self, Nat.testBit_zero,
· simp only [i_eq_n, Nat.le_refl, decide_true, Nat.sub_self, Nat.testBit_zero,
Bool.true_and, testBit_toNat, getLsbD_of_ge, Bool.or_false, reduceIte]
cases b <;> trivial
· have p1 : i n := by omega
@@ -3081,7 +3081,7 @@ theorem setWidth_succ (x : BitVec w) :
simp [j_eq]
else
have j_lt : j < i := Nat.lt_of_le_of_ne (Nat.le_of_succ_le_succ h) j_eq
simp [j_eq, j_lt]
simp [j_eq]
@[simp] theorem not_cons (x : BitVec w) (b : Bool) : ~~~(cons b x) = cons (!b) (~~~x) := by
simp [cons]
@@ -3111,17 +3111,17 @@ theorem cons_append (x : BitVec w₁) (y : BitVec w₂) (a : Bool) :
theorem cons_append_append (x : BitVec w₁) (y : BitVec w₂) (z : BitVec w₃) (a : Bool) :
(cons a x) ++ y ++ z = (cons a (x ++ y ++ z)).cast (by omega) := by
ext i h
simp only [cons, getElem_append, getElem_cast, getElem_ofBool, cast_cast, getLsbD_append, getLsbD_cast, getLsbD_ofBool]
simp only [cons, getElem_append, getElem_cast, getElem_ofBool, cast_cast]
by_cases h₀ : i < w₁ + w₂ + w₃
· simp only [h₀, reduceIte]
· simp only [h₀]
by_cases h₁ : i < w₃
· simp [h₁]
· simp only [h₁, reduceIte]
· simp only [h₁]
by_cases h₂ : i - w₃ < w₂
· simp [h₂]
· simp [h₂, show i - w₃ - w₂ < w₁ by omega]
· simp only [show ¬i - w₃ - w₂ < w₁ by omega, reduceIte, show i - w₃ - w₂ - w₁ = 0 by omega,
decide_true, Bool.true_and, h₀, show i - (w₁ + w₂ + w₃) = 0 by omega]
· simp only [show ¬i - w₃ - w₂ < w₁ by omega,
h₀]
by_cases h₂ : i < w₃
· simp [h₂]; omega
· simp [h₂]; omega
@@ -3146,7 +3146,7 @@ theorem getLsbD_concat (x : BitVec w) (b : Bool) (i : Nat) :
theorem getElem_concat (x : BitVec w) (b : Bool) (i : Nat) (h : i < w + 1) :
(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,
simp only [concat, getElem_eq_testBit_toNat, toNat_append,
toNat_ofBool, Nat.testBit_or, Nat.shiftLeft_eq]
cases i
· simp [Nat.mod_eq_of_lt b.toNat_lt]
@@ -3164,7 +3164,7 @@ theorem getLsbD_concat_zero : (concat x b).getLsbD 0 = b := by
@[simp] theorem getElem_concat_succ {x : BitVec w} {i : Nat} (h : i + 1 < w + 1) :
(concat x b)[i + 1] = x[i] := by
simp only [Nat.add_lt_add_iff_right] at h
simp [getElem_concat, h, getLsbD_eq_getElem]
simp [getElem_concat]
@[simp]
theorem getMsbD_concat {i w : Nat} {b : Bool} {x : BitVec w} :
@@ -3173,7 +3173,7 @@ theorem getMsbD_concat {i w : Nat} {b : Bool} {x : BitVec w} :
by_cases h₀ : i = w
· simp [h₀]
· by_cases h₁ : i < w
· simp [h, h, show ¬ w - i = 0 by omega, show i < w + 1 by omega, Nat.sub_sub, Nat.add_comm]
· simp [h₁, show ¬ w - i = 0 by omega, show i < w + 1 by omega, Nat.sub_sub, Nat.add_comm]
· simp only [show w - i = 0 by omega, reduceIte, h₁, h₀, decide_false, Bool.false_and,
Bool.and_eq_false_imp, decide_eq_true_eq]
intro
@@ -3186,7 +3186,7 @@ theorem msb_concat {w : Nat} {b : Bool} {x : BitVec w} :
Nat.sub_zero, Bool.true_and]
by_cases h₀ : 0 < w
· simp [getElem_concat, h₀, show ¬ w = 0 by omega, show w - 1 < w by omega]
· simp [h₀, show w = 0 by omega]
· simp [show w = 0 by omega]
@[simp] theorem toInt_concat (x : BitVec w) (b : Bool) :
(concat x b).toInt = if w = 0 then -b.toInt else x.toInt * 2 + b.toInt := by
@@ -3198,25 +3198,25 @@ theorem msb_concat {w : Nat} {b : Bool} {x : BitVec w} :
@[simp] theorem toFin_concat (x : BitVec w) (b : Bool) :
(concat x b).toFin = Fin.mk (x.toNat * 2 + b.toNat) (by
have := Bool.toNat_lt b
simp [ Nat.two_pow_pred_add_two_pow_pred, Bool.toNat_lt b]
simp [ Nat.two_pow_pred_add_two_pow_pred]
omega
) := by
simp [ Fin.val_inj]
@[simp] theorem not_concat (x : BitVec w) (b : Bool) : ~~~(concat x b) = concat (~~~x) !b := by
ext (_ | i) h <;> simp [getLsbD_concat]
ext (_ | i) h <;> simp
@[simp] theorem concat_or_concat (x y : BitVec w) (a b : Bool) :
(concat x a) ||| (concat y b) = concat (x ||| y) (a || b) := by
ext (_ | i) h <;> simp [getLsbD_concat]
ext (_ | i) h <;> simp
@[simp] theorem concat_and_concat (x y : BitVec w) (a b : Bool) :
(concat x a) &&& (concat y b) = concat (x &&& y) (a && b) := by
ext (_ | i) h <;> simp [getLsbD_concat]
ext (_ | i) h <;> simp
@[simp] theorem concat_xor_concat (x y : BitVec w) (a b : Bool) :
(concat x a) ^^^ (concat y b) = concat (x ^^^ y) (a ^^ b) := by
ext (_ | i) h <;> simp [getLsbD_concat]
ext (_ | i) h <;> simp
@[simp] theorem zero_concat_false : concat 0#w false = 0#(w + 1) := by
ext
@@ -3252,7 +3252,7 @@ theorem getLsbD_shiftConcat_eq_decide (x : BitVec w) (b : Bool) (i : Nat) :
theorem shiftRight_sub_one_eq_shiftConcat (n : BitVec w) (hwn : 0 < wn) :
n >>> (wn - 1) = (n >>> wn).shiftConcat (n.getLsbD (wn - 1)) := by
ext i h
simp only [getElem_ushiftRight, getElem_shiftConcat, h, decide_true, Bool.true_and]
simp only [getElem_ushiftRight, getElem_shiftConcat]
split
· simp [*]
· congr 1; omega
@@ -3338,7 +3338,7 @@ instance : Std.LawfulIdentity (α := BitVec n) (· + ·) 0#n where
theorem setWidth_add (x y : BitVec w) (h : i w) :
(x + y).setWidth i = x.setWidth i + y.setWidth i := by
have dvd : 2^i 2^w := Nat.pow_dvd_pow _ h
simp [bitvec_to_nat, h, Nat.mod_mod_of_dvd _ dvd]
simp [bitvec_to_nat, Nat.mod_mod_of_dvd _ dvd]
@[simp, bitvec_to_nat] theorem toInt_add (x y : BitVec w) :
(x + y).toInt = (x.toInt + y.toInt).bmod (2^w) := by
@@ -3379,7 +3379,7 @@ theorem shiftLeft_add_distrib {x y : BitVec w} {n : Nat} :
case zero =>
simp
case succ n ih =>
simp [ih, toNat_eq, Nat.shiftLeft_eq, Nat.add_mul]
simp [toNat_eq, Nat.shiftLeft_eq, Nat.add_mul]
theorem add_eq_xor {a b : BitVec 1} : a + b = a ^^^ b := by
have ha : a = 0 a = 1 := eq_zero_or_eq_one _
@@ -3466,7 +3466,7 @@ theorem sub_ofFin (x : BitVec n) (y : Fin (2^n)) : x - .ofFin y = .ofFin (x.toFi
-- If `x` and `n` are not literals, applying this theorem eagerly may not be a good idea.
theorem ofNat_sub_ofNat {n} (x y : Nat) : BitVec.ofNat n x - BitVec.ofNat n y = .ofNat n ((2^n - y % 2^n) + x) := by
apply eq_of_toNat_eq
simp [BitVec.ofNat, Fin.ofNat_sub]
simp [BitVec.ofNat]
theorem ofNat_sub_ofNat_of_le (x y : Nat) (hy : y < 2 ^ w) (hlt : y x):
BitVec.ofNat w x - BitVec.ofNat w y = BitVec.ofNat w (x - y) := by
@@ -3565,7 +3565,7 @@ abbrev negOne_eq_allOnes := @neg_one_eq_allOnes
theorem neg_eq_not_add (x : BitVec w) : -x = ~~~x + 1#w := by
apply eq_of_toNat_eq
simp only [toNat_neg, ofNat_eq_ofNat, toNat_add, toNat_not, toNat_ofNat, Nat.add_mod_mod]
simp only [toNat_neg, toNat_add, toNat_not, toNat_ofNat, Nat.add_mod_mod]
congr
have hx : x.toNat < 2^w := x.isLt
rw [Nat.sub_sub, Nat.add_comm 1 x.toNat, Nat.sub_sub, Nat.sub_add_cancel (by omega)]
@@ -3631,7 +3631,7 @@ theorem add_neg_eq_sub {x y : BitVec w} : x + - y = (x - y) := by
@[simp]
theorem sub_neg {x y : BitVec w} : x - - y = x + y := by
apply eq_of_toInt_eq
simp [toInt_neg, Int.bmod_neg]
simp [toInt_neg]
theorem neg_sub {x y : BitVec w} : - (x - y) = - x + y := by
rw [sub_eq_add_neg, neg_add, sub_neg]
@@ -3736,7 +3736,7 @@ theorem mul_def {n} {x y : BitVec n} : x * y = (ofFin <| x.toFin * y.toFin) := r
theorem ofNat_mul {n} (x y : Nat) : BitVec.ofNat n (x * y) = BitVec.ofNat n x * BitVec.ofNat n y := by
apply eq_of_toNat_eq
simp [BitVec.ofNat, Fin.ofNat_mul]
simp [BitVec.ofNat]
theorem ofNat_mul_ofNat {n} (x y : Nat) : BitVec.ofNat n x * BitVec.ofNat n y = BitVec.ofNat n (x * y) :=
(ofNat_mul x y).symm
@@ -3879,7 +3879,7 @@ theorem neg_eq_neg_one_mul (b : BitVec w) : -b = -1#w * b :=
theorem setWidth_mul (x y : BitVec w) (h : i w) :
(x * y).setWidth i = x.setWidth i * y.setWidth i := by
have dvd : 2^i 2^w := Nat.pow_dvd_pow _ h
simp [bitvec_to_nat, h, Nat.mod_mod_of_dvd _ dvd]
simp [bitvec_to_nat, Nat.mod_mod_of_dvd _ dvd]
/-! ### pow -/
@@ -3960,7 +3960,7 @@ protected theorem ne_of_lt {x y : BitVec n} : x < y → x ≠ y := by
apply Nat.ne_of_lt
protected theorem umod_lt (x : BitVec n) {y : BitVec n} : 0 < y x % y < y := by
simp only [ofNat_eq_ofNat, lt_def, toNat_ofNat, Nat.zero_mod, umod, toNat_ofNatLT]
simp only [ofNat_eq_ofNat, lt_def, toNat_ofNat, Nat.zero_mod]
apply Nat.mod_lt
theorem not_lt_iff_le {x y : BitVec w} : (¬ x < y) y x := by
@@ -4055,7 +4055,7 @@ theorem udiv_zero {x : BitVec n} : x / 0#n = 0#n := by
@[simp]
theorem udiv_one {x : BitVec w} : x / 1#w = x := by
simp only [udiv_eq, toNat_eq, toNat_udiv, toNat_ofNat]
simp only [toNat_eq, toNat_udiv, toNat_ofNat]
cases w
· simp [eq_nil x]
· simp
@@ -4075,7 +4075,7 @@ theorem udiv_self {x : BitVec w} :
by_cases h : x = 0#w
· simp [h]
· simp only [toNat_eq, toNat_ofNat, Nat.zero_mod] at h
simp only [udiv_eq, beq_iff_eq, toNat_eq, toNat_ofNat, Nat.zero_mod, h,
simp only [beq_iff_eq, toNat_eq, toNat_ofNat, Nat.zero_mod, h,
reduceIte, toNat_udiv]
rw [Nat.div_self (by omega), Nat.mod_eq_of_lt (by omega)]
@@ -4100,7 +4100,7 @@ theorem msb_udiv (x y : BitVec w) :
simpa using msb_x
| y + 2 =>
suffices x.toNat / (y + 2) < 2 ^ w by
simp_all [msb_eq_decide, hy]
simp_all [msb_eq_decide]
calc
x.toNat / (y + 2)
x.toNat / 2 := by apply Nat.div_add_le_right (by omega)
@@ -4256,7 +4256,7 @@ theorem toNat_sdiv {x y : BitVec w} : (x.sdiv y).toNat =
| false, true => (- (x.udiv (- y))).toNat
| true, false => (- ((- x).udiv y)).toNat
| true, true => ((- x).udiv (- y)).toNat := by
simp only [sdiv_eq, toNat_udiv]
simp only [sdiv_eq]
by_cases h : x.msb <;> by_cases h' : y.msb <;> simp [h, h']
@[simp]
@@ -4291,7 +4291,7 @@ theorem sdiv_self {x : BitVec w} :
· by_cases h : w = 1
· subst h
rcases x.msb with msb | msb <;> simp
· rcases x.msb with msb | msb <;> simp [h]
· rcases x.msb with msb | msb <;> simp
/-- Unsigned division never overflows. -/
theorem toNat_div_toNat_lt {w : Nat} {x y : BitVec w} :
@@ -4369,14 +4369,14 @@ theorem toInt_ediv_toInt_lt_of_nonpos_of_lt_neg_one {w : Nat} {x y : BitVec w} (
rcases w with _|_|w
· simp [of_length_zero]
· have hy := eq_zero_or_eq_one (a := y)
simp [ toInt_inj, toInt_zero, toInt_one] at hy
simp [ toInt_inj, toInt_zero] at hy
omega
· have xle := le_two_mul_toInt (x := x); have xlt := two_mul_toInt_lt (x := x)
have hx' : x.toInt = 0 x.toInt = - 1 x.toInt < - 1 := by omega
rcases hx' with hx'|hx'|hx'
· simp [hx']; omega
· have := BitVec.neg_one_ediv_toInt_eq (y := y)
simp only [toInt_allOnes, Nat.lt_add_left_iff_pos, Nat.zero_lt_succ, reduceIte,
simp only [
Int.reduceNeg] at this
simp [hx', this]
omega
@@ -4462,12 +4462,12 @@ theorem toNat_smod {x y : BitVec w} : (x.smod y).toNat =
let u := (-x).umod y
(if u = 0#w then u.toNat else (y - u).toNat)
| true, true => (- ((- x).umod (- y))).toNat := by
simp only [smod_eq, toNat_umod]
simp only [smod_eq]
by_cases h : x.msb <;> by_cases h' : y.msb
<;> by_cases h'' : (-x).umod y = 0#w <;> by_cases h''' : x.umod (-y) = 0#w
<;> simp only [h, h', h'', h''']
<;> simp only [umod, toNat_eq, toNat_ofNatLT, toNat_ofNat, Nat.zero_mod] at h'' h'''
<;> simp [h'', h''']
<;> simp
@[simp]
theorem smod_zero {x : BitVec w} : x.smod 0#w = x := by
@@ -4567,7 +4567,7 @@ theorem getLsbD_rotateLeftAux_of_ge {x : BitVec w} {r : Nat} {i : Nat} (hi : i
suffices (x >>> (w - r)).getLsbD i = false by
have hiltr : decide (i < r) = false := by
simp [hi]
simp [getLsbD_shiftLeft, Bool.or_false, hi, hiltr, this]
simp [getLsbD_shiftLeft, Bool.or_false, hiltr, this]
simp only [getLsbD_ushiftRight]
apply getLsbD_of_ge
omega
@@ -4673,7 +4673,7 @@ theorem toNat_rotateLeft {x : BitVec w} {r : Nat} :
theorem toInt_rotateLeft {x : BitVec w} {r : Nat} :
(x.rotateLeft r).toInt =
((x <<< (r % w)).toNat ||| (x >>> (w - r % w)).toNat : Int).bmod (2 ^ w) := by
simp [rotateLeft_def, toInt_shiftLeft, toInt_ushiftRight, toInt_or]
simp [rotateLeft_def, toInt_or]
theorem toFin_rotateLeft {x : BitVec w} {r : Nat} :
(x.rotateLeft r).toFin =
@@ -4802,7 +4802,7 @@ theorem getMsbD_rotateRight_of_lt {w n m : Nat} {x : BitVec w} (hr : m < w) :
show (w + 1 + n - m) < (w + 1) by omega, Nat.mod_eq_of_lt, Bool.true_and]
congr 1
omega
· simp [h, getMsbD_rotateRightAux_of_ge <| Nat.ge_of_not_lt h]
· simp [getMsbD_rotateRightAux_of_ge <| Nat.ge_of_not_lt h]
by_cases h₁ : n < w + 1
· simp [h, h₁, decide_true, Bool.true_and, Nat.mod_eq_of_lt hr]
· simp [h₁]
@@ -4836,7 +4836,7 @@ theorem toNat_rotateRight {x : BitVec w} {r : Nat} :
theorem toInt_rotateRight {x : BitVec w} {r : Nat} :
(x.rotateRight r).toInt = ((x >>> (r % w)).toNat ||| (x <<< (w - r % w)).toNat : Int).bmod (2 ^ w) := by
simp [rotateRight_def, toInt_shiftLeft, toInt_ushiftRight, toInt_or]
simp [rotateRight_def, toInt_or]
theorem toFin_rotateRight {x : BitVec w} {r : Nat} :
(x.rotateRight r).toFin = x.toFin / Fin.ofNat (2 ^ w) (2 ^ (r % w)) ||| Fin.ofNat (2 ^ w) (x.toNat <<< (w - r % w)) := by
@@ -4913,8 +4913,8 @@ theorem toInt_twoPow {w i : Nat} :
theorem toFin_twoPow {w i : Nat} :
(BitVec.twoPow w i).toFin = Fin.ofNat (2^w) (2^i) := by
rcases w with rfl | w
· simp [BitVec.twoPow, BitVec.toFin, toFin_shiftLeft, Fin.fin_one_eq_zero]
· simp [BitVec.twoPow, BitVec.toFin, toFin_shiftLeft, Nat.shiftLeft_eq]
· simp [BitVec.twoPow, Fin.fin_one_eq_zero]
· simp [BitVec.twoPow, toFin_shiftLeft, Nat.shiftLeft_eq]
@[simp]
theorem getElem_twoPow {i j : Nat} (h : j < w) : (twoPow w i)[j] = decide (j = i) := by
@@ -4932,7 +4932,7 @@ theorem getMsbD_twoPow {i j w: Nat} :
theorem and_twoPow (x : BitVec w) (i : Nat) :
x &&& (twoPow w i) = if x.getLsbD i then twoPow w i else 0#w := by
ext j h
simp only [getElem_and, getLsbD_twoPow]
simp only [getElem_and]
by_cases hj : i = j <;> by_cases hx : x.getLsbD i <;> simp_all <;> omega
theorem twoPow_and (x : BitVec w) (i : Nat) :
@@ -4957,7 +4957,7 @@ theorem twoPow_zero {w : Nat} : twoPow w 0 = 1#w := by
theorem shiftLeft_eq_mul_twoPow (x : BitVec w) (n : Nat) :
x <<< n = x * (BitVec.twoPow w n) := by
ext i
simp [getLsbD_shiftLeft, Fin.is_lt, decide_true, Bool.true_and, mul_twoPow_eq_shiftLeft]
simp [mul_twoPow_eq_shiftLeft]
/-- 2^i * 2^j = 2^(i + j) with bitvectors as well -/
theorem twoPow_mul_twoPow_eq {w : Nat} (i j : Nat) : twoPow w i * twoPow w j = twoPow w (i + j) := by
@@ -5041,12 +5041,12 @@ theorem setWidth_setWidth_succ_eq_setWidth_setWidth_or_twoPow_of_getLsbD_true
setWidth w (x.setWidth (i + 1)) =
setWidth w (x.setWidth i) ||| (twoPow w i) := by
ext k h
simp only [getElem_setWidth, h, getElem_or, getElem_twoPow]
simp only [getElem_setWidth, getElem_or, getElem_twoPow]
by_cases hik : i = k
· subst hik
simp [hx]
· by_cases hik' : k < i + 1
<;> simp [hik, hik', show ¬ (k = i) by omega]
<;> simp [hik', show ¬ (k = i) by omega]
<;> omega
/-- Bitwise and of `(x : BitVec w)` with `1#w` equals zero extending `x.lsb` to `w`. -/
@@ -5085,7 +5085,7 @@ theorem getLsbD_replicate {n w : Nat} {x : BitVec w} :
· simp only [hi', reduceIte]
rw [Nat.sub_mul_eq_mod_of_lt_of_le (by omega) (by omega)]
· rw [Nat.mul_succ] at hi
simp only [show ¬i < w * n by omega, decide_false, cond_false, hi, Bool.false_and]
simp only [show ¬i < w * n by omega, decide_false, hi, Bool.false_and]
apply BitVec.getLsbD_of_ge (x := x) (i := i - w * n) (ge := by omega)
@[simp]
@@ -5385,14 +5385,14 @@ theorem sdiv_neg_one {w : Nat} {x : BitVec w} :
x.toInt / -1 = -x.toInt := by
rcases w with _|w
· simp [of_length_zero]
· simp [toInt_allOnes]
· simp
theorem sdivOverflow_eq_negOverflow_of_eq_allOnes {w : Nat} {x y : BitVec w} (hy : y = allOnes w) :
sdivOverflow x y = negOverflow x := by
rcases w with _|w
· simp [sdivOverflow, negOverflow, of_length_zero]
· have xle := le_two_mul_toInt (x := x); have xlt := two_mul_toInt_lt (x := x)
simp only [sdivOverflow, hy, show ¬2 ^ w < x.toInt by omega, negOverflow]
simp only [sdivOverflow, hy, negOverflow]
by_cases hx : x.toInt = - 2 ^ w
· simp [hx]
· simp [show ¬x.toInt == -2 ^ w by simp only [beq_iff_eq, hx, not_false_eq_true]]; omega
@@ -5603,11 +5603,11 @@ theorem reverse_append {x : BitVec w} {y : BitVec v} :
simp only [getElem_reverse, getElem_cast, getElem_append]
by_cases hi : i < v
· by_cases hw : w i
· simp [getLsbD_reverse, hw]
· simp [getElem_reverse, hw, show i < w by omega]
· simp [hw]
· simp [hw, show i < w by omega]
· by_cases hw : w i
· simp [hw, show ¬ i < w by omega, getLsbD_reverse]
· simp [hw, show i < w by omega, getElem_reverse]
· simp [hw, show ¬ i < w by omega]
· simp [hw, show i < w by omega]
@[simp]
theorem reverse_cast {w v : Nat} (h : w = v) (x : BitVec w) :

View File

@@ -488,7 +488,7 @@ Converts `true` to `1` and `false` to `0`.
@[simp] theorem ite_eq_true_else_eq_false {q : Prop} :
(if b = true then q else b = false) (b = true q) := by
cases b <;> simp [not_eq_self]
cases b <;> simp
/-
`not_ite_eq_true_eq_true` and related theorems below are added for

View File

@@ -252,7 +252,7 @@ theorem foldl_succ_last (f : α → Fin (n+1) → α) (x) :
foldl (n+1) f x = f (foldl n (f · ·.castSucc) x) (last n) := by
rw [foldl_succ]
induction n generalizing x with
| zero => simp [foldl_succ, Fin.last]
| zero => simp [Fin.last]
| succ n ih => rw [foldl_succ, ih (f · ·.succ), foldl_succ]; simp
theorem foldl_add (f : α Fin (n + m) α) (x) :

View File

@@ -381,7 +381,7 @@ theorem zero_ne_one : (0 : Fin (n + 2)) ≠ 1 := Fin.ne_of_lt one_pos
@[simp] theorem val_succ (j : Fin n) : (j.succ : Nat) = j + 1 := rfl
@[simp] theorem succ_pos (a : Fin n) : (0 : Fin (n + 1)) < a.succ := by
simp [Fin.lt_def, Nat.succ_pos]
simp [Fin.lt_def]
@[simp] theorem succ_le_succ_iff {a b : Fin n} : a.succ b.succ a b := Nat.succ_le_succ_iff
@@ -414,7 +414,7 @@ theorem one_lt_succ_succ (a : Fin n) : (1 : Fin (n + 2)) < a.succ.succ := by
simp only [lt_def, val_add, val_last, Fin.ext_iff]
let k, hk := k
match Nat.eq_or_lt_of_le (Nat.le_of_lt_succ hk) with
| .inl h => cases h; simp [Nat.succ_pos]
| .inl h => cases h; simp
| .inr hk' => simp [Nat.ne_of_lt hk', Nat.mod_eq_of_lt (Nat.succ_lt_succ hk'), Nat.le_succ]
@[simp] theorem add_one_le_iff {n : Nat} : {k : Fin (n + 1)}, k + 1 k k = last _ := by
@@ -426,7 +426,7 @@ theorem one_lt_succ_succ (a : Fin n) : (1 : Fin (n + 2)) < a.succ.succ := by
intro (k : Fin (n+2))
rw [ add_one_lt_iff, lt_def, le_def, Nat.lt_iff_le_and_ne, and_iff_left]
rw [val_add_one]
split <;> simp [*, (Nat.succ_ne_zero _).symm, Nat.ne_of_gt (Nat.lt_succ_self _)]
split <;> simp [*, Nat.ne_of_gt (Nat.lt_succ_self _)]
@[simp] theorem last_le_iff {n : Nat} {k : Fin (n + 1)} : last n k k = last n := by
rw [Fin.ext_iff, Nat.le_antisymm_iff, le_def, and_iff_right (by apply le_last)]
@@ -738,7 +738,7 @@ theorem pred_mk {n : Nat} (i : Nat) (h : i < n + 1) (w) : Fin.pred ⟨i, h⟩ w
{a b : Fin (n + 1)} {ha : a 0} {hb : b 0}, a.pred ha = b.pred hb a = b
| 0, _, _, ha, _ => by simp only [mk_zero, ne_eq, not_true] at ha
| i + 1, _, 0, _, _, hb => by simp only [mk_zero, ne_eq, not_true] at hb
| i + 1, hi, j + 1, hj, ha, hb => by simp [Fin.ext_iff, Nat.succ.injEq]
| i + 1, hi, j + 1, hj, ha, hb => by simp [Fin.ext_iff]
@[simp] theorem pred_one {n : Nat} :
Fin.pred (1 : Fin (n + 2)) (Ne.symm (Fin.ne_of_lt one_pos)) = 0 := rfl
@@ -1117,7 +1117,7 @@ protected theorem mul_one [i : NeZero n] (k : Fin n) : k * 1 = k := by
| n + 1, _ =>
match n with
| 0 => exact Subsingleton.elim (α := Fin 1) ..
| n+1 => simp [Fin.ext_iff, mul_def, Nat.mod_eq_of_lt (is_lt k)]
| n+1 => simp [mul_def, Nat.mod_eq_of_lt (is_lt k)]
protected theorem mul_comm (a b : Fin n) : a * b = b * a :=
Fin.ext <| by rw [mul_def, mul_def, Nat.mul_comm]

View File

@@ -37,7 +37,7 @@ theorem compare_eq_ite_le (a b : Int) :
· next hlt => simp [Int.le_of_lt hlt, Int.not_le.2 hlt]
· next hge =>
split
· next hgt => simp [Int.le_of_lt hgt, Int.not_le.2 hgt]
· next hgt => simp [Int.not_le.2 hgt]
· next hle => simp [Int.not_lt.1 hge, Int.not_lt.1 hle]
protected theorem compare_swap (a b : Int) : (compare a b).swap = compare b a := by

View File

@@ -56,7 +56,7 @@ protected theorem dvd_trans : ∀ {a b c : Int}, a b → b c → a c
@[simp] 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]
-k, by simp [ e, 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

View File

@@ -217,7 +217,7 @@ theorem tdiv_eq_ediv {a b : 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]
simp only [Nat.succ_eq_add_one, false_or]
split <;> rename_i h
· rw [Int.add_zero, neg_ofNat_eq_negSucc_iff]
exact Nat.succ_div_of_mod_eq_zero h
@@ -1317,7 +1317,7 @@ protected theorem eq_tdiv_of_mul_eq_left {a b c : Int}
| 0, n => by simp [Int.neg_zero]
| succ _, (n:Nat) => by simp [tdiv, Int.negSucc_eq]
| -[_+1], 0 | -[_+1], -[_+1] => by
simp only [tdiv, neg_negSucc, Int.natCast_succ, Int.neg_neg]
simp only [tdiv, neg_negSucc, Int.neg_neg]
| succ _, -[_+1] | -[_+1], succ _ => (Int.neg_neg _).symm
protected theorem neg_tdiv_neg (a b : Int) : (-a).tdiv (-b) = a.tdiv b := by
@@ -1408,7 +1408,7 @@ theorem mul_tmod (a b n : Int) : (a * b).tmod n = (a.tmod n * b.tmod n).tmod n :
case inv => simp [Int.dvd_neg]
induction m using wlog_sign
case inv => simp
simp only [ Int.natCast_mul, ofNat_tmod]
simp only [ ofNat_tmod]
norm_cast at h
rw [Nat.mod_mod_of_dvd _ h]
@@ -1576,7 +1576,7 @@ theorem neg_mul_tmod_left (a b : Int) : (-(a * b)).tmod b = 0 := by
@[simp] protected theorem tdiv_one : a : Int, a.tdiv 1 = a
| (n:Nat) => congrArg ofNat (Nat.div_one _)
| -[n+1] => by simp [Int.tdiv, neg_ofNat_succ]; rfl
| -[n+1] => by simp [Int.tdiv]; rfl
@[simp] theorem tmod_one (a : Int) : tmod a 1 = 0 := by
simp [tmod_def, Int.tdiv_one, Int.one_mul, Int.sub_self]
@@ -1698,7 +1698,7 @@ theorem lt_ediv_iff_of_dvd_of_neg {a b c : Int} (hc : c < 0) (hcb : c b) :
theorem ediv_le_ediv_iff_of_dvd_of_pos_of_pos {a b c d : Int} (hb : 0 < b) (hd : 0 < d)
(hba : b a) (hdc : d c) : a / b c / d d * a c * b := by
obtain x, rfl, y, rfl := hba, hdc
simp [*, Int.ne_of_lt, Int.ne_of_gt, d.mul_assoc, b.mul_comm]
simp [*, Int.ne_of_gt, d.mul_assoc, b.mul_comm]
theorem ediv_le_ediv_iff_of_dvd_of_pos_of_neg {a b c d : Int} (hb : 0 < b) (hd : d < 0)
(hba : b a) (hdc : d c) : a / b c / d c * b d * a := by
@@ -1713,12 +1713,12 @@ theorem ediv_le_ediv_iff_of_dvd_of_neg_of_pos {a b c d : Int} (hb : b < 0) (hd :
theorem ediv_le_ediv_iff_of_dvd_of_neg_of_neg {a b c d : Int} (hb : b < 0) (hd : d < 0)
(hba : b a) (hdc : d c) : a / b c / d d * a c * b := by
obtain x, rfl, y, rfl := hba, hdc
simp [*, Int.ne_of_lt, Int.ne_of_gt, d.mul_assoc, b.mul_comm]
simp [*, Int.ne_of_lt, d.mul_assoc, b.mul_comm]
theorem ediv_lt_ediv_iff_of_dvd_of_pos {a b c d : Int} (hb : 0 < b) (hd : 0 < d) (hba : b a)
(hdc : d c) : a / b < c / d d * a < c * b := by
obtain x, rfl, y, rfl := hba, hdc
simp [*, Int.ne_of_lt, Int.ne_of_gt, d.mul_assoc, b.mul_comm]
simp [*, Int.ne_of_gt, d.mul_assoc, b.mul_comm]
theorem ediv_lt_ediv_iff_of_dvd_of_pos_of_neg {a b c d : Int} (hb : 0 < b) (hd : d < 0)
(hba : b a) (hdc : d c) : a / b < c / d c * b < d * a := by
@@ -1733,7 +1733,7 @@ theorem ediv_lt_ediv_iff_of_dvd_of_neg_of_pos {a b c d : Int} (hb : b < 0) (hd :
theorem ediv_lt_ediv_iff_of_dvd_of_neg_of_neg {a b c d : Int} (hb : b < 0) (hd : d < 0)
(hba : b a) (hdc : d c) : a / b < c / d d * a < c * b := by
obtain x, rfl, y, rfl := hba, hdc
simp [*, Int.ne_of_lt, Int.ne_of_gt, d.mul_assoc, b.mul_comm]
simp [*, Int.ne_of_lt, d.mul_assoc, b.mul_comm]
/-! ### `tdiv` and ordering -/
@@ -2446,7 +2446,7 @@ theorem lt_mul_fdiv_self_add {x k : Int} (h : 0 < k) : x < k * (x.fdiv k) + k :=
@[simp]
theorem emod_bmod (x : Int) (n : Nat) : Int.bmod (x%n) n = Int.bmod x n := by
simp [bmod, Int.emod_emod]
simp [bmod]
@[deprecated emod_bmod (since := "2025-04-11")]
theorem emod_bmod_congr (x : Int) (n : Nat) : Int.bmod (x%n) n = Int.bmod x n :=
@@ -2987,7 +2987,7 @@ theorem self_le_ediv_of_nonpos_of_nonneg {x y : Int} (hx : x ≤ 0) (hy : 0 ≤
· simp [hx', zero_ediv]
· by_cases hy : y = 0
· simp [hy]; omega
· simp only [ge_iff_le, Int.le_ediv_iff_mul_le (c := y) (a := x) (b := x) (by omega),
· simp only [Int.le_ediv_iff_mul_le (c := y) (a := x) (b := x) (by omega),
show (x * y x) = (x * y x * 1) by rw [Int.mul_one], Int.mul_one]
apply Int.mul_le_mul_of_nonpos_left (a := x) (b := y) (c := (1 : Int)) (by omega) (by omega)

View File

@@ -631,7 +631,7 @@ theorem lcm_mul_left_dvd_mul_lcm (k m n : Nat) : lcm (m * n) k lcm m k * lcm
simpa [lcm_comm, Nat.mul_comm] using lcm_mul_right_dvd_mul_lcm _ _ _
theorem lcm_dvd_mul_self_left_iff_dvd_mul {k n m : Nat} : lcm k n k * m n k * m := by
simp [ natAbs_dvd_natAbs, natAbs_mul, Nat.lcm_dvd_mul_self_left_iff_dvd_mul,
simp [Nat.lcm_dvd_mul_self_left_iff_dvd_mul,
lcm_eq_natAbs_lcm_natAbs]
theorem lcm_dvd_mul_self_right_iff_dvd_mul {k m n : Nat} : lcm n k m * k n m * k := by

View File

@@ -454,7 +454,7 @@ theorem negOfNat_eq_subNatNat_zero (n) : negOfNat n = subNatNat 0 n := by cases
theorem ofNat_mul_subNatNat (m n k : Nat) :
m * subNatNat n k = subNatNat (m * n) (m * k) := by
cases m with
| zero => simp [ofNat_zero, Int.zero_mul, Nat.zero_mul, subNatNat_self]
| zero => simp [Int.zero_mul, Nat.zero_mul, subNatNat_self]
| succ m => cases n.lt_or_ge k with
| inl h =>
have h' : succ m * n < succ m * k := Nat.mul_lt_mul_of_pos_left h (Nat.succ_pos m)

View File

@@ -79,8 +79,8 @@ where
theorem Poly.denote'_go_eq_denote (ctx : Context) (p : Poly) (r : Int) : denote'.go ctx r p = p.denote ctx + r := by
induction r, p using denote'.go.induct ctx <;> simp [denote'.go, denote]
next => rw [Int.add_comm]
next ih => simp [denote'.go] at ih; rw [ih]; ac_rfl
next ih => simp [denote'.go] at ih; rw [ih]; ac_rfl
next ih => simp at ih; rw [ih]; ac_rfl
next ih => simp at ih; rw [ih]; ac_rfl
theorem Poly.denote'_eq_denote (ctx : Context) (p : Poly) : p.denote' ctx = p.denote ctx := by
unfold denote' <;> split <;> simp [denote, denote'_go_eq_denote] <;> ac_rfl
@@ -363,7 +363,7 @@ theorem Expr.denote_toPoly'_go (ctx : Context) (e : Expr) :
simp [eq_of_beq h]
| case2 k k' h =>
simp only [toPoly'.go, h, cond_false]
simp [Var.denote]
simp
| case3 k i => simp [toPoly'.go]
| case4 k a b iha ihb => simp [toPoly'.go, iha, ihb]
| case5 k a b iha ihb =>
@@ -371,7 +371,7 @@ theorem Expr.denote_toPoly'_go (ctx : Context) (e : Expr) :
rw [Int.sub_eq_add_neg, Int.neg_mul, Int.add_assoc]
| case6 k k' a h
| case8 k a k' h =>
simp only [toPoly'.go, h, cond_false]
simp only [toPoly'.go, h]
simp [eq_of_beq h]
| case7 k a k' h ih =>
simp only [toPoly'.go, h, cond_false]
@@ -403,7 +403,7 @@ attribute [local simp] Poly.denote'_eq_denote
theorem Expr.eq_of_norm_eq (ctx : Context) (e : Expr) (p : Poly) (h : e.norm == p) : e.denote ctx = p.denote' ctx := by
have h := congrArg (Poly.denote ctx) (eq_of_beq h)
simp [Poly.norm] at h
simp at h
simp [*]
@[expose]
@@ -472,7 +472,7 @@ private theorem mul_le_zero_iff (a k : Int) (h₁ : k > 0) : k * a ≤ 0 ↔ a
simp at h; assumption
private theorem norm_le_coeff' (ctx : Context) (p p' : Poly) (k : Int) : p = p'.mul k k > 0 (p.denote ctx 0 p'.denote ctx 0) := by
simp [norm_eq_coeff_cert]
simp
intro; subst p; intro h; simp [mul_le_zero_iff, *]
theorem norm_le_coeff (ctx : Context) (lhs rhs : Expr) (p : Poly) (k : Int)
@@ -815,7 +815,7 @@ theorem dvd_solve_combine (ctx : Context) (d₁ : Int) (p₁ : Poly) (d₂ : Int
split <;> simp
next a₁ x₁ p₁ a₂ x₂ p₂ =>
intro _ hg hd hp; subst x₁ p
simp [Poly.denote'_add]
simp
intro h₁ h₂
rw [Int.add_comm] at h₁ h₂
rw [Int.add_comm _ (g * x₂.denote ctx), Int.add_left_comm, Int.add_assoc, hd]
@@ -1100,7 +1100,7 @@ theorem diseq_coeff (ctx : Context) (p p' : Poly) (k : Int) : eq_coeff_cert p p'
intro _ _; simp [mul_eq_zero_iff, *]
theorem diseq_neg (ctx : Context) (p p' : Poly) : p' == p.mul (-1) p.denote' ctx 0 p'.denote' ctx 0 := by
simp; intro _ _; simp [mul_eq_zero_iff, *]
simp; intro _ _; simp [*]
theorem diseq_unsat (ctx : Context) (p : Poly) : p.isUnsatDiseq p.denote' ctx 0 False := by
simp [Poly.isUnsatDiseq] <;> split <;> simp
@@ -1311,7 +1311,7 @@ def cooper_dvd_left_split_ineq_cert (p₁ p₂ : Poly) (k : Int) (b : Int) (p' :
theorem cooper_dvd_left_split_ineq (ctx : Context) (p₁ p₂ p₃ : Poly) (d : Int) (k : Nat) (b : Int) (p' : Poly)
: cooper_dvd_left_split ctx p₁ p₂ p₃ d k cooper_dvd_left_split_ineq_cert p₁ p₂ k b p' p'.denote' ctx 0 := by
simp [cooper_dvd_left_split_ineq_cert, cooper_dvd_left_split]
intros; subst p' b; simp [denote'_mul_combine_mul_addConst_eq]; assumption
intros; subst p' b; simp; assumption
@[expose]
def cooper_dvd_left_split_dvd1_cert (p₁ p' : Poly) (a : Int) (k : Int) : Bool :=
@@ -1348,7 +1348,7 @@ private theorem cooper_left_core
have h := cooper_dvd_left_core a_neg b_pos d_pos h₁ h₂ h₃
simp only [Int.mul_one, gcd_zero, ofNat_natAbs_of_nonpos (Int.le_of_lt a_neg), Int.ediv_neg,
Int.ediv_self (Int.ne_of_lt a_neg), Int.reduceNeg, lcm_neg_right, lcm_one,
Int.add_left_comm, Int.zero_mul, Int.mul_zero, Int.add_zero, Int.dvd_zero,
Int.zero_mul, Int.mul_zero, Int.add_zero, Int.dvd_zero,
and_true] at h
assumption
@@ -1398,7 +1398,7 @@ def cooper_left_split_ineq_cert (p₁ p₂ : Poly) (k : Int) (b : Int) (p' : Pol
theorem cooper_left_split_ineq (ctx : Context) (p₁ p₂ : Poly) (k : Nat) (b : Int) (p' : Poly)
: cooper_left_split ctx p₁ p₂ k cooper_left_split_ineq_cert p₁ p₂ k b p' p'.denote' ctx 0 := by
simp [cooper_left_split_ineq_cert, cooper_left_split]
intros; subst p' b; simp [denote'_mul_combine_mul_addConst_eq]; assumption
intros; subst p' b; simp; assumption
@[expose]
def cooper_left_split_dvd_cert (p₁ p' : Poly) (a : Int) (k : Int) : Bool :=
@@ -1422,7 +1422,7 @@ private theorem cooper_dvd_right_core
have h₁' : p (-a)*x := by rw [Int.neg_mul, Lean.Omega.Int.add_le_zero_iff_le_neg']; assumption
have h₂' : b * x -q := by rw [ Lean.Omega.Int.add_le_zero_iff_le_neg', Int.add_comm]; assumption
have k, h₁, h₂, h₃, h₄, h₅ := Int.cooper_resolution_dvd_right a_pos' b_pos d_pos |>.mp x, h₁', h₂', h₃
simp only [Int.neg_mul, neg_gcd, lcm_neg_left, Int.mul_neg, Int.neg_neg, Int.neg_dvd] at *
simp only [Int.neg_mul, Int.mul_neg, Int.neg_neg] at *
apply orOver_of_exists
have hlt := ofNat_lt h₁ h₂
replace h₃ := Int.add_le_add_right h₃ (-(a*q)); rw [Int.add_right_neg] at h₃
@@ -1432,7 +1432,7 @@ private theorem cooper_dvd_right_core
have : -(c * k) + -(c * q) + b * s = -(c * q) + b * s + -(c * k) := by ac_rfl
rw [this] at h₅; clear this
exists k.toNat
simp only [hlt, true_and, and_true, cast_toNat h₁, h₃, h₄, h₅]
simp only [hlt, and_true, cast_toNat h₁, h₃, h₄, h₅]
@[expose]
def cooper_dvd_right_cert (p₁ p₂ p₃ : Poly) (d : Int) (n : Nat) : Bool :=
@@ -1473,7 +1473,7 @@ theorem cooper_dvd_right (ctx : Context) (p₁ p₂ p₃ : Poly) (d : Int) (n :
intro h₁ h₂ h₃
have := cooper_dvd_right_core ha hb hd h₁ h₂ h₃
simp only [denote'_mul_combine_mul_addConst_eq]
simp only [denote'_addConst_eq, Int.neg_mul]
simp only [denote'_addConst_eq]
exact cooper_dvd_right_core ha hb hd h₁ h₂ h₃
@[expose]
@@ -1487,7 +1487,7 @@ def cooper_dvd_right_split_ineq_cert (p₁ p₂ : Poly) (k : Int) (a : Int) (p'
theorem cooper_dvd_right_split_ineq (ctx : Context) (p₁ p₂ p₃ : Poly) (d : Int) (k : Nat) (a : Int) (p' : Poly)
: cooper_dvd_right_split ctx p₁ p₂ p₃ d k cooper_dvd_right_split_ineq_cert p₁ p₂ k a p' p'.denote' ctx 0 := by
simp [cooper_dvd_right_split_ineq_cert, cooper_dvd_right_split]
intros; subst a p'; simp [denote'_mul_combine_mul_addConst_eq]; assumption
intros; subst a p'; simp; assumption
@[expose]
def cooper_dvd_right_split_dvd1_cert (p₂ p' : Poly) (b : Int) (k : Int) : Bool :=
@@ -1522,9 +1522,9 @@ private theorem cooper_right_core
have d_pos : (0 : Int) < 1 := by decide
have h₃ : 1 0*x + 0 := Int.one_dvd _
have h := cooper_dvd_right_core a_neg b_pos d_pos h₁ h₂ h₃
simp only [Int.mul_one, gcd_zero, Int.natAbs_of_nonneg (Int.le_of_lt b_pos), Int.ediv_neg,
Int.ediv_self (Int.ne_of_gt b_pos), Int.reduceNeg, lcm_neg_right, lcm_one,
Int.add_left_comm, Int.zero_mul, Int.mul_zero, Int.add_zero, Int.dvd_zero,
simp only [Int.mul_one, gcd_zero, Int.natAbs_of_nonneg (Int.le_of_lt b_pos),
Int.ediv_self (Int.ne_of_gt b_pos), lcm_one,
Int.zero_mul, Int.mul_zero, Int.add_zero, Int.dvd_zero,
and_true, Int.neg_zero] at h
assumption
@@ -1559,7 +1559,7 @@ theorem cooper_right (ctx : Context) (p₁ p₂ : Poly) (n : Nat)
intro h₁ h₂
have := cooper_right_core ha hb h₁ h₂
simp only [denote'_mul_combine_mul_addConst_eq]
simp only [denote'_addConst_eq, Int.neg_mul]
simp only [denote'_addConst_eq]
assumption
@[expose]
@@ -1573,7 +1573,7 @@ def cooper_right_split_ineq_cert (p₁ p₂ : Poly) (k : Int) (a : Int) (p' : Po
theorem cooper_right_split_ineq (ctx : Context) (p₁ p₂ : Poly) (k : Nat) (a : Int) (p' : Poly)
: cooper_right_split ctx p₁ p₂ k cooper_right_split_ineq_cert p₁ p₂ k a p' p'.denote' ctx 0 := by
simp [cooper_right_split_ineq_cert, cooper_right_split]
intros; subst a p'; simp [denote'_mul_combine_mul_addConst_eq]; assumption
intros; subst a p'; simp; assumption
@[expose]
def cooper_right_split_dvd_cert (p₂ p' : Poly) (b : Int) (k : Int) : Bool :=
@@ -1682,7 +1682,7 @@ theorem cooper_unsat (ctx : Context) (p₁ p₂ p₃ : Poly) (d : Int) (α β :
: cooper_unsat_cert p₁ p₂ p₃ d α β
p₁.denote' ctx 0 p₂.denote' ctx 0 d p₃.denote' ctx False := by
unfold cooper_unsat_cert <;> cases p₁ <;> cases p₂ <;> cases p₃ <;> simp only [Poly.casesOnAdd,
Bool.false_eq_true, Poly.denote'_add, mul_def, add_def, false_implies]
Bool.false_eq_true, Poly.denote'_add, false_implies]
next k₁ x p₁ k₂ y p₂ c z p₃ =>
cases p₁ <;> cases p₂ <;> cases p₃ <;> simp only [Poly.casesOnNum, Int.reduceNeg,
Bool.and_eq_true, beq_iff_eq, decide_eq_true_eq, and_imp, Bool.false_eq_true,
@@ -1819,7 +1819,7 @@ def dvd_neg_le_tight_cert (d : Int) (p₁ p₂ p₃ : Poly) : Bool :=
d > 0 && (p₂ == p.addConst b₂ && p₃ == p.addConst (b₁ - d*((b₁ - b₂)/d)))
theorem Poly.mul_minus_one_getConst_eq (p : Poly) : (p.mul (-1)).getConst = -p.getConst := by
simp [Poly.mul, Poly.getConst]
simp [Poly.mul]
induction p <;> simp [Poly.mul', Poly.getConst, *]
theorem dvd_neg_le_tight (ctx : Context) (d : Int) (p₁ p₂ p₃ : Poly)
@@ -1900,7 +1900,7 @@ theorem not_le_of_le (ctx : Context) (p q : Poly) (k : Nat)
intro h
apply Int.pos_of_neg_neg
apply Int.lt_of_add_one_le
simp [Int.neg_add, Int.neg_sub]
simp [Int.neg_add]
rw [ Int.add_assoc, Int.add_assoc, Int.add_neg_cancel_right, Lean.Omega.Int.add_le_zero_iff_le_neg']
simp; exact Int.le_trans h (Int.ofNat_zero_le _)

View File

@@ -51,7 +51,7 @@ def Expr.denoteAsInt (ctx : Context) : Expr → Int
| .mod a b => Int.emod (denoteAsInt ctx a) (denoteAsInt ctx b)
theorem Expr.denoteAsInt_eq (ctx : Context) (e : Expr) : e.denoteAsInt ctx = e.denote ctx := by
induction e <;> simp [denote, denoteAsInt, Int.natCast_ediv, *] <;> rfl
induction e <;> simp [denote, denoteAsInt, *] <;> rfl
theorem Expr.eq_denoteAsInt (ctx : Context) (e : Expr) : e.denote ctx = e.denoteAsInt ctx := by
apply Eq.symm; apply denoteAsInt_eq

View File

@@ -448,7 +448,7 @@ protected theorem le_max_left (a b : Int) : a ≤ max a b := by rw [Int.max_def]
protected theorem le_max_right (a b : Int) : b max a b := Int.max_comm .. Int.le_max_left ..
protected theorem max_eq_right {a b : Int} (h : a b) : max a b = b := by
simp [Int.max_def, h, Int.not_lt.2 h]
simp [Int.max_def, h]
protected theorem max_eq_left {a b : Int} (h : b a) : max a b = a := by
rw [ Int.max_comm b a]; exact Int.max_eq_right h

View File

@@ -188,10 +188,10 @@ protected theorem PostconditionT.bind_assoc {m : Type w → Type w'} [Monad m] [
protected theorem PostconditionT.map_pure {m : Type w Type w'} [Monad m] [LawfulMonad m]
{α : Type w} {β : Type w} {f : α β} {a : α} :
(pure a : PostconditionT m α).map f = pure (f a) := by
apply PostconditionT.ext <;> simp [pure, Functor.map, PostconditionT.map, PostconditionT.pure]
apply PostconditionT.ext <;> simp [pure, PostconditionT.map, PostconditionT.pure]
instance [Monad m] [LawfulMonad m] : LawfulMonad (PostconditionT m) where
map_const {α β} := by ext a x; simp [Functor.mapConst, Function.const_apply, Functor.map]
map_const {α β} := by ext a x; simp [Functor.mapConst, Functor.map]
id_map {α} x := by simp [Functor.map]
comp_map {α β γ} g h := by intro x; simp [Functor.map]; rfl
seqLeft_eq {α β} x y := by simp [SeqLeft.seqLeft, Functor.map, Seq.seq]; rfl

View File

@@ -255,7 +255,7 @@ set_option linter.deprecated false in
theorem get?_pmap {p : α Prop} (f : a, p a β) {l : List α} (h : a l, p a) (n : Nat) :
get? (pmap f l h) n = Option.pmap f (get? l n) fun x H => h x (mem_of_get? H) := by
simp only [get?_eq_getElem?]
simp [getElem?_pmap, h]
simp [getElem?_pmap]
-- The argument `f` is explicit to allow rewriting from right to left.
@[simp, grind =]
@@ -322,14 +322,14 @@ theorem getElem_attach {xs : List α} {i : Nat} (h : i < xs.attach.length) :
| nil => simp
| cons x xs ih =>
simp at ih
simp [head?_pmap, ih]
simp
@[simp, grind =] theorem head_pmap {P : α Prop} {f : (a : α) P a β} {xs : List α}
(H : (a : α), a xs P a) (h : xs.pmap f H []) :
(xs.pmap f H).head h = f (xs.head (by simpa using h)) (H _ (head_mem _)) := by
induction xs with
| nil => simp at h
| cons x xs ih => simp [head_pmap, ih]
| cons x xs ih => simp
@[simp, grind =] theorem head?_attachWith {P : α Prop} {xs : List α}
(H : (a : α), a xs P a) :
@@ -341,7 +341,7 @@ theorem getElem_attach {xs : List α} {i : Nat} (h : i < xs.attach.length) :
(xs.attachWith P H).head h = xs.head (by simpa using h), H _ (head_mem _) := by
cases xs with
| nil => simp at h
| cons x xs => simp [head_attachWith, h]
| cons x xs => simp
@[simp, grind =] theorem head?_attach {xs : List α} :
xs.attach.head? = xs.head?.pbind (fun a h => some a, mem_of_head? h) := by
@@ -351,7 +351,7 @@ theorem getElem_attach {xs : List α} {i : Nat} (h : i < xs.attach.length) :
xs.attach.head h = xs.head (by simpa using h), head_mem (by simpa using h) := by
cases xs with
| nil => simp at h
| cons x xs => simp [head_attach, h]
| cons x xs => simp
@[simp, grind =] theorem tail_pmap {P : α Prop} {f : (a : α) P a β} {xs : List α}
(H : (a : α), a xs P a) :
@@ -472,7 +472,7 @@ theorem attach_filterMap {l : List α} {f : α → Option β} :
induction l with
| nil => rfl
| cons x xs ih =>
simp only [filterMap_cons, attach_cons, ih, filterMap_map]
simp only [filterMap_cons, attach_cons, filterMap_map]
split <;> rename_i h
· simp only [Option.pbind_eq_none_iff, reduceCtorEq, exists_false,
or_false] at h
@@ -554,7 +554,7 @@ theorem pmap_append' {p : α → Prop} {f : ∀ a : α, p a → β} {l₁ l₂ :
@[simp, grind =] theorem attach_append {xs ys : List α} :
(xs ++ ys).attach = xs.attach.map (fun x, h => x, mem_append_left ys h) ++
ys.attach.map fun x, h => x, mem_append_right xs h := by
simp only [attach, attachWith, pmap, map_pmap, pmap_append]
simp only [attach, attachWith, map_pmap, pmap_append]
congr 1 <;>
exact pmap_congr_left _ fun _ _ _ _ => rfl
@@ -562,7 +562,7 @@ theorem pmap_append' {p : α → Prop} {f : ∀ a : α, p a → β} {l₁ l₂ :
{H : (a : α), a xs ++ ys P a} :
(xs ++ ys).attachWith P H = xs.attachWith P (fun a h => H a (mem_append_left ys h)) ++
ys.attachWith P (fun a h => H a (mem_append_right xs h)) := by
simp only [attachWith, attach_append, map_pmap, pmap_append]
simp only [attachWith, pmap_append]
@[simp, grind =] theorem pmap_reverse {P : α Prop} {f : (a : α) P a β} {xs : List α}
(H : (a : α), a xs.reverse P a) :
@@ -625,7 +625,7 @@ theorem reverse_attach {xs : List α} :
@[simp, grind =] theorem getLast_attachWith {P : α Prop} {xs : List α}
{H : (a : α), a xs P a} (h : xs.attachWith P H []) :
(xs.attachWith P H).getLast h = xs.getLast (by simpa using h), H _ (getLast_mem _) := by
simp only [getLast_eq_head_reverse, reverse_attachWith, head_attachWith, head_map]
simp only [getLast_eq_head_reverse, reverse_attachWith, head_attachWith]
@[simp, grind =]
theorem getLast?_attach {xs : List α} :
@@ -651,12 +651,12 @@ theorem countP_attachWith {p : α → Prop} {q : α → Bool} {l : List α} (H :
@[simp]
theorem count_attach [BEq α] {l : List α} {a : {x // x l}} :
l.attach.count a = l.count a :=
Eq.trans (countP_congr fun _ _ => by simp [Subtype.ext_iff]) <| countP_attach
Eq.trans (countP_congr fun _ _ => by simp) <| countP_attach
@[simp, grind =]
theorem count_attachWith [BEq α] {p : α Prop} {l : List α} (H : a l, p a) {a : {x // p x}} :
(l.attachWith p H).count a = l.count a :=
Eq.trans (countP_congr fun _ _ => by simp [Subtype.ext_iff]) <| countP_attachWith _
Eq.trans (countP_congr fun _ _ => by simp) <| countP_attachWith _
@[simp, grind =] theorem countP_pmap {p : α Prop} {g : a, p a β} {f : β Bool} {l : List α} (H₁) :
(l.pmap g H₁).countP f =
@@ -717,7 +717,7 @@ def unattach {α : Type _} {p : α → Prop} (l : List { x // p x }) : List α :
unfold unattach
induction l with
| nil => simp
| cons a l ih => simp [ih, Function.comp_def]
| cons a l ih => simp [ih]
@[simp] theorem getElem?_unattach {p : α Prop} {l : List { x // p x }} (i : Nat) :
l.unattach[i]? = l[i]?.map Subtype.val := by

View File

@@ -730,9 +730,9 @@ Examples:
-/
@[inline] def flatMap {α : Type u} {β : Type v} (b : α List β) (as : List α) : List β := flatten (map b as)
@[simp, grind] theorem flatMap_nil {f : α List β} : List.flatMap f [] = [] := by simp [flatten, List.flatMap]
@[simp, grind] theorem flatMap_nil {f : α List β} : List.flatMap f [] = [] := by simp [List.flatMap]
@[simp, grind] theorem flatMap_cons {x : α} {xs : List α} {f : α List β} :
List.flatMap f (x :: xs) = f x ++ List.flatMap f xs := by simp [flatten, List.flatMap]
List.flatMap f (x :: xs) = f x ++ List.flatMap f xs := by simp [List.flatMap]
/-! ### replicate -/
@@ -753,7 +753,7 @@ def replicate : (n : Nat) → (a : α) → List α
@[simp, grind] theorem length_replicate {n : Nat} {a : α} : (replicate n a).length = n := by
induction n with
| zero => simp
| succ n ih => simp only [ih, replicate_succ, length_cons, Nat.succ_eq_add_one]
| succ n ih => simp only [ih, replicate_succ, length_cons]
/-! ## Additional functions -/
@@ -892,7 +892,7 @@ theorem mem_of_elem_eq_true [BEq α] [LawfulBEq α] {a : α} {as : List α} : el
| a'::as =>
simp [elem]
split
next h => intros; simp [BEq.beq] at h; subst h; apply Mem.head
next h => intros; simp at h; subst h; apply Mem.head
next _ => intro h; exact Mem.tail _ (mem_of_elem_eq_true h)
theorem elem_eq_true_of_mem [BEq α] [ReflBEq α] {a : α} {as : List α} (h : a as) : elem a as = true := by
@@ -1780,7 +1780,7 @@ where
| a :: l, i, h =>
if p a then
some i, by
simp only [Nat.add_comm _ i, Nat.add_assoc] at h
simp only [Nat.add_comm _ i] at h
exact Nat.lt_of_add_right_lt (Nat.lt_of_succ_le (Nat.le_of_eq h))
else
go l (i + 1) (by simp at h; simpa [ Nat.add_assoc, Nat.add_right_comm] using h)
@@ -2015,7 +2015,7 @@ def zip : List α → List β → List (Prod α β) :=
zipWith Prod.mk
@[simp] theorem zip_nil_left : zip ([] : List α) (l : List β) = [] := rfl
@[simp] theorem zip_nil_right : zip (l : List α) ([] : List β) = [] := by simp [zip, zipWith]
@[simp] theorem zip_nil_right : zip (l : List α) ([] : List β) = [] := by simp [zip]
@[simp] theorem zip_cons_cons : zip (a :: as) (b :: bs) = (a, b) :: zip as bs := rfl
/-! ### zipWithAll -/

View File

@@ -276,7 +276,7 @@ theorem getElem_append_right {as bs : List α} {i : Nat} (h₁ : as.length ≤ i
induction as generalizing i with
| nil => trivial
| cons a as ih =>
cases i with simp [Nat.succ_sub_succ] <;> simp [Nat.succ_sub_succ] at h₁
cases i with simp [Nat.succ_sub_succ] <;> simp at h₁
| succ i => apply ih; simp [h₁]
@[deprecated "Deprecated without replacement." (since := "2025-02-13")]

View File

@@ -86,7 +86,7 @@ theorem countP_le_length : countP p l ≤ l.length := by
simp only [countP_eq_length_filter, filter_append, length_append]
@[simp] theorem countP_pos_iff {p} : 0 < countP p l a l, p a := by
simp only [countP_eq_length_filter, length_pos_iff_exists_mem, mem_filter, exists_prop]
simp only [countP_eq_length_filter, length_pos_iff_exists_mem, mem_filter]
@[simp] theorem one_le_countP_iff {p} : 1 countP p l a l, p a :=
countP_pos_iff
@@ -169,7 +169,7 @@ theorem length_filterMap_eq_countP {f : α → Option β} {l : List α} :
| nil => rfl
| cons x l ih =>
simp only [filterMap_cons, countP_cons]
split <;> simp [ih, *]
split <;> simp [*]
theorem countP_filterMap {p : β Bool} {f : α Option β} {l : List α} :
countP p (filterMap f l) = countP (fun a => ((f a).map p).getD false) l := by

View File

@@ -146,7 +146,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, length_eraseP]
split <;> rename_i h
· simp only [any_eq_true, length_eq_zero_iff] at h
· simp only [any_eq_true] at h
constructor
· intro; simp_all [Nat.sub_one_eq_self]
· intro; obtain x, m, h := h; simp_all
@@ -287,9 +287,9 @@ theorem eraseP_comm {l : List α} (h : ∀ a ∈ l, ¬ p a ¬ q a) :
by_cases h₁ : p a
· by_cases h₂ : q a
· simp_all
· simp [h₁, h₂, ih (fun b m => h b (mem_cons_of_mem _ m))]
· simp [h₁, h₂]
· by_cases h₂ : q a
· simp [h₁, h₂, ih (fun b m => h b (mem_cons_of_mem _ m))]
· simp [h₁, h₂]
· simp [h₁, h₂, ih (fun b m => h b (mem_cons_of_mem _ m))]
theorem head_eraseP_mem {xs : List α} {p : α Bool} (h) : (xs.eraseP p).head h xs :=
@@ -578,7 +578,7 @@ theorem eraseIdx_eq_take_drop_succ :
match l, i with
| [], _
| a::l, 0
| a::l, i + 1 => simp [Nat.succ_inj]
| a::l, i + 1 => simp
@[deprecated eraseIdx_eq_nil_iff (since := "2025-01-30")]
abbrev eraseIdx_eq_nil := @eraseIdx_eq_nil_iff
@@ -587,7 +587,7 @@ theorem eraseIdx_ne_nil_iff {l : List α} {i : Nat} : eraseIdx l i ≠ [] ↔ 2
match l with
| []
| [a]
| a::b::l => simp [Nat.succ_inj]
| a::b::l => simp
@[deprecated eraseIdx_ne_nil_iff (since := "2025-01-30")]
abbrev eraseIdx_ne_nil := @eraseIdx_ne_nil_iff

View File

@@ -183,7 +183,7 @@ grind_pattern Sublist.findSome?_isSome => l₁ <+ l₂, l₂.findSome? f
theorem Sublist.findSome?_eq_none {l₁ l₂ : List α} (h : l₁ <+ l₂) :
l₂.findSome? f = none l₁.findSome? f = none := by
simp only [List.findSome?_eq_none_iff, Bool.not_eq_true]
simp only [List.findSome?_eq_none_iff]
exact fun w x m => w x (Sublist.mem m h)
theorem IsPrefix.findSome?_eq_some {l₁ l₂ : List α} {f : α Option β} (h : l₁ <+: l₂) :
@@ -383,7 +383,7 @@ theorem find?_flatten_eq_some_iff {xs : List (List α)} {p : α → Bool} {a :
· simpa using h₂ x (by simpa using l, ma, m)
· specialize h₁ _ mb
simp_all
· simp [h₁]
· simp
refine as, bs, ?_
refine ?_, ?_, ?_
· simp_all
@@ -592,7 +592,7 @@ theorem findIdx_eq_length {p : α → Bool} {xs : List α} :
| cons x xs ih =>
rw [findIdx_cons, length_cons]
simp only [cond_eq_if]
split <;> simp_all [Nat.succ.injEq]
split <;> simp_all
theorem findIdx_eq_length_of_false {p : α Bool} {xs : List α} (h : x xs, p x = false) :
xs.findIdx p = xs.length := by
@@ -737,7 +737,7 @@ theorem findIdx?_eq_none_iff {xs : List α} {p : α → Bool} :
| nil => simp_all
| cons x xs ih =>
simp only [findIdx?_cons]
split <;> simp_all [cond_eq_if]
split <;> simp_all
@[simp, grind =]
theorem findIdx?_isSome {xs : List α} {p : α Bool} :
@@ -799,13 +799,13 @@ theorem findIdx?_eq_some_iff_getElem {xs : List α} {p : α → Bool} {i : Nat}
induction xs generalizing i with
| nil => simp
| cons x xs ih =>
simp only [findIdx?_cons, Nat.zero_add]
simp only [findIdx?_cons]
split
· simp only [Option.some.injEq, Bool.not_eq_true, length_cons]
cases i with
| zero => simp_all
| succ i =>
simp only [Bool.not_eq_true, zero_ne_add_one, getElem_cons_succ, false_iff, not_exists,
simp only [zero_ne_add_one, getElem_cons_succ, false_iff, not_exists,
not_and, Classical.not_forall, Bool.not_eq_false]
intros
refine 0, zero_lt_succ i, _
@@ -830,8 +830,8 @@ theorem of_findIdx?_eq_some {xs : List α} {p : α → Bool} (w : xs.findIdx? p
induction xs generalizing i with
| nil => simp_all
| cons x xs ih =>
simp_all only [findIdx?_cons, Nat.zero_add]
split at w <;> cases i <;> simp_all [succ_inj]
simp_all only [findIdx?_cons]
split at w <;> cases i <;> simp_all
@[deprecated of_findIdx?_eq_some (since := "2025-02-02")]
abbrev findIdx?_of_eq_some := @of_findIdx?_eq_some
@@ -842,7 +842,7 @@ theorem of_findIdx?_eq_none {xs : List α} {p : α → Bool} (w : xs.findIdx? p
induction xs generalizing i with
| nil => simp_all
| cons x xs ih =>
simp_all only [Bool.not_eq_true, findIdx?_cons, Nat.zero_add]
simp_all only [Bool.not_eq_true, findIdx?_cons]
cases i with
| zero =>
split at w <;> simp_all
@@ -888,7 +888,7 @@ theorem findIdx?_flatten {l : List (List α)} {p : α → Bool} :
cases n with
| zero => simp
| succ n =>
simp only [replicate, findIdx?_cons, Nat.zero_add, zero_lt_succ, true_and]
simp only [replicate, findIdx?_cons, zero_lt_succ, true_and]
split <;> simp_all
theorem findIdx?_eq_findSome?_zipIdx {xs : List α} {p : α Bool} :
@@ -899,7 +899,7 @@ theorem findIdx?_eq_findSome?_zipIdx {xs : List α} {p : α → Bool} :
simp only [findIdx?_cons, Nat.zero_add, zipIdx]
split
· simp_all
· simp_all only [zipIdx_cons, ite_false, Option.isNone_none, findSome?_cons_of_isNone, reduceCtorEq]
· simp_all only [ite_false, Option.isNone_none, findSome?_cons_of_isNone, reduceCtorEq]
rw [ map_snd_add_zipIdx_eq_zipIdx (n := 1) (k := 0)]
simp [Function.comp_def, findSome?_map]
@@ -975,7 +975,7 @@ theorem findIdx_eq_getD_findIdx? {xs : List α} {p : α → Bool} :
| nil => simp
| cons x xs ih =>
simp only [findIdx_cons, findIdx?_cons]
split <;> simp_all [ih]
split <;> simp_all
@[simp] theorem findIdx?_subtype {p : α Prop} {l : List { x // p x }}
{f : { x // p x } Bool} {g : α Bool} (hf : x h, f x, h = g x) :
@@ -985,7 +985,7 @@ theorem findIdx_eq_getD_findIdx? {xs : List α} {p : α → Bool} :
| nil => simp
| cons a l ih =>
simp [hf, findIdx?_cons]
split <;> simp [ih, Function.comp_def]
split <;> simp [ih]
/-! ### findFinIdx? -/
@@ -1078,7 +1078,7 @@ theorem isNone_findFinIdx? {l : List α} {p : α → Bool} :
{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
induction l with
| nil => simp [unattach]
| nil => simp
| cons a l ih =>
simp [hf, findFinIdx?_cons]
split <;> simp [ih, Function.comp_def]
@@ -1136,7 +1136,7 @@ theorem idxOf_lt_length_of_mem [BEq α] [EquivBEq α] {l : List α} (h : a ∈ l
simp only [mem_cons] at h
obtain rfl | h := h
· simp
· simp only [idxOf_cons, cond_eq_if, beq_iff_eq, length_cons]
· simp only [idxOf_cons, cond_eq_if, length_cons]
specialize ih h
split
· exact zero_lt_succ xs.length

View File

@@ -234,7 +234,7 @@ Examples:
intro xs; induction xs with intro acc
| nil => simp [takeWhile, takeWhileTR.go]
| cons x xs IH =>
simp only [takeWhileTR.go, Array.toListImpl_eq, takeWhile]
simp only [takeWhileTR.go, takeWhile]
split
· intro h; rw [IH] <;> simp_all
· simp [*]

View File

@@ -255,7 +255,7 @@ theorem getElem?_cons_zero {l : List α} : (a::l)[0]? = some a := rfl
@[grind =]
theorem getElem?_cons : (a :: l)[i]? = if i = 0 then some a else l[i-1]? := by
cases i <;> simp [getElem?_cons_zero]
cases i <;> simp
theorem getElem?_eq_some_iff {l : List α} : l[i]? = some a h : i < l.length, l[i] = a :=
match l with
@@ -287,16 +287,16 @@ theorem getElem_eq_iff {l : List α} {i : Nat} (h : i < l.length) : l[i] = x ↔
exact fun w => h, w, fun h => h.2
theorem getElem_eq_getElem?_get {l : List α} {i : Nat} (h : i < l.length) :
l[i] = l[i]?.get (by simp [getElem?_eq_getElem, h]) := by
simp [getElem_eq_iff]
l[i] = l[i]?.get (by simp [h]) := by
simp
theorem getD_getElem? {l : List α} {i : Nat} {d : α} :
l[i]?.getD d = if p : i < l.length then l[i]'p else d := by
if h : i < l.length then
simp [h, getElem?_def]
simp [h]
else
have p : i l.length := Nat.le_of_not_gt h
simp [getElem?_eq_none p, h]
simp [h]
@[simp] theorem getElem_singleton {a : α} {i : Nat} (h : i < 1) : [a][i] = a := by
match i, h with
@@ -332,7 +332,7 @@ theorem ext_getElem {l₁ l₂ : List α} (hl : length l₁ = length l₂)
(h : (i : Nat) (h₁ : i < l₁.length) (h₂ : i < l₂.length), l₁[i]'h₁ = l₂[i]'h₂) : l₁ = l₂ :=
ext_getElem? fun n =>
if h₁ : n < length l₁ then by
simp_all [getElem?_eq_getElem]
simp_all
else by
have h₁ := Nat.le_of_not_lt h₁
rw [getElem?_eq_none h₁, getElem?_eq_none]; rwa [ hl]
@@ -636,7 +636,7 @@ theorem all_bne' [BEq α] [PartialEquivBEq α] {l : List α} :
@[simp] theorem getElem?_set_self {l : List α} {i : Nat} {a : α} (h : i < l.length) :
(l.set i a)[i]? = some a := by
simp_all [getElem?_eq_some_iff]
simp_all
/-- This differs from `getElem?_set_self` by monadically mapping `Function.const _ a` over the `Option`
returned by `l[i]?`. -/
@@ -679,7 +679,7 @@ theorem getElem?_set_self' {l : List α} {i : Nat} {a : α} :
subst h
rw [if_pos rfl]
split <;> rename_i h
· simp only [getElem?_set_self (by simpa), h]
· simp only [getElem?_set_self (by simpa)]
· simp_all
else
simp [h]
@@ -1276,9 +1276,9 @@ theorem length_filter_le (p : α → Bool) (l : List α) :
induction l with
| nil => simp
| cons a l ih =>
simp only [filter_cons, length_cons, succ_eq_add_one]
simp only [filter_cons, length_cons]
split
· simp only [length_cons, succ_eq_add_one]
· simp only [length_cons]
exact Nat.succ_le_succ ih
· exact Nat.le_trans ih (Nat.le_add_right _ _)
@@ -1296,7 +1296,7 @@ theorem length_filter_eq_length_iff {l} : (filter p l).length = l.length ↔ ∀
induction l with
| nil => simp
| cons a l ih =>
simp only [filter_cons, length_cons, succ_eq_add_one, mem_cons, forall_eq_or_imp]
simp only [filter_cons, length_cons, mem_cons, forall_eq_or_imp]
split <;> rename_i h
· simp_all [Nat.add_one_inj] -- Why does the simproc not fire here?
· have := Nat.ne_of_lt (Nat.lt_succ.mpr (length_filter_le p l))
@@ -1388,7 +1388,7 @@ theorem filter_eq_cons_iff {l} {a} {as} :
· obtain l₁, l₂, rfl, w₁, w₂, w₃ := ih h
exact x :: l₁, l₂, by simp_all
· rintro l₁, l₂, rfl, h₁, h, h₂
simp [h₂, filter_cons, filter_eq_nil_iff.mpr h₁, h]
simp [h₂, filter_eq_nil_iff.mpr h₁, h]
theorem filter_congr {p q : α Bool} :
{l : List α}, ( x l, p x = q x) filter p l = filter q l
@@ -1404,7 +1404,7 @@ theorem head_filter_of_pos {p : α → Bool} {l : List α} (w : l ≠ []) (h : p
| nil => simp
| cons =>
simp only [head_cons] at h
simp [filter_cons, h]
simp [h]
@[simp] theorem filter_sublist {p : α Bool} : {l : List α}, filter p l <+ l
| [] => .slnil
@@ -1420,7 +1420,7 @@ theorem head_filter_of_pos {p : α → Bool} {l : List α} (w : l ≠ []) (h : p
@[simp]
theorem filterMap_eq_map {f : α β} : filterMap (some f) = map f := by
funext l; induction l <;> simp [*, filterMap_cons]
funext l; induction l <;> simp [*]
/-- Variant of `filterMap_eq_map` with `some ∘ f` expanded out to a lambda. -/
@[simp]
@@ -1453,7 +1453,7 @@ theorem filterMap_length_eq_length {l} :
induction l with
| nil => simp
| cons a l ih =>
simp only [filterMap_cons, length_cons, succ_eq_add_one, mem_cons, forall_eq_or_imp]
simp only [filterMap_cons, length_cons, mem_cons, forall_eq_or_imp]
split <;> rename_i h
· have := Nat.ne_of_lt (Nat.lt_succ.mpr (length_filterMap_le f l))
simp_all
@@ -1465,7 +1465,7 @@ theorem filterMap_eq_filter {p : α → Bool} :
funext l
induction l with
| nil => rfl
| cons a l IH => by_cases pa : p a <;> simp [filterMap_cons, Option.guard, pa, IH]
| cons a l IH => by_cases pa : p a <;> simp [Option.guard, pa, IH]
@[grind]
theorem filterMap_filterMap {f : α Option β} {g : β Option γ} {l : List α} :
@@ -1512,7 +1512,7 @@ theorem forall_mem_filterMap {f : α → Option β} {l : List α} {P : β → Pr
theorem map_filterMap_of_inv
{f : α Option β} {g : β α} (H : x : α, (f x).map g = some x) {l : List α} :
map g (filterMap f l) = l := by simp only [map_filterMap, H, filterMap_some, id]
map g (filterMap f l) = l := by simp only [map_filterMap, H, filterMap_some]
theorem head_filterMap_of_eq_some {f : α Option β} {l : List α} (w : l []) {b : β} (h : f (l.head w) = some b) :
(filterMap f l).head ((ne_nil_of_mem (mem_filterMap.2 _, head_mem w, h))) =
@@ -1521,7 +1521,7 @@ theorem head_filterMap_of_eq_some {f : α → Option β} {l : List α} (w : l
| nil => simp at w
| cons a l =>
simp only [head_cons] at h
simp [filterMap_cons, h]
simp [h]
@[grind ]
theorem forall_none_of_filterMap_eq_nil (h : filterMap f xs = []) : x xs, f x = none := by
@@ -1613,7 +1613,7 @@ theorem getElem?_append_left {l₁ l₂ : List α} {i : Nat} (hn : i < l₁.leng
(l₁ ++ l₂)[i]? = l₁[i]? := by
have hn' : i < (l₁ ++ l₂).length := Nat.lt_of_lt_of_le hn <|
length_append .. Nat.le_add_right ..
simp_all [getElem?_eq_getElem, getElem_append]
simp_all
theorem getElem?_append_right : {l₁ l₂ : List α} {i : Nat}, l₁.length i
(l₁ ++ l₂)[i]? = l₂[i - l₁.length]?
@@ -1817,10 +1817,10 @@ theorem filterMap_eq_append_iff {f : α → Option β} :
intro h
rcases cons_eq_append_iff.mp h with (rfl, rfl | _, rfl, h)
· refine [], x :: l, ?_
simp [filterMap_cons, w]
simp [w]
· obtain l₁, l₂, rfl, rfl, rfl := ih _
refine x :: l₁, l₂, ?_
simp [filterMap_cons, w]
simp [w]
· rintro l₁, l₂, rfl, rfl, rfl
simp
@@ -1885,7 +1885,7 @@ theorem append_concat {a : α} {l₁ l₂ : List α} : l₁ ++ concat l₂ a = c
theorem map_concat {f : α β} {a : α} {l : List α} : map f (concat l a) = concat (map f l) (f a) := by
induction l with
| nil => rfl
| cons x xs ih => simp [ih]
| cons x xs ih => simp
theorem eq_nil_or_concat : l : List α, l = [] l' b, l = concat l' b
| [] => .inl rfl
@@ -2191,7 +2191,7 @@ theorem forall_mem_replicate {p : α → Prop} {a : α} {n} :
· rw [getElem?_eq_none (by simpa using h), if_neg h]
@[simp] theorem getElem?_replicate_of_lt {n : Nat} {i : Nat} (h : i < n) : (replicate n a)[i]? = some a := by
simp [getElem?_replicate, h]
simp [h]
@[grind] theorem head?_replicate {a : α} {n : Nat} : (replicate n a).head? = if n = 0 then none else some a := by
cases n <;> simp [replicate_succ]
@@ -2329,8 +2329,8 @@ theorem filterMap_replicate_of_some {f : α → Option β} (h : f a = some b) :
induction n with
| zero => simp
| succ n ih =>
simp only [replicate_succ, flatten_cons, ih, replicate_append_replicate, replicate_inj, or_true,
and_true, add_one_mul, Nat.add_comm]
simp only [replicate_succ, flatten_cons, ih, replicate_append_replicate,
add_one_mul, Nat.add_comm]
theorem flatMap_replicate {β} {f : α List β} : (replicate n a).flatMap f = (replicate n (f a)).flatten := by
induction n with
@@ -2413,7 +2413,7 @@ theorem reverse_ne_nil_iff {xs : List α} : xs.reverse ≠ [] ↔ xs ≠ [] :=
theorem getElem?_reverse' : {l : List α} {i j}, i + j + 1 = length l
l.reverse[i]? = l[j]?
| [], _, _, _ => rfl
| a::l, i, 0, h => by simp [Nat.succ.injEq] at h; simp [h, getElem?_append_right, Nat.succ.injEq]
| a::l, i, 0, h => by simp [Nat.succ.injEq] at h; simp [h]
| a::l, i, j+1, h => by
have := Nat.succ.inj h; simp at this
rw [getElem?_append_left, getElem?_reverse' this]
@@ -2649,7 +2649,7 @@ theorem foldl_map_hom {g : α → β} {f : ααα} {f' : β → β →
(l.map g).foldl f' (g a) = g (l.foldl f a) := by
induction l generalizing a
· simp
· simp [*, h]
· simp [*]
@[deprecated foldl_map_hom (since := "2025-01-20")] abbrev foldl_map' := @foldl_map_hom
@@ -2658,7 +2658,7 @@ theorem foldr_map_hom {g : α → β} {f : ααα} {f' : β → β →
(l.map g).foldr f' (g a) = g (l.foldr f a) := by
induction l generalizing a
· simp
· simp [*, h]
· simp [*]
@[deprecated foldr_map_hom (since := "2025-01-20")] abbrev foldr_map' := @foldr_map_hom
@@ -2847,7 +2847,7 @@ theorem foldr_rel {l : List α} {f : α → β → β} {g : αγγ} {a
by_cases h' : l = []
· simp_all
· simp only [head_eq_iff_head?_eq_some, head?_reverse] at ih
simp [ih, h, h', getLast_cons, head_eq_iff_head?_eq_some]
simp [ih, h', getLast_cons, head_eq_iff_head?_eq_some]
theorem getLast_eq_head_reverse {l : List α} (h : l []) :
l.getLast h = l.reverse.head (by simp_all) := by
@@ -3398,14 +3398,14 @@ theorem replace_take {l : List α} {i : Nat} :
| nil => simp
| cons x xs ih =>
cases i with
| zero => simp [ih]
| zero => simp
| succ i =>
simp only [replace_cons, take_succ_cons]
split <;> simp_all
@[simp] theorem replace_replicate_self [LawfulBEq α] {a : α} (h : 0 < n) :
(replicate n a).replace a b = b :: replicate (n - 1) a := by
cases n <;> simp_all [replicate_succ, replace_cons]
cases n <;> simp_all [replicate_succ]
@[simp] theorem replace_replicate_ne [LawfulBEq α] {a b c : α} (h : !b == a) :
(replicate n a).replace b c = replicate n a := by
@@ -3507,11 +3507,11 @@ theorem getElem?_insert_succ {l : List α} {a : α} {i : Nat} :
apply Option.some.inj
rw [ getElem?_eq_getElem, getElem?_insert]
split
· simp [getElem?_eq_getElem, h]
· simp [h]
· split
· rfl
· have h' : i - 1 < l.length := Nat.lt_of_le_of_lt (Nat.pred_le _) h
simp [getElem?_eq_getElem, h']
simp [h']
theorem head?_insert {l : List α} {a : α} :
(l.insert a).head? = some (if h : a l then l.head (ne_nil_of_mem h) else a) := by
@@ -3532,7 +3532,7 @@ theorem head_insert {l : List α} {a : α} (w) :
theorem insert_append_of_mem_left {l₁ l₂ : List α} (h : a l₂) :
(l₁ ++ l₂).insert a = l₁ ++ l₂ := by
simp [insert_append, h]
simp [h]
theorem insert_append_of_not_mem_left {l₁ l₂ : List α} (h : ¬ a l₂) :
(l₁ ++ l₂).insert a = l₁.insert a ++ l₂ := by
@@ -3693,7 +3693,7 @@ theorem getElem!_of_getElem? [Inhabited α] : ∀ {l : List α} {i : Nat}, l[i]?
rw [getElem!_pos] <;> simp_all
| _::l, _+1, e => by
simp at e
simp_all [getElem!_of_getElem? (l := l) e]
simp_all
theorem ext_get {l₁ l₂ : List α} (hl : length l₁ = length l₂)
(h : n h₁ h₂, get l₁ n, h₁ = get l₂ n, h₂) : l₁ = l₂ :=

View File

@@ -218,8 +218,8 @@ theorem mapFinIdx_eq_cons_iff {l : List α} {b : β} {f : (i : Nat) → α → (
cases l with
| nil => simp
| cons x l' =>
simp only [mapFinIdx_cons, cons.injEq, length_cons, Fin.zero_eta, Fin.cast_succ_eq,
exists_and_left]
simp only [mapFinIdx_cons, cons.injEq,
]
constructor
· rintro rfl, rfl
refine x, l', rfl, rfl, by simp
@@ -267,7 +267,7 @@ theorem mapFinIdx_eq_append_iff {l : List α} {f : (i : Nat) → α → (h : i <
· simp
omega
· intro i hi₁ hi₂
simp only [getElem_mapFinIdx, getElem_take]
simp only [getElem_mapFinIdx]
simp only [length_take, getElem_drop]
have : l₁.length l.length := by omega
simp only [Nat.min_eq_left this, Nat.add_comm]
@@ -286,7 +286,7 @@ theorem mapFinIdx_eq_append_iff {l : List α} {f : (i : Nat) → α → (h : i <
theorem mapFinIdx_eq_mapFinIdx_iff {l : List α} {f g : (i : Nat) α (h : i < l.length) β} :
l.mapFinIdx f = l.mapFinIdx g (i : Nat) (h : i < l.length), f i l[i] h = g i l[i] h := by
rw [eq_comm, mapFinIdx_eq_iff]
simp [Fin.forall_iff]
simp
@[simp, grind =] theorem mapFinIdx_mapFinIdx {l : List α}
{f : (i : Nat) α (h : i < l.length) β}
@@ -341,7 +341,7 @@ theorem getElem?_mapIdx_go : ∀ {l : List α} {acc : Array β} {i : Nat},
(mapIdx.go f l acc)[i]? =
if h : i < acc.size then some acc[i] else Option.map (f i) l[i - acc.size]?
| [], acc, i => by
simp only [mapIdx.go, Array.toListImpl_eq, getElem?_def, Array.length_toList,
simp only [mapIdx.go, getElem?_def, Array.length_toList,
Array.getElem_toList, length_nil, Nat.not_lt_zero, reduceDIte, Option.map_none]
| a :: l, acc, i => by
rw [mapIdx.go, getElem?_mapIdx_go]
@@ -524,7 +524,7 @@ theorem mapIdx_eq_replicate_iff {l : List α} {f : Nat → α → β} {b : β} :
simp [mapIdx_eq_iff]
intro i
by_cases h : i < l.length
· simp [getElem?_reverse, h]
· simp [h]
congr
omega
· simp at h

View File

@@ -90,8 +90,8 @@ theorem foldlM_cons_eq_append [Monad m] [LawfulMonad m] {f : α → m β} {as :
induction as generalizing b bs with
| nil => simp
| cons a as ih =>
simp only [bind_pure_comp] at ih
simp [ih, _root_.map_bind, Functor.map_map, Function.comp_def]
simp only at ih
simp [ih, _root_.map_bind, Functor.map_map]
theorem mapM_eq_reverse_foldlM_cons [Monad m] [LawfulMonad m] {f : α m β} {l : List α} :
mapM f l = reverse <$> (l.foldlM (fun acc a => (· :: acc) <$> f a) []) := by
@@ -99,8 +99,8 @@ theorem mapM_eq_reverse_foldlM_cons [Monad m] [LawfulMonad m] {f : α → m β}
induction l with
| nil => simp
| cons a as ih =>
simp only [mapM'_cons, ih, bind_map_left, foldlM_cons, LawfulMonad.bind_assoc, pure_bind,
foldlM_cons_eq_append, _root_.map_bind, Functor.map_map, Function.comp_def, reverse_append,
simp only [mapM'_cons, ih, bind_map_left, foldlM_cons,
foldlM_cons_eq_append, _root_.map_bind, Functor.map_map, reverse_append,
reverse_cons, reverse_nil, nil_append, singleton_append]
simp [bind_pure_comp]
@@ -144,7 +144,7 @@ theorem flatMapM_loop_eq [Monad m] [LawfulMonad m] {f : α → m (List β)} {l :
induction l generalizing acc with
| nil => simp [flatMapM.loop]
| cons a l ih =>
simp only [flatMapM.loop, append_nil, _root_.map_bind]
simp only [flatMapM.loop, _root_.map_bind]
congr
funext bs
rw [ih, ih (acc := [bs])]
@@ -381,7 +381,7 @@ theorem forIn_eq_foldlM [Monad m] [LawfulMonad m]
induction l generalizing init with
| nil => simp
| cons a as ih =>
simp only [foldlM_cons, bind_pure_comp, forIn_cons, _root_.map_bind]
simp only [foldlM_cons, forIn_cons, _root_.map_bind]
congr 1
funext x
match x with
@@ -444,7 +444,7 @@ theorem allM_eq_not_anyM_not [Monad m] [LawfulMonad m] {p : α → m Bool} {as :
induction as with
| nil => simp
| cons a as ih =>
simp only [anyM, ih, pure_bind, all_cons]
simp only [anyM, ih, pure_bind]
split <;> simp_all
@[simp] theorem allM_pure [Monad m] [LawfulMonad m] {p : α Bool} {as : List α} :
@@ -486,7 +486,7 @@ and simplifies these to the function directly taking the value.
induction l generalizing x with
| nil => simp
| cons a l ih =>
simp [ih, hf, foldrM_cons]
simp [ih, foldrM_cons]
congr
funext b
simp [hf]

View File

@@ -68,7 +68,7 @@ theorem length_filterMap_pos_iff {xs : List α} {f : α → Option β} :
| cons x xs ih =>
simp only [filterMap, mem_cons, exists_prop, exists_eq_or_imp]
split
· simp_all [ih]
· simp_all
· simp_all
@[simp]
@@ -116,7 +116,7 @@ section intersperse
variable {l : List α} {sep : α} {i : Nat}
@[simp, grind =] theorem length_intersperse : (l.intersperse sep).length = 2 * l.length - 1 := by
fun_induction intersperse <;> simp only [intersperse, length_cons, length_nil] at *
fun_induction intersperse <;> simp only [length_cons, length_nil] at *
rename_i h _
have := length_pos_iff.mpr h
omega
@@ -194,7 +194,7 @@ theorem mem_eraseIdx_iff_getElem {x : α} :
| a::l, 0 => by simp [mem_iff_getElem, Nat.succ_lt_succ_iff]
| a::l, k+1 => by
rw [ Nat.or_exists_add_one]
simp [mem_eraseIdx_iff_getElem, @eq_comm _ a, succ_inj, Nat.succ_lt_succ_iff]
simp [mem_eraseIdx_iff_getElem, @eq_comm _ a, Nat.succ_lt_succ_iff]
theorem mem_eraseIdx_iff_getElem? {x : α} {l} {k} : x eraseIdx l k i k, l[i]? = some x := by
simp only [mem_eraseIdx_iff_getElem, getElem_eq_iff, exists_and_left]

View File

@@ -45,7 +45,7 @@ theorem countP_replace [BEq α] [LawfulBEq α] {a b : α} {l : List α} {p : α
simp [replace_cons]
split <;> rename_i h
· simp at h
simp [h, ih, countP_cons]
simp [h, countP_cons]
omega
· simp only [beq_eq_false_iff_ne, ne_eq] at h
simp only [countP_cons, ih, contains_eq_mem, decide_eq_true_eq, mem_cons, h, false_or]
@@ -75,12 +75,12 @@ theorem count_replace [BEq α] [LawfulBEq α] {a b c : α} {l : List α} :
· have := List.count_pos_iff.mpr (h' h)
omega
· rfl
· simp [h']
· simp
· rw [count_cons]
split <;> rename_i h'
· simp only [beq_iff_eq] at h'
rw [count_eq_zero.mpr (h' h)]
simp [h']
simp
· simp
/--

View File

@@ -29,7 +29,7 @@ theorem getElem?_eraseIdx {l : List α} {i : Nat} {j : Nat} :
· simp only [length_take, Nat.min_def, Nat.not_lt] at h
split at h
· omega
· simp_all [getElem?_eq_none]
· simp_all
omega
· simp only [length_take]
simp only [length_take, Nat.min_def, Nat.not_lt] at h
@@ -46,7 +46,7 @@ theorem getElem?_eraseIdx_of_lt {l : List α} {i : Nat} {j : Nat} (h : j < i) :
theorem getElem?_eraseIdx_of_ge {l : List α} {i : Nat} {j : Nat} (h : i j) :
(l.eraseIdx i)[j]? = l[j + 1]? := by
rw [getElem?_eraseIdx]
simp only [dite_eq_ite, ite_eq_right_iff]
simp only [ite_eq_right_iff]
intro h'
omega

View File

@@ -172,12 +172,12 @@ theorem modifyHead_eq_modify_zero (f : αα) (l : List α) :
i (l : List α) j, (l.modify i f)[j]? = (fun a => if i = j then f a else a) <$> l[j]?
| n, l, 0 => by cases l <;> cases n <;> simp
| n, [], _+1 => by cases n <;> rfl
| 0, _ :: l, j+1 => by cases h : l[j]? <;> simp [h, modify, j.succ_ne_zero.symm]
| 0, _ :: l, j+1 => by cases h : l[j]? <;> simp [h, modify]
| i+1, a :: l, j+1 => by
simp only [modify_succ_cons, getElem?_cons_succ, Nat.reduceEqDiff, Option.map_eq_map]
refine (getElem?_modify f i l j).trans ?_
cases h' : l[j]? <;> by_cases h : i = j <;>
simp [h, if_pos, if_neg, Option.map, mt Nat.succ.inj, not_false_iff, h']
simp [h, Option.map]
@[simp, grind =] theorem length_modify (f : α α) : (l : List α) i, (l.modify i f).length = l.length :=
length_modifyTailIdx _ fun l => by cases l <;> rfl
@@ -226,7 +226,7 @@ theorem modify_modify_ne (f g : αα) {i j} (l : List α) (h : i ≠ j) :
apply ext_getElem
· simp
· intro m' h₁ h₂
simp only [getElem_modify, getElem_modify_ne, h₂]
simp only [getElem_modify]
split <;> split <;> first | rfl | omega
theorem modify_eq_set [Inhabited α] (f : α α) (i) (l : List α) :
@@ -234,7 +234,7 @@ theorem modify_eq_set [Inhabited α] (f : αα) (i) (l : List α) :
apply ext_getElem
· simp
· intro m h₁ h₂
simp [getElem_modify, getElem_set, h₂]
simp [getElem_modify, getElem_set]
split <;> rename_i h
· subst h
simp only [length_modify] at h₁
@@ -287,7 +287,7 @@ theorem drop_modify_of_ge (f : αα) (i j) (l : List α) (h : i ≥ j) :
apply ext_getElem
· simp
· intro m' h₁ h₂
simp [getElem_drop, getElem_modify, ite_eq_right_iff]
simp [getElem_drop, getElem_modify]
split <;> split <;> first | rfl | omega
theorem eraseIdx_modify_of_eq (f : α α) (i) (l : List α) :

View File

@@ -508,7 +508,7 @@ theorem zipIdx_eq_append_iff {l : List α} {k : Nat} :
· rintro l₁', l₂', rfl, rfl, rfl
simp only [zipIdx_eq_zip_range']
refine l₁', l₂', range' k l₁'.length, range' (k + l₁'.length) l₂'.length, ?_
simp [Nat.add_comm]
simp
/-! ### enumFrom -/
@@ -635,7 +635,7 @@ theorem enumFrom_eq_append_iff {l : List α} {n : Nat} :
· rintro l₁', l₂', rfl, rfl, rfl
simp only [enumFrom_eq_zip_range']
refine range' n l₁'.length, range' (n + l₁'.length) l₂'.length, l₁', l₂', ?_
simp [Nat.add_comm]
simp
end

View File

@@ -141,7 +141,7 @@ theorem suffix_iff_eq_drop : l₁ <:+ l₂ ↔ l₁ = drop (length l₂ - length
xs.take i <+: xs.take j i j := by
simp only [prefix_iff_eq_take, length_take]
induction i generalizing xs j with
| zero => simp [Nat.min_eq_left, eq_self_iff_true, Nat.zero_le, take]
| zero => simp [Nat.min_eq_left, Nat.zero_le, take]
| succ i IH =>
cases xs with
| nil => simp_all
@@ -150,7 +150,7 @@ theorem suffix_iff_eq_drop : l₁ <:+ l₂ ↔ l₁ = drop (length l₂ - length
| zero =>
simp
| succ j =>
simp only [length_cons, Nat.succ_eq_add_one, Nat.add_lt_add_iff_right] at hm
simp only [length_cons, Nat.add_lt_add_iff_right] at hm
simp [ @IH j xs hm, Nat.min_eq_left, Nat.le_of_lt hm]
@[simp] theorem append_left_sublist_self {xs : List α} (ys : List α) : xs ++ ys <+ ys xs = [] := by
@@ -193,7 +193,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_iff, true_and, append_nil]
simp_all only [Nat.zero_add, length_eq_zero_iff, true_and]
exact Sublist.eq_of_length_le h' hl
· rintro rfl, rfl
simp

View File

@@ -28,8 +28,8 @@ open Nat
/-! ### take -/
@[simp, grind =] theorem length_take : {i : Nat} {l : List α}, (take i l).length = min i l.length
| 0, l => by simp [Nat.zero_min]
| succ n, [] => by simp [Nat.min_zero]
| 0, l => by simp
| succ n, [] => by simp
| succ n, _ :: l => by simp [Nat.succ_min_succ, length_take]
theorem length_take_le (i) (l : List α) : length (take i l) i := by simp [Nat.min_le_left]
@@ -119,8 +119,8 @@ theorem take_set_of_le {a : α} {i j : Nat} {l : List α} (h : j ≤ i) :
abbrev take_set_of_lt := @take_set_of_le
@[simp, grind =] 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]
| n, 0 => by simp
| 0, m => by simp
| succ n, succ m => by simp [replicate_succ, succ_min_succ, take_replicate]
@[simp, grind =] theorem drop_replicate {a : α} : {i n : Nat}, drop i (replicate n a) = replicate (n - i) a
@@ -136,7 +136,7 @@ theorem take_append {l₁ l₂ : List α} {i : Nat} :
· simp
· cases i
· simp [*]
· simp only [cons_append, take_succ_cons, length_cons, succ_eq_add_one, cons.injEq,
· simp only [cons_append, take_succ_cons, length_cons, cons.injEq,
append_cancel_left_eq, true_and, *]
congr 1
omega
@@ -157,10 +157,10 @@ theorem take_length_add_append {l₁ l₂ : List α} (i : Nat) :
@[simp]
theorem take_eq_take_iff :
{l : List α} {i j : Nat}, l.take i = l.take j min i l.length = min j l.length
| [], i, j => by simp [Nat.min_zero]
| [], i, j => by simp
| _ :: xs, 0, 0 => by simp
| x :: xs, i + 1, 0 => by simp [Nat.zero_min, succ_min_succ]
| x :: xs, 0, j + 1 => by simp [Nat.zero_min, succ_min_succ]
| x :: xs, i + 1, 0 => by simp [succ_min_succ]
| x :: xs, 0, j + 1 => by simp [succ_min_succ]
| x :: xs, i + 1, j + 1 => by simp [succ_min_succ, take_eq_take_iff]
@[deprecated take_eq_take_iff (since := "2025-02-16")]
@@ -279,7 +279,7 @@ theorem mem_drop_iff_getElem {l : List α} {a : α} :
@[simp] theorem head_drop {l : List α} {i : Nat} (h : l.drop i []) :
(l.drop i).head h = l[i]'(by simp_all) := by
have w : i < l.length := length_lt_of_drop_ne_nil h
simp [getElem?_eq_getElem, h, w, head_eq_iff_head?_eq_some]
simp [w, head_eq_iff_head?_eq_some]
theorem getLast?_drop {l : List α} : (l.drop i).getLast? = if l.length i then none else l.getLast? := by
rw [getLast?_eq_getElem?, getElem?_drop]
@@ -318,7 +318,7 @@ theorem drop_append {l₁ l₂ : List α} {i : Nat} :
· simp
· cases i
· simp [*]
· simp only [cons_append, drop_succ_cons, length_cons, succ_eq_add_one, append_cancel_left_eq, *]
· simp only [cons_append, drop_succ_cons, length_cons, append_cancel_left_eq, *]
congr 1
omega
@@ -463,7 +463,7 @@ theorem drop_sub_one {l : List α} {i : Nat} (h : 0 < i) :
theorem false_of_mem_take_findIdx {xs : List α} {p : α Bool} (h : x xs.take (xs.findIdx p)) :
p x = false := by
simp only [mem_take_iff_getElem, forall_exists_index] at h
simp only [mem_take_iff_getElem] at h
obtain i, h, rfl := h
exact not_of_lt_findIdx (by omega)
@@ -484,7 +484,7 @@ theorem false_of_mem_take_findIdx {xs : List α} {p : α → Bool} (h : x ∈ xs
induction xs with
| nil => simp
| cons x xs ih =>
simp [findIdx_cons, cond_eq_if, Bool.not_eq_eq_eq_not, Bool.not_true]
simp [findIdx_cons, cond_eq_if]
split <;> split <;> simp_all [Nat.add_min_add_right]
/-! ### findIdx? -/
@@ -550,7 +550,7 @@ theorem dropWhile_eq_drop_findIdx_not {xs : List α} {p : α → Bool} :
@[simp, grind =] theorem length_zipWith {f : α β γ} {l₁ : List α} {l₂ : List β} :
length (zipWith f l₁ l₂) = min (length l₁) (length l₂) := by
induction l₁ generalizing l₂ <;> cases l₂ <;>
simp_all [succ_min_succ, Nat.zero_min, Nat.min_zero]
simp_all [succ_min_succ]
theorem lt_length_left_of_zipWith {f : α β γ} {i : Nat} {l : List α} {l' : List β}
(h : i < (zipWith f l l').length) : i < l.length := by rw [length_zipWith] at h; omega

View File

@@ -96,7 +96,7 @@ theorem ofFn_add {n m} {f : Fin (n + m) → α} :
@[simp]
theorem ofFn_eq_nil_iff {f : Fin n α} : ofFn f = [] n = 0 := by
cases n <;> simp only [ofFn_zero, ofFn_succ, eq_self_iff_true, Nat.succ_ne_zero, reduceCtorEq]
cases n <;> simp only [ofFn_zero, ofFn_succ, Nat.succ_ne_zero, reduceCtorEq]
@[simp 500, grind =]
theorem mem_ofFn {n} {f : Fin n α} {a : α} : a ofFn f i, f i = a := by

View File

@@ -59,7 +59,7 @@ theorem Pairwise.and (hR : Pairwise R l) (hS : Pairwise S l) :
induction hR with
| nil => simp only [Pairwise.nil]
| cons R1 _ IH =>
simp only [Pairwise.nil, pairwise_cons] at hS
simp only [pairwise_cons] at hS
exact fun b bl => R1 b bl, hS.1 b bl, IH hS.2
theorem pairwise_and_iff : l.Pairwise (fun a b => R a b S a b) Pairwise R l Pairwise S l :=

View File

@@ -198,8 +198,8 @@ theorem Perm.filterMap (f : α → Option β) {l₁ l₂ : List α} (p : l₁ ~
filterMap f l₁ ~ filterMap f l₂ := by
induction p with
| nil => simp
| cons x _p IH => cases h : f x <;> simp [h, filterMap_cons, IH, Perm.cons]
| swap x y l₂ => cases hx : f x <;> cases hy : f y <;> simp [hx, hy, filterMap_cons, swap]
| cons x _p IH => cases h : f x <;> simp [h, IH, Perm.cons]
| swap x y l₂ => cases hx : f x <;> cases hy : f y <;> simp [hx, hy, swap]
| trans _p₁ _p₂ IH₁ IH₂ => exact IH₁.trans IH₂
grind_pattern Perm.filterMap => l₁ ~ l₂, filterMap f l₁
@@ -442,7 +442,7 @@ grind_pattern Perm.count => l₁ ~ l₂, count a l₂
theorem isPerm_iff : {l₁ l₂ : List α}, l₁.isPerm l₂ l₁ ~ l₂
| [], [] => by simp [isPerm, isEmpty]
| [], _ :: _ => by simp [isPerm, isEmpty, Perm.nil_eq]
| [], _ :: _ => by simp [isPerm, isEmpty]
| a :: l₁, l₂ => by simp [isPerm, isPerm_iff, cons_perm_iff_perm_erase]
instance decidablePerm {α} [DecidableEq α] (l₁ l₂ : List α) : Decidable (l₁ ~ l₂) := decidable_of_iff _ isPerm_iff

View File

@@ -88,7 +88,7 @@ theorem getElem?_range' {s step} :
(getElem?_eq_some_iff.1 <| getElem?_range' (by simpa using H)).2
theorem head?_range' : (range' s n).head? = if n = 0 then none else some s := by
induction n <;> simp_all [range'_succ, head?_append]
induction n <;> simp_all [range'_succ]
@[simp] theorem head_range' (h) : (range' s n).head h = s := by
repeat simp_all [head?_range', head_eq_iff_head?_eq_some]
@@ -246,11 +246,11 @@ theorem getElem_zipIdx {l : List α} (h : i < (l.zipIdx j).length) :
theorem tail_zipIdx {l : List α} {i : Nat} : (zipIdx l i).tail = zipIdx l.tail (i + 1) := by
induction l generalizing i with
| nil => simp
| cons _ l ih => simp [ih, zipIdx_cons]
| cons _ l ih => simp [zipIdx_cons]
theorem map_snd_add_zipIdx_eq_zipIdx {l : List α} {n k : Nat} :
map (Prod.map id (· + n)) (zipIdx l k) = zipIdx l (n + k) :=
ext_getElem? fun i by simp [(· ·), Nat.add_comm, Nat.add_left_comm]; rfl
ext_getElem? fun i by simp [Nat.add_comm, Nat.add_left_comm]; rfl
theorem zipIdx_cons' {i : Nat} {x : α} {xs : List α} :
zipIdx (x :: xs) i = (x, i) :: (zipIdx xs i).map (Prod.map id (· + 1)) := by
@@ -328,12 +328,12 @@ theorem getElem_enumFrom (l : List α) (n) (i : Nat) (h : i < (l.enumFrom n).len
theorem tail_enumFrom (l : List α) (n : Nat) : (enumFrom n l).tail = enumFrom (n + 1) l.tail := by
induction l generalizing n with
| nil => simp
| cons _ l ih => simp [ih, enumFrom_cons]
| cons _ l ih => simp [enumFrom_cons]
@[deprecated map_snd_add_zipIdx_eq_zipIdx (since := "2025-01-21"), simp]
theorem map_fst_add_enumFrom_eq_enumFrom (l : List α) (n k : Nat) :
map (Prod.map (· + n) id) (enumFrom k l) = enumFrom (n + k) l :=
ext_getElem? fun i by simp [(· ·), Nat.add_comm, Nat.add_left_comm]; rfl
ext_getElem? fun i by simp [Nat.add_comm, Nat.add_left_comm]; rfl
@[deprecated map_snd_add_zipIdx_eq_zipIdx (since := "2025-01-21"), simp]
theorem map_fst_add_enum_eq_enumFrom (l : List α) (n : Nat) :

View File

@@ -44,8 +44,8 @@ def merge (xs ys : List α) (le : αα → Bool := by exact fun a b => a
@[simp] theorem nil_merge (ys : List α) : merge [] ys le = ys := by simp [merge]
@[simp] theorem merge_right (xs : List α) : merge xs [] le = xs := by
induction xs with
| nil => simp [merge]
| cons x xs ih => simp [merge, ih]
| nil => simp
| cons x xs ih => simp [merge]
/--
Split a list in two equal parts. If the length is odd, the first part will be one element longer.

View File

@@ -57,10 +57,10 @@ where go : List α → List α → List α → List α
theorem mergeTR_go_eq : mergeTR.go le l₁ l₂ acc = acc.reverse ++ merge l₁ l₂ le := by
induction l₁ generalizing l₂ acc with
| nil => simp [mergeTR.go, merge, reverseAux_eq]
| nil => simp [mergeTR.go, reverseAux_eq]
| cons x l₁ ih₁ =>
induction l₂ generalizing acc with
| nil => simp [mergeTR.go, merge, reverseAux_eq]
| nil => simp [mergeTR.go, reverseAux_eq]
| cons y l₂ ih₂ =>
simp [mergeTR.go, merge]
split <;> simp [ih₁, ih₂]
@@ -172,7 +172,7 @@ theorem splitRevInTwo_snd (l : { l : List α // l.length = n }) :
theorem mergeSortTR_run_eq_mergeSort : {n : Nat} (l : { l : List α // l.length = n }) mergeSortTR.run le l = mergeSort l.1 le
| 0, [], _
| 1, [a], _ => by simp [mergeSortTR.run, mergeSort]
| 1, [a], _ => by simp [mergeSortTR.run]
| n+2, a :: b :: l, h => by
cases h
simp only [mergeSortTR.run, mergeSortTR.run, mergeSort]
@@ -189,7 +189,7 @@ set_option maxHeartbeats 400000 in
mutual
theorem mergeSortTR₂_run_eq_mergeSort : {n : Nat} (l : { l : List α // l.length = n }) mergeSortTR₂.run le l = mergeSort l.1 le
| 0, [], _
| 1, [a], _ => by simp [mergeSortTR₂.run, mergeSort]
| 1, [a], _ => by simp [mergeSortTR₂.run]
| n+2, a :: b :: l, h => by
cases h
simp only [mergeSortTR₂.run, mergeSort]
@@ -201,10 +201,10 @@ termination_by n => n
theorem mergeSortTR₂_run'_eq_mergeSort : {n : Nat} (l : { l : List α // l.length = n }) (w : l' = l.1.reverse) mergeSortTR₂.run' le l = mergeSort l' le
| 0, [], _, w
| 1, [a], _, w => by simp_all [mergeSortTR₂.run', mergeSort]
| 1, [a], _, w => by simp_all [mergeSortTR₂.run']
| n+2, a :: b :: l, h, w => by
cases h
simp only [mergeSortTR₂.run', mergeSort]
simp only [mergeSortTR₂.run']
rw [splitRevInTwo'_fst, splitRevInTwo'_snd]
rw [mergeSortTR₂_run_eq_mergeSort, mergeSortTR₂_run'_eq_mergeSort _ rfl]
rw [ merge_eq_mergeTR]
@@ -220,7 +220,7 @@ theorem mergeSortTR₂_run'_eq_mergeSort : {n : Nat} → (l : { l : List α // l
congr 2
· dsimp at w
simp only [w]
simp only [splitInTwo_fst, splitInTwo_snd, reverse_take, take_reverse]
simp only [splitInTwo_fst, take_reverse]
congr 1
rw [w, length_reverse]
simp

View File

@@ -33,11 +33,11 @@ namespace List
namespace MergeSort.Internal
@[simp] theorem splitInTwo_fst (l : { l : List α // l.length = n }) :
(splitInTwo l).1 = l.1.take ((n+1)/2), by simp [splitInTwo, splitAt_eq, l.2]; omega := by
(splitInTwo l).1 = l.1.take ((n+1)/2), by simp [l.2]; omega := by
simp [splitInTwo, splitAt_eq]
@[simp] theorem splitInTwo_snd (l : { l : List α // l.length = n }) :
(splitInTwo l).2 = l.1.drop ((n+1)/2), by simp [splitInTwo, splitAt_eq, l.2]; omega := by
(splitInTwo l).2 = l.1.drop ((n+1)/2), by simp [l.2]; omega := by
simp [splitInTwo, splitAt_eq]
theorem splitInTwo_fst_append_splitInTwo_snd (l : { l : List α // l.length = n }) : (splitInTwo l).1.1 ++ (splitInTwo l).2.1 = l.1 := by
@@ -166,15 +166,15 @@ The elements of `merge le xs ys` are exactly the elements of `xs` and `ys`.
-- We subsequently prove that `mergeSort_perm : merge le xs ys ~ xs ++ ys`.
theorem mem_merge {a : α} {xs ys : List α} : a merge xs ys le a xs a ys := by
induction xs generalizing ys with
| nil => simp [merge]
| nil => simp
| cons x xs ih =>
induction ys with
| nil => simp [merge]
| nil => simp
| cons y ys ih =>
simp only [merge]
split <;> rename_i h
· simp_all [or_assoc]
· simp only [mem_cons, or_assoc, Bool.not_eq_true, ih, or_assoc]
· simp only [mem_cons, ih, or_assoc]
apply or_congr_left
simp only [or_comm (a := a = y), or_assoc]
@@ -186,8 +186,8 @@ theorem mem_merge_right (s : αα → Bool) (h : x ∈ r) : x ∈ merge l r
theorem merge_stable : (xs ys) (_ : x y, x xs y ys x.2 y.2),
(merge xs ys (zipIdxLE le)).map (·.1) = merge (xs.map (·.1)) (ys.map (·.1)) le
| [], ys, _ => by simp [merge]
| xs, [], _ => by simp [merge]
| [], ys, _ => by simp
| xs, [], _ => by simp
| (i, x) :: xs, (j, y) :: ys, h => by
simp only [merge, zipIdxLE, map_cons]
split <;> rename_i w
@@ -239,7 +239,7 @@ theorem sorted_merge
theorem merge_of_le : {xs ys : List α} (_ : a b, a xs b ys le a b),
merge xs ys le = xs ++ ys
| [], ys, _
| xs, [], _ => by simp [merge]
| xs, [], _ => by simp
| x :: xs, y :: ys, h => by
simp only [merge, cons_append]
rw [if_pos, merge_of_le]
@@ -249,8 +249,8 @@ theorem merge_of_le : ∀ {xs ys : List α} (_ : ∀ a b, a ∈ xs → b ∈ ys
variable (le) in
theorem merge_perm_append : {xs ys : List α}, merge xs ys le ~ xs ++ ys
| [], ys => by simp [merge]
| xs, [] => by simp [merge]
| [], ys => by simp
| xs, [] => by simp
| x :: xs, y :: ys => by
simp only [merge]
split
@@ -269,8 +269,8 @@ theorem Perm.merge (s₁ s₂ : αα → Bool) (hl : l₁ ~ l₂) (hr : r
@[simp] theorem mergeSort_singleton (a : α) : [a].mergeSort r = [a] := by rw [List.mergeSort]
theorem mergeSort_perm : (l : List α) (le), mergeSort l le ~ l
| [], _ => by simp [mergeSort]
| [a], _ => by simp [mergeSort]
| [], _ => by simp
| [a], _ => by simp
| a :: b :: xs, le => by
simp only [mergeSort]
have : (splitInTwo a :: b :: xs, rfl).1.1.length < xs.length + 1 + 1 := by simp [splitInTwo_fst]; omega
@@ -297,8 +297,8 @@ theorem sorted_mergeSort
(trans : (a b c : α), le a b le b c le a c)
(total : (a b : α), le a b || le b a) :
(l : List α) (mergeSort l le).Pairwise le
| [] => by simp [mergeSort]
| [a] => by simp [mergeSort]
| [] => by simp
| [a] => by simp
| a :: b :: xs => by
rw [mergeSort]
apply sorted_merge @trans @total
@@ -310,8 +310,8 @@ termination_by l => l.length
If the input list is already sorted, then `mergeSort` does not change the list.
-/
theorem mergeSort_of_sorted : {l : List α} (_ : Pairwise le l), mergeSort l le = l
| [], _ => by simp [mergeSort]
| [a], _ => by simp [mergeSort]
| [], _ => by simp
| [a], _ => by simp
| a :: b :: xs, h => by
have : (splitInTwo a :: b :: xs, rfl).1.1.length < xs.length + 1 + 1 := by simp [splitInTwo_fst]; omega
have : (splitInTwo a :: b :: xs, rfl).2.1.length < xs.length + 1 + 1 := by simp [splitInTwo_snd]; omega
@@ -340,7 +340,7 @@ theorem mergeSort_zipIdx {l : List α} :
where go : (i : Nat) (l : List α),
(mergeSort (l.zipIdx i) (zipIdxLE le)).map (·.1) = mergeSort l le
| _, []
| _, [a] => by simp [mergeSort]
| _, [a] => by simp
| _, a :: b :: xs => by
have : (splitInTwo a :: b :: xs, rfl).1.1.length < xs.length + 1 + 1 := by simp [splitInTwo_fst]; omega
have : (splitInTwo a :: b :: xs, rfl).2.1.length < xs.length + 1 + 1 := by simp [splitInTwo_snd]; omega

View File

@@ -276,7 +276,7 @@ grind_pattern Sublist.map => l₁ <+ l₂, map f l₂
@[grind]
protected theorem Sublist.filterMap (f : α Option β) (s : l₁ <+ l₂) :
filterMap f l₁ <+ filterMap f l₂ := by
induction s <;> simp [filterMap_cons] <;> split <;> simp [*, cons, cons₂]
induction s <;> simp [filterMap_cons] <;> split <;> simp [*, cons]
grind_pattern Sublist.filterMap => l₁ <+ l₂, filterMap f l₁
grind_pattern Sublist.filterMap => l₁ <+ l₂, filterMap f l₂
@@ -542,7 +542,7 @@ theorem sublist_flatten_of_mem {L : List (List α)} {l} (h : l ∈ L) : l <+ L.f
| nil => cases h
| cons l' L ih =>
rcases mem_cons.1 h with (rfl | h)
· simp [h]
· simp
· simp [ih h, flatten_cons, sublist_append_of_sublist_right]
theorem sublist_flatten_iff {L : List (List α)} {l} :
@@ -914,7 +914,7 @@ theorem infix_cons_iff : l₁ <:+: a :: l₂ ↔ l₁ <+: a :: l₂ l₁ <:+
theorem prefix_concat_iff {l₁ l₂ : List α} {a : α} :
l₁ <+: l₂ ++ [a] l₁ = l₂ ++ [a] l₁ <+: l₂ := by
simp only [ reverse_suffix, reverse_concat, suffix_cons_iff]
simp only [concat_eq_append, reverse_concat, reverse_eq_iff, reverse_reverse]
simp only [ reverse_concat, reverse_eq_iff, reverse_reverse]
theorem suffix_concat_iff {l₁ l₂ : List α} {a : α} :
l₁ <:+ l₂ ++ [a] l₁ = [] t, l₁ = t ++ [a] t <:+ l₂ := by
@@ -941,7 +941,7 @@ theorem prefix_iff_getElem? {l₁ l₂ : List α} :
| nil =>
simpa using 0, by simp
| cons b l₂ =>
simp only [cons_append, cons_prefix_cons, ih]
simp only [cons_prefix_cons, ih]
rw (occs := [2]) [ Nat.and_forall_add_one]
simp [Nat.succ_lt_succ_iff, eq_comm]
@@ -964,7 +964,7 @@ theorem prefix_iff_getElem {l₁ l₂ : List α} :
| nil =>
exact nil_prefix
| cons _ _ =>
simp only [length_cons, Nat.add_le_add_iff_right, Fin.getElem_fin] at hl h
simp only [length_cons, Nat.add_le_add_iff_right] at hl h
simp only [cons_prefix_cons]
exact h 0 (zero_lt_succ _), tail_ih hl fun a ha h a.succ (succ_lt_succ ha)

View File

@@ -350,7 +350,7 @@ theorem takeWhile_filterMap {f : α → Option β} {p : β → Bool} {l : List
· simp only [takeWhile_cons, h]
split <;> simp_all
· simp [takeWhile_cons, h, ih]
split <;> simp_all [filterMap_cons]
split <;> simp_all
theorem dropWhile_filterMap {f : α Option β} {p : β Bool} {l : List α} :
(l.filterMap f).dropWhile p = (l.dropWhile fun a => (f a).all p).filterMap f := by
@@ -362,7 +362,7 @@ theorem dropWhile_filterMap {f : α → Option β} {p : β → Bool} {l : List
· simp only [dropWhile_cons, h]
split <;> simp_all
· simp [dropWhile_cons, h, ih]
split <;> simp_all [filterMap_cons]
split <;> simp_all
theorem takeWhile_filter {p q : α Bool} {l : List α} :
(l.filter p).takeWhile q = (l.takeWhile fun a => !p a || q a).filter p := by
@@ -393,7 +393,7 @@ theorem takeWhile_append {xs ys : List α} :
(l₁ ++ l₂).takeWhile p = l₁ ++ l₂.takeWhile p := by
induction l₁ with
| nil => simp
| cons x xs ih => simp_all [takeWhile_cons]
| cons x xs ih => simp_all
theorem dropWhile_append {xs ys : List α} :
(xs ++ ys).dropWhile p =
@@ -408,7 +408,7 @@ theorem dropWhile_append {xs ys : List α} :
(l₁ ++ l₂).dropWhile p = l₂.dropWhile p := by
induction l₁ with
| nil => simp
| cons x xs ih => simp_all [dropWhile_cons]
| cons x xs ih => simp_all
@[simp] theorem takeWhile_replicate_eq_filter {p : α Bool} :
(replicate n a).takeWhile p = (replicate n a).filter p := by
@@ -440,7 +440,7 @@ theorem take_takeWhile {l : List α} {p : α → Bool} :
induction l generalizing i with
| nil => simp
| cons x xs ih =>
by_cases h : p x <;> cases i <;> simp [takeWhile_cons, h, ih, take_succ_cons]
by_cases h : p x <;> cases i <;> simp [h, ih, take_succ_cons]
@[simp] theorem all_takeWhile {l : List α} : (l.takeWhile p).all p = true := by
induction l with
@@ -461,7 +461,7 @@ theorem replace_takeWhile [BEq α] [LawfulBEq α] {l : List α} {p : α → Bool
simp only [takeWhile_cons, replace_cons]
split <;> rename_i h₁ <;> split <;> rename_i h₂
· simp_all
· simp [replace_cons, h₂, takeWhile_cons, h₁, ih]
· simp [replace_cons, h₂, h₁, ih]
· simp_all
· simp_all

View File

@@ -576,7 +576,7 @@ theorem flatMap_toArray_cons {β} (f : α → Array β) (a : α) (as : List α)
rw [Array.eraseIdx]
split <;> rename_i h'
· rw [eraseIdx_toArray]
simp only [swap_toArray, Fin.getElem_fin, toList_toArray, mk.injEq]
simp only [swap_toArray, toList_toArray, mk.injEq]
rw [eraseIdx_set_gt (by simp), eraseIdx_set_eq]
simp
· simp at h h'
@@ -667,7 +667,7 @@ 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
· simp only [finIdxOf?_toArray] at h
rw [replace_of_not_mem]
exact finIdxOf?_eq_none_iff.mp h
· simp_all only [finIdxOf?_toArray, finIdxOf?_eq_some_iff, Fin.getElem_fin, set_toArray,

View File

@@ -184,7 +184,7 @@ theorem zipWith_eq_cons_iff {f : α → β → γ} {l₁ : List α} {l₂ : List
| [], b :: l₂ => simp
| a :: l₁, [] => simp
| a' :: l₁, b' :: l₂ =>
simp only [zip_cons_cons, cons.injEq, Prod.mk.injEq]
simp only [cons.injEq]
constructor
· rintro rfl, rfl, rfl
refine a', l₁, b', l₂, by simp

View File

@@ -937,7 +937,7 @@ protected theorem pred_succ (n : Nat) : pred n.succ = n := rfl
@[simp] protected theorem add_one_sub_one (n : Nat) : n + 1 - 1 = n := rfl
theorem sub_one_eq_self {n : Nat} : n - 1 = n n = 0 := by cases n <;> simp [ne_add_one]
theorem eq_self_sub_one {n : Nat} : n = n - 1 n = 0 := by cases n <;> simp [add_one_ne]
theorem eq_self_sub_one {n : Nat} : n = n - 1 n = 0 := by cases n <;> simp
theorem succ_pred {a : Nat} (h : a 0) : a.pred.succ = a := by
induction a with
@@ -1098,13 +1098,13 @@ theorem add_le_of_le_sub {a b c : Nat} (hle : b ≤ c) (h : a ≤ c - b) : a + b
| d, hd =>
apply @le.intro _ _ d
rw [Nat.eq_add_of_sub_eq hle hd.symm]
simp [Nat.add_comm, Nat.add_assoc, Nat.add_left_comm]
simp [Nat.add_comm, Nat.add_left_comm]
theorem le_sub_of_add_le {a b c : Nat} (h : a + b c) : a c - b := by
match le.dest h with
| d, hd =>
apply @le.intro _ _ d
have hd : a + d + b = c := by simp [ hd, Nat.add_comm, Nat.add_assoc, Nat.add_left_comm]
have hd : a + d + b = c := by simp [ hd, Nat.add_comm, Nat.add_left_comm]
have hd := Nat.sub_eq_of_eq_add hd.symm
exact hd.symm

View File

@@ -103,7 +103,7 @@ theorem shiftLeft_eq (a b : Nat) : a <<< b = a * 2 ^ b :=
match b with
| 0 => (Nat.mul_one _).symm
| b+1 => (shiftLeft_eq _ b).trans <| by
simp [Nat.pow_succ, Nat.mul_assoc, Nat.mul_left_comm, Nat.mul_comm]
simp [Nat.pow_succ, Nat.mul_assoc, Nat.mul_comm]
@[simp] theorem shiftRight_zero : n >>> 0 = n := rfl

View File

@@ -77,7 +77,7 @@ noncomputable def div2Induction {motive : Nat → Sort u}
simp only [HAnd.hAnd, AndOp.and, land]
unfold bitwise
cases mod_two_eq_zero_or_one x with | _ p =>
simp [xz, p, andz, mod_eq_of_lt]
simp [xz, p, andz]
/-! ### testBit -/
@@ -163,7 +163,7 @@ theorem exists_testBit_ne_of_ne {x y : Nat} (p : x ≠ y) : ∃ i, testBit x i
| ind y hyp =>
cases Nat.eq_zero_or_pos y with
| inl yz =>
simp only [yz, Nat.zero_testBit, Bool.eq_false_iff]
simp only [yz, Nat.zero_testBit]
simp only [yz] at p
have i,ip := exists_testBit_of_ne_zero p
apply Exists.intro i
@@ -283,14 +283,14 @@ theorem testBit_two_pow_add_gt {i j : Nat} (j_lt_i : j < i) (x : Nat) :
have i_def : i = j + (i-j) := (Nat.add_sub_cancel' (Nat.le_of_lt j_lt_i)).symm
rw [i_def]
simp only [testBit_eq_decide_div_mod_eq, Nat.pow_add,
Nat.add_comm x, Nat.mul_add_div (Nat.two_pow_pos _)]
Nat.mul_add_div (Nat.two_pow_pos _)]
match i_sub_j_eq : i - j with
| 0 =>
exfalso
rw [Nat.sub_eq_zero_iff_le] at i_sub_j_eq
exact Nat.not_le_of_gt j_lt_i i_sub_j_eq
| d+1 =>
simp [Nat.pow_succ, Nat.mul_comm _ 2, Nat.mul_add_mod]
simp [Nat.pow_succ, Nat.mul_comm _ 2]
@[simp, grind =] theorem testBit_mod_two_pow (x j i : Nat) :
testBit (x % 2^j) i = (decide (i < j) && testBit x i) := by
@@ -330,7 +330,7 @@ theorem testBit_two_pow_sub_succ (h₂ : x < 2 ^ n) (i : Nat) :
induction i generalizing n x with
| zero =>
match n with
| 0 => simp [succ_sub_succ_eq_sub]
| 0 => simp
| n+1 =>
simp [not_decide_mod_two_eq_one]
omega
@@ -338,7 +338,7 @@ theorem testBit_two_pow_sub_succ (h₂ : x < 2 ^ n) (i : Nat) :
simp only [testBit_succ]
match n with
| 0 =>
simp [decide_eq_false, succ_sub_succ_eq_sub]
simp [decide_eq_false]
| n+1 =>
rw [Nat.two_pow_succ_sub_succ_div_two, ih]
· simp [Nat.succ_lt_succ_iff]
@@ -352,8 +352,8 @@ theorem testBit_two_pow_sub_succ (h₂ : x < 2 ^ n) (i : Nat) :
theorem testBit_bool_to_nat (b : Bool) (i : Nat) :
testBit (Bool.toNat b) i = (decide (i = 0) && b) := by
cases b <;> cases i <;>
simp [testBit_eq_decide_div_mod_eq, Nat.pow_succ, Nat.mul_comm _ 2,
Nat.div_div_eq_div_mul _ 2, Nat.mod_eq_of_lt]
simp [testBit_eq_decide_div_mod_eq,
Nat.mod_eq_of_lt]
/-- `testBit 1 i` is true iff the index `i` equals 0. -/
theorem testBit_one_eq_true_iff_self_eq_zero {i : Nat} :
@@ -371,7 +371,7 @@ theorem testBit_two_pow {n m : Nat} : testBit (2 ^ n) m = decide (n = m) := by
simp
· rw [Nat.pow_div _ Nat.two_pos,
Nat.sub_add_cancel (succ_le_of_lt <| Nat.sub_pos_of_lt (by omega))]
simp [Nat.pow_succ, and_one_is_mod, mul_mod_left]
simp [Nat.pow_succ, mul_mod_left]
omega
@[simp]
@@ -415,11 +415,11 @@ theorem testBit_bitwise (of_false_false : f false false = false) (x y i : Nat) :
cases i with
| zero =>
cases p : f (decide (x % 2 = 1)) (decide (y % 2 = 1)) <;>
simp [p, Nat.mul_add_mod, mod_eq_of_lt]
simp [p]
| succ i =>
have hyp_i := hyp i (Nat.le_refl (i+1))
cases p : f (decide (x % 2 = 1)) (decide (y % 2 = 1)) <;>
simp [p, hyp_i, Nat.mul_add_div]
simp [hyp_i, Nat.mul_add_div]
/-! ### bitwise -/
@@ -437,7 +437,7 @@ private theorem eq_0_of_lt (x : Nat) : x < 2^ 0 ↔ x = 0 := eq_0_of_lt_one x
@[local simp]
private theorem zero_lt_pow (n : Nat) : 0 < 2^n := by
induction n
case zero => simp [eq_0_of_lt]
case zero => simp
case succ n hyp => simpa [Nat.pow_succ]
private theorem div_two_le_of_lt_two {m n : Nat} (p : m < 2 ^ succ n) : m / 2 < 2^n := by
@@ -457,10 +457,10 @@ theorem bitwise_lt_two_pow (left : x < 2^n) (right : y < 2^n) : (Nat.bitwise f x
simp only [x_zero, if_pos]
by_cases p : f false true = true <;> simp [p, right]
else if y_zero : y = 0 then
simp only [x_zero, y_zero, if_neg, if_pos]
simp only [x_zero, y_zero, if_pos]
by_cases p : f true false = true <;> simp [p, left]
else
simp only [x_zero, y_zero, if_neg]
simp only [x_zero, y_zero]
have hyp1 := hyp (div_two_le_of_lt_two left) (div_two_le_of_lt_two right)
by_cases p : f (decide (x % 2 = 1)) (decide (y % 2 = 1)) = true <;>
simp [p, Nat.pow_succ, mul_succ, Nat.add_assoc]
@@ -560,7 +560,7 @@ theorem and_mod_two_pow : (a &&& b) % 2 ^ n = (a % 2 ^ n) &&& (b % 2 ^ n) :=
@[simp, grind =] theorem zero_or (x : Nat) : 0 ||| x = x := by
simp only [HOr.hOr, OrOp.or, lor]
unfold bitwise
simp [@eq_comm _ 0]
simp
@[simp, grind =] theorem or_zero (x : Nat) : x ||| 0 = x := by
simp only [HOr.hOr, OrOp.or, lor]
@@ -720,8 +720,8 @@ theorem testBit_two_pow_mul_add (a : Nat) {b i : Nat} (b_lt : b < 2^i) (j : Nat)
rw [succ_pred_eq_of_pos] <;> omega
rw [i_def]
simp only [testBit_eq_decide_div_mod_eq, Nat.pow_add, Nat.mul_assoc]
simp only [Nat.mul_add_div (Nat.two_pow_pos _), Nat.mul_add_mod]
simp [Nat.pow_succ, Nat.mul_comm _ 2, Nat.mul_assoc, Nat.mul_add_mod]
simp only [Nat.mul_add_div (Nat.two_pow_pos _)]
simp [Nat.pow_succ, Nat.mul_comm _ 2, Nat.mul_assoc]
| inr j_ge =>
have j_def : j = i + (j-i) := (Nat.add_sub_cancel' j_ge).symm
simp only [
@@ -789,7 +789,7 @@ abbrev mul_add_lt_is_or := @two_pow_add_eq_or_of_lt
theorem bitwise_mul_two_pow (of_false_false : f false false = false := by rfl) :
(bitwise f x y) * 2 ^ n = bitwise f (x * 2 ^ n) (y * 2 ^ n) := by
apply Nat.eq_of_testBit_eq
simp only [testBit_mul_two_pow, testBit_bitwise of_false_false, Bool.if_false_right]
simp only [testBit_mul_two_pow, testBit_bitwise of_false_false]
intro i
by_cases hn : n i
· simp [hn]

View File

@@ -37,7 +37,7 @@ theorem compare_eq_ite_le (a b : Nat) :
· next hlt => simp [Nat.le_of_lt hlt, Nat.not_le.2 hlt]
· next hge =>
split
· next hgt => simp [Nat.le_of_lt hgt, Nat.not_le.2 hgt]
· next hgt => simp [Nat.not_le.2 hgt]
· next hle => simp [Nat.not_lt.1 hge, Nat.not_lt.1 hle]
@[deprecated compare_eq_ite_le (since := "2025-03_28")]

View File

@@ -512,7 +512,7 @@ theorem sub_mul_div_of_le (x n p : Nat) (h₁ : n*p ≤ x) : (x - n*p) / n = x /
rw [mul_succ] at h₁
exact h₁
rw [sub_succ, IH h₂, div_eq_sub_div h₀ h₃]
simp [Nat.pred_succ, mul_succ, Nat.sub_sub]
simp [mul_succ, Nat.sub_sub]
theorem mul_sub_div (x n p : Nat) (h₁ : x < n*p) : (n * p - (x + 1)) / n = p - ((x / n) + 1) := by
have npos : 0 < n := (eq_zero_or_pos _).resolve_left fun n0 => by

View File

@@ -80,7 +80,7 @@ theorem lt_div_mul_self (h : 0 < k) (w : k ≤ x) : x - k < x / k * k := by
theorem div_pos (hba : b a) (hb : 0 < b) : 0 < a / b := by
cases b
· contradiction
· simp [Nat.pos_iff_ne_zero, div_eq_zero_iff_lt, hba]
· simp [Nat.pos_iff_ne_zero, hba]
theorem div_le_div_left (hcb : c b) (hc : 0 < c) : a / b a / c :=
(Nat.le_div_iff_mul_le hc).2 <|

View File

@@ -137,7 +137,7 @@ theorem dvd_sub_iff_left {m n k : Nat} (hkn : k ≤ n) (h : m k) : m n -
protected theorem mul_dvd_mul {a b c d : Nat} : a b c d a * c b * d
| e, he, f, hf =>
e * f, by simp [he, hf, Nat.mul_assoc, Nat.mul_left_comm, Nat.mul_comm]
e * f, by simp [he, hf, Nat.mul_left_comm, Nat.mul_comm]
protected theorem mul_dvd_mul_left (a : Nat) (h : b c) : a * b a * c :=
Nat.mul_dvd_mul (Nat.dvd_refl a) h
@@ -161,7 +161,7 @@ protected theorem dvd_eq_true_of_mod_eq_zero {m n : Nat} (h : n % m == 0) : (m
simp [Nat.dvd_of_mod_eq_zero, eq_of_beq h]
protected theorem dvd_eq_false_of_mod_ne_zero {m n : Nat} (h : n % m != 0) : (m n) = False := by
simp [eq_of_beq] at h
simp at h
simp [dvd_iff_mod_eq_zero, h]
end Nat

View File

@@ -142,7 +142,7 @@ theorem foldTR_loop_congr {α : Type u} {n m : Nat} (w : n = m)
| succ m, n, f => by
have t : (m + 1) + n = m + (n + 1) := by omega
rw [foldTR.loop]
simp only [succ_eq_add_one, Nat.add_sub_cancel]
simp only [succ_eq_add_one]
rw [fold_congr t, foldTR_loop_congr t, go, fold]
congr
omega

View File

@@ -54,7 +54,7 @@ theorem gcd_def (x y : Nat) : gcd x y = if x = 0 then y else gcd (y % x) x := by
@[simp] theorem gcd_zero_right (n : Nat) : gcd n 0 = n := by
cases n with
| zero => simp [gcd_succ]
| zero => simp
| succ n =>
-- `simp [gcd_succ]` produces an invalid term unless `gcd_succ` is proved with `id rfl` instead
rw [gcd_succ]

View File

@@ -1044,7 +1044,7 @@ theorem div_le_iff_le_mul_of_dvd (hb : b ≠ 0) (hba : b a) : a / b ≤ c
exact mul_le_mul_right b, fun h Nat.le_of_mul_le_mul_right h (zero_lt_of_ne_zero hb)
protected theorem div_lt_div_right (ha : a 0) : a b a c (b / a < c / a b < c) := by
rintro d, rfl e, rfl; simp [Nat.mul_div_cancel, Nat.pos_iff_ne_zero.2 ha]
rintro d, rfl e, rfl; simp [Nat.pos_iff_ne_zero.2 ha]
protected theorem div_lt_div_left (ha : a 0) (hba : b a) (hca : c a) :
a / b < a / c c < b := by
@@ -1164,7 +1164,7 @@ protected theorem pow_le_pow_iff_right {a n m : Nat} (h : 1 < a) :
constructor
· apply Decidable.by_contra
intros w
simp [Decidable.not_imp_iff_and_not] at w
simp at w
apply Nat.lt_irrefl (a ^ n)
exact Nat.lt_of_le_of_lt w.1 (Nat.pow_lt_pow_of_lt h w.2)
· intro w
@@ -1320,7 +1320,7 @@ theorem le_log2 (h : n ≠ 0) : k ≤ n.log2 ↔ 2 ^ k ≤ n := by
| k+1 =>
rw [log2]; split
· have n0 : 0 < n / 2 := (Nat.le_div_iff_mul_le (by decide)).2 _
simp only [Nat.add_le_add_iff_right, le_log2 (Nat.ne_of_gt n0), le_div_iff_mul_le,
simp only [Nat.add_le_add_iff_right, le_log2 (Nat.ne_of_gt n0),
Nat.pow_succ]
exact Nat.le_div_iff_mul_le (by decide)
· simp only [le_zero_eq, succ_ne_zero, false_iff]
@@ -1434,7 +1434,7 @@ theorem le_iff_ne_zero_of_dvd (ha : a ≠ 0) (hab : a b) : a ≤ b ↔ b ≠
theorem div_ne_zero_iff_of_dvd (hba : b a) : a / b 0 a 0 b 0 := by
obtain rfl | hb := Decidable.em (b = 0) <;>
simp [Nat.div_ne_zero_iff, Nat.le_iff_ne_zero_of_dvd, *]
simp [Nat.le_iff_ne_zero_of_dvd, *]
theorem pow_mod (a b n : Nat) : a ^ b % n = (a % n) ^ b % n := by
induction b with
@@ -1706,12 +1706,12 @@ theorem shiftRight_succ_inside : ∀m n, m >>> (n+1) = (m/2) >>> n
rw [shiftRight_succ_inside _ k, shiftRight_succ]
@[simp] theorem zero_shiftLeft : n, 0 <<< n = 0
| 0 => by simp [shiftLeft]
| n + 1 => by simp [shiftLeft, zero_shiftLeft n, shiftLeft_succ]
| 0 => by simp
| n + 1 => by simp [zero_shiftLeft n, shiftLeft_succ]
@[simp] theorem zero_shiftRight : n, 0 >>> n = 0
| 0 => by simp [shiftRight]
| n + 1 => by simp [shiftRight, zero_shiftRight n, shiftRight_succ]
| 0 => by simp
| n + 1 => by simp [zero_shiftRight n, shiftRight_succ]
theorem shiftLeft_add (m n : Nat) : k, m <<< (n + k) = (m <<< n) <<< k
| 0 => rfl

View File

@@ -226,7 +226,7 @@ theorem Poly.denote_insert (ctx : Context) (k : Nat) (v : Var) (p : Poly) :
· by_cases h₂ : Nat.beq v v'
· simp only [insert, h₁, h₂, cond_false, cond_true]
simp [Nat.eq_of_beq_eq_true h₂]
· simp only [insert, h₁, h₂, cond_false, cond_true]
· simp only [insert, h₁, h₂, cond_false]
simp [denote_insert]
attribute [local simp] Poly.denote_insert
@@ -253,7 +253,7 @@ attribute [local simp] Poly.denote_append
theorem Poly.denote_cons (ctx : Context) (k : Nat) (v : Var) (p : Poly) : denote ctx ((k, v) :: p) = k * v.denote ctx + p.denote ctx := by
match p with
| [] => simp
| _ :: m => simp [denote_cons]
| _ :: m => simp
attribute [local simp] Poly.denote_cons
@@ -434,13 +434,13 @@ theorem Expr.denote_toPoly_go (ctx : Context) (e : Expr) :
simp [toPoly.go, h, Var.denote]
| case3 k i => simp [toPoly.go]
| case4 k a b iha ihb => simp [toPoly.go, iha, ihb]
| case5 k k' a h => simp [toPoly.go, h, eq_of_beq h]
| case5 k k' a h => simp [toPoly.go, eq_of_beq h]
| case6 k a k' h ih =>
simp only [toPoly.go, denote, mul_eq]
simp [h, cond_false, ih, Nat.mul_assoc]
| case7 k a k' h =>
simp only [toPoly.go, denote, mul_eq]
simp [h, eq_of_beq h]
simp [eq_of_beq h]
| case8 k a k' h ih =>
simp only [toPoly.go, denote, mul_eq]
simp [h, cond_false, ih, Nat.mul_assoc]

View File

@@ -29,7 +29,7 @@ namespace Nat
| succ a ih =>
cases a
· simp
· simp_all [succ_eq_add_one, Nat.right_distrib]
· simp_all [Nat.right_distrib]
omega
@[simp] protected theorem mul_lt_mul_right (a0 : 0 < a) : b * a < c * a b < c := by

View File

@@ -142,7 +142,7 @@ where
subst m₂
by_cases heq : k₁ + k₂ == 0 <;> simp! [heq, ih]
· simp [ Nat.add_assoc, Nat.right_distrib, eq_of_beq heq]
· simp [Nat.right_distrib, Nat.add_assoc, Nat.add_comm, Nat.add_left_comm]
· simp [Nat.right_distrib, Nat.add_assoc]
theorem Poly.denote_insertSorted (ctx : Context) (k : Nat) (m : Mon) (p : Poly) : (p.insertSorted k m).denote ctx = p.denote ctx + k * m.denote ctx := by
match p with

View File

@@ -82,7 +82,7 @@ abbrev attach_map_coe := @attach_map_val
theorem attachWith_map_val {p : α Prop} (f : α β) (o : Option α) (H : a, o = some a p a) :
((o.attachWith p H).map fun (i : { i // p i}) => f i.val) = o.map f := by
cases o <;> simp [H]
cases o <;> simp
@[deprecated attachWith_map_val (since := "2025-02-17")]
abbrev attachWith_map_coe := @attachWith_map_val
@@ -202,7 +202,7 @@ theorem map_attachWith_eq_pmap {o : Option α} {P : α → Prop} {H : ∀ (a :
@[simp]
theorem map_attach_eq_attachWith {o : Option α} {p : α Prop} (f : a, o = some a p a) :
o.attach.map (fun x => x.1, f x.1 x.2) = o.attachWith p f := by
cases o <;> simp_all [Function.comp_def]
cases o <;> simp_all
@[grind =] theorem attach_bind {o : Option α} {f : α Option β} :
(o.bind f).attach =
@@ -289,7 +289,7 @@ theorem toArray_pmap {p : α → Prop} {o : Option α} {f : (a : α) → p a →
cases o with
| none => simp
| some a =>
simp only [attach_some, eq_mp_eq_cast, id_eq, pbind_some]
simp only [attach_some, pbind_some]
rw [attach_congr pfilter_some]
split <;> simp [*]

View File

@@ -275,7 +275,7 @@ theorem join_ne_none' : ¬x.join = none ↔ ∃ z, x = some (some z) :=
join_ne_none
theorem join_eq_none_iff : o.join = none o = none o = some none :=
match o with | none | some none | some (some _) => by simp [bind_id_eq_join]
match o with | none | some none | some (some _) => by simp
@[deprecated join_eq_none_iff (since := "2025-04-10")]
abbrev join_eq_none := @join_eq_none_iff
@@ -302,7 +302,7 @@ abbrev map_eq_some := @map_eq_some_iff
abbrev map_eq_some' := @map_eq_some_iff
@[simp] theorem map_eq_none_iff : x.map f = none x = none := by
cases x <;> simp [map_none, map_some, eq_self_iff_true]
cases x <;> simp [map_none, map_some]
@[deprecated map_eq_none_iff (since := "2025-04-10")]
abbrev map_eq_none := @map_eq_none_iff

View File

@@ -110,7 +110,7 @@ theorem forIn'_id_yield_eq_pelim
theorem forIn'_join [Monad m] [LawfulMonad m] (b : β) (o : Option (Option α))
(f : (a : α) a o.join β m (ForInStep β)) :
forIn' o.join b f = forIn' o b (fun o' ho' b => ForInStep.yield <$> forIn' o' b (fun a ha b' => f a (by simp_all [join_eq_some_iff]) b')) := by
forIn' o.join b f = forIn' o b (fun o' ho' b => ForInStep.yield <$> forIn' o' b (fun a ha b' => f a (by simp_all) b')) := by
cases o with
| none => simp
| some a => simpa using forIn'_congr rfl rfl (by simp)

View File

@@ -351,7 +351,7 @@ theorem compareOfLessAndEq_eq_swap_of_lt_iff_not_gt_and_ne {α : Type u} [LT α]
simp only [h', this, reduceIte, Ordering.swap_eq]
· rename_i h' h''
replace h' := (h y x).mpr h', Ne.symm h''
simp only [h', Ne.symm h'', reduceIte, Ordering.swap_lt]
simp only [h', reduceIte, Ordering.swap_lt]
theorem lt_iff_not_gt_and_ne_of_antisymm_of_total_of_not_le
{α : Type u} [LT α] [LE α] [DecidableLT α] [DecidableEq α]

View File

@@ -716,7 +716,7 @@ theorem ISize.shiftLeft_or {a b c : ISize} : (a ||| b) <<< c = (a <<< c) ||| (b
@[simp] theorem Int32.neg_one_shiftLeft_or_shiftLeft {a b : Int32} :
(-1) <<< b ||| a <<< b = (-1) <<< b := by simp [ Int32.shiftLeft_or]
@[simp] theorem Int64.neg_one_shiftLeft_or_shiftLeft {a b : Int8} :
(-1) <<< b ||| a <<< b = (-1) <<< b := by simp [ Int64.shiftLeft_or]
(-1) <<< b ||| a <<< b = (-1) <<< b := by simp
@[simp] theorem ISize.neg_one_shiftLeft_or_shiftLeft {a b : ISize} :
(-1) <<< b ||| a <<< b = (-1) <<< b := by simp [ ISize.shiftLeft_or]

View File

@@ -1622,23 +1622,23 @@ theorem ISize.toInt_div_of_ne_right (a b : ISize) (h : b ≠ -1) : (a / b).toInt
exact Or.inr (by simpa [ toBitVec_inj] using h)
theorem Int8.toInt16_ne_minValue (a : Int8) : a.toInt16 Int16.minValue :=
have := a.le_toInt; by simp [ Int16.toInt_inj, Int16.toInt_minValue]; omega
have := a.le_toInt; by simp [ Int16.toInt_inj]; omega
theorem Int8.toInt32_ne_minValue (a : Int8) : a.toInt32 Int32.minValue :=
have := a.le_toInt; by simp [ Int32.toInt_inj, Int32.toInt_minValue]; omega
have := a.le_toInt; by simp [ Int32.toInt_inj]; omega
theorem Int8.toInt64_ne_minValue (a : Int8) : a.toInt64 Int64.minValue :=
have := a.le_toInt; by simp [ Int64.toInt_inj, Int64.toInt_minValue]; omega
have := a.le_toInt; by simp [ Int64.toInt_inj]; omega
theorem Int8.toISize_ne_minValue (a : Int8) : a.toISize ISize.minValue :=
have := a.le_toInt; have := ISize.toInt_minValue_le; by simp [ ISize.toInt_inj]; omega
theorem Int16.toInt32_ne_minValue (a : Int16) : a.toInt32 Int32.minValue :=
have := a.le_toInt; by simp [ Int32.toInt_inj, Int32.toInt_minValue]; omega
have := a.le_toInt; by simp [ Int32.toInt_inj]; omega
theorem Int16.toInt64_ne_minValue (a : Int16) : a.toInt64 Int64.minValue :=
have := a.le_toInt; by simp [ Int64.toInt_inj, Int64.toInt_minValue]; omega
have := a.le_toInt; by simp [ Int64.toInt_inj]; omega
theorem Int16.toISize_ne_minValue (a : Int16) : a.toISize ISize.minValue :=
have := a.le_toInt; have := ISize.toInt_minValue_le; by simp [ ISize.toInt_inj]; omega
theorem Int32.toInt64_ne_minValue (a : Int32) : a.toInt64 Int64.minValue :=
have := a.le_toInt; by simp [ Int64.toInt_inj, Int64.toInt_minValue]; omega
have := a.le_toInt; by simp [ Int64.toInt_inj]; omega
theorem Int32.toISize_ne_minValue (a : Int32) (ha : a minValue) : a.toISize ISize.minValue := by
have := a.le_toInt
have := ISize.toInt_minValue_le

View File

@@ -163,7 +163,7 @@ def toUTF8 (a : @& String) : ByteArray :=
@[simp] theorem size_toUTF8 (s : String) : s.toUTF8.size = s.utf8ByteSize := by
simp [toUTF8, ByteArray.size, Array.size, utf8ByteSize, List.flatMap]
induction s.data <;> simp [List.map, List.flatten, utf8ByteSize.go, Nat.add_comm, *]
induction s.data <;> simp [List.map, utf8ByteSize.go, Nat.add_comm, *]
/--
Accesses the indicated byte in the UTF-8 encoding of a string.

View File

@@ -1231,7 +1231,7 @@ theorem USize.shiftLeft_add {a b c : USize} (hb : b < USize.ofNat System.Platfor
@[simp] theorem UInt32.neg_one_shiftLeft_or_shiftLeft {a b : UInt32} :
(-1) <<< b ||| a <<< b = (-1) <<< b := by simp [ UInt32.shiftLeft_or]
@[simp] theorem UInt64.neg_one_shiftLeft_or_shiftLeft {a b : UInt8} :
(-1) <<< b ||| a <<< b = (-1) <<< b := by simp [ UInt64.shiftLeft_or]
(-1) <<< b ||| a <<< b = (-1) <<< b := by simp
@[simp] theorem USize.neg_one_shiftLeft_or_shiftLeft {a b : USize} :
(-1) <<< b ||| a <<< b = (-1) <<< b := by simp [ USize.shiftLeft_or]

View File

@@ -1765,7 +1765,7 @@ theorem USize.le_iff_toFin_le {a b : USize} : a ≤ b ↔ a.toFin ≤ b.toFin :=
simp [lt_iff_toNat_lt, UInt32.lt_iff_toNat_lt]
@[simp] theorem USize.toUInt32_lt {a b : USize} : a.toUInt32 < b.toUInt32 a % 4294967296 < b % 4294967296 := by
rw [ UInt32.toUSize_lt, toUSize_toUInt32]
simp [lt_iff_toNat_lt, UInt32.lt_iff_toNat_lt]
simp [lt_iff_toNat_lt]
@[simp] theorem UInt64.toUSize_lt {a b : UInt64} : a.toUSize < b.toUSize a % UInt64.ofNat USize.size < b % UInt64.ofNat USize.size := by
simp only [USize.lt_iff_toNat_lt, toNat_toUSize, lt_iff_toNat_lt, UInt64.toNat_mod, toNat_ofNat', Nat.reducePow]
@@ -1815,10 +1815,10 @@ theorem USize.le_iff_toFin_le {a b : USize} : a ≤ b ↔ a.toFin ≤ b.toFin :=
simp [le_iff_toNat_le, UInt32.le_iff_toNat_le]
@[simp] theorem USize.toUInt32_le {a b : USize} : a.toUInt32 b.toUInt32 a % 4294967296 b % 4294967296 := by
rw [ UInt32.toUSize_le, toUSize_toUInt32]
simp [le_iff_toNat_le, UInt32.le_iff_toNat_le]
simp [le_iff_toNat_le]
@[simp] theorem UInt64.toUSize_le {a b : UInt64} : a.toUSize b.toUSize a % UInt64.ofNat USize.size b % UInt64.ofNat USize.size := by
simp only [USize.le_iff_toNat_le, toNat_toUSize, le_iff_toNat_le, UInt64.toNat_mod, UInt64.reduceToNat]
simp only [USize.le_iff_toNat_le, toNat_toUSize, le_iff_toNat_le, UInt64.toNat_mod]
cases System.Platform.numBits_eq <;> simp_all [USize.size]
@[simp] theorem UInt16.toUInt8_neg (a : UInt16) : (-a).toUInt8 = -a.toUInt8 := UInt8.toBitVec_inj.1 (by simp)
@@ -1927,7 +1927,7 @@ theorem USize.sub_eq_add_mul (a b : USize) : a - b = a + USize.ofNatLT (USize.si
@[simp] theorem UInt16.ofNat_usizeSize_sub_one : UInt16.ofNat (USize.size - 1) = 65535 := UInt16.toNat.inj (by simp)
@[simp] theorem UInt32.ofNat_usizeSize_sub_one : UInt32.ofNat (USize.size - 1) = 4294967295 := UInt32.toNat.inj (by simp)
@[simp] theorem USize.ofNat_uInt64Size_sub_one : USize.ofNat (UInt64.size - 1) = USize.ofNatLT (USize.size - 1) (Nat.sub_one_lt (Nat.pos_iff_ne_zero.1 size_pos)) :=
USize.toNat.inj (by simp [USize.toNat_ofNat])
USize.toNat.inj (by simp)
@[simp] theorem UInt16.toUInt8_sub (a b : UInt16) : (a - b).toUInt8 = a.toUInt8 - b.toUInt8 := by
simp [UInt16.sub_eq_add_neg, UInt8.sub_eq_add_neg]
@@ -2093,11 +2093,11 @@ theorem USize.ofNat_eq_iff_mod_eq_toNat (a : Nat) (b : USize) : USize.ofNat a =
@[simp] theorem USize.ofInt_one : ofInt 1 = 1 := by
rcases System.Platform.numBits_eq with h | h <;>
· apply USize.toNat_inj.mp
simp_all [USize.ofInt, USize.ofNat, size, toNat]
simp_all [USize.ofInt, USize.ofNat, toNat]
@[simp] theorem USize.ofInt_neg_one : ofInt (-1) = -1 := by
rcases System.Platform.numBits_eq with h | h <;>
· apply USize.toNat_inj.mp
simp_all [USize.ofInt, USize.ofNat, size, toNat]
simp_all [USize.ofInt, USize.ofNat, toNat]
@[simp] theorem UInt8.ofNat_add (a b : Nat) : UInt8.ofNat (a + b) = UInt8.ofNat a + UInt8.ofNat b := by
simp [UInt8.ofNat_eq_iff_mod_eq_toNat]

View File

@@ -292,7 +292,7 @@ See however `foldl_subtype` below.
theorem foldl_attach {xs : Vector α n} {f : β α β} {b : β} :
xs.attach.foldl (fun acc t => f acc t.1) b = xs.foldl f b := by
rcases xs with xs, rfl
simp [Array.foldl_attach]
simp
/--
If we fold over `l.attach` with a function that ignores the membership predicate,
@@ -307,7 +307,7 @@ See however `foldr_subtype` below.
theorem foldr_attach {xs : Vector α n} {f : α β β} {b : β} :
xs.attach.foldr (fun t acc => f t.1 acc) b = xs.foldr f b := by
rcases xs with xs, rfl
simp [Array.foldr_attach]
simp
@[grind =]
theorem attach_map {xs : Vector α n} {f : α β} :
@@ -378,7 +378,7 @@ theorem pmap_append' {p : α → Prop} {f : ∀ a : α, p a → β} {xs : Vector
{H : (a : α), a xs ++ ys P a} :
(xs ++ ys).attachWith P H = xs.attachWith P (fun a h => H a (mem_append_left ys h)) ++
ys.attachWith P (fun a h => H a (mem_append_right xs h)) := by
simp [attachWith, attach_append, map_pmap, pmap_append]
simp [attachWith]
@[simp, grind =] theorem pmap_reverse {P : α Prop} {f : (a : α) P a β} {xs : Vector α n}
(H : (a : α), a xs.reverse P a) :
@@ -439,7 +439,7 @@ theorem back?_attach {xs : Vector α n} :
theorem countP_attach {xs : Vector α n} {p : α Bool} :
xs.attach.countP (fun a : {x // x xs} => p a) = xs.countP p := by
cases xs
simp [Function.comp_def]
simp
@[simp]
theorem countP_attachWith {p : α Prop} {q : α Bool} {xs : Vector α n} {H : a xs, p a} :

View File

@@ -77,7 +77,7 @@ theorem countP_le_size {xs : Vector α n} : countP p xs ≤ n := by
simp
theorem countP_replicate {a : α} {n : Nat} : countP p (replicate n a) = if p a then n else 0 := by
simp only [replicate_eq_mk_replicate, countP_cast, countP_mk]
simp only [replicate_eq_mk_replicate, countP_mk]
simp [Array.countP_replicate]
@[deprecated countP_replicate (since := "2025-03-18")]
@@ -91,7 +91,7 @@ theorem boole_getElem_le_countP {p : α → Bool} {xs : Vector α n} (h : i < n)
theorem countP_set {p : α Bool} {xs : Vector α n} {a : α} (h : i < n) :
(xs.set i a).countP p = xs.countP p - (if p xs[i] then 1 else 0) + (if p a then 1 else 0) := by
rcases xs with xs, rfl
simp [Array.countP_set, h]
simp [Array.countP_set]
@[simp] theorem countP_true : (countP fun (_ : α) => true) = (fun (_ : Vector α n) => n) := by
funext xs
@@ -177,12 +177,12 @@ theorem count_le_count_push {a b : α} {xs : Vector α n} : count a xs ≤ count
theorem boole_getElem_le_count {a : α} {xs : Vector α n} (h : i < n) :
(if xs[i] == a then 1 else 0) xs.count a := by
rcases xs with xs, rfl
simp [Array.boole_getElem_le_count, h]
simp [Array.boole_getElem_le_count]
theorem count_set {a b : α} {xs : Vector α n} (h : i < n) :
(xs.set i a).count b = xs.count b - (if xs[i] == b then 1 else 0) + (if a == b then 1 else 0) := by
rcases xs with xs, rfl
simp [Array.count_set, h]
simp [Array.count_set]
@[simp] theorem count_cast {xs : Vector α n} : (xs.cast h).count a = xs.count a := by
rcases xs with xs, rfl
@@ -203,7 +203,7 @@ theorem count_singleton_self {a : α} : count a #v[a] = 1 := by simp
@[simp]
theorem count_pos_iff {a : α} {xs : Vector α n} : 0 < count a xs a xs := by
rcases xs with xs, rfl
simp [Array.count_pos_iff, beq_iff_eq, exists_eq_right]
simp [Array.count_pos_iff]
@[simp] theorem one_le_count_iff {a : α} {xs : Vector α n} : 1 count a xs a xs :=
count_pos_iff
@@ -222,14 +222,14 @@ theorem count_eq_size {xs : Vector α n} : count a xs = n ↔ ∀ b ∈ xs, a =
simp [Array.count_eq_size]
@[simp] theorem count_replicate_self {a : α} {n : Nat} : count a (replicate n a) = n := by
simp only [replicate_eq_mk_replicate, count_cast, count_mk]
simp only [replicate_eq_mk_replicate, count_mk]
simp
@[deprecated count_replicate_self (since := "2025-03-18")]
abbrev count_mkVector_self := @count_replicate_self
theorem count_replicate {a b : α} {n : Nat} : count a (replicate n b) = if b == a then n else 0 := by
simp only [replicate_eq_mk_replicate, count_cast, count_mk]
simp only [replicate_eq_mk_replicate, count_mk]
simp [Array.count_replicate]
@[deprecated count_replicate (since := "2025-03-18")]

View File

@@ -42,7 +42,7 @@ theorem getElem?_eraseIdx_of_lt {xs : Vector α n} {i : Nat} (h : i < n) {j : Na
theorem getElem?_eraseIdx_of_ge {xs : Vector α n} {i : Nat} (h : i < n) {j : Nat} (h' : i j) :
(xs.eraseIdx i)[j]? = xs[j + 1]? := by
rw [getElem?_eraseIdx]
simp only [dite_eq_ite, ite_eq_right_iff]
simp only [ite_eq_right_iff]
intro h'
omega

View File

@@ -51,7 +51,7 @@ theorem extract_append_extract {xs : Vector α n} {i j k : Nat} :
theorem push_extract_getElem {xs : Vector α n} {i j : Nat} (h : j < n) :
(xs.extract i j).push xs[j] = (xs.extract (min i j) (j + 1)).cast (by omega) := by
rcases xs with xs, rfl
simp [h]
simp
theorem extract_succ_right {xs : Vector α n} {i j : Nat} (w : i < j + 1) (h : j < n) :
xs.extract i (j + 1) = ((xs.extract i j).push xs[j]).cast (by omega) := by
@@ -67,7 +67,7 @@ theorem extract_sub_one {xs : Vector α n} {i j : Nat} (h : j < n) :
theorem getElem?_extract_of_lt {xs : Vector α n} {i j k : Nat} (h : k < min j n - i) :
(xs.extract i j)[k]? = some (xs[i + k]'(by omega)) := by
rcases xs with xs, rfl
simp [getElem?_extract, h]
simp [h]
theorem getElem?_extract_of_succ {xs : Vector α n} {j : Nat} :
(xs.extract 0 (j + 1))[j]? = xs[j]? := by
@@ -161,7 +161,7 @@ theorem mem_extract_iff_getElem {xs : Vector α n} {a : α} {i j : Nat} :
theorem set_eq_push_extract_append_extract {xs : Vector α n} {i : Nat} (h : i < n) {a : α} :
xs.set i a = ((xs.extract 0 i).push a ++ (xs.extract (i + 1) n)).cast (by omega) := by
rcases xs with as, rfl
simp [Array.set_eq_push_extract_append_extract, h]
simp [Array.set_eq_push_extract_append_extract]
@[grind =]
theorem extract_reverse {xs : Vector α n} {i j : Nat} :

View File

@@ -30,7 +30,7 @@ open Nat
@[simp, grind] theorem findSome?_empty : (#v[] : Vector α 0).findSome? f = none := rfl
@[simp, grind] theorem findSome?_push {xs : Vector α n} : (xs.push a).findSome? f = (xs.findSome? f).or (f a) := by
cases xs; simp [List.findSome?_append]
cases xs; simp
@[grind]
theorem findSome?_singleton {a : α} {f : α Option β} : #v[a].findSome? f = f a := by
@@ -124,7 +124,7 @@ theorem getElem_zero_flatten.proof {xss : Vector (Vector α m) n} (h : 0 < n * m
theorem getElem_zero_flatten {xss : Vector (Vector α m) n} (h : 0 < n * m) :
(flatten xss)[0] = (xss.findSome? fun xs => xs[0]?).get (getElem_zero_flatten.proof h) := by
have t := getElem?_zero_flatten (xss := xss)
simp [getElem?_eq_getElem, h] at t
simp [h] at t
simp [ t]
@[grind =]
@@ -251,7 +251,7 @@ theorem find?_flatten_eq_none_iff {xs : Vector (Vector α m) n} {p : α → Bool
@[simp, grind =] theorem find?_flatMap {xs : Vector α n} {f : α Vector β m} {p : β Bool} :
(xs.flatMap f).find? p = xs.findSome? (fun x => (f x).find? p) := by
cases xs
simp [Array.find?_flatMap, Array.flatMap_toArray]
simp [Array.find?_flatMap]
theorem find?_flatMap_eq_none_iff {xs : Vector α n} {f : α Vector β m} {p : β Bool} :

View File

@@ -98,22 +98,22 @@ theorem getElem_insertIdx {xs : Vector α n} {x : α} {i k : Nat} (w : i ≤ n)
else
xs[k-1] := by
rcases xs with xs, rfl
simp [Array.getElem_insertIdx, w]
simp [Array.getElem_insertIdx]
theorem getElem_insertIdx_of_lt {xs : Vector α n} {x : α} {i k : Nat} (w : i n) (h : k < i) :
(xs.insertIdx i x)[k] = xs[k] := by
rcases xs with xs, rfl
simp [Array.getElem_insertIdx, w, h]
simp [Array.getElem_insertIdx, h]
theorem getElem_insertIdx_self {xs : Vector α n} {x : α} {i : Nat} (w : i n) :
(xs.insertIdx i x)[i] = x := by
rcases xs with xs, rfl
simp [Array.getElem_insertIdx, w]
simp [Array.getElem_insertIdx]
theorem getElem_insertIdx_of_gt {xs : Vector α n} {x : α} {i k : Nat} (w : k n) (h : k > i) :
(xs.insertIdx i x)[k] = xs[k - 1] := by
rcases xs with xs, rfl
simp [Array.getElem_insertIdx, w, h]
simp [Array.getElem_insertIdx]
rw [dif_neg (by omega), dif_neg (by omega)]
@[grind =]
@@ -127,7 +127,7 @@ theorem getElem?_insertIdx {xs : Vector α n} {x : α} {i k : Nat} (h : i ≤ n)
else
xs[k-1]? := by
rcases xs with xs, rfl
simp [Array.getElem?_insertIdx, h]
simp [Array.getElem?_insertIdx]
theorem getElem?_insertIdx_of_lt {xs : Vector α n} {x : α} {i k : Nat} (w : i n) (h : k < i) :
(xs.insertIdx i x)[k]? = xs[k]? := by

View File

@@ -55,7 +55,7 @@ theorem toArray_mk {xs : Array α} (h : xs.size = n) : (Vector.mk xs h).toArray
@[simp] theorem push_mk {xs : Array α} {size : xs.size = n} :
(Vector.mk xs size).push =
fun x => Vector.mk (xs.push x) (by simp [size, Nat.succ_eq_add_one]) := rfl
fun x => Vector.mk (xs.push x) (by simp [size]) := rfl
@[simp] theorem pop_mk {xs : Array α} {size : xs.size = n} :
(Vector.mk xs size).pop = Vector.mk xs.pop (by simp [size]) := rfl
@@ -96,14 +96,14 @@ theorem toArray_mk {xs : Array α} (h : xs.size = n) : (Vector.mk xs h).toArray
(Vector.mk xs h).eraseIdx i h' = Vector.mk (xs.eraseIdx i) (by simp [h]) := rfl
@[simp] theorem eraseIdx!_mk {xs : Array α} {h : xs.size = n} {i} (hi : i < n) :
(Vector.mk xs h).eraseIdx! i = Vector.mk (xs.eraseIdx i) (by simp [h, hi]) := by
(Vector.mk xs h).eraseIdx! i = Vector.mk (xs.eraseIdx i) (by simp [h]) := by
simp [Vector.eraseIdx!, hi]
@[simp] theorem insertIdx_mk {xs : Array α} {h : xs.size = n} {i x} (h') :
(Vector.mk xs h).insertIdx i x h' = Vector.mk (xs.insertIdx i x) (by simp [h, h']) := rfl
(Vector.mk xs h).insertIdx i x h' = Vector.mk (xs.insertIdx i x) (by simp [h]) := rfl
@[simp] theorem insertIdx!_mk {xs : Array α} {h : xs.size = n} {i x} (hi : i n) :
(Vector.mk xs h).insertIdx! i x = Vector.mk (xs.insertIdx i x) (by simp [h, hi]) := by
(Vector.mk xs h).insertIdx! i x = Vector.mk (xs.insertIdx i x) (by simp [h]) := by
simp [Vector.insertIdx!, hi]
@[simp] theorem cast_mk {xs : Array α} {h : xs.size = n} {h' : n = m} :
@@ -367,7 +367,7 @@ theorem toArray_mapM_go [Monad m] [LawfulMonad m] {f : α → m β} {xs : Vector
@[simp, grind] theorem toArray_singleton {x : α} : (Vector.singleton x).toArray = #[x] := rfl
@[simp, grind] theorem toArray_swap {xs : Vector α n} {i j} (hi hj) : (xs.swap i j).toArray =
xs.toArray.swap i j (by simp [hi, hj]) (by simp [hi, hj]) := rfl
xs.toArray.swap i j (by simp [hj]) (by simp [hi]) := rfl
@[simp, grind] theorem toArray_swapIfInBounds {xs : Vector α n} {i j} :
(xs.swapIfInBounds i j).toArray = xs.toArray.swapIfInBounds i j := rfl
@@ -539,14 +539,14 @@ theorem toList_eraseIdx {xs : Vector α n} {i} (h) :
@[simp] theorem toList_eraseIdx! {xs : Vector α n} {i} (hi : i < n) :
(xs.eraseIdx! i).toList = xs.toList.eraseIdx i := by
cases xs; simp_all [Array.eraseIdx!]
cases xs; simp_all
theorem toList_insertIdx {xs : Vector α n} {i x} (h) :
(xs.insertIdx i x h).toList = xs.toList.insertIdx i x := by simp [toList]
theorem toList_insertIdx! {xs : Vector α n} {i x} (hi : i n) :
(xs.insertIdx! i x).toList = xs.toList.insertIdx i x := by
cases xs; simp_all [Array.insertIdx!]
cases xs; simp_all
theorem toList_cast {xs : Vector α n} (h : n = m) :
(xs.cast h).toList = xs.toList := rfl
@@ -593,7 +593,7 @@ theorem toList_swap {xs : Vector α n} {i j} (hi hj) :
(xs.swap i j).toList = (xs.toList.set i xs[j]).set j xs[i] := rfl
@[simp] theorem toList_take {xs : Vector α n} {i} : (xs.take i).toList = xs.toList.take i := by
simp [toList, List.take_of_length_le]
simp [toList]
@[simp] theorem toList_zipWith {f : α β γ} {as : Vector α n} {bs : Vector β n} :
(Vector.zipWith f as bs).toList = List.zipWith f as.toList bs.toList := by
@@ -822,7 +822,7 @@ theorem none_eq_getElem?_iff {xs : Vector α n} {i : Nat} : none = xs[i]? ↔ n
simp
theorem getElem?_eq_none {xs : Vector α n} (h : n i) : xs[i]? = none := by
simp [getElem?_eq_none_iff, h]
simp [h]
-- This is a more aggressive pattern than for `List/Array.getElem?_eq_none`, because
-- `length/size` won't appear.
@@ -854,16 +854,16 @@ theorem getElem_eq_iff {xs : Vector α n} {i : Nat} {h : i < n} : xs[i] = x ↔
exact fun w => h, w, fun h => h.2
theorem getElem_eq_getElem?_get {xs : Vector α n} {i : Nat} (h : i < n) :
xs[i] = xs[i]?.get (by simp [getElem?_eq_getElem, h]) := by
simp [getElem_eq_iff]
xs[i] = xs[i]?.get (by simp [h]) := by
simp
theorem getD_getElem? {xs : Vector α n} {i : Nat} {d : α} :
xs[i]?.getD d = if p : i < n then xs[i]'p else d := by
if h : i < n then
simp [h, getElem?_def]
simp [h]
else
have p : i n := Nat.le_of_not_gt h
simp [getElem?_eq_none p, h]
simp [h]
@[simp] theorem getElem?_empty {i : Nat} : (#v[] : Vector α 0)[i]? = none := rfl
@@ -880,7 +880,7 @@ set_option linter.indexVariables false in
theorem getElem_push {xs : Vector α n} {x : α} {i : Nat} (h : i < n + 1) :
(xs.push x)[i] = if h : i < n then xs[i] else x := by
rcases xs with xs, rfl
simp [Array.getElem_push, h]
simp [Array.getElem_push]
theorem getElem?_push {xs : Vector α n} {x : α} {i : Nat} : (xs.push x)[i]? = if i = n then some x else xs[i]? := by
simp [getElem?_def, getElem_push]
@@ -1220,12 +1220,12 @@ instance [BEq α] [LawfulBEq α] (a : α) (as : Vector α n) : Decidable (a ∈
@[simp] theorem any_push [BEq α] {as : Vector α n} {a : α} {p : α Bool} :
(as.push a).any p = (as.any p || p a) := by
rcases as with as, rfl
simp [Array.any_push]
simp
@[simp] theorem all_push [BEq α] {as : Vector α n} {a : α} {p : α Bool} :
(as.push a).all p = (as.all p && p a) := by
rcases as with as, rfl
simp [Array.all_push]
simp
@[simp] theorem contains_push [BEq α] {xs : Vector α n} {a : α} {b : α} :
(xs.push a).contains b = (xs.contains b || b == a) := by
@@ -1237,7 +1237,7 @@ instance [BEq α] [LawfulBEq α] (a : α) (as : Vector α n) : Decidable (a ∈
@[grind] theorem getElem_set {xs : Vector α n} {i : Nat} {x : α} (hi : i < n) {j : Nat} (hj : j < n) :
(xs.set i x hi)[j] = if i = j then x else xs[j] := by
cases xs
split <;> simp_all [Array.getElem_set]
split <;> simp_all
@[simp] theorem getElem_set_self {xs : Vector α n} {i : Nat} {x : α} (hi : i < n) :
(xs.set i x hi)[i] = x := by simp [getElem_set]
@@ -1251,10 +1251,10 @@ abbrev getElem_set_eq := @getElem_set_self
@[grind] theorem getElem?_set {xs : Vector α n} {x : α} (hi : i < n) :
(xs.set i x hi)[j]? = if i = j then some x else xs[j]? := by
cases xs
split <;> simp_all [getElem?_eq_getElem, getElem_set]
split <;> simp_all
@[simp] theorem getElem?_set_self {xs : Vector α n} {x : α} (hi : i < n) :
(xs.set i x hi)[i]? = some x := by simp [getElem?_eq_getElem, hi]
(xs.set i x hi)[i]? = some x := by simp [hi]
@[simp] theorem getElem?_set_ne {xs : Vector α n} {x : α} (hi : i < n) (h : i j) :
(xs.set i x hi)[j]? = xs[j]? := by
@@ -1298,10 +1298,10 @@ theorem mem_or_eq_of_mem_set {xs : Vector α n} {i : Nat} {a b : α} {hi : i < n
@[grind] theorem getElem_setIfInBounds {xs : Vector α n} {x : α} (hj : j < n) :
(xs.setIfInBounds i x)[j] = if i = j then x else xs[j] := by
cases xs
split <;> simp_all [Array.getElem_setIfInBounds]
split <;> simp_all
@[simp] theorem getElem_setIfInBounds_self {xs : Vector α n} {x : α} (hi : i < n) :
(xs.setIfInBounds i x)[i] = x := by simp [getElem_setIfInBounds, hi]
(xs.setIfInBounds i x)[i] = x := by simp [getElem_setIfInBounds]
@[deprecated getElem_setIfInBounds_self (since := "2024-12-12")]
abbrev getElem_setIfInBounds_eq := @getElem_setIfInBounds_self
@@ -1318,7 +1318,7 @@ theorem getElem?_setIfInBounds_self {xs : Vector α n} {x : α} :
(xs.setIfInBounds i x)[i]? = if i < n then some x else none := by simp [getElem?_setIfInBounds]
@[simp] theorem getElem?_setIfInBounds_self_of_lt {xs : Vector α n} {x : α} (h : i < n) :
(xs.setIfInBounds i x)[i]? = some x := by simp [getElem?_setIfInBounds, h]
(xs.setIfInBounds i x)[i]? = some x := by simp [h]
@[simp] theorem getElem?_setIfInBounds_ne {xs : Vector α n} {x : α} (h : i j) :
(xs.setIfInBounds i x)[j]? = xs[j]? := by simp [getElem?_setIfInBounds, h]
@@ -1669,7 +1669,7 @@ theorem getElem_append {xs : Vector α n} {ys : Vector α m} (hi : i < n + m) :
(xs ++ ys)[i] = if h : i < n then xs[i] else ys[i - n] := by
rcases xs with xs, rfl
rcases ys with ys, rfl
simp [Array.getElem_append, hi]
simp [Array.getElem_append]
@[simp]
theorem getElem_append_left {xs : Vector α n} {ys : Vector α m} (hi : i < n) :
@@ -1683,7 +1683,7 @@ theorem getElem_append_right {xs : Vector α n} {ys : Vector α m} (h : i < n +
theorem getElem?_append_left {xs : Vector α n} {ys : Vector α m} (hn : i < n) :
(xs ++ ys)[i]? = xs[i]? := by
have hn' : i < n + m := by omega
simp_all [getElem?_eq_getElem, getElem_append]
simp_all
theorem getElem?_append_right {xs : Vector α n} {ys : Vector α m} (h : n i) :
(xs ++ ys)[i]? = ys[i - n]? := by
@@ -2036,7 +2036,7 @@ theorem flatMap_singleton {f : α → Vector β m} {x : α} : #v[x].flatMap f =
(xs ++ ys).flatMap f = (xs.flatMap f ++ ys.flatMap f).cast (by simp [Nat.add_mul]) := by
rcases xs with xs
rcases ys with ys
simp [flatMap_def, flatten_append]
simp [flatMap_def]
theorem flatMap_assoc {xs : Vector α n} {f : α Vector β m} {g : β Vector γ k} :
(xs.flatMap f).flatMap g = (xs.flatMap fun x => (f x).flatMap g).cast (by simp [Nat.mul_assoc]) := by
@@ -2107,7 +2107,7 @@ abbrev getElem_mkVector := @getElem_replicate
abbrev getElem?_mkVector := @getElem?_replicate
@[simp] theorem getElem?_replicate_of_lt {n : Nat} {i : Nat} (h : i < n) : (replicate n a)[i]? = some a := by
simp [getElem?_replicate, h]
simp [h]
@[deprecated getElem?_replicate_of_lt (since := "2025-03-18")]
abbrev getElem?_mkVector_of_lt := @getElem?_replicate_of_lt
@@ -2197,21 +2197,21 @@ abbrev flatten_mkVector_empty := @flatten_replicate_empty
@[simp] theorem flatten_replicate_singleton : (replicate n #v[a]).flatten = (replicate n a).cast (by simp) := by
ext i h
simp [h]
simp
@[deprecated flatten_replicate_singleton (since := "2025-03-18")]
abbrev flatten_mkVector_singleton := @flatten_replicate_singleton
@[simp] theorem flatten_replicate_replicate : (replicate n (replicate m a)).flatten = replicate (n * m) a := by
ext i h
simp [h]
simp
@[deprecated flatten_replicate_replicate (since := "2025-03-18")]
abbrev flatten_mkVector_mkVector := @flatten_replicate_replicate
theorem flatMap_replicate {f : α Vector β m} : (replicate n a).flatMap f = (replicate n (f a)).flatten := by
ext i h
simp [h]
simp
@[deprecated flatMap_replicate (since := "2025-03-18")]
abbrev flatMap_mkVector := @flatMap_replicate
@@ -2402,7 +2402,7 @@ theorem id_run_foldrM {f : α → β → Id β} {b} {xs : Vector α n} :
@[simp] theorem foldlM_reverse [Monad m] {xs : Vector α n} {f : β α m β} {b} :
xs.reverse.foldlM f b = xs.foldrM (fun x y => f y x) b := by
rcases xs with xs, rfl
simp [Array.foldlM_reverse]
simp
@[simp] theorem foldrM_reverse [Monad m] {xs : Vector α n} {f : α β m β} {b} :
xs.reverse.foldrM f b = xs.foldlM (fun x y => f y x) b := by
@@ -2412,7 +2412,7 @@ theorem id_run_foldrM {f : α → β → Id β} {b} {xs : Vector α n} :
@[simp, grind] theorem foldrM_push [Monad m] {f : α β m β} {init : β} {xs : Vector α n} {a : α} :
(xs.push a).foldrM f init = f a init >>= xs.foldrM f := by
rcases xs with xs, rfl
simp [Array.foldrM_push]
simp
/-! ### foldl / foldr -/
@@ -2435,12 +2435,12 @@ theorem foldr_congr {xs ys : Vector α n} (h₀ : xs = ys) {f g : α → β →
@[simp, grind] theorem foldl_push {f : β α β} {init : β} {xs : Vector α n} {a : α} :
(xs.push a).foldl f init = f (xs.foldl f init) a := by
rcases xs with xs, rfl
simp [Array.foldl_push]
simp
@[simp, grind] theorem foldr_push {f : α β β} {init : β} {xs : Vector α n} {a : α} :
(xs.push a).foldr f init = xs.foldr f (f a init) := by
rcases xs with xs, rfl
simp [Array.foldr_push]
simp
theorem foldl_map {f : β₁ β₂} {g : α β₂ α} {xs : Vector β₁ n} {init : α} :
(xs.map f).foldl g init = xs.foldl (fun x y => g x (f y)) init := by
@@ -2726,7 +2726,7 @@ theorem contains_append [BEq α] {xs : Vector α n} {ys : Vector α m} {x : α}
theorem contains_flatten [BEq α] {xs : Vector (Vector α n) m} {x : α} :
(xs.flatten).contains x = xs.any fun xs => xs.contains x := by
rcases xs with xs, rfl
simp [Function.comp_def]
simp
@[simp, grind]
theorem contains_reverse [BEq α] {xs : Vector α n} {x : α} :
@@ -2788,7 +2788,7 @@ theorem pop_append {xs : Vector α n} {ys : Vector α m} :
(xs ++ ys).pop = if h : m = 0 then xs.pop.cast (by omega) else (xs ++ ys.pop).cast (by omega) := by
rcases xs with xs, rfl
rcases ys with ys, rfl
simp only [mk_append_mk, pop_mk, List.length_eq_zero_iff, Array.toList_eq_nil_iff, cast_mk, mk_eq]
simp only [mk_append_mk, pop_mk, cast_mk, mk_eq]
rw [Array.pop_append]
split <;> simp_all
@@ -3010,7 +3010,7 @@ theorem getElem_replace_of_ne {xs : Vector α n} {i : Nat} {h : i < n} (h' : xs[
(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, rfl
rcases ys with ys, rfl
simp only [mk_append_mk, replace_mk, eq_mk, Array.replace_append]
simp only [mk_append_mk, replace_mk, Array.replace_append]
split <;> simp_all
theorem replace_append_left {xs : Vector α n} {ys : Vector α m} (h : a xs) :

View File

@@ -160,7 +160,7 @@ protected theorem le_iff_lt_or_eq [DecidableEq α] [LT α] [DecidableLT α]
{xs ys : Vector α n} : lex xs ys = false ys xs := by
cases xs
cases ys
simp [Array.not_lt_iff_ge]
simp
instance [DecidableEq α] [LT α] [DecidableLT α] : DecidableLT (Vector α n) :=
fun xs ys => decidable_of_iff (lex xs ys = true) lex_eq_true_iff_lt
@@ -206,7 +206,7 @@ theorem lex_eq_false_iff_exists [BEq α] [PartialEquivBEq α] (lt : αα
( (i : Nat) (h : i < n),( j, (hj : j < i) xs[j] == ys[j]) lt ys[i] xs[i]) := by
rcases xs with xs, rfl
rcases ys with ys, n₂
simp_all [Array.lex_eq_false_iff_exists, n₂]
simp_all [Array.lex_eq_false_iff_exists]
protected theorem lt_iff_exists [DecidableEq α] [LT α] [DecidableLT α] {xs ys : Vector α n} :
xs < ys

View File

@@ -186,7 +186,7 @@ theorem mapFinIdx_eq_append_iff {xs : Vector α (n + m)} {f : (i : Nat) → α
rcases ys with ys, rfl
rcases zs with zs, rfl
simp only [mapFinIdx_mk, mk_append_mk, eq_mk, Array.mapFinIdx_eq_append_iff, toArray_mapFinIdx,
mk_eq, toArray_append, exists_and_left, exists_prop]
mk_eq, toArray_append]
constructor
· rintro ys', zs', rfl, h₁, h₂
have h₁' := congrArg Array.size h₁
@@ -290,7 +290,7 @@ theorem mapIdx_eq_push_iff {xs : Vector α (n + 1)} {b : β} :
mapIdx f xs = ys.push b
(a : α) (zs : Vector α n), xs = zs.push a mapIdx f zs = ys f n a = b := by
rw [mapIdx_eq_mapFinIdx, mapFinIdx_eq_push_iff]
simp only [mapFinIdx_eq_mapIdx, exists_and_left, exists_prop]
simp only [mapFinIdx_eq_mapIdx]
constructor
· rintro zs, a, rfl, rfl, rfl
exact a, zs, by simp
@@ -327,7 +327,7 @@ theorem mapIdx_eq_iff {xs : Vector α n} {f : Nat → α → β} {ys : Vector β
· specialize h' w
simp_all
· simp only [Nat.not_lt] at w
simp_all [Array.getElem?_eq_none_iff.mpr w]
simp_all
theorem mapIdx_eq_mapIdx_iff {xs : Vector α n} :
mapIdx f xs = mapIdx g xs (i : Nat) (h : i < n), f i xs[i] = g i xs[i] := by

View File

@@ -80,13 +80,13 @@ theorem foldrM_map [Monad m] [LawfulMonad m] {f : β₁ → β₂} {g : β₂
{xs : Vector α n} {q : α Prop} (H : a, a xs q a) {f : β { x // q x} m β} {b} :
(xs.attachWith q H).foldlM f b = xs.attach.foldlM (fun b a, h => f b a, H _ h) b := by
rcases xs with xs, rfl
simp [Array.foldlM_map]
simp
@[simp] theorem foldrM_attachWith [Monad m] [LawfulMonad m]
{xs : Vector α n} {q : α Prop} (H : a, a xs q a) {f : { x // q x} β m β} {b} :
(xs.attachWith q H).foldrM f b = xs.attach.foldrM (fun a acc => f a.1, H _ a.2 acc) b := by
rcases xs with xs, rfl
simp [Array.foldrM_map]
simp
/-! ### forM -/
@@ -146,7 +146,7 @@ theorem forIn'_eq_foldlM [Monad m] [LawfulMonad m]
forIn' xs init (fun a m b => pure (.yield (f a m b))) =
pure (f := m) (xs.attach.foldl (fun b a, h => f a h b) init) := by
rcases xs with xs, rfl
simp [Array.forIn'_pure_yield_eq_foldl, Array.foldl_map]
simp [Array.forIn'_pure_yield_eq_foldl]
theorem idRun_forIn'_yield_eq_foldl
{xs : Vector α n} (f : (a : α) a xs β Id β) (init : β) :
@@ -194,7 +194,7 @@ theorem forIn_eq_foldlM [Monad m] [LawfulMonad m]
forIn xs init (fun a b => pure (.yield (f a b))) =
pure (f := m) (xs.foldl (fun b a => f a b) init) := by
rcases xs with xs, rfl
simp [Array.forIn_pure_yield_eq_foldl, Array.foldl_map]
simp [Array.forIn_pure_yield_eq_foldl]
theorem idRun_forIn_yield_eq_foldl
{xs : Vector α n} (f : α β Id β) (init : β) :

View File

@@ -44,7 +44,7 @@ theorem Perm.toList {as bs : Vector α n} : as ~ bs → as.toList ~ bs.toList :=
@[simp] theorem perm_mk (as bs : Array α) (ha : as.size = n) (hb : bs.size = n) :
mk as ha ~ mk bs hb as ~ bs := by
simp [perm_iff_toArray_perm, ha, hb]
simp [perm_iff_toArray_perm]
theorem toArray_perm_iff (xs : Vector α n) (ys : Array α) : xs.toArray ~ ys h, xs ~ Vector.mk ys h := by
constructor
@@ -112,7 +112,7 @@ theorem Perm.push_comm (x y : α) {xs ys : Vector α n} (p : xs ~ ys) :
theorem swap_perm {xs : Vector α n} {i j : Nat} (h₁ : i < n) (h₂ : j < n) :
xs.swap i j ~ xs := by
rcases xs with xs, rfl
simp only [swap, perm_iff_toList_perm, toList_set]
simp only [swap, perm_iff_toList_perm]
apply set_set_perm
namespace Perm

View File

@@ -39,7 +39,7 @@ theorem range'_eq_mk_range' {start size step} :
@[simp, grind =] theorem getElem_range' {start size step i} (h : i < size) :
(range' start size step)[i] = start + step * i := by
simp [range', h]
simp [range']
@[simp, grind =] theorem getElem?_range' {start size step i} :
(range' start size step)[i]? = if i < size then some (start + step * i) else none := by
@@ -58,7 +58,7 @@ theorem range'_zero : range' s 0 step = #v[] := by
@[simp] theorem range'_inj : range' s n = range' s' n (n = 0 s = s') := by
rw [ toArray_inj]
simp [List.range'_inj]
simp
@[grind =]
theorem mem_range' {n} : m range' s n step i < n, m = s + step * i := by

View File

@@ -194,14 +194,14 @@ theorem getElem_zip {as : Vector α n} {bs : Vector β n} {i : Nat} {h : i < n}
theorem zip_eq_zipWith {as : Vector α n} {bs : Vector β n} : zip as bs = zipWith Prod.mk as bs := by
rcases as with as, rfl
rcases bs with bs, h
simp [Array.zip_eq_zipWith, h]
simp [Array.zip_eq_zipWith]
@[grind _=_]
theorem zip_map {f : α γ} {g : β δ} {as : Vector α n} {bs : Vector β n} :
zip (as.map f) (bs.map g) = (zip as bs).map (Prod.map f g) := by
rcases as with as, rfl
rcases bs with bs, h
simp [Array.zip_map, h]
simp [Array.zip_map]
@[grind _=_]
theorem zip_map_left {f : α γ} {as : Vector α n} {bs : Vector β n} :
@@ -218,7 +218,7 @@ theorem zip_append {as : Vector α n} {bs : Vector β n} {as' : Vector α m} {bs
rcases bs with bs, h
rcases as' with as', rfl
rcases bs' with bs', h'
simp [Array.zip_append, h, h']
simp [Array.zip_append, h]
@[grind =]
theorem zip_map' {f : α β} {g : α γ} {xs : Vector α n} :
@@ -287,7 +287,7 @@ theorem unzip_snd : (unzip xs).snd = xs.map Prod.snd := by
@[grind =]
theorem unzip_eq_map {xs : Vector (α × β) n} : unzip xs = (xs.map Prod.fst, xs.map Prod.snd) := by
cases xs
simp [List.unzip_eq_map]
simp
-- The argument `xs` is explicit so we can rewrite from right to left.
theorem zip_unzip (xs : Vector (α × β) n) : zip (unzip xs).1 (unzip xs).2 = xs := by
@@ -298,19 +298,19 @@ theorem unzip_zip_left {as : Vector α n} {bs : Vector β n} :
(unzip (zip as bs)).1 = as := by
rcases as with as, rfl
rcases bs with bs, h
simp [Array.unzip_zip_left, h, Array.map_fst_zip]
simp [h, Array.map_fst_zip]
theorem unzip_zip_right {as : Vector α n} {bs : Vector β n} :
(unzip (zip as bs)).2 = bs := by
rcases as with as, rfl
rcases bs with bs, h
simp [Array.unzip_zip_right, h, Array.map_snd_zip]
simp [h, Array.map_snd_zip]
theorem unzip_zip {as : Vector α n} {bs : Vector β n} :
unzip (zip as bs) = (as, bs) := by
rcases as with as, rfl
rcases bs with bs, h
simp [Array.unzip_zip, h, Array.map_fst_zip, Array.map_snd_zip]
simp [Array.unzip_zip, h]
theorem zip_of_prod {as : Vector α n} {bs : Vector β n} {xs : Vector (α × β) n} (hl : xs.map Prod.fst = as)
(hr : xs.map Prod.snd = bs) : xs = as.zip bs := by

View File

@@ -180,12 +180,12 @@ instance (priority := low) [GetElem coll idx elem valid] [∀ xs i, Decidable (v
[Inhabited elem] (c : cont) (i : idx) (h : dom c i) :
c[i]! = c[i]'h := by
have : Decidable (dom c i) := .isTrue h
simp [getElem!_def, getElem?_def, h]
simp [getElem!_def, h]
@[simp, grind] theorem getElem!_neg [GetElem? cont idx elem dom] [LawfulGetElem cont idx elem dom]
[Inhabited elem] (c : cont) (i : idx) (h : ¬dom c i) : c[i]! = default := by
have : Decidable (dom c i) := .isFalse h
simp [getElem!_def, getElem?_def, h]
simp [getElem!_def, h]
@[simp, grind =] theorem get_getElem? [GetElem? cont idx elem dom] [LawfulGetElem cont idx elem dom]
(c : cont) (i : idx) [Decidable (dom c i)] (h) :

View File

@@ -48,7 +48,11 @@ satisfying appropriate compatibilities.
Equivalently, an additive commutative group.
-/
class IntModule (M : Type u) extends Zero M, Add M, Neg M, Sub M, HMul Int M M where
class IntModule (M : Type u) extends Zero M, Add M, Neg M, Sub M where
/-- Scalar multiplication by natural numbers. -/
[hmulNat : HMul Nat M M]
/-- Scalar multiplication by integers. -/
[hmulInt : HMul Int M M]
/-- Zero is the right identity for addition. -/
add_zero : a : M, a + 0 = a
/-- Addition is commutative. -/
@@ -69,6 +73,8 @@ class IntModule (M : Type u) extends Zero M, Add M, Neg M, Sub M, HMul Int M M w
neg_add_cancel : a : M, -a + a = 0
/-- Subtraction is addition of the negative. -/
sub_eq_add_neg : a b : M, a - b = a + -b
/-- Scalar multiplication by natural numbers is consistent with scalar multiplication by integers. -/
hmul_nat : n : Nat, a : M, (n : Int) * a = n * a
namespace NatModule
@@ -83,27 +89,33 @@ theorem mul_hmul (n m : Nat) (a : M) : (n * m) * a = n * (m * a) := by
| succ n ih =>
rw [Nat.add_one_mul, add_hmul, ih, add_hmul, one_hmul]
instance (priority := 100) (M : Type u) [NatModule M] : SMul Nat M where
smul a x := a * x
end NatModule
namespace IntModule
attribute [instance 100] IntModule.toZero IntModule.toAdd IntModule.toNeg IntModule.toSub IntModule.toHMul
attribute [instance 100] IntModule.toZero IntModule.toAdd IntModule.toNeg IntModule.toSub
IntModule.hmulNat IntModule.hmulInt
instance toNatModule (M : Type u) [i : IntModule M] : NatModule M :=
{ i with
hMul a x := (a : Int) * x
hmul_zero := by simp [IntModule.hmul_zero]
add_hmul := by simp [IntModule.add_hmul]
hmul_add := by simp [IntModule.hmul_add] }
variable {M : Type u} [IntModule M]
hMul := i.hmulNat.hMul
zero_hmul := by simp [ hmul_nat, zero_hmul]
one_hmul := by simp [ hmul_nat, one_hmul]
hmul_zero := by simp [ hmul_nat, hmul_zero]
add_hmul := by simp [ hmul_nat, add_hmul]
hmul_add := by simp [ hmul_nat, hmul_add] }
instance (priority := 100) (M : Type u) [IntModule M] : SMul Nat M where
smul a x := (a : Int) * x
smul a x := a * x
instance (priority := 100) (M : Type u) [IntModule M] : SMul Int M where
smul a x := a * x
variable {M : Type u} [IntModule M]
theorem zero_add (a : M) : 0 + a = a := by
rw [add_comm, add_zero]
@@ -171,6 +183,9 @@ theorem hmul_sub (k : Int) (a b : M) : k * (a - b) = k * a - k * b := by
theorem sub_hmul (k₁ k₂ : Int) (a : M) : (k₁ - k₂) * a = k₁ * a - k₂ * a := by
rw [Int.sub_eq_add_neg, add_hmul, neg_hmul, sub_eq_add_neg]
theorem nat_zero_hmul (a : M) : (0 : Nat) * a = 0 := by
rw [ hmul_nat, Int.natCast_zero, zero_hmul]
private theorem nat_mul_hmul (n : Nat) (m : Int) (a : M) :
((n : Int) * m) * a = (n : Int) * (m * a) := by
induction n with
@@ -188,15 +203,30 @@ end IntModule
/--
We say a module has no natural number zero divisors if
`k * a = 0` implies `k = 0` or `a = 0` (here `k` is a natural number and `a` is an element of the module).
This is a special case of Mathlib's `NoZeroSMulDivisors Nat α`.
`k ≠ 0` and `k * a = k * b` implies `a = b` (here `k` is a natural number and `a` and `b` are element of the module).
-/
class NoNatZeroDivisors (α : Type u) [Zero α] [HMul Nat α α] where
no_nat_zero_divisors : (k : Nat) (a : α), k 0 k * a = 0 a = 0
class NoNatZeroDivisors (α : Type u) [HMul Nat α α] where
no_nat_zero_divisors : (k : Nat) (a b : α), k 0 k * a = k * b a = b
export NoNatZeroDivisors (no_nat_zero_divisors)
namespace NoNatZeroDivisors
/-- Alternative constructor for `NoNatZeroDivisors` when we have an `IntModule`. -/
def mk' {α} [IntModule α] (eq_zero_of_mul_eq_zero : (k : Nat) (a : α), k 0 k * a = 0 a = 0) : NoNatZeroDivisors α where
no_nat_zero_divisors k a b h₁ h₂ := by
rw [ IntModule.sub_eq_zero_iff, IntModule.hmul_nat, IntModule.hmul_nat, IntModule.hmul_sub, IntModule.hmul_nat] at h₂
rw [ IntModule.sub_eq_zero_iff]
apply eq_zero_of_mul_eq_zero k (a - b) h₁ h₂
theorem eq_zero_of_mul_eq_zero {α : Type u} [NatModule α] [NoNatZeroDivisors α] {k : Nat} {a : α}
: k 0 k * a = 0 a = 0 := by
intro h₁ h₂
replace h₁ : k 0 := by intro h; simp [h] at h₁
exact no_nat_zero_divisors k a 0 h₁ (by rwa [NatModule.hmul_zero])
end NoNatZeroDivisors
instance [ToInt α (some lo) (some hi)] [IntModule α] [ToInt.Zero α (some lo) (some hi)] [ToInt.Add α (some lo) (some hi)] : ToInt.Neg α (some lo) (some hi) where
toInt_neg x := by
have := (ToInt.Add.toInt_add (-x) x).symm

Some files were not shown because too many files have changed in this diff Show More