mirror of
https://github.com/leanprover/lean4.git
synced 2026-03-21 20:34:07 +00:00
Compare commits
1 Commits
grind_offs
...
vector_tai
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
45d16fb1eb |
24
.github/workflows/awaiting-mathlib.yml
vendored
24
.github/workflows/awaiting-mathlib.yml
vendored
@@ -10,29 +10,11 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check awaiting-mathlib label
|
||||
id: check-awaiting-mathlib-label
|
||||
if: github.event_name == 'pull_request'
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const { labels, number: prNumber } = context.payload.pull_request;
|
||||
const hasAwaiting = labels.some(label => label.name == "awaiting-mathlib");
|
||||
const hasBreaks = labels.some(label => label.name == "breaks-mathlib");
|
||||
const hasBuilds = labels.some(label => label.name == "builds-mathlib");
|
||||
|
||||
if (hasAwaiting && hasBreaks) {
|
||||
core.setFailed('PR has both "awaiting-mathlib" and "breaks-mathlib" labels.');
|
||||
} else if (hasAwaiting && !hasBreaks && !hasBuilds) {
|
||||
core.info('PR is marked "awaiting-mathlib" but neither "breaks-mathlib" nor "builds-mathlib" labels are present.');
|
||||
core.setOutput('awaiting', 'true');
|
||||
const { labels } = context.payload.pull_request;
|
||||
if (labels.some(label => label.name == "awaiting-mathlib") && !labels.some(label => label.name == "builds-mathlib")) {
|
||||
core.setFailed('PR is marked "awaiting-mathlib" but "builds-mathlib" label has not been applied yet by the bot');
|
||||
}
|
||||
|
||||
- name: Wait for mathlib compatibility
|
||||
if: github.event_name == 'pull_request' && steps.check-awaiting-mathlib-label.outputs.awaiting == 'true'
|
||||
run: |
|
||||
echo "::notice title=Awaiting mathlib::PR is marked 'awaiting-mathlib' but neither 'breaks-mathlib' nor 'builds-mathlib' labels are present."
|
||||
echo "This check will remain in progress until the PR is updated with appropriate mathlib compatibility labels."
|
||||
# Keep the job running indefinitely to show "in progress" status
|
||||
while true; do
|
||||
sleep 3600 # Sleep for 1 hour at a time
|
||||
done
|
||||
|
||||
9
.github/workflows/ci.yml
vendored
9
.github/workflows/ci.yml
vendored
@@ -103,13 +103,6 @@ jobs:
|
||||
echo "Tag ${TAG_NAME} did not match SemVer regex."
|
||||
fi
|
||||
|
||||
- name: Check for custom releases (e.g., not in the main lean repository)
|
||||
if: startsWith(github.ref, 'refs/tags/') && github.repository != 'leanprover/lean4'
|
||||
id: set-release-custom
|
||||
run: |
|
||||
TAG_NAME="${GITHUB_REF##*/}"
|
||||
echo "RELEASE_TAG=$TAG_NAME" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Set check level
|
||||
id: set-level
|
||||
# We do not use github.event.pull_request.labels.*.name here because
|
||||
@@ -118,7 +111,7 @@ jobs:
|
||||
run: |
|
||||
check_level=0
|
||||
|
||||
if [[ -n "${{ steps.set-nightly.outputs.nightly }}" || -n "${{ steps.set-release.outputs.RELEASE_TAG }}" || -n "${{ steps.set-release-custom.outputs.RELEASE_TAG }}" ]]; then
|
||||
if [[ -n "${{ steps.set-nightly.outputs.nightly }}" || -n "${{ steps.set-release.outputs.RELEASE_TAG }}" ]]; then
|
||||
check_level=2
|
||||
elif [[ "${{ github.event_name }}" != "pull_request" ]]; then
|
||||
check_level=1
|
||||
|
||||
38
.github/workflows/update-stage0.yml
vendored
38
.github/workflows/update-stage0.yml
vendored
@@ -40,24 +40,34 @@ jobs:
|
||||
run: |
|
||||
git config --global user.name "Lean stage0 autoupdater"
|
||||
git config --global user.email "<>"
|
||||
# Would be nice, but does not work yet:
|
||||
# https://github.com/DeterminateSystems/magic-nix-cache/issues/39
|
||||
# This action does not run that often and building runs in a few minutes, so ok for now
|
||||
#- if: env.should_update_stage0 == 'yes'
|
||||
# uses: DeterminateSystems/magic-nix-cache-action@v2
|
||||
- if: env.should_update_stage0 == 'yes'
|
||||
name: Restore Build Cache
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: nix-store-cache
|
||||
key: Nix Linux-nix-store-cache-${{ github.sha }}
|
||||
# fall back to (latest) previous cache
|
||||
restore-keys: |
|
||||
Nix Linux-nix-store-cache
|
||||
- if: env.should_update_stage0 == 'yes'
|
||||
name: Further Set Up Nix Cache
|
||||
shell: bash -euxo pipefail {0}
|
||||
run: |
|
||||
# Nix seems to mutate the cache, so make a copy
|
||||
cp -r nix-store-cache nix-store-cache-copy || true
|
||||
- if: env.should_update_stage0 == 'yes'
|
||||
name: Install Nix
|
||||
uses: DeterminateSystems/nix-installer-action@main
|
||||
- name: Open Nix shell once
|
||||
if: env.should_update_stage0 == 'yes'
|
||||
run: true
|
||||
shell: 'nix develop -c bash -euxo pipefail {0}'
|
||||
- name: Set up NPROC
|
||||
if: env.should_update_stage0 == 'yes'
|
||||
run: |
|
||||
echo "NPROC=$(nproc 2>/dev/null || sysctl -n hw.logicalcpu 2>/dev/null || echo 4)" >> $GITHUB_ENV
|
||||
shell: 'nix develop -c bash -euxo pipefail {0}'
|
||||
with:
|
||||
extra-conf: |
|
||||
substituters = file://${{ github.workspace }}/nix-store-cache-copy?priority=10&trusted=true https://cache.nixos.org
|
||||
- if: env.should_update_stage0 == 'yes'
|
||||
run: cmake --preset release
|
||||
shell: 'nix develop -c bash -euxo pipefail {0}'
|
||||
- if: env.should_update_stage0 == 'yes'
|
||||
run: make -j$NPROC -C build/release update-stage0-commit
|
||||
shell: 'nix develop -c bash -euxo pipefail {0}'
|
||||
run: nix run .#update-stage0-commit
|
||||
- if: env.should_update_stage0 == 'yes'
|
||||
run: git show --stat
|
||||
- if: env.should_update_stage0 == 'yes' && github.event_name == 'push'
|
||||
|
||||
@@ -49,7 +49,7 @@ abbrev forIn_eq_forin' := @forIn_eq_forIn'
|
||||
/--
|
||||
Extracts the value from a `ForInStep`, ignoring whether it is `ForInStep.done` or `ForInStep.yield`.
|
||||
-/
|
||||
@[expose] def ForInStep.value (x : ForInStep α) : α :=
|
||||
def ForInStep.value (x : ForInStep α) : α :=
|
||||
match x with
|
||||
| ForInStep.done b => b
|
||||
| ForInStep.yield b => b
|
||||
|
||||
@@ -136,7 +136,7 @@ may throw the corresponding exception.
|
||||
|
||||
This is the inverse of `ExceptT.run`.
|
||||
-/
|
||||
@[always_inline, inline, expose]
|
||||
@[always_inline, inline]
|
||||
def ExceptT.mk {ε : Type u} {m : Type u → Type v} {α : Type u} (x : m (Except ε α)) : ExceptT ε m α := x
|
||||
|
||||
/--
|
||||
@@ -144,7 +144,7 @@ Use a monadic action that may throw an exception as an action that may return an
|
||||
|
||||
This is the inverse of `ExceptT.mk`.
|
||||
-/
|
||||
@[always_inline, inline, expose]
|
||||
@[always_inline, inline]
|
||||
def ExceptT.run {ε : Type u} {m : Type u → Type v} {α : Type u} (x : ExceptT ε m α) : m (Except ε α) := x
|
||||
|
||||
namespace ExceptT
|
||||
@@ -154,14 +154,14 @@ variable {ε : Type u} {m : Type u → Type v} [Monad m]
|
||||
/--
|
||||
Returns the value `a` without throwing exceptions or having any other effect.
|
||||
-/
|
||||
@[always_inline, inline, expose]
|
||||
@[always_inline, inline]
|
||||
protected def pure {α : Type u} (a : α) : ExceptT ε m α :=
|
||||
ExceptT.mk <| pure (Except.ok a)
|
||||
|
||||
/--
|
||||
Handles exceptions thrown by an action that can have no effects _other_ than throwing exceptions.
|
||||
-/
|
||||
@[always_inline, inline, expose]
|
||||
@[always_inline, inline]
|
||||
protected def bindCont {α β : Type u} (f : α → ExceptT ε m β) : Except ε α → m (Except ε β)
|
||||
| Except.ok a => f a
|
||||
| Except.error e => pure (Except.error e)
|
||||
@@ -170,14 +170,14 @@ protected def bindCont {α β : Type u} (f : α → ExceptT ε m β) : Except ε
|
||||
Sequences two actions that may throw exceptions. Typically used via `do`-notation or the `>>=`
|
||||
operator.
|
||||
-/
|
||||
@[always_inline, inline, expose]
|
||||
@[always_inline, inline]
|
||||
protected def bind {α β : Type u} (ma : ExceptT ε m α) (f : α → ExceptT ε m β) : ExceptT ε m β :=
|
||||
ExceptT.mk <| ma >>= ExceptT.bindCont f
|
||||
|
||||
/--
|
||||
Transforms a successful computation's value using `f`. Typically used via the `<$>` operator.
|
||||
-/
|
||||
@[always_inline, inline, expose]
|
||||
@[always_inline, inline]
|
||||
protected def map {α β : Type u} (f : α → β) (x : ExceptT ε m α) : ExceptT ε m β :=
|
||||
ExceptT.mk <| x >>= fun a => match a with
|
||||
| (Except.ok a) => pure <| Except.ok (f a)
|
||||
@@ -186,7 +186,7 @@ protected def map {α β : Type u} (f : α → β) (x : ExceptT ε m α) : Excep
|
||||
/--
|
||||
Runs a computation from an underlying monad in the transformed monad with exceptions.
|
||||
-/
|
||||
@[always_inline, inline, expose]
|
||||
@[always_inline, inline]
|
||||
protected def lift {α : Type u} (t : m α) : ExceptT ε m α :=
|
||||
ExceptT.mk <| Except.ok <$> t
|
||||
|
||||
@@ -197,7 +197,7 @@ instance : MonadLift m (ExceptT ε m) := ⟨ExceptT.lift⟩
|
||||
/--
|
||||
Handles exceptions produced in the `ExceptT ε` transformer.
|
||||
-/
|
||||
@[always_inline, inline, expose]
|
||||
@[always_inline, inline]
|
||||
protected def tryCatch {α : Type u} (ma : ExceptT ε m α) (handle : ε → ExceptT ε m α) : ExceptT ε m α :=
|
||||
ExceptT.mk <| ma >>= fun res => match res with
|
||||
| Except.ok a => pure (Except.ok a)
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace ExceptCpsT
|
||||
/--
|
||||
Use a monadic action that may throw an exception as an action that may return an exception's value.
|
||||
-/
|
||||
@[always_inline, inline, expose]
|
||||
@[always_inline, inline]
|
||||
def run {ε α : Type u} [Monad m] (x : ExceptCpsT ε m α) : m (Except ε α) :=
|
||||
x _ (fun a => pure (Except.ok a)) (fun e => pure (Except.error e))
|
||||
|
||||
@@ -43,7 +43,7 @@ Returns the value of a computation, forgetting whether it was an exception or a
|
||||
|
||||
This corresponds to early return.
|
||||
-/
|
||||
@[always_inline, inline, expose]
|
||||
@[always_inline, inline]
|
||||
def runCatch [Monad m] (x : ExceptCpsT α m α) : m α :=
|
||||
x α pure pure
|
||||
|
||||
@@ -63,7 +63,7 @@ instance : MonadExceptOf ε (ExceptCpsT ε m) where
|
||||
/--
|
||||
Run an action from the transformed monad in the exception monad.
|
||||
-/
|
||||
@[always_inline, inline, expose]
|
||||
@[always_inline, inline]
|
||||
def lift [Monad m] (x : m α) : ExceptCpsT ε m α :=
|
||||
fun _ k _ => x >>= k
|
||||
|
||||
|
||||
@@ -9,4 +9,3 @@ prelude
|
||||
import Init.Control.Lawful.Basic
|
||||
import Init.Control.Lawful.Instances
|
||||
import Init.Control.Lawful.Lemmas
|
||||
import Init.Control.Lawful.MonadLift
|
||||
|
||||
@@ -6,7 +6,6 @@ Authors: Sebastian Ullrich, Leonardo de Moura, Mario Carneiro
|
||||
module
|
||||
|
||||
prelude
|
||||
import Init.Ext
|
||||
import Init.SimpLemmas
|
||||
import Init.Meta
|
||||
|
||||
@@ -242,23 +241,13 @@ theorem LawfulMonad.mk' (m : Type u → Type v) [Monad m]
|
||||
|
||||
namespace Id
|
||||
|
||||
@[ext] theorem ext {x y : Id α} (h : x.run = y.run) : x = y := h
|
||||
@[simp] theorem map_eq (x : Id α) (f : α → β) : f <$> x = f x := rfl
|
||||
@[simp] theorem bind_eq (x : Id α) (f : α → id β) : x >>= f = f x := rfl
|
||||
@[simp] theorem pure_eq (a : α) : (pure a : Id α) = a := rfl
|
||||
|
||||
instance : LawfulMonad Id := by
|
||||
refine LawfulMonad.mk' _ ?_ ?_ ?_ <;> intros <;> rfl
|
||||
|
||||
@[simp] theorem run_map (x : Id α) (f : α → β) : (f <$> x).run = f x.run := rfl
|
||||
@[simp] theorem run_bind (x : Id α) (f : α → Id β) : (x >>= f).run = (f x.run).run := rfl
|
||||
@[simp] theorem run_pure (a : α) : (pure a : Id α).run = a := rfl
|
||||
@[simp] theorem run_seqRight (x y : Id α) : (x *> y).run = y.run := rfl
|
||||
@[simp] theorem run_seqLeft (x y : Id α) : (x <* y).run = x.run := rfl
|
||||
@[simp] theorem run_seq (f : Id (α → β)) (x : Id α) : (f <*> x).run = f.run x.run := rfl
|
||||
|
||||
-- These lemmas are bad as they abuse the defeq of `Id α` and `α`
|
||||
@[deprecated run_map (since := "2025-03-05")] theorem map_eq (x : Id α) (f : α → β) : f <$> x = f x := rfl
|
||||
@[deprecated run_bind (since := "2025-03-05")] theorem bind_eq (x : Id α) (f : α → id β) : x >>= f = f x := rfl
|
||||
@[deprecated run_pure (since := "2025-03-05")] theorem pure_eq (a : α) : (pure a : Id α) = a := rfl
|
||||
|
||||
end Id
|
||||
|
||||
/-! # Option -/
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
/-
|
||||
Copyright (c) 2025 Lean FRO, LLC. All rights reserved.
|
||||
Released under Apache 2.0 license as described in the file LICENSE.
|
||||
Authors: Paul Reichert
|
||||
-/
|
||||
module
|
||||
|
||||
prelude
|
||||
import Init.Control.Lawful.MonadLift.Basic
|
||||
import Init.Control.Lawful.MonadLift.Lemmas
|
||||
import Init.Control.Lawful.MonadLift.Instances
|
||||
@@ -1,52 +0,0 @@
|
||||
/-
|
||||
Copyright (c) 2025 Quang Dao. All rights reserved.
|
||||
Released under Apache 2.0 license as described in the file LICENSE.
|
||||
Authors: Quang Dao
|
||||
-/
|
||||
module
|
||||
|
||||
prelude
|
||||
import Init.Control.Basic
|
||||
|
||||
/-!
|
||||
# LawfulMonadLift and LawfulMonadLiftT
|
||||
|
||||
This module provides classes asserting that `MonadLift` and `MonadLiftT` are lawful, which means
|
||||
that `monadLift` is compatible with `pure` and `bind`.
|
||||
-/
|
||||
|
||||
section MonadLift
|
||||
|
||||
/-- The `MonadLift` typeclass only contains the lifting operation. `LawfulMonadLift` further
|
||||
asserts that lifting commutes with `pure` and `bind`:
|
||||
```
|
||||
monadLift (pure a) = pure a
|
||||
monadLift (ma >>= f) = monadLift ma >>= monadLift ∘ f
|
||||
```
|
||||
-/
|
||||
class LawfulMonadLift (m : semiOutParam (Type u → Type v)) (n : Type u → Type w)
|
||||
[Monad m] [Monad n] [inst : MonadLift m n] : Prop where
|
||||
/-- Lifting preserves `pure` -/
|
||||
monadLift_pure {α : Type u} (a : α) : inst.monadLift (pure a) = pure a
|
||||
/-- Lifting preserves `bind` -/
|
||||
monadLift_bind {α β : Type u} (ma : m α) (f : α → m β) :
|
||||
inst.monadLift (ma >>= f) = inst.monadLift ma >>= (fun x => inst.monadLift (f x))
|
||||
|
||||
/-- The `MonadLiftT` typeclass only contains the transitive lifting operation.
|
||||
`LawfulMonadLiftT` further asserts that lifting commutes with `pure` and `bind`:
|
||||
```
|
||||
monadLift (pure a) = pure a
|
||||
monadLift (ma >>= f) = monadLift ma >>= monadLift ∘ f
|
||||
```
|
||||
-/
|
||||
class LawfulMonadLiftT (m : Type u → Type v) (n : Type u → Type w) [Monad m] [Monad n]
|
||||
[inst : MonadLiftT m n] : Prop where
|
||||
/-- Lifting preserves `pure` -/
|
||||
monadLift_pure {α : Type u} (a : α) : inst.monadLift (pure a) = pure a
|
||||
/-- Lifting preserves `bind` -/
|
||||
monadLift_bind {α β : Type u} (ma : m α) (f : α → m β) :
|
||||
inst.monadLift (ma >>= f) = monadLift ma >>= (fun x => monadLift (f x))
|
||||
|
||||
export LawfulMonadLiftT (monadLift_pure monadLift_bind)
|
||||
|
||||
end MonadLift
|
||||
@@ -1,137 +0,0 @@
|
||||
/-
|
||||
Copyright (c) 2025 Quang Dao. All rights reserved.
|
||||
Released under Apache 2.0 license as described in the file LICENSE.
|
||||
Authors: Quang Dao, Paul Reichert
|
||||
-/
|
||||
module
|
||||
|
||||
prelude
|
||||
import all Init.Control.Option
|
||||
import all Init.Control.Except
|
||||
import all Init.Control.ExceptCps
|
||||
import all Init.Control.StateRef
|
||||
import all Init.Control.StateCps
|
||||
import Init.Control.Lawful.MonadLift.Lemmas
|
||||
import Init.Control.Lawful.Instances
|
||||
|
||||
universe u v w x
|
||||
|
||||
variable {m : Type u → Type v} {n : Type u → Type w} {o : Type u → Type x}
|
||||
|
||||
variable (m n o) in
|
||||
instance [Monad m] [Monad n] [Monad o] [MonadLift n o] [MonadLiftT m n]
|
||||
[LawfulMonadLift n o] [LawfulMonadLiftT m n] : LawfulMonadLiftT m o where
|
||||
monadLift_pure := fun a => by
|
||||
simp only [monadLift, LawfulMonadLift.monadLift_pure, liftM_pure]
|
||||
monadLift_bind := fun ma f => by
|
||||
simp only [monadLift, LawfulMonadLift.monadLift_bind, liftM_bind]
|
||||
|
||||
variable (m) in
|
||||
instance [Monad m] : LawfulMonadLiftT m m where
|
||||
monadLift_pure _ := rfl
|
||||
monadLift_bind _ _ := rfl
|
||||
|
||||
namespace StateT
|
||||
|
||||
variable [Monad m] [LawfulMonad m]
|
||||
|
||||
instance {σ : Type u} : LawfulMonadLift m (StateT σ m) where
|
||||
monadLift_pure _ := by ext; simp [MonadLift.monadLift]
|
||||
monadLift_bind _ _ := by ext; simp [MonadLift.monadLift]
|
||||
|
||||
end StateT
|
||||
|
||||
namespace ReaderT
|
||||
|
||||
variable [Monad m]
|
||||
|
||||
instance {ρ : Type u} : LawfulMonadLift m (ReaderT ρ m) where
|
||||
monadLift_pure _ := rfl
|
||||
monadLift_bind _ _ := rfl
|
||||
|
||||
end ReaderT
|
||||
|
||||
namespace OptionT
|
||||
|
||||
variable [Monad m] [LawfulMonad m]
|
||||
|
||||
@[simp]
|
||||
theorem lift_pure {α : Type u} (a : α) : OptionT.lift (pure a : m α) = pure a := by
|
||||
simp only [OptionT.lift, OptionT.mk, bind_pure_comp, map_pure, pure, OptionT.pure]
|
||||
|
||||
@[simp]
|
||||
theorem lift_bind {α β : Type u} (ma : m α) (f : α → m β) :
|
||||
OptionT.lift (ma >>= f) = OptionT.lift ma >>= (fun a => OptionT.lift (f a)) := by
|
||||
simp only [instMonad, OptionT.bind, OptionT.mk, OptionT.lift, bind_pure_comp, bind_map_left,
|
||||
map_bind]
|
||||
|
||||
instance : LawfulMonadLift m (OptionT m) where
|
||||
monadLift_pure := lift_pure
|
||||
monadLift_bind := lift_bind
|
||||
|
||||
end OptionT
|
||||
|
||||
namespace ExceptT
|
||||
|
||||
variable [Monad m] [LawfulMonad m]
|
||||
|
||||
@[simp]
|
||||
theorem lift_bind {α β ε : Type u} (ma : m α) (f : α → m β) :
|
||||
ExceptT.lift (ε := ε) (ma >>= f) = ExceptT.lift ma >>= (fun a => ExceptT.lift (f a)) := by
|
||||
simp only [instMonad, ExceptT.bind, mk, ExceptT.lift, bind_map_left, ExceptT.bindCont, map_bind]
|
||||
|
||||
instance : LawfulMonadLift m (ExceptT ε m) where
|
||||
monadLift_pure := lift_pure
|
||||
monadLift_bind := lift_bind
|
||||
|
||||
instance : LawfulMonadLift (Except ε) (ExceptT ε m) where
|
||||
monadLift_pure _ := by
|
||||
simp only [MonadLift.monadLift, mk, pure, Except.pure, ExceptT.pure]
|
||||
monadLift_bind ma _ := by
|
||||
simp only [instMonad, ExceptT.bind, mk, MonadLift.monadLift, pure_bind, ExceptT.bindCont,
|
||||
Except.instMonad, Except.bind]
|
||||
rcases ma with _ | _ <;> simp
|
||||
|
||||
end ExceptT
|
||||
|
||||
namespace StateRefT'
|
||||
|
||||
instance {ω σ : Type} {m : Type → Type} [Monad m] : LawfulMonadLift m (StateRefT' ω σ m) where
|
||||
monadLift_pure _ := by
|
||||
simp only [MonadLift.monadLift, pure]
|
||||
unfold StateRefT'.lift ReaderT.pure
|
||||
simp only
|
||||
monadLift_bind _ _ := by
|
||||
simp only [MonadLift.monadLift, bind]
|
||||
unfold StateRefT'.lift ReaderT.bind
|
||||
simp only
|
||||
|
||||
end StateRefT'
|
||||
|
||||
namespace StateCpsT
|
||||
|
||||
instance {σ : Type u} [Monad m] [LawfulMonad m] : LawfulMonadLift m (StateCpsT σ m) where
|
||||
monadLift_pure _ := by
|
||||
simp only [MonadLift.monadLift, pure]
|
||||
unfold StateCpsT.lift
|
||||
simp only [pure_bind]
|
||||
monadLift_bind _ _ := by
|
||||
simp only [MonadLift.monadLift, bind]
|
||||
unfold StateCpsT.lift
|
||||
simp only [bind_assoc]
|
||||
|
||||
end StateCpsT
|
||||
|
||||
namespace ExceptCpsT
|
||||
|
||||
instance {ε : Type u} [Monad m] [LawfulMonad m] : LawfulMonadLift m (ExceptCpsT ε m) where
|
||||
monadLift_pure _ := by
|
||||
simp only [MonadLift.monadLift, pure]
|
||||
unfold ExceptCpsT.lift
|
||||
simp only [pure_bind]
|
||||
monadLift_bind _ _ := by
|
||||
simp only [MonadLift.monadLift, bind]
|
||||
unfold ExceptCpsT.lift
|
||||
simp only [bind_assoc]
|
||||
|
||||
end ExceptCpsT
|
||||
@@ -1,63 +0,0 @@
|
||||
/-
|
||||
Copyright (c) 2025 Quang Dao. All rights reserved.
|
||||
Released under Apache 2.0 license as described in the file LICENSE.
|
||||
Authors: Quang Dao
|
||||
-/
|
||||
module
|
||||
|
||||
prelude
|
||||
import Init.Control.Lawful.Basic
|
||||
import Init.Control.Lawful.MonadLift.Basic
|
||||
|
||||
universe u v w
|
||||
|
||||
variable {m : Type u → Type v} {n : Type u → Type w} [Monad m] [Monad n] [MonadLiftT m n]
|
||||
[LawfulMonadLiftT m n] {α β : Type u}
|
||||
|
||||
theorem monadLift_map [LawfulMonad m] [LawfulMonad n] (f : α → β) (ma : m α) :
|
||||
monadLift (f <$> ma) = f <$> (monadLift ma : n α) := by
|
||||
rw [← bind_pure_comp, ← bind_pure_comp, monadLift_bind]
|
||||
simp only [bind_pure_comp, monadLift_pure]
|
||||
|
||||
theorem monadLift_seq [LawfulMonad m] [LawfulMonad n] (mf : m (α → β)) (ma : m α) :
|
||||
monadLift (mf <*> ma) = monadLift mf <*> (monadLift ma : n α) := by
|
||||
simp only [seq_eq_bind, monadLift_map, monadLift_bind]
|
||||
|
||||
theorem monadLift_seqLeft [LawfulMonad m] [LawfulMonad n] (x : m α) (y : m β) :
|
||||
monadLift (x <* y) = (monadLift x : n α) <* (monadLift y : n β) := by
|
||||
simp only [seqLeft_eq, monadLift_map, monadLift_seq]
|
||||
|
||||
theorem monadLift_seqRight [LawfulMonad m] [LawfulMonad n] (x : m α) (y : m β) :
|
||||
monadLift (x *> y) = (monadLift x : n α) *> (monadLift y : n β) := by
|
||||
simp only [seqRight_eq, monadLift_map, monadLift_seq]
|
||||
|
||||
/-! We duplicate the theorems for `monadLift` to `liftM` since `rw` matches on syntax only. -/
|
||||
|
||||
@[simp]
|
||||
theorem liftM_pure (a : α) : liftM (pure a : m α) = pure (f := n) a :=
|
||||
monadLift_pure _
|
||||
|
||||
@[simp]
|
||||
theorem liftM_bind (ma : m α) (f : α → m β) :
|
||||
liftM (n := n) (ma >>= f) = liftM ma >>= (fun a => liftM (f a)) :=
|
||||
monadLift_bind _ _
|
||||
|
||||
@[simp]
|
||||
theorem liftM_map [LawfulMonad m] [LawfulMonad n] (f : α → β) (ma : m α) :
|
||||
liftM (f <$> ma) = f <$> (liftM ma : n α) :=
|
||||
monadLift_map _ _
|
||||
|
||||
@[simp]
|
||||
theorem liftM_seq [LawfulMonad m] [LawfulMonad n] (mf : m (α → β)) (ma : m α) :
|
||||
liftM (mf <*> ma) = liftM mf <*> (liftM ma : n α) :=
|
||||
monadLift_seq _ _
|
||||
|
||||
@[simp]
|
||||
theorem liftM_seqLeft [LawfulMonad m] [LawfulMonad n] (x : m α) (y : m β) :
|
||||
liftM (x <* y) = (liftM x : n α) <* (liftM y : n β) :=
|
||||
monadLift_seqLeft _ _
|
||||
|
||||
@[simp]
|
||||
theorem liftM_seqRight [LawfulMonad m] [LawfulMonad n] (x : m α) (y : m β) :
|
||||
liftM (x *> y) = (liftM x : n α) *> (liftM y : n β) :=
|
||||
monadLift_seqRight _ _
|
||||
@@ -29,7 +29,7 @@ of a value and a state.
|
||||
Executes an action from a monad with added state in the underlying monad `m`. Given an initial
|
||||
state, it returns a value paired with the final state.
|
||||
-/
|
||||
@[always_inline, inline, expose]
|
||||
@[always_inline, inline]
|
||||
def StateT.run {σ : Type u} {m : Type u → Type v} {α : Type u} (x : StateT σ m α) (s : σ) : m (α × σ) :=
|
||||
x s
|
||||
|
||||
@@ -37,7 +37,7 @@ def StateT.run {σ : Type u} {m : Type u → Type v} {α : Type u} (x : StateT
|
||||
Executes an action from a monad with added state in the underlying monad `m`. Given an initial
|
||||
state, it returns a value, discarding the final state.
|
||||
-/
|
||||
@[always_inline, inline, expose]
|
||||
@[always_inline, inline]
|
||||
def StateT.run' {σ : Type u} {m : Type u → Type v} [Functor m] {α : Type u} (x : StateT σ m α) (s : σ) : m α :=
|
||||
(·.1) <$> x s
|
||||
|
||||
@@ -66,21 +66,21 @@ variable [Monad m] {α β : Type u}
|
||||
/--
|
||||
Returns the given value without modifying the state. Typically used via `Pure.pure`.
|
||||
-/
|
||||
@[always_inline, inline, expose]
|
||||
@[always_inline, inline]
|
||||
protected def pure (a : α) : StateT σ m α :=
|
||||
fun s => pure (a, s)
|
||||
|
||||
/--
|
||||
Sequences two actions. Typically used via the `>>=` operator.
|
||||
-/
|
||||
@[always_inline, inline, expose]
|
||||
@[always_inline, inline]
|
||||
protected def bind (x : StateT σ m α) (f : α → StateT σ m β) : StateT σ m β :=
|
||||
fun s => do let (a, s) ← x s; f a s
|
||||
|
||||
/--
|
||||
Modifies the value returned by a computation. Typically used via the `<$>` operator.
|
||||
-/
|
||||
@[always_inline, inline, expose]
|
||||
@[always_inline, inline]
|
||||
protected def map (f : α → β) (x : StateT σ m α) : StateT σ m β :=
|
||||
fun s => do let (a, s) ← x s; pure (f a, s)
|
||||
|
||||
@@ -114,14 +114,14 @@ Retrieves the current value of the monad's mutable state.
|
||||
|
||||
This increments the reference count of the state, which may inhibit in-place updates.
|
||||
-/
|
||||
@[always_inline, inline, expose]
|
||||
@[always_inline, inline]
|
||||
protected def get : StateT σ m σ :=
|
||||
fun s => pure (s, s)
|
||||
|
||||
/--
|
||||
Replaces the mutable state with a new value.
|
||||
-/
|
||||
@[always_inline, inline, expose]
|
||||
@[always_inline, inline]
|
||||
protected def set : σ → StateT σ m PUnit :=
|
||||
fun s' _ => pure (⟨⟩, s')
|
||||
|
||||
@@ -133,7 +133,7 @@ It is equivalent to `do let (a, s) := f (← StateT.get); StateT.set s; pure a`.
|
||||
`StateT.modifyGet` may lead to better performance because it doesn't add a new reference to the
|
||||
state value, and additional references can inhibit in-place updates of data.
|
||||
-/
|
||||
@[always_inline, inline, expose]
|
||||
@[always_inline, inline]
|
||||
protected def modifyGet (f : σ → α × σ) : StateT σ m α :=
|
||||
fun s => pure (f s)
|
||||
|
||||
@@ -143,7 +143,7 @@ Runs an action from the underlying monad in the monad with state. The state is n
|
||||
This function is typically implicitly accessed via a `MonadLiftT` instance as part of [automatic
|
||||
lifting](lean-manual://section/monad-lifting).
|
||||
-/
|
||||
@[always_inline, inline, expose]
|
||||
@[always_inline, inline]
|
||||
protected def lift {α : Type u} (t : m α) : StateT σ m α :=
|
||||
fun s => do let a ← t; pure (a, s)
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ variable {α σ : Type u} {m : Type u → Type v}
|
||||
Runs a stateful computation that's represented using continuation passing style by providing it with
|
||||
an initial state and a continuation.
|
||||
-/
|
||||
@[always_inline, inline, expose]
|
||||
@[always_inline, inline]
|
||||
def runK (x : StateCpsT σ m α) (s : σ) (k : α → σ → m β) : m β :=
|
||||
x _ s k
|
||||
|
||||
@@ -39,7 +39,7 @@ state, it returns a value paired with the final state.
|
||||
While the state is internally represented in continuation passing style, the resulting value is the
|
||||
same as for a non-CPS state monad.
|
||||
-/
|
||||
@[always_inline, inline, expose]
|
||||
@[always_inline, inline]
|
||||
def run [Monad m] (x : StateCpsT σ m α) (s : σ) : m (α × σ) :=
|
||||
runK x s (fun a s => pure (a, s))
|
||||
|
||||
@@ -47,7 +47,7 @@ def run [Monad m] (x : StateCpsT σ m α) (s : σ) : m (α × σ) :=
|
||||
Executes an action from a monad with added state in the underlying monad `m`. Given an initial
|
||||
state, it returns a value, discarding the final state.
|
||||
-/
|
||||
@[always_inline, inline, expose]
|
||||
@[always_inline, inline]
|
||||
def run' [Monad m] (x : StateCpsT σ m α) (s : σ) : m α :=
|
||||
runK x s (fun a _ => pure a)
|
||||
|
||||
@@ -72,7 +72,7 @@ Runs an action from the underlying monad in the monad with state. The state is n
|
||||
This function is typically implicitly accessed via a `MonadLiftT` instance as part of [automatic
|
||||
lifting](lean-manual://section/monad-lifting).
|
||||
-/
|
||||
@[always_inline, inline, expose]
|
||||
@[always_inline, inline]
|
||||
protected def lift [Monad m] (x : m α) : StateCpsT σ m α :=
|
||||
fun _ s k => x >>= (k . s)
|
||||
|
||||
|
||||
@@ -43,14 +43,14 @@ and `flip (·<·)` is the greater-than relation.
|
||||
theorem Function.comp_def {α β δ} (f : β → δ) (g : α → β) : f ∘ g = fun x => f (g x) := rfl
|
||||
|
||||
@[simp] theorem Function.const_comp {f : α → β} {c : γ} :
|
||||
(Function.const β c ∘ f) = Function.const α c :=
|
||||
(Function.const β c ∘ f) = Function.const α c := by
|
||||
rfl
|
||||
@[simp] theorem Function.comp_const {f : β → γ} {b : β} :
|
||||
(f ∘ Function.const α b) = Function.const α (f b) :=
|
||||
(f ∘ Function.const α b) = Function.const α (f b) := by
|
||||
rfl
|
||||
@[simp] theorem Function.true_comp {f : α → β} : ((fun _ => true) ∘ f) = fun _ => true :=
|
||||
@[simp] theorem Function.true_comp {f : α → β} : ((fun _ => true) ∘ f) = fun _ => true := by
|
||||
rfl
|
||||
@[simp] theorem Function.false_comp {f : α → β} : ((fun _ => false) ∘ f) = fun _ => false :=
|
||||
@[simp] theorem Function.false_comp {f : α → β} : ((fun _ => false) ∘ f) = fun _ => false := by
|
||||
rfl
|
||||
|
||||
@[simp] theorem Function.comp_id (f : α → β) : f ∘ id = f := rfl
|
||||
@@ -897,43 +897,43 @@ section
|
||||
variable {α β φ : Sort u} {a a' : α} {b b' : β} {c : φ}
|
||||
|
||||
/-- Non-dependent recursor for `HEq` -/
|
||||
noncomputable def HEq.ndrec.{u1, u2} {α : Sort u2} {a : α} {motive : {β : Sort u2} → β → Sort u1} (m : motive a) {β : Sort u2} {b : β} (h : a ≍ b) : motive b :=
|
||||
noncomputable def HEq.ndrec.{u1, u2} {α : Sort u2} {a : α} {motive : {β : Sort u2} → β → Sort u1} (m : motive a) {β : Sort u2} {b : β} (h : HEq a b) : motive b :=
|
||||
h.rec m
|
||||
|
||||
/-- `HEq.ndrec` variant -/
|
||||
noncomputable def HEq.ndrecOn.{u1, u2} {α : Sort u2} {a : α} {motive : {β : Sort u2} → β → Sort u1} {β : Sort u2} {b : β} (h : a ≍ b) (m : motive a) : motive b :=
|
||||
noncomputable def HEq.ndrecOn.{u1, u2} {α : Sort u2} {a : α} {motive : {β : Sort u2} → β → Sort u1} {β : Sort u2} {b : β} (h : HEq a b) (m : motive a) : motive b :=
|
||||
h.rec m
|
||||
|
||||
/-- `HEq.ndrec` variant -/
|
||||
noncomputable def HEq.elim {α : Sort u} {a : α} {p : α → Sort v} {b : α} (h₁ : a ≍ b) (h₂ : p a) : p b :=
|
||||
noncomputable def HEq.elim {α : Sort u} {a : α} {p : α → Sort v} {b : α} (h₁ : HEq a b) (h₂ : p a) : p b :=
|
||||
eq_of_heq h₁ ▸ h₂
|
||||
|
||||
/-- Substitution with heterogeneous equality. -/
|
||||
theorem HEq.subst {p : (T : Sort u) → T → Prop} (h₁ : a ≍ b) (h₂ : p α a) : p β b :=
|
||||
theorem HEq.subst {p : (T : Sort u) → T → Prop} (h₁ : HEq a b) (h₂ : p α a) : p β b :=
|
||||
HEq.ndrecOn h₁ h₂
|
||||
|
||||
/-- Heterogeneous equality is symmetric. -/
|
||||
@[symm] theorem HEq.symm (h : a ≍ b) : b ≍ a :=
|
||||
@[symm] theorem HEq.symm (h : HEq a b) : HEq b a :=
|
||||
h.rec (HEq.refl a)
|
||||
|
||||
/-- Propositionally equal terms are also heterogeneously equal. -/
|
||||
theorem heq_of_eq (h : a = a') : a ≍ a' :=
|
||||
theorem heq_of_eq (h : a = a') : HEq a a' :=
|
||||
Eq.subst h (HEq.refl a)
|
||||
|
||||
/-- Heterogeneous equality is transitive. -/
|
||||
theorem HEq.trans (h₁ : a ≍ b) (h₂ : b ≍ c) : a ≍ c :=
|
||||
theorem HEq.trans (h₁ : HEq a b) (h₂ : HEq b c) : HEq a c :=
|
||||
HEq.subst h₂ h₁
|
||||
|
||||
/-- Heterogeneous equality precomposes with propositional equality. -/
|
||||
theorem heq_of_heq_of_eq (h₁ : a ≍ b) (h₂ : b = b') : a ≍ b' :=
|
||||
theorem heq_of_heq_of_eq (h₁ : HEq a b) (h₂ : b = b') : HEq a b' :=
|
||||
HEq.trans h₁ (heq_of_eq h₂)
|
||||
|
||||
/-- Heterogeneous equality postcomposes with propositional equality. -/
|
||||
theorem heq_of_eq_of_heq (h₁ : a = a') (h₂ : a' ≍ b) : a ≍ b :=
|
||||
theorem heq_of_eq_of_heq (h₁ : a = a') (h₂ : HEq a' b) : HEq a b :=
|
||||
HEq.trans (heq_of_eq h₁) h₂
|
||||
|
||||
/-- If two terms are heterogeneously equal then their types are propositionally equal. -/
|
||||
theorem type_eq_of_heq (h : a ≍ b) : α = β :=
|
||||
theorem type_eq_of_heq (h : HEq a b) : α = β :=
|
||||
h.rec (Eq.refl α)
|
||||
|
||||
end
|
||||
@@ -942,7 +942,7 @@ end
|
||||
Rewriting inside `φ` using `Eq.recOn` yields a term that's heterogeneously equal to the original
|
||||
term.
|
||||
-/
|
||||
theorem eqRec_heq {α : Sort u} {φ : α → Sort v} {a a' : α} : (h : a = a') → (p : φ a) → Eq.recOn (motive := fun x _ => φ x) h p ≍ p
|
||||
theorem eqRec_heq {α : Sort u} {φ : α → Sort v} {a a' : α} : (h : a = a') → (p : φ a) → HEq (Eq.recOn (motive := fun x _ => φ x) h p) p
|
||||
| rfl, p => HEq.refl p
|
||||
|
||||
/--
|
||||
@@ -950,8 +950,8 @@ Heterogeneous equality with an `Eq.rec` application on the left is equivalent to
|
||||
equality on the original term.
|
||||
-/
|
||||
theorem eqRec_heq_iff {α : Sort u} {a : α} {motive : (b : α) → a = b → Sort v}
|
||||
{b : α} {refl : motive a (Eq.refl a)} {h : a = b} {c : motive b h}
|
||||
: @Eq.rec α a motive refl b h ≍ c ↔ refl ≍ c :=
|
||||
{b : α} {refl : motive a (Eq.refl a)} {h : a = b} {c : motive b h} :
|
||||
HEq (@Eq.rec α a motive refl b h) c ↔ HEq refl c :=
|
||||
h.rec (fun _ => ⟨id, id⟩) c
|
||||
|
||||
/--
|
||||
@@ -960,7 +960,7 @@ equality on the original term.
|
||||
-/
|
||||
theorem heq_eqRec_iff {α : Sort u} {a : α} {motive : (b : α) → a = b → Sort v}
|
||||
{b : α} {refl : motive a (Eq.refl a)} {h : a = b} {c : motive b h} :
|
||||
c ≍ @Eq.rec α a motive refl b h ↔ c ≍ refl :=
|
||||
HEq c (@Eq.rec α a motive refl b h) ↔ HEq c refl :=
|
||||
h.rec (fun _ => ⟨id, id⟩) c
|
||||
|
||||
/--
|
||||
@@ -977,7 +977,7 @@ theorem apply_eqRec {α : Sort u} {a : α} (motive : (b : α) → a = b → Sort
|
||||
If casting a term with `Eq.rec` to another type makes it equal to some other term, then the two
|
||||
terms are heterogeneously equal.
|
||||
-/
|
||||
theorem heq_of_eqRec_eq {α β : Sort u} {a : α} {b : β} (h₁ : α = β) (h₂ : Eq.rec (motive := fun α _ => α) a h₁ = b) : a ≍ b := by
|
||||
theorem heq_of_eqRec_eq {α β : Sort u} {a : α} {b : β} (h₁ : α = β) (h₂ : Eq.rec (motive := fun α _ => α) a h₁ = b) : HEq a b := by
|
||||
subst h₁
|
||||
apply heq_of_eq
|
||||
exact h₂
|
||||
@@ -985,7 +985,7 @@ theorem heq_of_eqRec_eq {α β : Sort u} {a : α} {b : β} (h₁ : α = β) (h
|
||||
/--
|
||||
The result of casting a term with `cast` is heterogeneously equal to the original term.
|
||||
-/
|
||||
theorem cast_heq {α β : Sort u} : (h : α = β) → (a : α) → cast h a ≍ a
|
||||
theorem cast_heq {α β : Sort u} : (h : α = β) → (a : α) → HEq (cast h a) a
|
||||
| rfl, a => HEq.refl a
|
||||
|
||||
variable {a b c d : Prop}
|
||||
@@ -1014,8 +1014,8 @@ instance : Trans Iff Iff Iff where
|
||||
theorem Eq.comm {a b : α} : a = b ↔ b = a := Iff.intro Eq.symm Eq.symm
|
||||
theorem eq_comm {a b : α} : a = b ↔ b = a := Eq.comm
|
||||
|
||||
theorem HEq.comm {a : α} {b : β} : a ≍ b ↔ b ≍ a := Iff.intro HEq.symm HEq.symm
|
||||
theorem heq_comm {a : α} {b : β} : a ≍ b ↔ b ≍ a := HEq.comm
|
||||
theorem HEq.comm {a : α} {b : β} : HEq a b ↔ HEq b a := Iff.intro HEq.symm HEq.symm
|
||||
theorem heq_comm {a : α} {b : β} : HEq a b ↔ HEq b a := HEq.comm
|
||||
|
||||
@[symm] theorem Iff.symm (h : a ↔ b) : b ↔ a := Iff.intro h.mpr h.mp
|
||||
theorem Iff.comm : (a ↔ b) ↔ (b ↔ a) := Iff.intro Iff.symm Iff.symm
|
||||
@@ -1048,6 +1048,11 @@ theorem Exists.elim {α : Sort u} {p : α → Prop} {b : Prop}
|
||||
| isFalse _ => rfl
|
||||
| isTrue h => False.elim h
|
||||
|
||||
set_option linter.missingDocs false in
|
||||
@[deprecated decide_true (since := "2024-11-05")] abbrev decide_true_eq_true := decide_true
|
||||
set_option linter.missingDocs false in
|
||||
@[deprecated decide_false (since := "2024-11-05")] abbrev decide_false_eq_false := decide_false
|
||||
|
||||
/-- Similar to `decide`, but uses an explicit instance -/
|
||||
@[inline] def toBoolUsing {p : Prop} (d : Decidable p) : Bool :=
|
||||
decide (h := d)
|
||||
@@ -1234,7 +1239,7 @@ protected theorem Subsingleton.elim {α : Sort u} [h : Subsingleton α] : (a b :
|
||||
If two types are equal and one of them is a subsingleton, then all of their elements are
|
||||
[heterogeneously equal](lean-manual://section/HEq).
|
||||
-/
|
||||
protected theorem Subsingleton.helim {α β : Sort u} [h₁ : Subsingleton α] (h₂ : α = β) (a : α) (b : β) : a ≍ b := by
|
||||
protected theorem Subsingleton.helim {α β : Sort u} [h₁ : Subsingleton α] (h₂ : α = β) (a : α) (b : β) : HEq a b := by
|
||||
subst h₂
|
||||
apply heq_of_eq
|
||||
apply Subsingleton.elim
|
||||
@@ -1685,7 +1690,7 @@ theorem true_iff_false : (True ↔ False) ↔ False := iff_false_intro (·.mp T
|
||||
theorem false_iff_true : (False ↔ True) ↔ False := iff_false_intro (·.mpr True.intro)
|
||||
|
||||
theorem iff_not_self : ¬(a ↔ ¬a) | H => let f h := H.1 h h; f (H.2 f)
|
||||
theorem heq_self_iff_true (a : α) : a ≍ a ↔ True := iff_true_intro HEq.rfl
|
||||
theorem heq_self_iff_true (a : α) : HEq a a ↔ True := iff_true_intro HEq.rfl
|
||||
|
||||
/-! ## implies -/
|
||||
|
||||
@@ -1885,7 +1890,7 @@ a structure.
|
||||
protected abbrev hrecOn
|
||||
(q : Quot r)
|
||||
(f : (a : α) → motive (Quot.mk r a))
|
||||
(c : (a b : α) → (p : r a b) → f a ≍ f b)
|
||||
(c : (a b : α) → (p : r a b) → HEq (f a) (f b))
|
||||
: motive q :=
|
||||
Quot.recOn q f fun a b p => eq_of_heq (eqRec_heq_iff.mpr (c a b p))
|
||||
|
||||
@@ -2083,7 +2088,7 @@ a structure.
|
||||
protected abbrev hrecOn
|
||||
(q : Quotient s)
|
||||
(f : (a : α) → motive (Quotient.mk s a))
|
||||
(c : (a b : α) → (p : a ≈ b) → f a ≍ f b)
|
||||
(c : (a b : α) → (p : a ≈ b) → HEq (f a) (f b))
|
||||
: motive q :=
|
||||
Quot.hrecOn q f c
|
||||
end
|
||||
|
||||
@@ -22,7 +22,7 @@ an array `xs : Array α`, given a proof that every element of `xs` in fact satis
|
||||
|
||||
`Array.pmap`, named for “partial map,” is the equivalent of `Array.map` for such partial functions.
|
||||
-/
|
||||
@[expose]
|
||||
|
||||
def pmap {P : α → Prop} (f : ∀ a, P a → β) (xs : Array α) (H : ∀ a ∈ xs, P a) : Array β :=
|
||||
(xs.toList.pmap f (fun a m => H a (mem_def.mpr m))).toArray
|
||||
|
||||
@@ -39,7 +39,7 @@ of elements in the corresponding subtype `{ x // P x }`.
|
||||
|
||||
`O(1)`.
|
||||
-/
|
||||
@[implemented_by attachWithImpl, expose] def attachWith
|
||||
@[implemented_by attachWithImpl] def attachWith
|
||||
(xs : Array α) (P : α → Prop) (H : ∀ x ∈ xs, P x) : Array {x // P x} :=
|
||||
⟨xs.toList.attachWith P fun x h => H x (Array.Mem.mk h)⟩
|
||||
|
||||
@@ -54,7 +54,7 @@ recursion](lean-manual://section/well-founded-recursion) that use higher-order f
|
||||
`Array.map`) to prove that an value taken from a list is smaller than the list. This allows the
|
||||
well-founded recursion mechanism to prove that the function terminates.
|
||||
-/
|
||||
@[inline, expose] def attach (xs : Array α) : Array {x // x ∈ xs} := xs.attachWith _ fun _ => id
|
||||
@[inline] def attach (xs : Array α) : Array {x // x ∈ xs} := xs.attachWith _ fun _ => id
|
||||
|
||||
@[simp, grind =] theorem _root_.List.attachWith_toArray {l : List α} {P : α → Prop} {H : ∀ x ∈ l.toArray, P x} :
|
||||
l.toArray.attachWith P H = (l.attachWith P (by simpa using H)).toArray := by
|
||||
@@ -69,11 +69,11 @@ well-founded recursion mechanism to prove that the function terminates.
|
||||
simp [pmap]
|
||||
|
||||
@[simp] theorem toList_attachWith {xs : Array α} {P : α → Prop} {H : ∀ x ∈ xs, P x} :
|
||||
(xs.attachWith P H).toList = xs.toList.attachWith P (by simpa [mem_toList_iff] using H) := by
|
||||
(xs.attachWith P H).toList = xs.toList.attachWith P (by simpa [mem_toList] using H) := by
|
||||
simp [attachWith]
|
||||
|
||||
@[simp] theorem toList_attach {xs : Array α} :
|
||||
xs.attach.toList = xs.toList.attachWith (· ∈ xs) (by simp [mem_toList_iff]) := by
|
||||
xs.attach.toList = xs.toList.attachWith (· ∈ xs) (by simp [mem_toList]) := by
|
||||
simp [attach]
|
||||
|
||||
@[simp] theorem toList_pmap {xs : Array α} {P : α → Prop} {f : ∀ a, P a → β} {H : ∀ a ∈ xs, P a} :
|
||||
@@ -574,12 +574,9 @@ state, the right approach is usually the tactic `simp [Array.unattach, -Array.ma
|
||||
-/
|
||||
def unattach {α : Type _} {p : α → Prop} (xs : Array { x // p x }) : Array α := xs.map (·.val)
|
||||
|
||||
@[simp] theorem unattach_empty {p : α → Prop} : (#[] : Array { x // p x }).unattach = #[] := by
|
||||
@[simp] theorem unattach_nil {p : α → Prop} : (#[] : Array { x // p x }).unattach = #[] := by
|
||||
simp [unattach]
|
||||
|
||||
@[deprecated unattach_empty (since := "2025-05-26")]
|
||||
abbrev unattach_nil := @unattach_empty
|
||||
|
||||
@[simp] theorem unattach_push {p : α → Prop} {a : { x // p x }} {xs : Array { x // p x }} :
|
||||
(xs.push a).unattach = xs.unattach.push a.1 := by
|
||||
simp only [unattach, Array.map_push]
|
||||
|
||||
@@ -91,8 +91,7 @@ theorem ext' {xs ys : Array α} (h : xs.toList = ys.toList) : xs = ys := by
|
||||
@[simp, grind =] theorem getElem_toList {xs : Array α} {i : Nat} (h : i < xs.size) : xs.toList[i] = xs[i] := rfl
|
||||
|
||||
@[simp, grind =] theorem getElem?_toList {xs : Array α} {i : Nat} : xs.toList[i]? = xs[i]? := by
|
||||
simp only [getElem?_def, getElem_toList]
|
||||
simp only [Array.size]
|
||||
simp [getElem?_def]
|
||||
|
||||
/-- `a ∈ as` is a predicate which asserts that `a` is in the array `as`. -/
|
||||
-- NB: This is defined as a structure rather than a plain def so that a lemma
|
||||
@@ -113,7 +112,7 @@ theorem mem_def {a : α} {as : Array α} : a ∈ as ↔ a ∈ as.toList :=
|
||||
rw [Array.mem_def, ← getElem_toList]
|
||||
apply List.getElem_mem
|
||||
|
||||
@[simp, grind =] theorem emptyWithCapacity_eq {α n} : @emptyWithCapacity α n = #[] := rfl
|
||||
@[simp] theorem emptyWithCapacity_eq {α n} : @emptyWithCapacity α n = #[] := rfl
|
||||
|
||||
@[simp] theorem mkEmpty_eq {α n} : @mkEmpty α n = #[] := rfl
|
||||
|
||||
@@ -168,7 +167,7 @@ Low-level indexing operator which is as fast as a C array read.
|
||||
|
||||
This avoids overhead due to unboxing a `Nat` used as an index.
|
||||
-/
|
||||
@[extern "lean_array_uget", simp, expose]
|
||||
@[extern "lean_array_uget", simp]
|
||||
def uget (a : @& Array α) (i : USize) (h : i.toNat < a.size) : α :=
|
||||
a[i.toNat]
|
||||
|
||||
@@ -191,7 +190,7 @@ Examples:
|
||||
* `#["orange", "yellow"].pop = #["orange"]`
|
||||
* `(#[] : Array String).pop = #[]`
|
||||
-/
|
||||
@[extern "lean_array_pop", expose]
|
||||
@[extern "lean_array_pop"]
|
||||
def pop (xs : Array α) : Array α where
|
||||
toList := xs.toList.dropLast
|
||||
|
||||
@@ -210,7 +209,7 @@ Examples:
|
||||
* `Array.replicate 3 () = #[(), (), ()]`
|
||||
* `Array.replicate 0 "anything" = #[]`
|
||||
-/
|
||||
@[extern "lean_mk_array", expose]
|
||||
@[extern "lean_mk_array"]
|
||||
def replicate {α : Type u} (n : Nat) (v : α) : Array α where
|
||||
toList := List.replicate n v
|
||||
|
||||
@@ -238,7 +237,7 @@ Examples:
|
||||
* `#["red", "green", "blue", "brown"].swap 1 2 = #["red", "blue", "green", "brown"]`
|
||||
* `#["red", "green", "blue", "brown"].swap 3 0 = #["brown", "green", "blue", "red"]`
|
||||
-/
|
||||
@[extern "lean_array_fswap", expose]
|
||||
@[extern "lean_array_fswap"]
|
||||
def swap (xs : Array α) (i j : @& Nat) (hi : i < xs.size := by get_elem_tactic) (hj : j < xs.size := by get_elem_tactic) : Array α :=
|
||||
let v₁ := xs[i]
|
||||
let v₂ := xs[j]
|
||||
@@ -268,6 +267,8 @@ def swapIfInBounds (xs : Array α) (i j : @& Nat) : Array α :=
|
||||
else xs
|
||||
else xs
|
||||
|
||||
@[deprecated swapIfInBounds (since := "2024-11-24")] abbrev swap! := @swapIfInBounds
|
||||
|
||||
/-! ### GetElem instance for `USize`, backed by `uget` -/
|
||||
|
||||
instance : GetElem (Array α) USize α fun xs i => i.toNat < xs.size where
|
||||
@@ -289,7 +290,6 @@ Examples:
|
||||
* `#[1, 2].isEmpty = false`
|
||||
* `#[()].isEmpty = false`
|
||||
-/
|
||||
@[expose]
|
||||
def isEmpty (xs : Array α) : Bool :=
|
||||
xs.size = 0
|
||||
|
||||
@@ -331,14 +331,12 @@ Examples:
|
||||
* `Array.ofFn (n := 3) toString = #["0", "1", "2"]`
|
||||
* `Array.ofFn (fun i => #["red", "green", "blue"].get i.val i.isLt) = #["red", "green", "blue"]`
|
||||
-/
|
||||
def ofFn {n} (f : Fin n → α) : Array α := go (emptyWithCapacity n) n (Nat.le_refl n) where
|
||||
/-- Auxiliary for `ofFn`. `ofFn.go f acc i h = acc ++ #[f (n - i), ..., f(n - 1)]` -/
|
||||
go (acc : Array α) : (i : Nat) → i ≤ n → Array α
|
||||
| i + 1, h =>
|
||||
have w : n - i - 1 < n :=
|
||||
Nat.lt_of_lt_of_le (Nat.sub_one_lt (Nat.sub_ne_zero_iff_lt.mpr h)) (Nat.sub_le n i)
|
||||
go (acc.push (f ⟨n - i - 1, w⟩)) i (Nat.le_of_succ_le h)
|
||||
| 0, _ => acc
|
||||
def ofFn {n} (f : Fin n → α) : Array α := go 0 (emptyWithCapacity n) where
|
||||
/-- Auxiliary for `ofFn`. `ofFn.go f i acc = acc ++ #[f i, ..., f(n - 1)]` -/
|
||||
@[semireducible] -- This is otherwise irreducible because it uses well-founded recursion.
|
||||
go (i : Nat) (acc : Array α) : Array α :=
|
||||
if h : i < n then go (i+1) (acc.push (f ⟨i, h⟩)) else acc
|
||||
decreasing_by simp_wf; decreasing_trivial_pre_omega
|
||||
|
||||
-- See also `Array.ofFnM` defined in `Init.Data.Array.OfFn`.
|
||||
|
||||
@@ -375,7 +373,7 @@ Examples:
|
||||
* `Array.singleton 5 = #[5]`
|
||||
* `Array.singleton "one" = #["one"]`
|
||||
-/
|
||||
@[inline, expose] protected def singleton (v : α) : Array α := #[v]
|
||||
@[inline] protected def singleton (v : α) : Array α := #[v]
|
||||
|
||||
/--
|
||||
Returns the last element of an array, or panics if the array is empty.
|
||||
@@ -404,7 +402,7 @@ that requires a proof the array is non-empty.
|
||||
def back? (xs : Array α) : Option α :=
|
||||
xs[xs.size - 1]?
|
||||
|
||||
@[deprecated "Use `a[i]?` instead." (since := "2025-02-12"), expose]
|
||||
@[deprecated "Use `a[i]?` instead." (since := "2025-02-12")]
|
||||
def get? (xs : Array α) (i : Nat) : Option α :=
|
||||
if h : i < xs.size then some xs[i] else none
|
||||
|
||||
@@ -418,7 +416,7 @@ Examples:
|
||||
* `#["spinach", "broccoli", "carrot"].swapAt 1 "pepper" = ("broccoli", #["spinach", "pepper", "carrot"])`
|
||||
* `#["spinach", "broccoli", "carrot"].swapAt 2 "pepper" = ("carrot", #["spinach", "broccoli", "pepper"])`
|
||||
-/
|
||||
@[inline, expose] def swapAt (xs : Array α) (i : Nat) (v : α) (hi : i < xs.size := by get_elem_tactic) : α × Array α :=
|
||||
@[inline] def swapAt (xs : Array α) (i : Nat) (v : α) (hi : i < xs.size := by get_elem_tactic) : α × Array α :=
|
||||
let e := xs[i]
|
||||
let xs' := xs.set i v
|
||||
(e, xs')
|
||||
@@ -433,7 +431,7 @@ Examples:
|
||||
* `#["spinach", "broccoli", "carrot"].swapAt! 1 "pepper" = (#["spinach", "pepper", "carrot"], "broccoli")`
|
||||
* `#["spinach", "broccoli", "carrot"].swapAt! 2 "pepper" = (#["spinach", "broccoli", "pepper"], "carrot")`
|
||||
-/
|
||||
@[inline, expose]
|
||||
@[inline]
|
||||
def swapAt! (xs : Array α) (i : Nat) (v : α) : α × Array α :=
|
||||
if h : i < xs.size then
|
||||
swapAt xs i v
|
||||
@@ -546,7 +544,7 @@ Examples:
|
||||
-/
|
||||
@[inline]
|
||||
def modify (xs : Array α) (i : Nat) (f : α → α) : Array α :=
|
||||
Id.run <| modifyM xs i (pure <| f ·)
|
||||
Id.run <| modifyM xs i f
|
||||
|
||||
set_option linter.indexVariables false in -- Changing `idx` causes bootstrapping issues, haven't investigated.
|
||||
/--
|
||||
@@ -579,7 +577,7 @@ def modifyOp (xs : Array α) (idx : Nat) (f : α → α) : Array α :=
|
||||
loop 0 b
|
||||
|
||||
/-- Reference implementation for `forIn'` -/
|
||||
@[implemented_by Array.forIn'Unsafe, expose]
|
||||
@[implemented_by Array.forIn'Unsafe]
|
||||
protected def forIn' {α : Type u} {β : Type v} {m : Type v → Type w} [Monad m] (as : Array α) (b : β) (f : (a : α) → a ∈ as → β → m (ForInStep β)) : m β :=
|
||||
let rec loop (i : Nat) (h : i ≤ as.size) (b : β) : m β := do
|
||||
match i, h with
|
||||
@@ -646,7 +644,7 @@ example [Monad m] (f : α → β → m α) :
|
||||
```
|
||||
-/
|
||||
-- Reference implementation for `foldlM`
|
||||
@[implemented_by foldlMUnsafe, expose]
|
||||
@[implemented_by foldlMUnsafe]
|
||||
def foldlM {α : Type u} {β : Type v} {m : Type v → Type w} [Monad m] (f : β → α → m β) (init : β) (as : Array α) (start := 0) (stop := as.size) : m β :=
|
||||
let fold (stop : Nat) (h : stop ≤ as.size) :=
|
||||
let rec loop (i : Nat) (j : Nat) (b : β) : m β := do
|
||||
@@ -711,7 +709,7 @@ example [Monad m] (f : α → β → m β) :
|
||||
```
|
||||
-/
|
||||
-- Reference implementation for `foldrM`
|
||||
@[implemented_by foldrMUnsafe, expose]
|
||||
@[implemented_by foldrMUnsafe]
|
||||
def foldrM {α : Type u} {β : Type v} {m : Type v → Type w} [Monad m] (f : α → β → m β) (init : β) (as : Array α) (start := as.size) (stop := 0) : m β :=
|
||||
let rec fold (i : Nat) (h : i ≤ as.size) (b : β) : m β := do
|
||||
if i == stop then
|
||||
@@ -766,11 +764,13 @@ def mapM {α : Type u} {β : Type v} {m : Type v → Type w} [Monad m] (f : α
|
||||
decreasing_by simp_wf; decreasing_trivial_pre_omega
|
||||
map 0 (emptyWithCapacity as.size)
|
||||
|
||||
@[deprecated mapM (since := "2024-11-11")] abbrev sequenceMap := @mapM
|
||||
|
||||
/--
|
||||
Applies the monadic action `f` to every element in the array, along with the element's index and a
|
||||
proof that the index is in bounds, from left to right. Returns the array of results.
|
||||
-/
|
||||
@[inline, expose]
|
||||
@[inline]
|
||||
def mapFinIdxM {α : Type u} {β : Type v} {m : Type v → Type w} [Monad m]
|
||||
(as : Array α) (f : (i : Nat) → α → (h : i < as.size) → m β) : m (Array β) :=
|
||||
let rec @[specialize] map (i : Nat) (j : Nat) (inv : i + j = as.size) (bs : Array β) : m (Array β) := do
|
||||
@@ -788,7 +788,7 @@ def mapFinIdxM {α : Type u} {β : Type v} {m : Type v → Type w} [Monad m]
|
||||
Applies the monadic action `f` to every element in the array, along with the element's index, from
|
||||
left to right. Returns the array of results.
|
||||
-/
|
||||
@[inline, expose]
|
||||
@[inline]
|
||||
def mapIdxM {α : Type u} {β : Type v} {m : Type v → Type w} [Monad m] (f : Nat → α → m β) (as : Array α) : m (Array β) :=
|
||||
as.mapFinIdxM fun i a _ => f i a
|
||||
|
||||
@@ -834,7 +834,7 @@ Almost! 5
|
||||
some 10
|
||||
```
|
||||
-/
|
||||
@[inline, expose]
|
||||
@[inline]
|
||||
def findSomeM? {α : Type u} {β : Type v} {m : Type v → Type w} [Monad m] (f : α → m (Option β)) (as : Array α) : m (Option β) := do
|
||||
for a in as do
|
||||
match (← f a) with
|
||||
@@ -915,7 +915,7 @@ The optional parameters `start` and `stop` control the region of the array to be
|
||||
elements with indices from `start` (inclusive) to `stop` (exclusive) are checked. By default, the
|
||||
entire array is checked.
|
||||
-/
|
||||
@[implemented_by anyMUnsafe, expose]
|
||||
@[implemented_by anyMUnsafe]
|
||||
def anyM {α : Type u} {m : Type → Type w} [Monad m] (p : α → m Bool) (as : Array α) (start := 0) (stop := as.size) : m Bool :=
|
||||
let any (stop : Nat) (h : stop ≤ as.size) :=
|
||||
let rec @[semireducible] -- This is otherwise irreducible because it uses well-founded recursion.
|
||||
@@ -1057,9 +1057,9 @@ Examples:
|
||||
* `#[1, 2, 3].foldl (· ++ toString ·) "" = "123"`
|
||||
* `#[1, 2, 3].foldl (s!"({·} {·})") "" = "((( 1) 2) 3)"`
|
||||
-/
|
||||
@[inline, expose]
|
||||
@[inline]
|
||||
def foldl {α : Type u} {β : Type v} (f : β → α → β) (init : β) (as : Array α) (start := 0) (stop := as.size) : β :=
|
||||
Id.run <| as.foldlM (pure <| f · ·) init start stop
|
||||
Id.run <| as.foldlM f init start stop
|
||||
|
||||
/--
|
||||
Folds a function over an array from the right, accumulating a value starting with `init`. The
|
||||
@@ -1074,9 +1074,9 @@ Examples:
|
||||
* `#[1, 2, 3].foldr (toString · ++ ·) "" = "123"`
|
||||
* `#[1, 2, 3].foldr (s!"({·} {·})") "!" = "(1 (2 (3 !)))"`
|
||||
-/
|
||||
@[inline, expose]
|
||||
@[inline]
|
||||
def foldr {α : Type u} {β : Type v} (f : α → β → β) (init : β) (as : Array α) (start := as.size) (stop := 0) : β :=
|
||||
Id.run <| as.foldrM (pure <| f · ·) init start stop
|
||||
Id.run <| as.foldrM f init start stop
|
||||
|
||||
/--
|
||||
Computes the sum of the elements of an array.
|
||||
@@ -1085,7 +1085,7 @@ Examples:
|
||||
* `#[a, b, c].sum = a + (b + (c + 0))`
|
||||
* `#[1, 2, 5].sum = 8`
|
||||
-/
|
||||
@[inline, expose]
|
||||
@[inline]
|
||||
def sum {α} [Add α] [Zero α] : Array α → α :=
|
||||
foldr (· + ·) 0
|
||||
|
||||
@@ -1097,7 +1097,7 @@ Examples:
|
||||
* `#[1, 2, 3, 4, 5].countP (· < 5) = 4`
|
||||
* `#[1, 2, 3, 4, 5].countP (· > 5) = 0`
|
||||
-/
|
||||
@[inline, expose]
|
||||
@[inline]
|
||||
def countP {α : Type u} (p : α → Bool) (as : Array α) : Nat :=
|
||||
as.foldr (init := 0) fun a acc => bif p a then acc + 1 else acc
|
||||
|
||||
@@ -1109,7 +1109,7 @@ Examples:
|
||||
* `#[1, 1, 2, 3, 5].count 5 = 1`
|
||||
* `#[1, 1, 2, 3, 5].count 4 = 0`
|
||||
-/
|
||||
@[inline, expose]
|
||||
@[inline]
|
||||
def count {α : Type u} [BEq α] (a : α) (as : Array α) : Nat :=
|
||||
countP (· == a) as
|
||||
|
||||
@@ -1122,9 +1122,9 @@ Examples:
|
||||
* `#["one", "two", "three"].map (·.length) = #[3, 3, 5]`
|
||||
* `#["one", "two", "three"].map (·.reverse) = #["eno", "owt", "eerht"]`
|
||||
-/
|
||||
@[inline, expose]
|
||||
@[inline]
|
||||
def map {α : Type u} {β : Type v} (f : α → β) (as : Array α) : Array β :=
|
||||
Id.run <| as.mapM (pure <| f ·)
|
||||
Id.run <| as.mapM f
|
||||
|
||||
instance : Functor Array where
|
||||
map := map
|
||||
@@ -1137,9 +1137,9 @@ that the index is valid.
|
||||
`Array.mapIdx` is a variant that does not provide the function with evidence that the index is
|
||||
valid.
|
||||
-/
|
||||
@[inline, expose]
|
||||
@[inline]
|
||||
def mapFinIdx {α : Type u} {β : Type v} (as : Array α) (f : (i : Nat) → α → (h : i < as.size) → β) : Array β :=
|
||||
Id.run <| as.mapFinIdxM (pure <| f · · ·)
|
||||
Id.run <| as.mapFinIdxM f
|
||||
|
||||
/--
|
||||
Applies a function to each element of the array along with the index at which that element is found,
|
||||
@@ -1148,9 +1148,9 @@ returning the array of results.
|
||||
`Array.mapFinIdx` is a variant that additionally provides the function with a proof that the index
|
||||
is valid.
|
||||
-/
|
||||
@[inline, expose]
|
||||
@[inline]
|
||||
def mapIdx {α : Type u} {β : Type v} (f : Nat → α → β) (as : Array α) : Array β :=
|
||||
Id.run <| as.mapIdxM (pure <| f · ·)
|
||||
Id.run <| as.mapIdxM f
|
||||
|
||||
/--
|
||||
Pairs each element of an array with its index, optionally starting from an index other than `0`.
|
||||
@@ -1159,7 +1159,6 @@ Examples:
|
||||
* `#[a, b, c].zipIdx = #[(a, 0), (b, 1), (c, 2)]`
|
||||
* `#[a, b, c].zipIdx 5 = #[(a, 5), (b, 6), (c, 7)]`
|
||||
-/
|
||||
@[expose]
|
||||
def zipIdx (xs : Array α) (start := 0) : Array (α × Nat) :=
|
||||
xs.mapIdx fun i a => (a, start + i)
|
||||
|
||||
@@ -1173,7 +1172,7 @@ Examples:
|
||||
* `#[7, 6, 5, 8, 1, 2, 6].find? (· < 5) = some 1`
|
||||
* `#[7, 6, 5, 8, 1, 2, 6].find? (· < 1) = none`
|
||||
-/
|
||||
@[inline, expose]
|
||||
@[inline]
|
||||
def find? {α : Type u} (p : α → Bool) (as : Array α) : Option α :=
|
||||
Id.run do
|
||||
for a in as do
|
||||
@@ -1197,9 +1196,9 @@ Example:
|
||||
some 10
|
||||
```
|
||||
-/
|
||||
@[inline, expose]
|
||||
@[inline]
|
||||
def findSome? {α : Type u} {β : Type v} (f : α → Option β) (as : Array α) : Option β :=
|
||||
Id.run <| as.findSomeM? (pure <| f ·)
|
||||
Id.run <| as.findSomeM? f
|
||||
|
||||
/--
|
||||
Returns the first non-`none` result of applying the function `f` to each element of the
|
||||
@@ -1233,7 +1232,7 @@ Examples:
|
||||
-/
|
||||
@[inline]
|
||||
def findSomeRev? {α : Type u} {β : Type v} (f : α → Option β) (as : Array α) : Option β :=
|
||||
Id.run <| as.findSomeRevM? (pure <| f ·)
|
||||
Id.run <| as.findSomeRevM? f
|
||||
|
||||
/--
|
||||
Returns the last element of the array for which the predicate `p` returns `true`, or `none` if no
|
||||
@@ -1245,7 +1244,7 @@ Examples:
|
||||
-/
|
||||
@[inline]
|
||||
def findRev? {α : Type} (p : α → Bool) (as : Array α) : Option α :=
|
||||
Id.run <| as.findRevM? (pure <| p ·)
|
||||
Id.run <| as.findRevM? p
|
||||
|
||||
/--
|
||||
Returns the index of the first element for which `p` returns `true`, or `none` if there is no such
|
||||
@@ -1255,7 +1254,7 @@ Examples:
|
||||
* `#[7, 6, 5, 8, 1, 2, 6].findIdx (· < 5) = some 4`
|
||||
* `#[7, 6, 5, 8, 1, 2, 6].findIdx (· < 1) = none`
|
||||
-/
|
||||
@[inline, expose]
|
||||
@[inline]
|
||||
def findIdx? {α : Type u} (p : α → Bool) (as : Array α) : Option Nat :=
|
||||
let rec @[semireducible] -- This is otherwise irreducible because it uses well-founded recursion.
|
||||
loop (j : Nat) :=
|
||||
@@ -1309,7 +1308,7 @@ Examples:
|
||||
* `#[7, 6, 5, 8, 1, 2, 6].findIdx (· < 5) = 4`
|
||||
* `#[7, 6, 5, 8, 1, 2, 6].findIdx (· < 1) = 7`
|
||||
-/
|
||||
@[inline, expose]
|
||||
@[inline]
|
||||
def findIdx (p : α → Bool) (as : Array α) : Nat := (as.findIdx? p).getD as.size
|
||||
|
||||
@[semireducible] -- This is otherwise irreducible because it uses well-founded recursion.
|
||||
@@ -1363,6 +1362,10 @@ Examples:
|
||||
def idxOf? [BEq α] (xs : Array α) (v : α) : Option Nat :=
|
||||
(xs.finIdxOf? v).map (·.val)
|
||||
|
||||
@[deprecated idxOf? (since := "2024-11-20")]
|
||||
def getIdx? [BEq α] (xs : Array α) (v : α) : Option Nat :=
|
||||
xs.findIdx? fun a => a == v
|
||||
|
||||
/--
|
||||
Returns `true` if `p` returns `true` for any element of `as`.
|
||||
|
||||
@@ -1378,9 +1381,9 @@ Examples:
|
||||
* `#[2, 4, 5, 6].any (· % 2 = 0) = true`
|
||||
* `#[2, 4, 5, 6].any (· % 2 = 1) = true`
|
||||
-/
|
||||
@[inline, expose]
|
||||
@[inline]
|
||||
def any (as : Array α) (p : α → Bool) (start := 0) (stop := as.size) : Bool :=
|
||||
Id.run <| as.anyM (pure <| p ·) start stop
|
||||
Id.run <| as.anyM p start stop
|
||||
|
||||
/--
|
||||
Returns `true` if `p` returns `true` for every element of `as`.
|
||||
@@ -1398,7 +1401,7 @@ Examples:
|
||||
-/
|
||||
@[inline]
|
||||
def all (as : Array α) (p : α → Bool) (start := 0) (stop := as.size) : Bool :=
|
||||
Id.run <| as.allM (pure <| p ·) start stop
|
||||
Id.run <| as.allM p start stop
|
||||
|
||||
/--
|
||||
Checks whether `a` is an element of `as`, using `==` to compare elements.
|
||||
@@ -1409,7 +1412,6 @@ Examples:
|
||||
* `#[1, 4, 2, 3, 3, 7].contains 3 = true`
|
||||
* `Array.contains #[1, 4, 2, 3, 3, 7] 5 = false`
|
||||
-/
|
||||
@[expose]
|
||||
def contains [BEq α] (as : Array α) (a : α) : Bool :=
|
||||
as.any (a == ·)
|
||||
|
||||
@@ -1458,7 +1460,6 @@ Examples:
|
||||
* `#[] ++ #[4, 5] = #[4, 5]`.
|
||||
* `#[1, 2, 3] ++ #[] = #[1, 2, 3]`.
|
||||
-/
|
||||
@[expose]
|
||||
protected def append (as : Array α) (bs : Array α) : Array α :=
|
||||
bs.foldl (init := as) fun xs v => xs.push v
|
||||
|
||||
@@ -1496,7 +1497,7 @@ Examples:
|
||||
* `#[2, 3, 2].flatMap Array.range = #[0, 1, 0, 1, 2, 0, 1]`
|
||||
* `#[['a', 'b'], ['c', 'd', 'e']].flatMap List.toArray = #['a', 'b', 'c', 'd', 'e']`
|
||||
-/
|
||||
@[inline, expose]
|
||||
@[inline]
|
||||
def flatMap (f : α → Array β) (as : Array α) : Array β :=
|
||||
as.foldl (init := empty) fun bs a => bs ++ f a
|
||||
|
||||
@@ -1509,7 +1510,7 @@ Examples:
|
||||
* `#[#[0, 1], #[], #[2], #[1, 0, 1]].flatten = #[0, 1, 2, 1, 0, 1]`
|
||||
* `(#[] : Array Nat).flatten = #[]`
|
||||
-/
|
||||
@[inline, expose] def flatten (xss : Array (Array α)) : Array α :=
|
||||
@[inline] def flatten (xss : Array (Array α)) : Array α :=
|
||||
xss.foldl (init := empty) fun acc xs => acc ++ xs
|
||||
|
||||
/--
|
||||
@@ -1522,7 +1523,6 @@ Examples:
|
||||
* `#[0, 1].reverse = #[1, 0]`
|
||||
* `#[0, 1, 2].reverse = #[2, 1, 0]`
|
||||
-/
|
||||
@[expose]
|
||||
def reverse (as : Array α) : Array α :=
|
||||
if h : as.size ≤ 1 then
|
||||
as
|
||||
@@ -1555,7 +1555,7 @@ Examples:
|
||||
* `#[1, 2, 5, 2, 7, 7].filter (fun _ => true) (start := 3) = #[2, 7, 7]`
|
||||
* `#[1, 2, 5, 2, 7, 7].filter (fun _ => true) (stop := 3) = #[1, 2, 5]`
|
||||
-/
|
||||
@[inline, expose]
|
||||
@[inline]
|
||||
def filter (p : α → Bool) (as : Array α) (start := 0) (stop := as.size) : Array α :=
|
||||
as.foldl (init := #[]) (start := start) (stop := stop) fun acc a =>
|
||||
if p a then acc.push a else acc
|
||||
@@ -1648,7 +1648,7 @@ Examining 7
|
||||
#[10, 14, 14]
|
||||
```
|
||||
-/
|
||||
@[specialize, expose]
|
||||
@[specialize]
|
||||
def filterMapM [Monad m] (f : α → m (Option β)) (as : Array α) (start := 0) (stop := as.size) : m (Array β) :=
|
||||
as.foldlM (init := #[]) (start := start) (stop := stop) fun bs a => do
|
||||
match (← f a) with
|
||||
@@ -1668,9 +1668,9 @@ Example:
|
||||
#[10, 14, 14]
|
||||
```
|
||||
-/
|
||||
@[inline, expose]
|
||||
@[inline]
|
||||
def filterMap (f : α → Option β) (as : Array α) (start := 0) (stop := as.size) : Array β :=
|
||||
Id.run <| as.filterMapM (pure <| f ·) (start := start) (stop := stop)
|
||||
Id.run <| as.filterMapM f (start := start) (stop := stop)
|
||||
|
||||
/--
|
||||
Returns the largest element of the array, as determined by the comparison `lt`, or `none` if
|
||||
@@ -1881,6 +1881,8 @@ Examples:
|
||||
let as := as.push a
|
||||
loop as ⟨j, size_push .. ▸ j.lt_succ_self⟩
|
||||
|
||||
@[deprecated insertIdx (since := "2024-11-20")] abbrev insertAt := @insertIdx
|
||||
|
||||
/--
|
||||
Inserts an element into an array at the specified index. Panics if the index is greater than the
|
||||
size of the array.
|
||||
@@ -1901,6 +1903,8 @@ def insertIdx! (as : Array α) (i : Nat) (a : α) : Array α :=
|
||||
insertIdx as i a
|
||||
else panic! "invalid index"
|
||||
|
||||
@[deprecated insertIdx! (since := "2024-11-20")] abbrev insertAt! := @insertIdx!
|
||||
|
||||
/--
|
||||
Inserts an element into an array at the specified index. The array is returned unmodified if the
|
||||
index is greater than the size of the array.
|
||||
@@ -2023,6 +2027,11 @@ Examples:
|
||||
def unzip (as : Array (α × β)) : Array α × Array β :=
|
||||
as.foldl (init := (#[], #[])) fun (as, bs) (a, b) => (as.push a, bs.push b)
|
||||
|
||||
@[deprecated partition (since := "2024-11-06")]
|
||||
def split (as : Array α) (p : α → Bool) : Array α × Array α :=
|
||||
as.foldl (init := (#[], #[])) fun (as, bs) a =>
|
||||
if p a then (as.push a, bs) else (as, bs.push a)
|
||||
|
||||
/--
|
||||
Replaces the first occurrence of `a` with `b` in an array. The modification is performed in-place
|
||||
when the reference to the array is unique. Returns the array unmodified when `a` is not present.
|
||||
|
||||
@@ -88,4 +88,4 @@ pointer equality, and does not allocate a new array if the result of each functi
|
||||
pointer-equal to its argument.
|
||||
-/
|
||||
@[inline] def Array.mapMono (as : Array α) (f : α → α) : Array α :=
|
||||
Id.run <| as.mapMonoM (pure <| f ·)
|
||||
Id.run <| as.mapMonoM f
|
||||
|
||||
@@ -129,6 +129,6 @@ Examples:
|
||||
* `#[].binInsert (· < ·) 1 = #[1]`
|
||||
-/
|
||||
@[inline] def binInsert {α : Type u} (lt : α → α → Bool) (as : Array α) (k : α) : Array α :=
|
||||
Id.run <| binInsertM lt (fun _ => pure k) (fun _ => pure k) as k
|
||||
Id.run <| binInsertM lt (fun _ => k) (fun _ => k) as k
|
||||
|
||||
end Array
|
||||
|
||||
@@ -40,7 +40,7 @@ Use the indexing notation `a[i]!` instead.
|
||||
|
||||
Access an element from an array, or panic if the index is out of bounds.
|
||||
-/
|
||||
@[deprecated "Use indexing notation `as[i]!` instead" (since := "2025-02-17"), expose]
|
||||
@[deprecated "Use indexing notation `as[i]!` instead" (since := "2025-02-17")]
|
||||
def get! {α : Type u} [Inhabited α] (a : @& Array α) (i : @& Nat) : α :=
|
||||
Array.getD a i default
|
||||
|
||||
@@ -78,8 +78,7 @@ theorem foldrM_eq_reverse_foldlM_toList [Monad m] {f : α → β → m β} {init
|
||||
have : xs = #[] ∨ 0 < xs.size :=
|
||||
match xs with | ⟨[]⟩ => .inl rfl | ⟨a::l⟩ => .inr (Nat.zero_lt_succ _)
|
||||
match xs, this with | _, .inl rfl => simp [foldrM] | xs, .inr h => ?_
|
||||
simp only [foldrM, h, ← foldrM_eq_reverse_foldlM_toList.aux]
|
||||
simp [Array.size]
|
||||
simp [foldrM, h, ← foldrM_eq_reverse_foldlM_toList.aux, List.take_length]
|
||||
|
||||
@[simp, grind =] theorem foldrM_toList [Monad m]
|
||||
{f : α → β → m β} {init : β} {xs : Array α} :
|
||||
@@ -90,13 +89,9 @@ theorem foldrM_eq_reverse_foldlM_toList [Monad m] {f : α → β → m β} {init
|
||||
xs.toList.foldr f init = xs.foldr f init :=
|
||||
List.foldr_eq_foldrM .. ▸ foldrM_toList ..
|
||||
|
||||
@[simp, grind =] theorem toList_push {xs : Array α} {x : α} : (xs.push x).toList = xs.toList ++ [x] := by
|
||||
rcases xs with ⟨xs⟩
|
||||
@[simp, grind =] theorem push_toList {xs : Array α} {a : α} : (xs.push a).toList = xs.toList ++ [a] := by
|
||||
simp [push, List.concat_eq_append]
|
||||
|
||||
@[deprecated toList_push (since := "2025-05-26")]
|
||||
abbrev push_toList := @toList_push
|
||||
|
||||
@[simp, grind =] theorem toListAppend_eq {xs : Array α} {l : List α} : xs.toListAppend l = xs.toList ++ l := by
|
||||
simp [toListAppend, ← foldr_toList]
|
||||
|
||||
@@ -143,4 +138,26 @@ abbrev nil_append := @empty_append
|
||||
@[deprecated toList_appendList (since := "2024-12-11")]
|
||||
abbrev appendList_toList := @toList_appendList
|
||||
|
||||
@[deprecated "Use the reverse direction of `foldrM_toList`." (since := "2024-11-13")]
|
||||
theorem foldrM_eq_foldrM_toList [Monad m]
|
||||
{f : α → β → m β} {init : β} {xs : Array α} :
|
||||
xs.foldrM f init = xs.toList.foldrM f init := by
|
||||
simp
|
||||
|
||||
@[deprecated "Use the reverse direction of `foldlM_toList`." (since := "2024-11-13")]
|
||||
theorem foldlM_eq_foldlM_toList [Monad m]
|
||||
{f : β → α → m β} {init : β} {xs : Array α} :
|
||||
xs.foldlM f init = xs.toList.foldlM f init:= by
|
||||
simp
|
||||
|
||||
@[deprecated "Use the reverse direction of `foldr_toList`." (since := "2024-11-13")]
|
||||
theorem foldr_eq_foldr_toList {f : α → β → β} {init : β} {xs : Array α} :
|
||||
xs.foldr f init = xs.toList.foldr f init := by
|
||||
simp
|
||||
|
||||
@[deprecated "Use the reverse direction of `foldl_toList`." (since := "2024-11-13")]
|
||||
theorem foldl_eq_foldl_toList {f : β → α → β} {init : β} {xs : Array α} :
|
||||
xs.foldl f init = xs.toList.foldl f init:= by
|
||||
simp
|
||||
|
||||
end Array
|
||||
|
||||
@@ -52,8 +52,8 @@ theorem countP_push {a : α} {xs : Array α} : countP p (xs.push a) = countP p x
|
||||
rcases xs with ⟨xs⟩
|
||||
simp_all
|
||||
|
||||
theorem countP_singleton {a : α} : countP p #[a] = if p a then 1 else 0 := by
|
||||
simp
|
||||
@[simp] theorem countP_singleton {a : α} : countP p #[a] = if p a then 1 else 0 := by
|
||||
simp [countP_push]
|
||||
|
||||
theorem size_eq_countP_add_countP {xs : Array α} : xs.size = countP p xs + countP (fun a => ¬p a) xs := by
|
||||
rcases xs with ⟨xs⟩
|
||||
@@ -105,7 +105,6 @@ theorem boole_getElem_le_countP {xs : Array α} {i : Nat} (h : i < xs.size) :
|
||||
theorem countP_set {xs : Array α} {i : Nat} {a : α} (h : i < xs.size) :
|
||||
(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⟩
|
||||
simp at h
|
||||
simp [List.countP_set, h]
|
||||
|
||||
theorem countP_filter {xs : Array α} :
|
||||
|
||||
@@ -69,7 +69,7 @@ theorem isEqv_eq_decide (xs ys : Array α) (r) :
|
||||
simpa [isEqv_iff_rel] using h'
|
||||
|
||||
@[simp, grind =] theorem isEqv_toList [BEq α] (xs ys : Array α) : (xs.toList.isEqv ys.toList r) = (xs.isEqv ys r) := by
|
||||
simp [isEqv_eq_decide, List.isEqv_eq_decide, Array.size]
|
||||
simp [isEqv_eq_decide, List.isEqv_eq_decide]
|
||||
|
||||
theorem eq_of_isEqv [DecidableEq α] (xs ys : Array α) (h : Array.isEqv xs ys (fun x y => x = y)) : xs = ys := by
|
||||
have ⟨h, h'⟩ := rel_of_isEqv h
|
||||
@@ -100,7 +100,7 @@ theorem beq_eq_decide [BEq α] (xs ys : Array α) :
|
||||
simp [BEq.beq, isEqv_eq_decide]
|
||||
|
||||
@[simp, grind =] theorem beq_toList [BEq α] (xs ys : Array α) : (xs.toList == ys.toList) = (xs == ys) := by
|
||||
simp [beq_eq_decide, List.beq_eq_decide, Array.size]
|
||||
simp [beq_eq_decide, List.beq_eq_decide]
|
||||
|
||||
end Array
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ open Nat
|
||||
|
||||
/-! ### eraseP -/
|
||||
|
||||
theorem eraseP_empty : #[].eraseP p = #[] := by simp
|
||||
@[simp] theorem eraseP_empty : #[].eraseP p = #[] := by simp
|
||||
|
||||
theorem eraseP_of_forall_mem_not {xs : Array α} (h : ∀ a, a ∈ xs → ¬p a) : xs.eraseP p = xs := by
|
||||
rcases xs with ⟨xs⟩
|
||||
|
||||
@@ -238,9 +238,11 @@ theorem extract_append_left {as bs : Array α} :
|
||||
(as ++ bs).extract 0 as.size = as.extract 0 as.size := by
|
||||
simp
|
||||
|
||||
theorem extract_append_right {as bs : Array α} :
|
||||
@[simp] theorem extract_append_right {as bs : Array α} :
|
||||
(as ++ bs).extract as.size (as.size + i) = bs.extract 0 i := by
|
||||
simp
|
||||
simp only [extract_append, extract_size_left, Nat.sub_self, empty_append]
|
||||
congr 1
|
||||
omega
|
||||
|
||||
@[simp] theorem map_extract {as : Array α} {i j : Nat} :
|
||||
(as.extract i j).map f = (as.map f).extract i j := by
|
||||
|
||||
@@ -142,9 +142,9 @@ abbrev findSome?_mkArray_of_isNone := @findSome?_replicate_of_isNone
|
||||
|
||||
@[simp] theorem find?_empty : find? p #[] = none := rfl
|
||||
|
||||
theorem find?_singleton {a : α} {p : α → Bool} :
|
||||
@[simp] theorem find?_singleton {a : α} {p : α → Bool} :
|
||||
#[a].find? p = if p a then some a else none := by
|
||||
simp
|
||||
simp [singleton_eq_toArray_singleton]
|
||||
|
||||
@[simp] theorem findRev?_push_of_pos {xs : Array α} (h : p a) :
|
||||
findRev? p (xs.push a) = some a := by
|
||||
@@ -347,8 +347,7 @@ theorem find?_eq_some_iff_getElem {xs : Array α} {p : α → Bool} {b : α} :
|
||||
|
||||
/-! ### findIdx -/
|
||||
|
||||
theorem findIdx_empty : findIdx p #[] = 0 := rfl
|
||||
|
||||
@[simp] theorem findIdx_empty : findIdx p #[] = 0 := rfl
|
||||
theorem findIdx_singleton {a : α} {p : α → Bool} :
|
||||
#[a].findIdx p = if p a then 0 else 1 := by
|
||||
simp
|
||||
@@ -601,8 +600,7 @@ theorem findIdx?_eq_some_le_of_findIdx?_eq_some {xs : Array α} {p q : α → Bo
|
||||
|
||||
/-! ### findFinIdx? -/
|
||||
|
||||
theorem findFinIdx?_empty {p : α → Bool} : findFinIdx? p #[] = none := by simp
|
||||
|
||||
@[simp] theorem findFinIdx?_empty {p : α → Bool} : findFinIdx? p #[] = none := by simp
|
||||
theorem findFinIdx?_singleton {a : α} {p : α → Bool} :
|
||||
#[a].findFinIdx? p = if p a then some ⟨0, by simp⟩ else none := by
|
||||
simp
|
||||
@@ -655,13 +653,13 @@ theorem findFinIdx?_append {xs ys : Array α} {p : α → Bool} :
|
||||
theorem isSome_findFinIdx? {xs : Array α} {p : α → Bool} :
|
||||
(xs.findFinIdx? p).isSome = xs.any p := by
|
||||
rcases xs with ⟨xs⟩
|
||||
simp [Array.size]
|
||||
simp
|
||||
|
||||
@[simp]
|
||||
theorem isNone_findFinIdx? {xs : Array α} {p : α → Bool} :
|
||||
(xs.findFinIdx? p).isNone = xs.all (fun x => ¬ p x) := by
|
||||
rcases xs with ⟨xs⟩
|
||||
simp [Array.size]
|
||||
simp
|
||||
|
||||
@[simp] theorem findFinIdx?_subtype {p : α → Prop} {xs : Array { x // p x }}
|
||||
{f : { x // p x } → Bool} {g : α → Bool} (hf : ∀ x h, f ⟨x, h⟩ = g x) :
|
||||
@@ -669,8 +667,7 @@ theorem isNone_findFinIdx? {xs : Array α} {p : α → Bool} :
|
||||
cases xs
|
||||
simp only [List.findFinIdx?_toArray, hf, List.findFinIdx?_subtype]
|
||||
rw [findFinIdx?_congr List.unattach_toArray]
|
||||
simp only [Option.map_map, Function.comp_def, Fin.cast_trans]
|
||||
simp [Array.size]
|
||||
simp [Function.comp_def]
|
||||
|
||||
/-! ### idxOf
|
||||
|
||||
@@ -702,7 +699,7 @@ The verification API for `idxOf?` is still incomplete.
|
||||
The lemmas below should be made consistent with those for `findIdx?` (and proved using them).
|
||||
-/
|
||||
|
||||
theorem idxOf?_empty [BEq α] : (#[] : Array α).idxOf? a = none := by simp
|
||||
@[simp] theorem idxOf?_empty [BEq α] : (#[] : Array α).idxOf? a = none := by simp
|
||||
|
||||
@[simp] theorem idxOf?_eq_none_iff [BEq α] [LawfulBEq α] {xs : Array α} {a : α} :
|
||||
xs.idxOf? a = none ↔ a ∉ xs := by
|
||||
@@ -715,10 +712,14 @@ theorem isSome_idxOf? [BEq α] [LawfulBEq α] {xs : Array α} {a : α} :
|
||||
rcases xs with ⟨xs⟩
|
||||
simp
|
||||
|
||||
@[simp]
|
||||
theorem isNone_idxOf? [BEq α] [LawfulBEq α] {xs : Array α} {a : α} :
|
||||
(xs.idxOf? a).isNone = ¬ a ∈ xs := by
|
||||
rcases xs with ⟨xs⟩
|
||||
simp
|
||||
|
||||
|
||||
|
||||
/-! ### finIdxOf?
|
||||
|
||||
The verification API for `finIdxOf?` is still incomplete.
|
||||
@@ -729,27 +730,28 @@ 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]
|
||||
|
||||
theorem finIdxOf?_empty [BEq α] : (#[] : Array α).finIdxOf? a = none := by simp
|
||||
@[simp] theorem finIdxOf?_empty [BEq α] : (#[] : Array α).finIdxOf? a = none := by simp
|
||||
|
||||
@[simp] theorem finIdxOf?_eq_none_iff [BEq α] [LawfulBEq α] {xs : Array α} {a : α} :
|
||||
xs.finIdxOf? a = none ↔ a ∉ xs := by
|
||||
rcases xs with ⟨xs⟩
|
||||
simp [List.finIdxOf?_eq_none_iff, Array.size]
|
||||
simp [List.finIdxOf?_eq_none_iff]
|
||||
|
||||
@[simp] theorem finIdxOf?_eq_some_iff [BEq α] [LawfulBEq α] {xs : Array α} {a : α} {i : Fin xs.size} :
|
||||
xs.finIdxOf? a = some i ↔ xs[i] = a ∧ ∀ j (_ : j < i), ¬xs[j] = a := by
|
||||
rcases xs with ⟨xs⟩
|
||||
unfold Array.size at i ⊢
|
||||
simp [List.finIdxOf?_eq_some_iff]
|
||||
|
||||
@[simp]
|
||||
theorem isSome_finIdxOf? [BEq α] [LawfulBEq α] {xs : Array α} {a : α} :
|
||||
(xs.finIdxOf? a).isSome ↔ a ∈ xs := by
|
||||
rcases xs with ⟨xs⟩
|
||||
simp [Array.size]
|
||||
simp
|
||||
|
||||
@[simp]
|
||||
theorem isNone_finIdxOf? [BEq α] [LawfulBEq α] {xs : Array α} {a : α} :
|
||||
(xs.finIdxOf? a).isNone = ¬ a ∈ xs := by
|
||||
rcases xs with ⟨xs⟩
|
||||
simp
|
||||
|
||||
end Array
|
||||
|
||||
@@ -44,7 +44,6 @@ theorem insertIdx_zero {xs : Array α} {x : α} : xs.insertIdx 0 x = #[x] ++ xs
|
||||
|
||||
@[simp] theorem size_insertIdx {xs : Array α} (h : i ≤ xs.size) : (xs.insertIdx i a).size = xs.size + 1 := by
|
||||
rcases xs with ⟨xs⟩
|
||||
simp at h
|
||||
simp [List.length_insertIdx, h]
|
||||
|
||||
theorem eraseIdx_insertIdx {i : Nat} {xs : Array α} (h : i ≤ xs.size) :
|
||||
|
||||
@@ -75,7 +75,8 @@ theorem ne_empty_of_size_pos (h : 0 < xs.size) : xs ≠ #[] := by
|
||||
cases xs
|
||||
simpa using List.ne_nil_of_length_pos h
|
||||
|
||||
@[simp] theorem size_eq_zero_iff : xs.size = 0 ↔ xs = #[] :=
|
||||
@[grind]
|
||||
theorem size_eq_zero_iff : xs.size = 0 ↔ xs = #[] :=
|
||||
⟨eq_empty_of_size_eq_zero, fun h => h ▸ rfl⟩
|
||||
|
||||
@[deprecated size_eq_zero_iff (since := "2025-02-24")]
|
||||
@@ -116,11 +117,14 @@ abbrev size_eq_one := @size_eq_one_iff
|
||||
|
||||
/-! ## L[i] and L[i]? -/
|
||||
|
||||
theorem getElem?_eq_none_iff {xs : Array α} : xs[i]? = none ↔ xs.size ≤ i := by
|
||||
simp
|
||||
@[simp] theorem getElem?_eq_none_iff {xs : Array α} : xs[i]? = none ↔ xs.size ≤ i := by
|
||||
by_cases h : i < xs.size
|
||||
· simp [getElem?_pos, h]
|
||||
· rw [getElem?_neg xs i h]
|
||||
simp_all
|
||||
|
||||
theorem none_eq_getElem?_iff {xs : Array α} {i : Nat} : none = xs[i]? ↔ xs.size ≤ i := by
|
||||
simp
|
||||
@[simp] theorem none_eq_getElem?_iff {xs : Array α} {i : Nat} : none = xs[i]? ↔ xs.size ≤ i := by
|
||||
simp [eq_comm (a := none)]
|
||||
|
||||
theorem getElem?_eq_none {xs : Array α} (h : xs.size ≤ i) : xs[i]? = none := by
|
||||
simp [getElem?_eq_none_iff, h]
|
||||
@@ -130,8 +134,8 @@ grind_pattern Array.getElem?_eq_none => xs.size ≤ i, xs[i]?
|
||||
@[simp] theorem getElem?_eq_getElem {xs : Array α} {i : Nat} (h : i < xs.size) : xs[i]? = some xs[i] :=
|
||||
getElem?_pos ..
|
||||
|
||||
theorem getElem?_eq_some_iff {xs : Array α} : xs[i]? = some b ↔ ∃ h : i < xs.size, xs[i] = b :=
|
||||
_root_.getElem?_eq_some_iff
|
||||
theorem getElem?_eq_some_iff {xs : Array α} : xs[i]? = some b ↔ ∃ h : i < xs.size, xs[i] = b := by
|
||||
simp [getElem?_def]
|
||||
|
||||
@[grind →]
|
||||
theorem getElem_of_getElem? {xs : Array α} : xs[i]? = some a → ∃ h : i < xs.size, xs[i] = a :=
|
||||
@@ -140,13 +144,13 @@ theorem getElem_of_getElem? {xs : Array α} : xs[i]? = some a → ∃ h : i < xs
|
||||
theorem some_eq_getElem?_iff {xs : Array α} : some b = xs[i]? ↔ ∃ h : i < xs.size, xs[i] = b := by
|
||||
rw [eq_comm, getElem?_eq_some_iff]
|
||||
|
||||
theorem some_getElem_eq_getElem?_iff (xs : Array α) (i : Nat) (h : i < xs.size) :
|
||||
@[simp] theorem some_getElem_eq_getElem?_iff (xs : Array α) (i : Nat) (h : i < xs.size) :
|
||||
(some xs[i] = xs[i]?) ↔ True := by
|
||||
simp
|
||||
simp [h]
|
||||
|
||||
theorem getElem?_eq_some_getElem_iff (xs : Array α) (i : Nat) (h : i < xs.size) :
|
||||
@[simp] theorem getElem?_eq_some_getElem_iff (xs : Array α) (i : Nat) (h : i < xs.size) :
|
||||
(xs[i]? = some xs[i]) ↔ True := by
|
||||
simp
|
||||
simp [h]
|
||||
|
||||
theorem getElem_eq_iff {xs : Array α} {i : Nat} {h : i < xs.size} : xs[i] = x ↔ xs[i]? = some x := by
|
||||
simp only [getElem?_eq_some_iff]
|
||||
@@ -169,7 +173,6 @@ theorem getD_getElem? {xs : Array α} {i : Nat} {d : α} :
|
||||
theorem getElem_push_lt {xs : Array α} {x : α} {i : Nat} (h : i < xs.size) :
|
||||
have : i < (xs.push x).size := by simp [*, Nat.lt_succ_of_le, Nat.le_of_lt]
|
||||
(xs.push x)[i] = xs[i] := by
|
||||
rw [Array.size] at h
|
||||
simp only [push, ← getElem_toList, List.concat_eq_append, List.getElem_append_left, h]
|
||||
|
||||
@[simp] theorem getElem_push_eq {xs : Array α} {x : α} : (xs.push x)[xs.size] = x := by
|
||||
@@ -183,15 +186,16 @@ theorem getElem_push {xs : Array α} {x : α} {i : Nat} (h : i < (xs.push x).siz
|
||||
· simp at h
|
||||
simp [getElem_push_lt, 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
|
||||
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]
|
||||
(repeat' split) <;> first | rfl | omega
|
||||
|
||||
theorem getElem?_push_size {xs : Array α} {x} : (xs.push x)[xs.size]? = some x := by
|
||||
simp
|
||||
@[simp] theorem getElem?_push_size {xs : Array α} {x} : (xs.push x)[xs.size]? = some x := by
|
||||
simp [getElem?_push]
|
||||
|
||||
theorem getElem_singleton {a : α} {i : Nat} (h : i < 1) : #[a][i] = a := by
|
||||
simp
|
||||
@[simp] theorem getElem_singleton {a : α} {i : Nat} (h : i < 1) : #[a][i] = a :=
|
||||
match i, h with
|
||||
| 0, _ => rfl
|
||||
|
||||
@[grind]
|
||||
theorem getElem?_singleton {a : α} {i : Nat} : #[a][i]? = if i = 0 then some a else none := by
|
||||
@@ -240,6 +244,10 @@ theorem back?_pop {xs : Array α} :
|
||||
|
||||
@[simp] theorem push_empty : #[].push x = #[x] := rfl
|
||||
|
||||
@[simp] theorem toList_push {xs : Array α} {x : α} : (xs.push x).toList = xs.toList ++ [x] := by
|
||||
rcases xs with ⟨xs⟩
|
||||
simp
|
||||
|
||||
@[simp] theorem push_ne_empty {a : α} {xs : Array α} : xs.push a ≠ #[] := by
|
||||
cases xs
|
||||
simp
|
||||
@@ -419,7 +427,8 @@ theorem eq_empty_iff_forall_not_mem {xs : Array α} : xs = #[] ↔ ∀ a, a ∉
|
||||
theorem eq_of_mem_singleton (h : a ∈ #[b]) : a = b := by
|
||||
simpa using h
|
||||
|
||||
theorem mem_singleton {a b : α} : a ∈ #[b] ↔ a = b := by simp
|
||||
@[simp] theorem mem_singleton {a b : α} : a ∈ #[b] ↔ a = b :=
|
||||
⟨eq_of_mem_singleton, (by simp [·])⟩
|
||||
|
||||
theorem forall_mem_push {p : α → Prop} {xs : Array α} {a : α} :
|
||||
(∀ x, x ∈ xs.push a → p x) ↔ p a ∧ ∀ x, x ∈ xs → p x := by
|
||||
@@ -604,13 +613,13 @@ theorem anyM_loop_cons [Monad m] {p : α → m Bool} {a : α} {as : List α} {st
|
||||
|
||||
-- Auxiliary for `any_iff_exists`.
|
||||
theorem anyM_loop_iff_exists {p : α → Bool} {as : Array α} {start stop} (h : stop ≤ as.size) :
|
||||
(anyM.loop (m := Id) (pure <| p ·) as stop h start).run = true ↔
|
||||
anyM.loop (m := Id) p as stop h start = true ↔
|
||||
∃ (i : Nat) (_ : i < as.size), start ≤ i ∧ i < stop ∧ p as[i] = true := by
|
||||
unfold anyM.loop
|
||||
split <;> rename_i h₁
|
||||
· dsimp
|
||||
split <;> rename_i h₂
|
||||
· simp only [true_iff, Id.run_pure]
|
||||
· simp only [true_iff]
|
||||
refine ⟨start, by omega, by omega, by omega, h₂⟩
|
||||
· rw [anyM_loop_iff_exists]
|
||||
constructor
|
||||
@@ -627,9 +636,9 @@ termination_by stop - start
|
||||
-- This could also be proved from `SatisfiesM_anyM_iff_exists` in `Batteries.Data.Array.Init.Monadic`
|
||||
theorem any_iff_exists {p : α → Bool} {as : Array α} {start stop} :
|
||||
as.any p start stop ↔ ∃ (i : Nat) (_ : i < as.size), start ≤ i ∧ i < stop ∧ p as[i] := by
|
||||
dsimp [any, anyM]
|
||||
dsimp [any, anyM, Id.run]
|
||||
split
|
||||
· rw [anyM_loop_iff_exists (p := p)]
|
||||
· rw [anyM_loop_iff_exists]
|
||||
· rw [anyM_loop_iff_exists]
|
||||
constructor
|
||||
· rintro ⟨i, hi, ge, _, h⟩
|
||||
@@ -863,8 +872,8 @@ theorem elem_eq_mem [BEq α] [LawfulBEq α] {a : α} {xs : Array α} :
|
||||
@[simp, grind] theorem contains_eq_mem [BEq α] [LawfulBEq α] {a : α} {xs : Array α} :
|
||||
xs.contains a = decide (a ∈ xs) := by rw [← elem_eq_contains, elem_eq_mem]
|
||||
|
||||
@[grind] theorem any_empty [BEq α] {p : α → Bool} : (#[] : Array α).any p = false := by simp
|
||||
@[grind] theorem all_empty [BEq α] {p : α → Bool} : (#[] : Array α).all p = true := by simp
|
||||
@[simp, grind] theorem any_empty [BEq α] {p : α → Bool} : (#[] : Array α).any p = false := by simp
|
||||
@[simp, grind] theorem all_empty [BEq α] {p : α → Bool} : (#[] : Array α).all p = true := by simp
|
||||
|
||||
/-- Variant of `any_push` with a side condition on `stop`. -/
|
||||
@[simp, grind] theorem any_push' [BEq α] {xs : Array α} {a : α} {p : α → Bool} (h : stop = xs.size + 1) :
|
||||
@@ -1223,7 +1232,7 @@ where
|
||||
@[simp] theorem mapM_empty [Monad m] (f : α → m β) : mapM f #[] = pure #[] := by
|
||||
rw [mapM, mapM.map]; rfl
|
||||
|
||||
@[grind] theorem map_empty {f : α → β} : map f #[] = #[] := by simp
|
||||
@[simp, grind] theorem map_empty {f : α → β} : map f #[] = #[] := mapM_empty f
|
||||
|
||||
@[simp, grind] theorem map_push {f : α → β} {as : Array α} {x : α} :
|
||||
(as.push x).map f = (as.map f).push (f x) := by
|
||||
@@ -1361,17 +1370,17 @@ theorem mapM_eq_mapM_toList [Monad m] [LawfulMonad m] {f : α → m β} {xs : Ar
|
||||
|
||||
@[deprecated "Use `mapM_eq_foldlM` instead" (since := "2025-01-08")]
|
||||
theorem mapM_map_eq_foldl {as : Array α} {f : α → β} {i : Nat} :
|
||||
mapM.map (m := Id) (pure <| f ·) as i b = pure (as.foldl (start := i) (fun acc a => acc.push (f a)) b) := by
|
||||
mapM.map (m := Id) f as i b = as.foldl (start := i) (fun acc a => acc.push (f a)) b := by
|
||||
unfold mapM.map
|
||||
split <;> rename_i h
|
||||
· ext : 1
|
||||
dsimp [foldl, foldlM]
|
||||
· simp only [Id.bind_eq]
|
||||
dsimp [foldl, Id.run, foldlM]
|
||||
rw [mapM_map_eq_foldl, dif_pos (by omega), foldlM.loop, dif_pos h]
|
||||
-- Calling `split` here gives a bad goal.
|
||||
have : size as - i = Nat.succ (size as - i - 1) := by omega
|
||||
rw [this]
|
||||
simp [foldl, foldlM, Nat.sub_add_eq]
|
||||
· dsimp [foldl, foldlM]
|
||||
simp [foldl, foldlM, Id.run, Nat.sub_add_eq]
|
||||
· dsimp [foldl, Id.run, foldlM]
|
||||
rw [dif_pos (by omega), foldlM.loop, dif_neg h]
|
||||
rfl
|
||||
termination_by as.size - i
|
||||
@@ -1593,8 +1602,8 @@ theorem filterMap_congr {as bs : Array α} (h : as = bs)
|
||||
as.toList ++ List.filterMap f xs := ?_
|
||||
exact this #[]
|
||||
induction xs
|
||||
· simp_all
|
||||
· simp_all [List.filterMap_cons]
|
||||
· simp_all [Id.run]
|
||||
· simp_all [Id.run, List.filterMap_cons]
|
||||
split <;> simp_all
|
||||
|
||||
@[grind] theorem toList_filterMap {f : α → Option β} {xs : Array α} :
|
||||
@@ -1808,8 +1817,7 @@ theorem toArray_append {xs : List α} {ys : Array α} :
|
||||
|
||||
theorem singleton_eq_toArray_singleton {a : α} : #[a] = [a].toArray := rfl
|
||||
|
||||
@[deprecated empty_append (since := "2025-05-26")]
|
||||
theorem empty_append_fun : ((#[] : Array α) ++ ·) = id := by
|
||||
@[simp] theorem empty_append_fun : ((#[] : Array α) ++ ·) = id := by
|
||||
funext ⟨l⟩
|
||||
simp
|
||||
|
||||
@@ -1859,7 +1867,7 @@ theorem getElem_append_right {xs ys : Array α} {h : i < (xs ++ ys).size} (hle :
|
||||
(xs ++ ys)[i] = ys[i - xs.size]'(Nat.sub_lt_left_of_lt_add hle (size_append .. ▸ h)) := by
|
||||
simp only [← getElem_toList]
|
||||
have h' : i < (xs.toList ++ ys.toList).length := by rwa [← length_toList, toList_append] at h
|
||||
conv => rhs; unfold Array.size; rw [← List.getElem_append_right (h₁ := hle) (h₂ := h')]
|
||||
conv => rhs; rw [← List.getElem_append_right (h₁ := hle) (h₂ := h')]
|
||||
apply List.get_of_eq; rw [toList_append]
|
||||
|
||||
theorem getElem?_append_left {xs ys : Array α} {i : Nat} (hn : i < xs.size) :
|
||||
@@ -1960,8 +1968,8 @@ theorem append_left_inj {xs₁ xs₂ : Array α} (ys) : xs₁ ++ ys = xs₂ ++ y
|
||||
theorem eq_empty_of_append_eq_empty {xs ys : Array α} (h : xs ++ ys = #[]) : xs = #[] ∧ ys = #[] :=
|
||||
append_eq_empty_iff.mp h
|
||||
|
||||
theorem empty_eq_append_iff {xs ys : Array α} : #[] = xs ++ ys ↔ xs = #[] ∧ ys = #[] := by
|
||||
simp
|
||||
@[simp] theorem empty_eq_append_iff {xs ys : Array α} : #[] = xs ++ ys ↔ xs = #[] ∧ ys = #[] := by
|
||||
rw [eq_comm, append_eq_empty_iff]
|
||||
|
||||
theorem append_ne_empty_of_left_ne_empty {xs ys : Array α} (h : xs ≠ #[]) : xs ++ ys ≠ #[] := by
|
||||
simp_all
|
||||
@@ -2026,10 +2034,10 @@ theorem append_eq_append_iff {ws xs ys zs : Array α} :
|
||||
xs ++ ys.set (i - xs.size) x (by simp at h; omega) := by
|
||||
rcases xs with ⟨s⟩
|
||||
rcases ys with ⟨t⟩
|
||||
simp only [List.append_toArray, List.set_toArray, List.set_append, Array.size]
|
||||
simp only [List.append_toArray, List.set_toArray, List.set_append]
|
||||
split <;> simp
|
||||
|
||||
@[simp] theorem set_append_left {xs ys : Array α} {i : Nat} {x : α} (h : i < xs.size) :
|
||||
@[simp] theorem set_append_left {xs ys : Array α} {i : Nat} {x : α} (h : i < xs.size) :
|
||||
(xs ++ ys).set i x (by simp; omega) = xs.set i x ++ ys := by
|
||||
simp [set_append, h]
|
||||
|
||||
@@ -2046,7 +2054,7 @@ theorem append_eq_append_iff {ws xs ys zs : Array α} :
|
||||
xs ++ ys.setIfInBounds (i - xs.size) x := by
|
||||
rcases xs with ⟨s⟩
|
||||
rcases ys with ⟨t⟩
|
||||
simp only [List.append_toArray, List.setIfInBounds_toArray, List.set_append, Array.size]
|
||||
simp only [List.append_toArray, List.setIfInBounds_toArray, List.set_append]
|
||||
split <;> simp
|
||||
|
||||
@[simp] theorem setIfInBounds_append_left {xs ys : Array α} {i : Nat} {x : α} (h : i < xs.size) :
|
||||
@@ -2104,13 +2112,14 @@ theorem append_eq_map_iff {f : α → β} :
|
||||
| nil => simp
|
||||
| cons as => induction as.toList <;> simp [*]
|
||||
|
||||
@[simp] theorem flatten_toArray_map {L : List (List α)} :
|
||||
(L.map List.toArray).toArray.flatten = L.flatten.toArray := by
|
||||
@[simp] theorem flatten_map_toArray {L : List (List α)} :
|
||||
(L.toArray.map List.toArray).flatten = L.flatten.toArray := by
|
||||
apply ext'
|
||||
simp [Function.comp_def]
|
||||
|
||||
theorem flatten_map_toArray {L : List (List α)} :
|
||||
(L.toArray.map List.toArray).flatten = L.flatten.toArray := by
|
||||
@[simp] theorem flatten_toArray_map {L : List (List α)} :
|
||||
(L.map List.toArray).toArray.flatten = L.flatten.toArray := by
|
||||
rw [← flatten_map_toArray]
|
||||
simp
|
||||
|
||||
-- We set this to lower priority so that `flatten_toArray_map` is applied first when relevant.
|
||||
@@ -2138,8 +2147,8 @@ theorem mem_flatten : ∀ {xss : Array (Array α)}, a ∈ xss.flatten ↔ ∃ xs
|
||||
induction xss using array₂_induction
|
||||
simp
|
||||
|
||||
theorem empty_eq_flatten_iff {xss : Array (Array α)} : #[] = xss.flatten ↔ ∀ xs ∈ xss, xs = #[] := by
|
||||
simp
|
||||
@[simp] theorem empty_eq_flatten_iff {xss : Array (Array α)} : #[] = xss.flatten ↔ ∀ xs ∈ xss, xs = #[] := by
|
||||
rw [eq_comm, flatten_eq_empty_iff]
|
||||
|
||||
theorem flatten_ne_empty_iff {xss : Array (Array α)} : xss.flatten ≠ #[] ↔ ∃ xs, xs ∈ xss ∧ xs ≠ #[] := by
|
||||
simp
|
||||
@@ -2279,9 +2288,15 @@ theorem eq_iff_flatten_eq {xss₁ xss₂ : Array (Array α)} :
|
||||
rw [List.map_inj_right]
|
||||
simp +contextual
|
||||
|
||||
theorem flatten_toArray_map_toArray {xss : List (List α)} :
|
||||
@[simp] theorem flatten_toArray_map_toArray {xss : List (List α)} :
|
||||
(xss.map List.toArray).toArray.flatten = xss.flatten.toArray := by
|
||||
simp
|
||||
simp [flatten]
|
||||
suffices ∀ as, List.foldl (fun acc bs => acc ++ bs) as (List.map List.toArray xss) = as ++ xss.flatten.toArray by
|
||||
simpa using this #[]
|
||||
intro as
|
||||
induction xss generalizing as with
|
||||
| nil => simp
|
||||
| cons xs xss ih => simp [ih]
|
||||
|
||||
/-! ### flatMap -/
|
||||
|
||||
@@ -2311,9 +2326,13 @@ theorem flatMap_toArray_cons {β} {f : α → Array β} {a : α} {as : List α}
|
||||
intro cs
|
||||
induction as generalizing cs <;> simp_all
|
||||
|
||||
theorem flatMap_toArray {β} {f : α → Array β} {as : List α} :
|
||||
@[simp, grind =] theorem flatMap_toArray {β} {f : α → Array β} {as : List α} :
|
||||
as.toArray.flatMap f = (as.flatMap (fun a => (f a).toList)).toArray := by
|
||||
simp
|
||||
induction as with
|
||||
| nil => simp
|
||||
| cons a as ih =>
|
||||
apply ext'
|
||||
simp [ih, flatMap_toArray_cons]
|
||||
|
||||
@[simp] theorem flatMap_id {xss : Array (Array α)} : xss.flatMap id = xss.flatten := by simp [flatMap_def]
|
||||
|
||||
@@ -2779,7 +2798,7 @@ theorem reverse_eq_iff {xs ys : Array α} : xs.reverse = ys ↔ xs = ys.reverse
|
||||
cases xs
|
||||
simp
|
||||
|
||||
@[grind _=_] theorem filterMap_reverse {f : α → Option β} {xs : Array α} : (xs.reverse.filterMap f) = (xs.filterMap f).reverse := by
|
||||
@[grind _=_]theorem filterMap_reverse {f : α → Option β} {xs : Array α} : (xs.reverse.filterMap f) = (xs.filterMap f).reverse := by
|
||||
cases xs
|
||||
simp
|
||||
|
||||
@@ -3015,21 +3034,19 @@ theorem take_size {xs : Array α} : xs.take xs.size = xs := by
|
||||
| succ n ih =>
|
||||
simp [shrink.loop, ih]
|
||||
|
||||
-- This doesn't need to be a simp lemma, as shortly we will simplify `shrink` to `take`.
|
||||
theorem size_shrink {xs : Array α} {i : Nat} : (xs.shrink i).size = min i xs.size := by
|
||||
@[simp] theorem size_shrink {xs : Array α} {i : Nat} : (xs.shrink i).size = min i xs.size := by
|
||||
simp [shrink]
|
||||
omega
|
||||
|
||||
-- This doesn't need to be a simp lemma, as shortly we will simplify `shrink` to `take`.
|
||||
theorem getElem_shrink {xs : Array α} {i j : Nat} (h : j < (xs.shrink i).size) :
|
||||
(xs.shrink i)[j] = xs[j]'(by simp [size_shrink] at h; omega) := by
|
||||
@[simp] theorem getElem_shrink {xs : Array α} {i j : Nat} (h : j < (xs.shrink i).size) :
|
||||
(xs.shrink i)[j] = xs[j]'(by simp at h; omega) := by
|
||||
simp [shrink]
|
||||
|
||||
@[simp] theorem shrink_eq_take {xs : Array α} {i : Nat} : xs.shrink i = xs.take i := by
|
||||
ext <;> simp [size_shrink, getElem_shrink]
|
||||
@[simp] theorem toList_shrink {xs : Array α} {i : Nat} : (xs.shrink i).toList = xs.toList.take i := by
|
||||
apply List.ext_getElem <;> simp
|
||||
|
||||
theorem toList_shrink {xs : Array α} {i : Nat} : (xs.shrink i).toList = xs.toList.take i := by
|
||||
simp
|
||||
@[simp] theorem shrink_eq_take {xs : Array α} {i : Nat} : xs.shrink i = xs.take i := by
|
||||
ext <;> simp
|
||||
|
||||
/-! ### foldlM and foldrM -/
|
||||
|
||||
@@ -3198,16 +3215,18 @@ theorem foldlM_push [Monad m] [LawfulMonad m] {xs : Array α} {a : α} {f : β
|
||||
rw [foldr, foldrM_start_stop, ← foldrM_toList, List.foldrM_pure, foldr_toList, foldr, ← foldrM_start_stop]
|
||||
|
||||
theorem foldl_eq_foldlM {f : β → α → β} {b} {xs : Array α} {start stop : Nat} :
|
||||
xs.foldl f b start stop = (xs.foldlM (m := Id) (pure <| f · ·) b start stop).run := rfl
|
||||
xs.foldl f b start stop = xs.foldlM (m := Id) f b start stop := by
|
||||
simp [foldl, Id.run]
|
||||
|
||||
theorem foldr_eq_foldrM {f : α → β → β} {b} {xs : Array α} {start stop : Nat} :
|
||||
xs.foldr f b start stop = (xs.foldrM (m := Id) (pure <| f · ·) b start stop).run := rfl
|
||||
xs.foldr f b start stop = xs.foldrM (m := Id) f b start stop := by
|
||||
simp [foldr, Id.run]
|
||||
|
||||
@[simp] theorem id_run_foldlM {f : β → α → Id β} {b} {xs : Array α} {start stop : Nat} :
|
||||
Id.run (xs.foldlM f b start stop) = xs.foldl (f · · |>.run) b start stop := rfl
|
||||
Id.run (xs.foldlM f b start stop) = xs.foldl f b start stop := foldl_eq_foldlM.symm
|
||||
|
||||
@[simp] theorem id_run_foldrM {f : α → β → Id β} {b} {xs : Array α} {start stop : Nat} :
|
||||
Id.run (xs.foldrM f b start stop) = xs.foldr (f · · |>.run) b start stop := rfl
|
||||
Id.run (xs.foldrM f b start stop) = xs.foldr f b start stop := foldr_eq_foldrM.symm
|
||||
|
||||
/-- Variant of `foldlM_reverse` with a side condition for the `stop` argument. -/
|
||||
@[simp] theorem foldlM_reverse' [Monad m] {xs : Array α} {f : β → α → m β} {b} {stop : Nat}
|
||||
@@ -3236,7 +3255,7 @@ theorem foldrM_reverse [Monad m] {xs : Array α} {f : α → β → m β} {b} :
|
||||
|
||||
theorem foldrM_push [Monad m] {f : α → β → m β} {init : β} {xs : Array α} {a : α} :
|
||||
(xs.push a).foldrM f init = f a init >>= xs.foldrM f := by
|
||||
simp only [foldrM_eq_reverse_foldlM_toList, toList_push, List.reverse_append, List.reverse_cons,
|
||||
simp only [foldrM_eq_reverse_foldlM_toList, push_toList, List.reverse_append, List.reverse_cons,
|
||||
List.reverse_nil, List.nil_append, List.singleton_append, List.foldlM_cons, List.foldlM_reverse]
|
||||
|
||||
/--
|
||||
@@ -3507,16 +3526,17 @@ theorem foldrM_append [Monad m] [LawfulMonad m] {f : α → β → m β} {b} {xs
|
||||
|
||||
@[simp] theorem foldr_append' {f : α → β → β} {b} {xs ys : Array α} {start : Nat}
|
||||
(w : start = xs.size + ys.size) :
|
||||
(xs ++ ys).foldr f b start 0 = xs.foldr f (ys.foldr f b) :=
|
||||
foldrM_append' w
|
||||
(xs ++ ys).foldr f b start 0 = xs.foldr f (ys.foldr f b) := by
|
||||
subst w
|
||||
simp [foldr_eq_foldrM]
|
||||
|
||||
@[grind _=_] theorem foldl_append {β : Type _} {f : β → α → β} {b} {xs ys : Array α} :
|
||||
(xs ++ ys).foldl f b = ys.foldl f (xs.foldl f b) :=
|
||||
foldlM_append
|
||||
@[grind _=_]theorem foldl_append {β : Type _} {f : β → α → β} {b} {xs ys : Array α} :
|
||||
(xs ++ ys).foldl f b = ys.foldl f (xs.foldl f b) := by
|
||||
simp [foldl_eq_foldlM]
|
||||
|
||||
@[grind _=_] theorem foldr_append {f : α → β → β} {b} {xs ys : Array α} :
|
||||
(xs ++ ys).foldr f b = xs.foldr f (ys.foldr f b) :=
|
||||
foldrM_append
|
||||
(xs ++ ys).foldr f b = xs.foldr f (ys.foldr f b) := by
|
||||
simp [foldr_eq_foldrM]
|
||||
|
||||
@[simp] theorem foldl_flatten' {f : β → α → β} {b} {xss : Array (Array α)} {stop : Nat}
|
||||
(w : stop = xss.flatten.size) :
|
||||
@@ -3545,22 +3565,21 @@ theorem foldrM_append [Monad m] [LawfulMonad m] {f : α → β → m β} {b} {xs
|
||||
/-- Variant of `foldl_reverse` with a side condition for the `stop` argument. -/
|
||||
@[simp] theorem foldl_reverse' {xs : Array α} {f : β → α → β} {b} {stop : Nat}
|
||||
(w : stop = xs.size) :
|
||||
xs.reverse.foldl f b 0 stop = xs.foldr (fun x y => f y x) b :=
|
||||
foldlM_reverse' w
|
||||
xs.reverse.foldl f b 0 stop = xs.foldr (fun x y => f y x) b := by
|
||||
simp [w, foldl_eq_foldlM, foldr_eq_foldrM]
|
||||
|
||||
/-- Variant of `foldr_reverse` with a side condition for the `start` argument. -/
|
||||
@[simp] theorem foldr_reverse' {xs : Array α} {f : α → β → β} {b} {start : Nat}
|
||||
(w : start = xs.size) :
|
||||
xs.reverse.foldr f b start 0 = xs.foldl (fun x y => f y x) b :=
|
||||
foldrM_reverse' w
|
||||
xs.reverse.foldr f b start 0 = xs.foldl (fun x y => f y x) b := by
|
||||
simp [w, foldl_eq_foldlM, foldr_eq_foldrM]
|
||||
|
||||
@[grind] theorem foldl_reverse {xs : Array α} {f : β → α → β} {b} :
|
||||
xs.reverse.foldl f b = xs.foldr (fun x y => f y x) b :=
|
||||
foldlM_reverse
|
||||
xs.reverse.foldl f b = xs.foldr (fun x y => f y x) b := by simp [foldl_eq_foldlM, foldr_eq_foldrM]
|
||||
|
||||
@[grind] theorem foldr_reverse {xs : Array α} {f : α → β → β} {b} :
|
||||
xs.reverse.foldr f b = xs.foldl (fun x y => f y x) b :=
|
||||
foldrM_reverse
|
||||
(foldl_reverse ..).symm.trans <| by simp
|
||||
|
||||
theorem foldl_eq_foldr_reverse {xs : Array α} {f : β → α → β} {b} :
|
||||
xs.foldl f b = xs.reverse.foldr (fun x y => f y x) b := by simp
|
||||
@@ -3641,7 +3660,7 @@ theorem foldr_rel {xs : Array α} {f g : α → β → β} {a b : β} {r : β
|
||||
theorem back?_eq_some_iff {xs : Array α} {a : α} :
|
||||
xs.back? = some a ↔ ∃ ys : Array α, xs = ys.push a := by
|
||||
rcases xs with ⟨xs⟩
|
||||
simp only [List.back?_toArray, List.getLast?_eq_some_iff, toArray_eq, toList_push]
|
||||
simp only [List.back?_toArray, List.getLast?_eq_some_iff, toArray_eq, push_toList]
|
||||
constructor
|
||||
· rintro ⟨ys, rfl⟩
|
||||
exact ⟨ys.toArray, by simp⟩
|
||||
@@ -3766,7 +3785,7 @@ theorem contains_iff_exists_mem_beq [BEq α] {xs : Array α} {a : α} :
|
||||
rcases xs with ⟨xs⟩
|
||||
simp [List.contains_iff_exists_mem_beq]
|
||||
|
||||
@[grind _=_]
|
||||
@[grind]
|
||||
theorem contains_iff_mem [BEq α] [LawfulBEq α] {xs : Array α} {a : α} :
|
||||
xs.contains a ↔ a ∈ xs := by
|
||||
simp
|
||||
@@ -4075,16 +4094,15 @@ abbrev all_mkArray := @all_replicate
|
||||
/-! ### modify -/
|
||||
|
||||
@[simp] theorem size_modify {xs : Array α} {i : Nat} {f : α → α} : (xs.modify i f).size = xs.size := by
|
||||
unfold modify modifyM
|
||||
unfold modify modifyM Id.run
|
||||
split <;> simp
|
||||
|
||||
theorem getElem_modify {xs : Array α} {j i} (h : i < (xs.modify j f).size) :
|
||||
(xs.modify j f)[i] = if j = i then f (xs[i]'(by simpa using h)) else xs[i]'(by simpa using h) := by
|
||||
simp only [modify, modifyM]
|
||||
simp only [modify, modifyM, Id.run, Id.pure_eq]
|
||||
split
|
||||
· simp only [getElem_set, Id.run_pure, Id.run_bind]; split <;> simp [*]
|
||||
· simp only [Id.run_pure]
|
||||
rw [if_neg (mt (by rintro rfl; exact h) (by simp_all))]
|
||||
· simp only [Id.bind_eq, getElem_set]; split <;> simp [*]
|
||||
· rw [if_neg (mt (by rintro rfl; exact h) (by simp_all))]
|
||||
|
||||
@[simp] theorem toList_modify {xs : Array α} {f : α → α} {i : Nat} :
|
||||
(xs.modify i f).toList = xs.toList.modify i f := by
|
||||
@@ -4153,6 +4171,8 @@ theorem swap_comm {xs : Array α} {i j : Nat} (hi hj) : xs.swap i j hi hj = xs.s
|
||||
@[simp] theorem size_swapIfInBounds {xs : Array α} {i j : Nat} :
|
||||
(xs.swapIfInBounds i j).size = xs.size := by unfold swapIfInBounds; split <;> (try split) <;> simp [size_swap]
|
||||
|
||||
@[deprecated size_swapIfInBounds (since := "2024-11-24")] abbrev size_swap! := @size_swapIfInBounds
|
||||
|
||||
/-! ### swapAt -/
|
||||
|
||||
@[simp] theorem swapAt_def {xs : Array α} {i : Nat} {v : α} (hi) :
|
||||
@@ -4284,44 +4304,42 @@ Examples:
|
||||
|
||||
/-! ### Preliminaries about `ofFn` -/
|
||||
|
||||
@[simp] theorem size_ofFn_go {n} {f : Fin n → α} {i acc h} :
|
||||
(ofFn.go f acc i h).size = acc.size + i := by
|
||||
induction i generalizing acc with
|
||||
| zero => simp [ofFn.go]
|
||||
| succ i ih =>
|
||||
simpa [ofFn.go, ih] using Nat.succ_add_eq_add_succ acc.size i
|
||||
@[simp] theorem size_ofFn_go {n} {f : Fin n → α} {i acc} :
|
||||
(ofFn.go f i acc).size = acc.size + (n - i) := by
|
||||
if hin : i < n then
|
||||
unfold ofFn.go
|
||||
have : 1 + (n - (i + 1)) = n - i :=
|
||||
Nat.sub_sub .. ▸ Nat.add_sub_cancel' (Nat.le_sub_of_add_le (Nat.add_comm .. ▸ hin))
|
||||
rw [dif_pos hin, size_ofFn_go, size_push, Nat.add_assoc, this]
|
||||
else
|
||||
have : n - i = 0 := Nat.sub_eq_zero_of_le (Nat.le_of_not_lt hin)
|
||||
unfold ofFn.go
|
||||
simp [hin, this]
|
||||
termination_by n - i
|
||||
|
||||
@[simp] theorem size_ofFn {n : Nat} {f : Fin n → α} : (ofFn f).size = n := by simp [ofFn]
|
||||
|
||||
-- Recall `ofFn.go f acc i h = acc ++ #[f (n - i), ..., f(n - 1)]`
|
||||
theorem getElem_ofFn_go {f : Fin n → α} {acc i k} (h : i ≤ n) (w₁ : k < acc.size + i) :
|
||||
(ofFn.go f acc i h)[k]'(by simpa using w₁) =
|
||||
if w₂ : k < acc.size then acc[k] else f ⟨n - i + k - acc.size, by omega⟩ := by
|
||||
induction i generalizing acc k with
|
||||
| zero =>
|
||||
simp at w₁
|
||||
simp_all [ofFn.go]
|
||||
| succ i ih =>
|
||||
unfold ofFn.go
|
||||
rw [ih]
|
||||
· simp only [size_push]
|
||||
split <;> rename_i h'
|
||||
· rw [Array.getElem_push]
|
||||
split
|
||||
· rfl
|
||||
· congr 2
|
||||
omega
|
||||
· split
|
||||
· omega
|
||||
· congr 2
|
||||
omega
|
||||
· simp
|
||||
omega
|
||||
theorem getElem_ofFn_go {f : Fin n → α} {i} {acc k}
|
||||
(hki : k < n) (hin : i ≤ n) (hi : i = acc.size)
|
||||
(hacc : ∀ j, ∀ hj : j < acc.size, acc[j] = f ⟨j, Nat.lt_of_lt_of_le hj (hi ▸ hin)⟩) :
|
||||
haveI : acc.size + (n - acc.size) = n := Nat.add_sub_cancel' (hi ▸ hin)
|
||||
(ofFn.go f i acc)[k]'(by simp [*]) = f ⟨k, hki⟩ := by
|
||||
unfold ofFn.go
|
||||
if hin : i < n then
|
||||
have : 1 + (n - (i + 1)) = n - i :=
|
||||
Nat.sub_sub .. ▸ Nat.add_sub_cancel' (Nat.le_sub_of_add_le (Nat.add_comm .. ▸ hin))
|
||||
simp only [dif_pos hin]
|
||||
rw [getElem_ofFn_go _ hin (by simp [*]) (fun j hj => ?hacc)]
|
||||
cases (Nat.lt_or_eq_of_le <| Nat.le_of_lt_succ (by simpa using hj)) with
|
||||
| inl hj => simp [getElem_push, hj, hacc j hj]
|
||||
| inr hj => simp [getElem_push, *]
|
||||
else
|
||||
simp [hin, hacc k (Nat.lt_of_lt_of_le hki (Nat.le_of_not_lt (hi ▸ hin)))]
|
||||
termination_by n - i
|
||||
|
||||
@[simp] theorem getElem_ofFn {f : Fin n → α} {i : Nat} (h : i < (ofFn f).size) :
|
||||
(ofFn f)[i] = f ⟨i, size_ofFn (f := f) ▸ h⟩ := by
|
||||
unfold ofFn
|
||||
rw [getElem_ofFn_go] <;> simp_all
|
||||
(ofFn f)[i] = f ⟨i, size_ofFn (f := f) ▸ h⟩ :=
|
||||
getElem_ofFn_go _ (by simp) (by simp) nofun
|
||||
|
||||
theorem getElem?_ofFn {f : Fin n → α} {i : Nat} :
|
||||
(ofFn f)[i]? = if h : i < n then some (f ⟨i, h⟩) else none := by
|
||||
@@ -4412,8 +4430,7 @@ theorem getElem!_eq_getD [Inhabited α] {xs : Array α} {i} : xs[i]! = xs.getD i
|
||||
|
||||
/-! # mem -/
|
||||
|
||||
@[deprecated mem_toList_iff (since := "2025-05-26")]
|
||||
theorem mem_toList {a : α} {xs : Array α} : a ∈ xs.toList ↔ a ∈ xs := mem_def.symm
|
||||
@[simp, grind =] theorem mem_toList {a : α} {xs : Array α} : a ∈ xs.toList ↔ a ∈ xs := mem_def.symm
|
||||
|
||||
@[deprecated not_mem_empty (since := "2025-03-25")]
|
||||
theorem not_mem_nil (a : α) : ¬ a ∈ #[] := nofun
|
||||
@@ -4433,7 +4450,7 @@ 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
|
||||
@@ -4462,7 +4479,7 @@ theorem getElem?_push_eq {xs : Array α} {x : α} : (xs.push x)[xs.size]? = some
|
||||
simp
|
||||
|
||||
@[simp, grind =] theorem forIn'_toList [Monad m] {xs : Array α} {b : β} {f : (a : α) → a ∈ xs.toList → β → m (ForInStep β)} :
|
||||
forIn' xs.toList b f = forIn' xs b (fun a m b => f a (mem_toList_iff.mpr m) b) := by
|
||||
forIn' xs.toList b f = forIn' xs b (fun a m b => f a (mem_toList.mpr m) b) := by
|
||||
cases xs
|
||||
simp
|
||||
|
||||
@@ -4501,7 +4518,6 @@ abbrev contains_def [DecidableEq α] {a : α} {xs : Array α} : xs.contains a
|
||||
@[simp] theorem size_zipWith {xs : Array α} {ys : Array β} {f : α → β → γ} :
|
||||
(zipWith f xs ys).size = min xs.size ys.size := by
|
||||
rw [size_eq_length_toList, toList_zipWith, List.length_zipWith]
|
||||
simp only [Array.size]
|
||||
|
||||
@[simp] theorem size_zip {xs : Array α} {ys : Array β} :
|
||||
(zip xs ys).size = min xs.size ys.size :=
|
||||
@@ -4560,8 +4576,8 @@ Our goal is to have `simp` "pull `List.toArray` outwards" as much as possible.
|
||||
|
||||
theorem toListRev_toArray {l : List α} : l.toArray.toListRev = l.reverse := by simp
|
||||
|
||||
@[grind =] theorem take_toArray {l : List α} {i : Nat} : l.toArray.take i = (l.take i).toArray := by
|
||||
simp
|
||||
@[simp, grind =] theorem take_toArray {l : List α} {i : Nat} : l.toArray.take i = (l.take i).toArray := by
|
||||
apply Array.ext <;> simp
|
||||
|
||||
@[simp, grind =] theorem mapM_toArray [Monad m] [LawfulMonad m] {f : α → m β} {l : List α} :
|
||||
l.toArray.mapM f = List.toArray <$> l.mapM f := by
|
||||
@@ -4574,7 +4590,7 @@ theorem toListRev_toArray {l : List α} : l.toArray.toListRev = l.reverse := by
|
||||
| nil => simp
|
||||
| cons a l ih =>
|
||||
simp only [foldlM_toArray] at ih
|
||||
rw [size_toArray, mapM'_cons]
|
||||
rw [size_toArray, mapM'_cons, foldlM_toArray]
|
||||
simp [ih]
|
||||
|
||||
theorem uset_toArray {l : List α} {i : USize} {a : α} {h : i.toNat < l.toArray.size} :
|
||||
@@ -4627,12 +4643,12 @@ namespace Array
|
||||
@[simp] theorem findSomeRev?_eq_findSome?_reverse {f : α → Option β} {xs : Array α} :
|
||||
xs.findSomeRev? f = xs.reverse.findSome? f := by
|
||||
cases xs
|
||||
simp [findSomeRev?]
|
||||
simp [findSomeRev?, Id.run]
|
||||
|
||||
@[simp] theorem findRev?_eq_find?_reverse {f : α → Bool} {xs : Array α} :
|
||||
xs.findRev? f = xs.reverse.find? f := by
|
||||
cases xs
|
||||
simp [findRev?]
|
||||
simp [findRev?, Id.run]
|
||||
|
||||
/-! ### unzip -/
|
||||
|
||||
@@ -4688,6 +4704,13 @@ namespace List
|
||||
end List
|
||||
|
||||
/-! ### Deprecations -/
|
||||
|
||||
namespace List
|
||||
|
||||
@[deprecated setIfInBounds_toArray (since := "2024-11-24")] abbrev setD_toArray := @setIfInBounds_toArray
|
||||
|
||||
end List
|
||||
|
||||
namespace Array
|
||||
|
||||
@[deprecated size_toArray (since := "2024-12-11")]
|
||||
@@ -4740,6 +4763,17 @@ theorem get_set_eq (xs : Array α) (i : Nat) (v : α) (h : i < xs.size) :
|
||||
(xs.set i v h)[i]'(by simp [h]) = v := by
|
||||
simp only [set, ← getElem_toList, List.getElem_set_self]
|
||||
|
||||
@[deprecated set!_is_setIfInBounds (since := "2024-11-24")] abbrev set_is_setIfInBounds := @set!_eq_setIfInBounds
|
||||
@[deprecated size_setIfInBounds (since := "2024-11-24")] abbrev size_setD := @size_setIfInBounds
|
||||
@[deprecated getElem_setIfInBounds_eq (since := "2024-11-24")] abbrev getElem_setD_eq := @getElem_setIfInBounds_self
|
||||
@[deprecated getElem?_setIfInBounds_eq (since := "2024-11-24")] abbrev get?_setD_eq := @getElem?_setIfInBounds_self
|
||||
@[deprecated getD_getElem?_setIfInBounds (since := "2025-04-04")] abbrev getD_get?_setIfInBounds := @getD_getElem?_setIfInBounds
|
||||
@[deprecated getD_getElem?_setIfInBounds (since := "2024-11-24")] abbrev getD_setD := @getD_getElem?_setIfInBounds
|
||||
@[deprecated getElem_setIfInBounds (since := "2024-11-24")] abbrev getElem_setD := @getElem_setIfInBounds
|
||||
|
||||
@[deprecated List.getElem_toArray (since := "2024-11-29")]
|
||||
theorem getElem_mk {xs : List α} {i : Nat} (h : i < xs.length) : (Array.mk xs)[i] = xs[i] := rfl
|
||||
|
||||
@[deprecated Array.getElem_toList (since := "2024-12-08")]
|
||||
theorem getElem_eq_getElem_toList {xs : Array α} (h : i < xs.size) : xs[i] = xs.toList[i] := rfl
|
||||
|
||||
|
||||
@@ -29,12 +29,16 @@ protected theorem not_le_iff_gt [DecidableEq α] [LT α] [DecidableLT α] {xs ys
|
||||
Decidable.not_not
|
||||
|
||||
@[simp] theorem lex_empty [BEq α] {lt : α → α → Bool} {xs : Array α} : xs.lex #[] lt = false := by
|
||||
simp [lex]
|
||||
simp [lex, Id.run]
|
||||
|
||||
@[simp] theorem singleton_lex_singleton [BEq α] {lt : α → α → Bool} : #[a].lex #[b] lt = lt a b := by
|
||||
simp only [lex, List.getElem_toArray, List.getElem_singleton]
|
||||
cases lt a b <;> cases a != b <;> simp [Id.run]
|
||||
|
||||
private theorem cons_lex_cons [BEq α] {lt : α → α → Bool} {a b : α} {xs ys : Array α} :
|
||||
(#[a] ++ xs).lex (#[b] ++ ys) lt =
|
||||
(lt a b || a == b && xs.lex ys lt) := by
|
||||
simp only [lex]
|
||||
simp only [lex, Id.run]
|
||||
simp only [Std.Range.forIn'_eq_forIn'_range', size_append, List.size_toArray, List.length_singleton,
|
||||
Nat.add_comm 1]
|
||||
simp [Nat.add_min_add_right, List.range'_succ, getElem_append_left, List.range'_succ_left,
|
||||
@@ -47,16 +51,13 @@ private theorem cons_lex_cons [BEq α] {lt : α → α → Bool} {a b : α} {xs
|
||||
@[simp, grind =] theorem _root_.List.lex_toArray [BEq α] {lt : α → α → Bool} {l₁ l₂ : List α} :
|
||||
l₁.toArray.lex l₂.toArray lt = l₁.lex l₂ lt := by
|
||||
induction l₁ generalizing l₂ with
|
||||
| nil => cases l₂ <;> simp [lex]
|
||||
| nil => cases l₂ <;> simp [lex, Id.run]
|
||||
| cons x l₁ ih =>
|
||||
cases l₂ with
|
||||
| nil => simp [lex]
|
||||
| nil => simp [lex, Id.run]
|
||||
| cons y l₂ =>
|
||||
rw [List.toArray_cons, List.toArray_cons y, cons_lex_cons, List.lex, ih]
|
||||
|
||||
theorem singleton_lex_singleton [BEq α] {lt : α → α → Bool} : #[a].lex #[b] lt = lt a b := by
|
||||
simp
|
||||
|
||||
@[simp, grind =] theorem lex_toList [BEq α] {lt : α → α → Bool} {xs ys : Array α} :
|
||||
xs.toList.lex ys.toList lt = xs.lex ys lt := by
|
||||
cases xs <;> cases ys <;> simp
|
||||
|
||||
@@ -27,7 +27,7 @@ theorem mapFinIdx_induction (xs : Array α) (f : (i : Nat) → α → (h : i < x
|
||||
motive xs.size ∧ ∃ eq : (Array.mapFinIdx xs f).size = xs.size,
|
||||
∀ i h, p i ((Array.mapFinIdx xs f)[i]) h := by
|
||||
let rec go {bs i j h} (h₁ : j = bs.size) (h₂ : ∀ i h h', p i bs[i] h) (hm : motive j) :
|
||||
let as : Array β := Id.run <| Array.mapFinIdxM.map xs (pure <| f · · ·) i j h bs
|
||||
let as : Array β := Array.mapFinIdxM.map (m := Id) xs f i j h bs
|
||||
motive xs.size ∧ ∃ eq : as.size = xs.size, ∀ i h, p i as[i] h := by
|
||||
induction i generalizing j bs with simp [mapFinIdxM.map]
|
||||
| zero =>
|
||||
@@ -192,8 +192,7 @@ theorem mapFinIdx_empty {f : (i : Nat) → α → (h : i < 0) → β} : mapFinId
|
||||
theorem mapFinIdx_eq_ofFn {xs : Array α} {f : (i : Nat) → α → (h : i < xs.size) → β} :
|
||||
xs.mapFinIdx f = Array.ofFn fun i : Fin xs.size => f i xs[i] i.2 := by
|
||||
cases xs
|
||||
simp only [List.mapFinIdx_toArray, List.mapFinIdx_eq_ofFn, Fin.getElem_fin, List.getElem_toArray]
|
||||
simp [Array.size]
|
||||
simp [List.mapFinIdx_eq_ofFn]
|
||||
|
||||
theorem mapFinIdx_append {xs ys : Array α} {f : (i : Nat) → α → (h : i < (xs ++ ys).size) → β} :
|
||||
(xs ++ ys).mapFinIdx f =
|
||||
@@ -201,7 +200,7 @@ theorem mapFinIdx_append {xs ys : Array α} {f : (i : Nat) → α → (h : i < (
|
||||
ys.mapFinIdx (fun i a h => f (i + xs.size) a (by simp; omega)) := by
|
||||
cases xs
|
||||
cases ys
|
||||
simp [List.mapFinIdx_append, Array.size]
|
||||
simp [List.mapFinIdx_append]
|
||||
|
||||
@[simp]
|
||||
theorem mapFinIdx_push {xs : Array α} {a : α} {f : (i : Nat) → α → (h : i < (xs.push a).size) → β} :
|
||||
@@ -265,12 +264,12 @@ theorem mapFinIdx_eq_append_iff {xs : Array α} {f : (i : Nat) → α → (h : i
|
||||
toArray_eq_append_iff]
|
||||
constructor
|
||||
· rintro ⟨l₁, l₂, rfl, rfl, rfl⟩
|
||||
refine ⟨l₁.toArray, l₂.toArray, by simp_all [Array.size]⟩
|
||||
refine ⟨l₁.toArray, l₂.toArray, by simp_all⟩
|
||||
· rintro ⟨⟨l₁⟩, ⟨l₂⟩, rfl, h₁, h₂⟩
|
||||
simp [← toList_inj] at h₁ h₂
|
||||
obtain rfl := h₁
|
||||
obtain rfl := h₂
|
||||
refine ⟨l₁, l₂, by simp_all [Array.size]⟩
|
||||
refine ⟨l₁, l₂, by simp_all⟩
|
||||
|
||||
theorem mapFinIdx_eq_push_iff {xs : Array α} {b : β} {f : (i : Nat) → α → (h : i < xs.size) → β} :
|
||||
xs.mapFinIdx f = ys.push b ↔
|
||||
@@ -308,7 +307,7 @@ abbrev mapFinIdx_eq_mkArray_iff := @mapFinIdx_eq_replicate_iff
|
||||
@[simp] theorem mapFinIdx_reverse {xs : Array α} {f : (i : Nat) → α → (h : i < xs.reverse.size) → β} :
|
||||
xs.reverse.mapFinIdx f = (xs.mapFinIdx (fun i a h => f (xs.size - 1 - i) a (by simp; omega))).reverse := by
|
||||
rcases xs with ⟨l⟩
|
||||
simp [List.mapFinIdx_reverse, Array.size]
|
||||
simp [List.mapFinIdx_reverse]
|
||||
|
||||
/-! ### mapIdx -/
|
||||
|
||||
@@ -487,7 +486,7 @@ namespace List
|
||||
| x :: xs => simp only [mapFinIdxM.go, mapIdxM.go, go]
|
||||
unfold Array.mapIdxM
|
||||
rw [mapFinIdxM_toArray]
|
||||
simp only [mapFinIdxM, mapIdxM, Array.size]
|
||||
simp only [mapFinIdxM, mapIdxM]
|
||||
rw [go]
|
||||
|
||||
end List
|
||||
|
||||
@@ -25,10 +25,10 @@ open Nat
|
||||
|
||||
/-! ## Monadic operations -/
|
||||
|
||||
theorem map_toList_inj [Monad m] [LawfulMonad m]
|
||||
@[simp] theorem map_toList_inj [Monad m] [LawfulMonad m]
|
||||
{xs : m (Array α)} {ys : m (Array α)} :
|
||||
toList <$> xs = toList <$> ys ↔ xs = ys := by
|
||||
simp
|
||||
toList <$> xs = toList <$> ys ↔ xs = ys :=
|
||||
_root_.map_inj_right (by simp)
|
||||
|
||||
/-! ### mapM -/
|
||||
|
||||
@@ -36,11 +36,7 @@ theorem map_toList_inj [Monad m] [LawfulMonad m]
|
||||
xs.mapM (m := m) (pure <| f ·) = pure (xs.map f) := by
|
||||
induction xs; simp_all
|
||||
|
||||
@[simp] theorem idRun_mapM {xs : Array α} {f : α → Id β} : (xs.mapM f).run = xs.map (f · |>.run) :=
|
||||
mapM_pure
|
||||
|
||||
@[deprecated idRun_mapM (since := "2025-05-21")]
|
||||
theorem mapM_id {xs : Array α} {f : α → Id β} : xs.mapM f = xs.map f :=
|
||||
@[simp] theorem mapM_id {xs : Array α} {f : α → Id β} : xs.mapM f = xs.map f :=
|
||||
mapM_pure
|
||||
|
||||
@[simp] theorem mapM_map [Monad m] [LawfulMonad m] {f : α → β} {g : β → m γ} {xs : Array α} :
|
||||
@@ -195,18 +191,12 @@ theorem forIn'_eq_foldlM [Monad m] [LawfulMonad m]
|
||||
rcases xs with ⟨xs⟩
|
||||
simp [List.forIn'_pure_yield_eq_foldl, List.foldl_map]
|
||||
|
||||
theorem idRun_forIn'_yield_eq_foldl
|
||||
{xs : Array α} (f : (a : α) → a ∈ xs → β → Id β) (init : β) :
|
||||
(forIn' xs init (fun a m b => .yield <$> f a m b)).run =
|
||||
xs.attach.foldl (fun b ⟨a, h⟩ => f a h b |>.run) init := by
|
||||
simp
|
||||
|
||||
@[deprecated idRun_forIn'_yield_eq_foldl (since := "2025-05-21")]
|
||||
theorem forIn'_yield_eq_foldl
|
||||
@[simp] theorem forIn'_yield_eq_foldl
|
||||
{xs : Array α} (f : (a : α) → a ∈ xs → β → β) (init : β) :
|
||||
forIn' (m := Id) xs init (fun a m b => .yield (f a m b)) =
|
||||
xs.attach.foldl (fun b ⟨a, h⟩ => f a h b) init :=
|
||||
forIn'_pure_yield_eq_foldl _ _
|
||||
xs.attach.foldl (fun b ⟨a, h⟩ => f a h b) init := by
|
||||
rcases xs with ⟨xs⟩
|
||||
simp [List.foldl_map]
|
||||
|
||||
@[simp] theorem forIn'_map [Monad m] [LawfulMonad m]
|
||||
{xs : Array α} (g : α → β) (f : (b : β) → b ∈ xs.map g → γ → m (ForInStep γ)) :
|
||||
@@ -243,18 +233,12 @@ theorem forIn_eq_foldlM [Monad m] [LawfulMonad m]
|
||||
rcases xs with ⟨xs⟩
|
||||
simp [List.forIn_pure_yield_eq_foldl, List.foldl_map]
|
||||
|
||||
theorem idRun_forIn_yield_eq_foldl
|
||||
{xs : Array α} (f : α → β → Id β) (init : β) :
|
||||
(forIn xs init (fun a b => .yield <$> f a b)).run =
|
||||
xs.foldl (fun b a => f a b |>.run) init := by
|
||||
simp
|
||||
|
||||
@[deprecated idRun_forIn_yield_eq_foldl (since := "2025-05-21")]
|
||||
theorem forIn_yield_eq_foldl
|
||||
@[simp] theorem forIn_yield_eq_foldl
|
||||
{xs : Array α} (f : α → β → β) (init : β) :
|
||||
forIn (m := Id) xs init (fun a b => .yield (f a b)) =
|
||||
xs.foldl (fun b a => f a b) init :=
|
||||
forIn_pure_yield_eq_foldl _ _
|
||||
xs.foldl (fun b a => f a b) init := by
|
||||
rcases xs with ⟨xs⟩
|
||||
simp [List.foldl_map]
|
||||
|
||||
@[simp] theorem forIn_map [Monad m] [LawfulMonad m]
|
||||
{xs : Array α} {g : α → β} {f : β → γ → m (ForInStep γ)} :
|
||||
@@ -310,7 +294,7 @@ namespace List
|
||||
@[simp] theorem filterM_toArray' [Monad m] [LawfulMonad m] {l : List α} {p : α → m Bool} (w : stop = l.length) :
|
||||
l.toArray.filterM p 0 stop = toArray <$> l.filterM p := by
|
||||
subst w
|
||||
simp [← filterM_toArray]
|
||||
rw [filterM_toArray]
|
||||
|
||||
@[grind =] theorem filterRevM_toArray [Monad m] [LawfulMonad m] {l : List α} {p : α → m Bool} :
|
||||
l.toArray.filterRevM p = toArray <$> l.filterRevM p := by
|
||||
@@ -322,7 +306,7 @@ namespace List
|
||||
@[simp] theorem filterRevM_toArray' [Monad m] [LawfulMonad m] {l : List α} {p : α → m Bool} (w : start = l.length) :
|
||||
l.toArray.filterRevM p start 0 = toArray <$> l.filterRevM p := by
|
||||
subst w
|
||||
simp [← filterRevM_toArray]
|
||||
rw [filterRevM_toArray]
|
||||
|
||||
@[grind =] theorem filterMapM_toArray [Monad m] [LawfulMonad m] {l : List α} {f : α → m (Option β)} :
|
||||
l.toArray.filterMapM f = toArray <$> l.filterMapM f := by
|
||||
@@ -340,7 +324,7 @@ namespace List
|
||||
@[simp] theorem filterMapM_toArray' [Monad m] [LawfulMonad m] {l : List α} {f : α → m (Option β)} (w : stop = l.length) :
|
||||
l.toArray.filterMapM f 0 stop = toArray <$> l.filterMapM f := by
|
||||
subst w
|
||||
simp [← filterMapM_toArray]
|
||||
rw [filterMapM_toArray]
|
||||
|
||||
@[simp, grind =] theorem flatMapM_toArray [Monad m] [LawfulMonad m] {l : List α} {f : α → m (Array β)} :
|
||||
l.toArray.flatMapM f = toArray <$> l.flatMapM (fun a => Array.toList <$> f a) := by
|
||||
|
||||
@@ -129,6 +129,7 @@ theorem ofFnM_pure [Monad m] [LawfulMonad m] {n} {f : Fin n → α} :
|
||||
|
||||
@[simp, grind =] theorem idRun_ofFnM {f : Fin n → Id α} :
|
||||
Id.run (ofFnM f) = ofFn (fun i => Id.run (f i)) := by
|
||||
unfold Id.run
|
||||
induction n with
|
||||
| zero => simp
|
||||
| succ n ih => simp [ofFnM_succ', ofFn_succ', ih]
|
||||
|
||||
@@ -27,27 +27,23 @@ Internal implementation of `Array.qsort`.
|
||||
|
||||
It does so by first swapping the elements at indices `lo`, `mid := (lo + hi) / 2`, and `hi`
|
||||
if necessary so that the middle (pivot) element is at index `hi`.
|
||||
We then iterate from `k = lo` to `k = hi`, with a pointer `i` starting at `lo`, and
|
||||
We then iterate from `j = lo` to `j = hi`, with a pointer `i` starting at `lo`, and
|
||||
swapping each element which is less than the pivot to position `i`, and then incrementing `i`.
|
||||
-/
|
||||
def qpartition {n} (as : Vector α n) (lt : α → α → Bool) (lo hi : Nat) (w : lo ≤ hi := by omega)
|
||||
(hlo : lo < n := by omega) (hhi : hi < n := by omega) : {m : Nat // lo ≤ m ∧ m ≤ hi} × Vector α n :=
|
||||
def qpartition {n} (as : Vector α n) (lt : α → α → Bool) (lo hi : Nat)
|
||||
(hlo : lo < n := by omega) (hhi : hi < n := by omega) : {m : Nat // lo ≤ m ∧ m < n} × Vector α n :=
|
||||
let mid := (lo + hi) / 2
|
||||
let as := if lt as[mid] as[lo] then as.swap lo mid else as
|
||||
let as := if lt as[hi] as[lo] then as.swap lo hi else as
|
||||
let as := if lt as[mid] as[hi] then as.swap mid hi else as
|
||||
let pivot := as[hi]
|
||||
-- During this loop, elements below in `[lo, i)` are less than `pivot`,
|
||||
-- elements in `[i, k)` are greater than or equal to `pivot`,
|
||||
-- elements in `[k, hi)` are unexamined,
|
||||
-- while `as[hi]` is (by definition) the pivot.
|
||||
let rec loop (as : Vector α n) (i k : Nat)
|
||||
(ilo : lo ≤ i := by omega) (ik : i ≤ k := by omega) (w : k ≤ hi := by omega) :=
|
||||
if h : k < hi then
|
||||
if lt as[k] pivot then
|
||||
loop (as.swap i k) (i+1) (k+1)
|
||||
let rec loop (as : Vector α n) (i j : Nat)
|
||||
(ilo : lo ≤ i := by omega) (jh : j < n := by omega) (w : i ≤ j := by omega) :=
|
||||
if h : j < hi then
|
||||
if lt as[j] pivot then
|
||||
loop (as.swap i j) (i+1) (j+1)
|
||||
else
|
||||
loop as i (k+1)
|
||||
loop as i (j+1)
|
||||
else
|
||||
(⟨i, ilo, by omega⟩, as.swap i hi)
|
||||
loop as lo lo
|
||||
@@ -55,28 +51,25 @@ def qpartition {n} (as : Vector α n) (lt : α → α → Bool) (lo hi : Nat) (w
|
||||
/--
|
||||
In-place quicksort.
|
||||
|
||||
`qsort as lt lo hi` sorts the subarray `as[lo:hi+1]` in-place using `lt` to compare elements.
|
||||
`qsort as lt low high` sorts the subarray `as[low:high+1]` in-place using `lt` to compare elements.
|
||||
-/
|
||||
@[inline] def qsort (as : Array α) (lt : α → α → Bool := by exact (· < ·))
|
||||
(lo := 0) (hi := as.size - 1) : Array α :=
|
||||
let rec @[specialize] sort {n} (as : Vector α n) (lo hi : Nat) (w : lo ≤ hi := by omega)
|
||||
(low := 0) (high := as.size - 1) : Array α :=
|
||||
let rec @[specialize] sort {n} (as : Vector α n) (lo hi : Nat)
|
||||
(hlo : lo < n := by omega) (hhi : hi < n := by omega) :=
|
||||
if h₁ : lo < hi then
|
||||
let ⟨⟨mid, hmid⟩, as⟩ := qpartition as lt lo hi
|
||||
if h₂ : mid ≥ hi then
|
||||
-- This only occurs when `hi ≤ lo`,
|
||||
-- and thus `as[lo:hi+1]` is trivially already sorted.
|
||||
as
|
||||
else
|
||||
-- Otherwise, we recursively sort the two subarrays.
|
||||
sort (sort as lo mid) (mid+1) hi
|
||||
else as
|
||||
if h : as.size = 0 then
|
||||
as
|
||||
else
|
||||
let lo := min lo (as.size - 1)
|
||||
let hi := max lo (min hi (as.size - 1))
|
||||
sort as.toVector lo hi |>.toArray
|
||||
let low := min low (as.size - 1)
|
||||
let high := min high (as.size - 1)
|
||||
sort as.toVector low high |>.toArray
|
||||
|
||||
set_option linter.unusedVariables.funArgs false in
|
||||
/--
|
||||
|
||||
@@ -24,7 +24,7 @@ Examples:
|
||||
* `#[0, 1, 2].set 1 5 = #[0, 5, 2]`
|
||||
* `#["orange", "apple"].set 1 "grape" = #["orange", "grape"]`
|
||||
-/
|
||||
@[extern "lean_array_fset", expose]
|
||||
@[extern "lean_array_fset"]
|
||||
def Array.set (xs : Array α) (i : @& Nat) (v : α) (h : i < xs.size := by get_elem_tactic) :
|
||||
Array α where
|
||||
toList := xs.toList.set i v
|
||||
@@ -40,15 +40,17 @@ Examples:
|
||||
* `#["orange", "apple"].setIfInBounds 1 "grape" = #["orange", "grape"]`
|
||||
* `#["orange", "apple"].setIfInBounds 5 "grape" = #["orange", "apple"]`
|
||||
-/
|
||||
@[inline, expose] def Array.setIfInBounds (xs : Array α) (i : Nat) (v : α) : Array α :=
|
||||
@[inline] def Array.setIfInBounds (xs : Array α) (i : Nat) (v : α) : Array α :=
|
||||
dite (LT.lt i xs.size) (fun h => xs.set i v h) (fun _ => xs)
|
||||
|
||||
@[deprecated Array.setIfInBounds (since := "2024-11-24")] abbrev Array.setD := @Array.setIfInBounds
|
||||
|
||||
/--
|
||||
Set an element in an array, or panic if the index is out of bounds.
|
||||
|
||||
This will perform the update destructively provided that `a` has a reference
|
||||
count of 1 when called.
|
||||
-/
|
||||
@[extern "lean_array_set", expose]
|
||||
@[extern "lean_array_set"]
|
||||
def Array.set! (xs : Array α) (i : @& Nat) (v : α) : Array α :=
|
||||
Array.setIfInBounds xs i v
|
||||
|
||||
@@ -290,7 +290,7 @@ Examples:
|
||||
-/
|
||||
@[inline]
|
||||
def foldl {α : Type u} {β : Type v} (f : β → α → β) (init : β) (as : Subarray α) : β :=
|
||||
Id.run <| as.foldlM (pure <| f · ·) (init := init)
|
||||
Id.run <| as.foldlM f (init := init)
|
||||
|
||||
/--
|
||||
Folds an operation from right to left over the elements in a subarray.
|
||||
@@ -304,7 +304,7 @@ Examples:
|
||||
-/
|
||||
@[inline]
|
||||
def foldr {α : Type u} {β : Type v} (f : α → β → β) (init : β) (as : Subarray α) : β :=
|
||||
Id.run <| as.foldrM (pure <| f · ·) (init := init)
|
||||
Id.run <| as.foldrM f (init := init)
|
||||
|
||||
/--
|
||||
Checks whether any of the elements in a subarray satisfy a Boolean predicate.
|
||||
@@ -314,7 +314,7 @@ an element that satisfies the predicate is found.
|
||||
-/
|
||||
@[inline]
|
||||
def any {α : Type u} (p : α → Bool) (as : Subarray α) : Bool :=
|
||||
Id.run <| as.anyM (pure <| p ·)
|
||||
Id.run <| as.anyM p
|
||||
|
||||
/--
|
||||
Checks whether all of the elements in a subarray satisfy a Boolean predicate.
|
||||
@@ -324,7 +324,7 @@ an element that does not satisfy the predicate is found.
|
||||
-/
|
||||
@[inline]
|
||||
def all {α : Type u} (p : α → Bool) (as : Subarray α) : Bool :=
|
||||
Id.run <| as.allM (pure <| p ·)
|
||||
Id.run <| as.allM p
|
||||
|
||||
/--
|
||||
Applies a monadic function to each element in a subarray in reverse order, stopping at the first
|
||||
@@ -394,7 +394,7 @@ Examples:
|
||||
-/
|
||||
@[inline]
|
||||
def findRev? {α : Type} (as : Subarray α) (p : α → Bool) : Option α :=
|
||||
Id.run <| as.findRevM? (pure <| p ·)
|
||||
Id.run <| as.findRevM? p
|
||||
|
||||
end Subarray
|
||||
|
||||
|
||||
@@ -334,13 +334,11 @@ abbrev zipWithAll_mkArray := @zipWithAll_replicate
|
||||
|
||||
/-! ### unzip -/
|
||||
|
||||
@[deprecated fst_unzip (since := "2025-05-26")]
|
||||
theorem unzip_fst : (unzip l).fst = l.map Prod.fst := by
|
||||
simp
|
||||
@[simp] theorem unzip_fst : (unzip l).fst = l.map Prod.fst := by
|
||||
induction l <;> simp_all
|
||||
|
||||
@[deprecated snd_unzip (since := "2025-05-26")]
|
||||
theorem unzip_snd : (unzip l).snd = l.map Prod.snd := by
|
||||
simp
|
||||
@[simp] theorem unzip_snd : (unzip l).snd = l.map Prod.snd := by
|
||||
induction l <;> simp_all
|
||||
|
||||
theorem unzip_eq_map {xs : Array (α × β)} : unzip xs = (xs.map Prod.fst, xs.map Prod.snd) := by
|
||||
cases xs
|
||||
@@ -373,7 +371,7 @@ theorem unzip_zip {as : Array α} {bs : Array β} (h : as.size = bs.size) :
|
||||
|
||||
theorem zip_of_prod {as : Array α} {bs : Array β} {xs : Array (α × β)} (hl : xs.map Prod.fst = as)
|
||||
(hr : xs.map Prod.snd = bs) : xs = as.zip bs := by
|
||||
rw [← hl, ← hr, ← zip_unzip xs, ← fst_unzip, ← snd_unzip, zip_unzip, zip_unzip]
|
||||
rw [← hl, ← hr, ← zip_unzip xs, ← unzip_fst, ← unzip_snd, zip_unzip, zip_unzip]
|
||||
|
||||
@[simp] theorem unzip_replicate {n : Nat} {a : α} {b : β} :
|
||||
unzip (replicate n (a, b)) = (replicate n a, replicate n b) := by
|
||||
|
||||
@@ -27,7 +27,7 @@ class EquivBEq (α) [BEq α] : Prop extends PartialEquivBEq α, ReflBEq α
|
||||
theorem BEq.symm [BEq α] [PartialEquivBEq α] {a b : α} : a == b → b == a :=
|
||||
PartialEquivBEq.symm
|
||||
|
||||
theorem BEq.comm [BEq α] [PartialEquivBEq α] {a b : α} : (a == b) = (b == a) :=
|
||||
@[grind] theorem BEq.comm [BEq α] [PartialEquivBEq α] {a b : α} : (a == b) = (b == a) :=
|
||||
Bool.eq_iff_iff.2 ⟨BEq.symm, BEq.symm⟩
|
||||
|
||||
theorem bne_comm [BEq α] [PartialEquivBEq α] {a b : α} : (a != b) = (b != a) := by
|
||||
|
||||
@@ -61,7 +61,7 @@ end subsingleton
|
||||
section zero_allOnes
|
||||
|
||||
/-- Returns a bitvector of size `n` where all bits are `0`. -/
|
||||
@[expose] protected def zero (n : Nat) : BitVec n := .ofNatLT 0 (Nat.two_pow_pos n)
|
||||
protected def zero (n : Nat) : BitVec n := .ofNatLT 0 (Nat.two_pow_pos n)
|
||||
instance : Inhabited (BitVec n) where default := .zero n
|
||||
|
||||
/-- Returns a bitvector of size `n` where all bits are `1`. -/
|
||||
@@ -77,10 +77,10 @@ Returns the `i`th least significant bit.
|
||||
|
||||
This will be renamed `getLsb` after the existing deprecated alias is removed.
|
||||
-/
|
||||
@[inline, expose] def getLsb' (x : BitVec w) (i : Fin w) : Bool := x.toNat.testBit i
|
||||
@[inline] def getLsb' (x : BitVec w) (i : Fin w) : Bool := x.toNat.testBit i
|
||||
|
||||
/-- Returns the `i`th least significant bit, or `none` if `i ≥ w`. -/
|
||||
@[inline, expose] def getLsb? (x : BitVec w) (i : Nat) : Option Bool :=
|
||||
@[inline] def getLsb? (x : BitVec w) (i : Nat) : Option Bool :=
|
||||
if h : i < w then some (getLsb' x ⟨i, h⟩) else none
|
||||
|
||||
/--
|
||||
@@ -95,7 +95,7 @@ This will be renamed `BitVec.getMsb` after the existing deprecated alias is remo
|
||||
if h : i < w then some (getMsb' x ⟨i, h⟩) else none
|
||||
|
||||
/-- Returns the `i`th least significant bit or `false` if `i ≥ w`. -/
|
||||
@[inline, expose] def getLsbD (x : BitVec w) (i : Nat) : Bool :=
|
||||
@[inline] def getLsbD (x : BitVec w) (i : Nat) : Bool :=
|
||||
x.toNat.testBit i
|
||||
|
||||
/-- Returns the `i`th most significant bit, or `false` if `i ≥ w`. -/
|
||||
@@ -134,7 +134,6 @@ section Int
|
||||
/--
|
||||
Interprets the bitvector as an integer stored in two's complement form.
|
||||
-/
|
||||
@[expose]
|
||||
protected def toInt (x : BitVec n) : Int :=
|
||||
if 2 * x.toNat < 2^n then
|
||||
x.toNat
|
||||
@@ -148,7 +147,6 @@ over- and underflowing as needed.
|
||||
The underlying `Nat` is `(2^n + (i mod 2^n)) mod 2^n`. Converting the bitvector back to an `Int`
|
||||
with `BitVec.toInt` results in the value `i.bmod (2^n)`.
|
||||
-/
|
||||
@[expose]
|
||||
protected def ofInt (n : Nat) (i : Int) : BitVec n := .ofNatLT (i % (Int.ofNat (2^n))).toNat (by
|
||||
apply (Int.toNat_lt _).mpr
|
||||
· apply Int.emod_lt_of_pos
|
||||
@@ -220,14 +218,12 @@ Usually accessed via the `-` prefix operator.
|
||||
|
||||
SMT-LIB name: `bvneg`.
|
||||
-/
|
||||
@[expose]
|
||||
protected def neg (x : BitVec n) : BitVec n := .ofNat n (2^n - x.toNat)
|
||||
instance : Neg (BitVec n) := ⟨.neg⟩
|
||||
|
||||
/--
|
||||
Returns the absolute value of a signed bitvector.
|
||||
-/
|
||||
@[expose]
|
||||
protected def abs (x : BitVec n) : BitVec n := if x.msb then .neg x else x
|
||||
|
||||
/--
|
||||
@@ -236,7 +232,6 @@ modulo `2^n`. Usually accessed via the `*` operator.
|
||||
|
||||
SMT-LIB name: `bvmul`.
|
||||
-/
|
||||
@[expose]
|
||||
protected def mul (x y : BitVec n) : BitVec n := BitVec.ofNat n (x.toNat * y.toNat)
|
||||
instance : Mul (BitVec n) := ⟨.mul⟩
|
||||
|
||||
@@ -247,7 +242,6 @@ Note that this is currently an inefficient implementation,
|
||||
and should be replaced via an `@[extern]` with a native implementation.
|
||||
See https://github.com/leanprover/lean4/issues/7887.
|
||||
-/
|
||||
@[expose]
|
||||
protected def pow (x : BitVec n) (y : Nat) : BitVec n :=
|
||||
match y with
|
||||
| 0 => 1
|
||||
@@ -259,7 +253,6 @@ instance : Pow (BitVec n) Nat where
|
||||
Unsigned division of bitvectors using the Lean convention where division by zero returns zero.
|
||||
Usually accessed via the `/` operator.
|
||||
-/
|
||||
@[expose]
|
||||
def udiv (x y : BitVec n) : BitVec n :=
|
||||
(x.toNat / y.toNat)#'(Nat.lt_of_le_of_lt (Nat.div_le_self _ _) x.isLt)
|
||||
instance : Div (BitVec n) := ⟨.udiv⟩
|
||||
@@ -269,7 +262,6 @@ Unsigned modulo for bitvectors. Usually accessed via the `%` operator.
|
||||
|
||||
SMT-LIB name: `bvurem`.
|
||||
-/
|
||||
@[expose]
|
||||
def umod (x y : BitVec n) : BitVec n :=
|
||||
(x.toNat % y.toNat)#'(Nat.lt_of_le_of_lt (Nat.mod_le _ _) x.isLt)
|
||||
instance : Mod (BitVec n) := ⟨.umod⟩
|
||||
@@ -281,7 +273,6 @@ where division by zero returns `BitVector.allOnes n`.
|
||||
|
||||
SMT-LIB name: `bvudiv`.
|
||||
-/
|
||||
@[expose]
|
||||
def smtUDiv (x y : BitVec n) : BitVec n := if y = 0 then allOnes n else udiv x y
|
||||
|
||||
/--
|
||||
@@ -351,7 +342,6 @@ end arithmetic
|
||||
section bool
|
||||
|
||||
/-- Turns a `Bool` into a bitvector of length `1`. -/
|
||||
@[expose]
|
||||
def ofBool (b : Bool) : BitVec 1 := cond b 1 0
|
||||
|
||||
@[simp] theorem ofBool_false : ofBool false = 0 := by trivial
|
||||
@@ -369,7 +359,6 @@ Unsigned less-than for bitvectors.
|
||||
|
||||
SMT-LIB name: `bvult`.
|
||||
-/
|
||||
@[expose]
|
||||
protected def ult (x y : BitVec n) : Bool := x.toNat < y.toNat
|
||||
|
||||
/--
|
||||
@@ -377,7 +366,6 @@ Unsigned less-than-or-equal-to for bitvectors.
|
||||
|
||||
SMT-LIB name: `bvule`.
|
||||
-/
|
||||
@[expose]
|
||||
protected def ule (x y : BitVec n) : Bool := x.toNat ≤ y.toNat
|
||||
|
||||
/--
|
||||
@@ -389,7 +377,6 @@ Examples:
|
||||
* `BitVec.slt 6#4 7 = true`
|
||||
* `BitVec.slt 7#4 8 = false`
|
||||
-/
|
||||
@[expose]
|
||||
protected def slt (x y : BitVec n) : Bool := x.toInt < y.toInt
|
||||
|
||||
/--
|
||||
@@ -397,7 +384,6 @@ Signed less-than-or-equal-to for bitvectors.
|
||||
|
||||
SMT-LIB name: `bvsle`.
|
||||
-/
|
||||
@[expose]
|
||||
protected def sle (x y : BitVec n) : Bool := x.toInt ≤ y.toInt
|
||||
|
||||
end relations
|
||||
@@ -411,7 +397,7 @@ width `m`.
|
||||
Using `x.cast eq` should be preferred over `eq ▸ x` because there are special-purpose `simp` lemmas
|
||||
that can more consistently simplify `BitVec.cast` away.
|
||||
-/
|
||||
@[inline, expose] protected def cast (eq : n = m) (x : BitVec n) : BitVec m := .ofNatLT x.toNat (eq ▸ x.isLt)
|
||||
@[inline] protected def cast (eq : n = m) (x : BitVec n) : BitVec m := .ofNatLT x.toNat (eq ▸ x.isLt)
|
||||
|
||||
@[simp] theorem cast_ofNat {n m : Nat} (h : n = m) (x : Nat) :
|
||||
(BitVec.ofNat n x).cast h = BitVec.ofNat m x := by
|
||||
@@ -427,7 +413,6 @@ that can more consistently simplify `BitVec.cast` away.
|
||||
Extracts the bits `start` to `start + len - 1` from a bitvector of size `n` to yield a
|
||||
new bitvector of size `len`. If `start + len > n`, then the bitvector is zero-extended.
|
||||
-/
|
||||
@[expose]
|
||||
def extractLsb' (start len : Nat) (x : BitVec n) : BitVec len := .ofNat _ (x.toNat >>> start)
|
||||
|
||||
/--
|
||||
@@ -438,7 +423,6 @@ The resulting bitvector has size `hi - lo + 1`.
|
||||
|
||||
SMT-LIB name: `extract`.
|
||||
-/
|
||||
@[expose]
|
||||
def extractLsb (hi lo : Nat) (x : BitVec n) : BitVec (hi - lo + 1) := extractLsb' lo _ x
|
||||
|
||||
/--
|
||||
@@ -447,7 +431,6 @@ Increases the width of a bitvector to one that is at least as large by zero-exte
|
||||
This is a constant-time operation because the underlying `Nat` is unmodified; because the new width
|
||||
is at least as large as the old one, no overflow is possible.
|
||||
-/
|
||||
@[expose]
|
||||
def setWidth' {n w : Nat} (le : n ≤ w) (x : BitVec n) : BitVec w :=
|
||||
x.toNat#'(by
|
||||
apply Nat.lt_of_lt_of_le x.isLt
|
||||
@@ -456,7 +439,6 @@ def setWidth' {n w : Nat} (le : n ≤ w) (x : BitVec n) : BitVec w :=
|
||||
/--
|
||||
Returns `zeroExtend (w+n) x <<< n` without needing to compute `x % 2^(2+n)`.
|
||||
-/
|
||||
@[expose]
|
||||
def shiftLeftZeroExtend (msbs : BitVec w) (m : Nat) : BitVec (w + m) :=
|
||||
let shiftLeftLt {x : Nat} (p : x < 2^w) (m : Nat) : x <<< m < 2^(w + m) := by
|
||||
simp [Nat.shiftLeft_eq, Nat.pow_add]
|
||||
@@ -513,7 +495,6 @@ SMT-LIB name: `bvand`.
|
||||
Example:
|
||||
* `0b1010#4 &&& 0b0110#4 = 0b0010#4`
|
||||
-/
|
||||
@[expose]
|
||||
protected def and (x y : BitVec n) : BitVec n :=
|
||||
(x.toNat &&& y.toNat)#'(Nat.and_lt_two_pow x.toNat y.isLt)
|
||||
instance : AndOp (BitVec w) := ⟨.and⟩
|
||||
@@ -526,7 +507,6 @@ SMT-LIB name: `bvor`.
|
||||
Example:
|
||||
* `0b1010#4 ||| 0b0110#4 = 0b1110#4`
|
||||
-/
|
||||
@[expose]
|
||||
protected def or (x y : BitVec n) : BitVec n :=
|
||||
(x.toNat ||| y.toNat)#'(Nat.or_lt_two_pow x.isLt y.isLt)
|
||||
instance : OrOp (BitVec w) := ⟨.or⟩
|
||||
@@ -539,7 +519,6 @@ SMT-LIB name: `bvxor`.
|
||||
Example:
|
||||
* `0b1010#4 ^^^ 0b0110#4 = 0b1100#4`
|
||||
-/
|
||||
@[expose]
|
||||
protected def xor (x y : BitVec n) : BitVec n :=
|
||||
(x.toNat ^^^ y.toNat)#'(Nat.xor_lt_two_pow x.isLt y.isLt)
|
||||
instance : Xor (BitVec w) := ⟨.xor⟩
|
||||
@@ -552,7 +531,6 @@ SMT-LIB name: `bvnot`.
|
||||
Example:
|
||||
* `~~~(0b0101#4) == 0b1010`
|
||||
-/
|
||||
@[expose]
|
||||
protected def not (x : BitVec n) : BitVec n := allOnes n ^^^ x
|
||||
instance : Complement (BitVec w) := ⟨.not⟩
|
||||
|
||||
@@ -562,7 +540,6 @@ equivalent to `x * 2^s`, modulo `2^n`.
|
||||
|
||||
SMT-LIB name: `bvshl` except this operator uses a `Nat` shift value.
|
||||
-/
|
||||
@[expose]
|
||||
protected def shiftLeft (x : BitVec n) (s : Nat) : BitVec n := BitVec.ofNat n (x.toNat <<< s)
|
||||
instance : HShiftLeft (BitVec w) Nat (BitVec w) := ⟨.shiftLeft⟩
|
||||
|
||||
@@ -574,7 +551,6 @@ As a numeric operation, this is equivalent to `x / 2^s`, rounding down.
|
||||
|
||||
SMT-LIB name: `bvlshr` except this operator uses a `Nat` shift value.
|
||||
-/
|
||||
@[expose]
|
||||
def ushiftRight (x : BitVec n) (s : Nat) : BitVec n :=
|
||||
(x.toNat >>> s)#'(by
|
||||
let ⟨x, lt⟩ := x
|
||||
@@ -592,7 +568,6 @@ As a numeric operation, this is equivalent to `x.toInt >>> s`.
|
||||
|
||||
SMT-LIB name: `bvashr` except this operator uses a `Nat` shift value.
|
||||
-/
|
||||
@[expose]
|
||||
def sshiftRight (x : BitVec n) (s : Nat) : BitVec n := .ofInt n (x.toInt >>> s)
|
||||
|
||||
instance {n} : HShiftLeft (BitVec m) (BitVec n) (BitVec m) := ⟨fun x y => x <<< y.toNat⟩
|
||||
@@ -606,12 +581,10 @@ As a numeric operation, this is equivalent to `a.toInt >>> s.toNat`.
|
||||
|
||||
SMT-LIB name: `bvashr`.
|
||||
-/
|
||||
@[expose]
|
||||
def sshiftRight' (a : BitVec n) (s : BitVec m) : BitVec n := a.sshiftRight s.toNat
|
||||
|
||||
/-- Auxiliary function for `rotateLeft`, which does not take into account the case where
|
||||
the rotation amount is greater than the bitvector width. -/
|
||||
@[expose]
|
||||
def rotateLeftAux (x : BitVec w) (n : Nat) : BitVec w :=
|
||||
x <<< n ||| x >>> (w - n)
|
||||
|
||||
@@ -626,7 +599,6 @@ SMT-LIB name: `rotate_left`, except this operator uses a `Nat` shift amount.
|
||||
Example:
|
||||
* `(0b0011#4).rotateLeft 3 = 0b1001`
|
||||
-/
|
||||
@[expose]
|
||||
def rotateLeft (x : BitVec w) (n : Nat) : BitVec w := rotateLeftAux x (n % w)
|
||||
|
||||
|
||||
@@ -634,7 +606,6 @@ def rotateLeft (x : BitVec w) (n : Nat) : BitVec w := rotateLeftAux x (n % w)
|
||||
Auxiliary function for `rotateRight`, which does not take into account the case where
|
||||
the rotation amount is greater than the bitvector width.
|
||||
-/
|
||||
@[expose]
|
||||
def rotateRightAux (x : BitVec w) (n : Nat) : BitVec w :=
|
||||
x >>> n ||| x <<< (w - n)
|
||||
|
||||
@@ -649,7 +620,6 @@ SMT-LIB name: `rotate_right`, except this operator uses a `Nat` shift amount.
|
||||
Example:
|
||||
* `rotateRight 0b01001#5 1 = 0b10100`
|
||||
-/
|
||||
@[expose]
|
||||
def rotateRight (x : BitVec w) (n : Nat) : BitVec w := rotateRightAux x (n % w)
|
||||
|
||||
/--
|
||||
@@ -661,7 +631,6 @@ SMT-LIB name: `concat`.
|
||||
Example:
|
||||
* `0xAB#8 ++ 0xCD#8 = 0xABCD#16`.
|
||||
-/
|
||||
@[expose]
|
||||
def append (msbs : BitVec n) (lsbs : BitVec m) : BitVec (n+m) :=
|
||||
shiftLeftZeroExtend msbs m ||| setWidth' (Nat.le_add_left m n) lsbs
|
||||
|
||||
@@ -684,7 +653,6 @@ result of appending a single bit to the front in the naive implementation).
|
||||
|
||||
/-- Append a single bit to the end of a bitvector, using big endian order (see `append`).
|
||||
That is, the new bit is the least significant bit. -/
|
||||
@[expose]
|
||||
def concat {n} (msbs : BitVec n) (lsb : Bool) : BitVec (n+1) := msbs ++ (ofBool lsb)
|
||||
|
||||
/--
|
||||
@@ -692,7 +660,6 @@ Shifts all bits of `x` to the left by `1` and sets the least significant bit to
|
||||
|
||||
This is a non-dependent version of `BitVec.concat` that does not change the total bitwidth.
|
||||
-/
|
||||
@[expose]
|
||||
def shiftConcat (x : BitVec n) (b : Bool) : BitVec n :=
|
||||
(x.concat b).truncate n
|
||||
|
||||
@@ -701,7 +668,6 @@ Prepends a single bit to the front of a bitvector, using big-endian order (see `
|
||||
|
||||
The new bit is the most significant bit.
|
||||
-/
|
||||
@[expose]
|
||||
def cons {n} (msb : Bool) (lsbs : BitVec n) : BitVec (n+1) :=
|
||||
((ofBool msb) ++ lsbs).cast (Nat.add_comm ..)
|
||||
|
||||
@@ -786,7 +752,6 @@ Checks whether subtraction of `x` and `y` results in *unsigned* overflow.
|
||||
|
||||
SMT-Lib name: `bvusubo`.
|
||||
-/
|
||||
@[expose]
|
||||
def usubOverflow {w : Nat} (x y : BitVec w) : Bool := x.toNat < y.toNat
|
||||
|
||||
/--
|
||||
@@ -795,7 +760,6 @@ Checks whether the subtraction of `x` and `y` results in *signed* overflow, trea
|
||||
|
||||
SMT-Lib name: `bvssubo`.
|
||||
-/
|
||||
@[expose]
|
||||
def ssubOverflow {w : Nat} (x y : BitVec w) : Bool :=
|
||||
(x.toInt - y.toInt ≥ 2 ^ (w - 1)) || (x.toInt - y.toInt < - 2 ^ (w - 1))
|
||||
|
||||
@@ -806,7 +770,6 @@ For a bitvector `x` with nonzero width, this only happens if `x = intMin`.
|
||||
|
||||
SMT-Lib name: `bvnego`.
|
||||
-/
|
||||
@[expose]
|
||||
def negOverflow {w : Nat} (x : BitVec w) : Bool :=
|
||||
x.toInt == - 2 ^ (w - 1)
|
||||
|
||||
@@ -816,7 +779,6 @@ For BitVecs `x` and `y` with nonzero width, this only happens if `x = intMin` an
|
||||
|
||||
SMT-LIB name: `bvsdivo`.
|
||||
-/
|
||||
@[expose]
|
||||
def sdivOverflow {w : Nat} (x y : BitVec w) : Bool :=
|
||||
(2 ^ (w - 1) ≤ x.toInt / y.toInt) || (x.toInt / y.toInt < - 2 ^ (w - 1))
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ The bitvector with value `i mod 2^n`.
|
||||
-/
|
||||
@[expose, match_pattern]
|
||||
protected def ofNat (n : Nat) (i : Nat) : BitVec n where
|
||||
toFin := Fin.ofNat (2^n) i
|
||||
toFin := Fin.ofNat' (2^n) i
|
||||
|
||||
instance instOfNat : OfNat (BitVec n) i where ofNat := .ofNat n i
|
||||
|
||||
@@ -41,7 +41,6 @@ Usually accessed via the `+` operator.
|
||||
|
||||
SMT-LIB name: `bvadd`.
|
||||
-/
|
||||
@[expose]
|
||||
protected def add (x y : BitVec n) : BitVec n := .ofNat n (x.toNat + y.toNat)
|
||||
instance : Add (BitVec n) := ⟨BitVec.add⟩
|
||||
|
||||
@@ -50,7 +49,6 @@ Subtracts one bitvector from another. This can be interpreted as either signed o
|
||||
modulo `2^n`. Usually accessed via the `-` operator.
|
||||
|
||||
-/
|
||||
@[expose]
|
||||
protected def sub (x y : BitVec n) : BitVec n := .ofNat n ((2^n - y.toNat) + x.toNat)
|
||||
instance : Sub (BitVec n) := ⟨BitVec.sub⟩
|
||||
|
||||
|
||||
@@ -631,7 +631,6 @@ A recurrence that describes multiplication as repeated addition.
|
||||
|
||||
This function is useful for bit blasting multiplication.
|
||||
-/
|
||||
@[expose]
|
||||
def mulRec (x y : BitVec w) (s : Nat) : BitVec w :=
|
||||
let cur := if y.getLsbD s then (x <<< s) else 0
|
||||
match s with
|
||||
@@ -1092,7 +1091,6 @@ theorem lawful_divSubtractShift (qr : DivModState w) (h : qr.Poised args) :
|
||||
/-! ### Core division algorithm circuit -/
|
||||
|
||||
/-- A recursive definition of division for bit blasting, in terms of a shift-subtraction circuit. -/
|
||||
@[expose]
|
||||
def divRec {w : Nat} (m : Nat) (args : DivModArgs w) (qr : DivModState w) :
|
||||
DivModState w :=
|
||||
match m with
|
||||
|
||||
@@ -68,11 +68,11 @@ theorem lt_of_getMsbD {x : BitVec w} {i : Nat} : getMsbD x i = true → i < w :=
|
||||
@[simp] theorem getElem?_eq_getElem {l : BitVec w} {n} (h : n < w) : l[n]? = some l[n] := by
|
||||
simp only [getElem?_def, h, ↓reduceDIte]
|
||||
|
||||
theorem getElem?_eq_some_iff {l : BitVec w} : l[n]? = some a ↔ ∃ h : n < w, l[n] = a :=
|
||||
_root_.getElem?_eq_some_iff
|
||||
|
||||
theorem some_eq_getElem?_iff {l : BitVec w} : some a = l[n]? ↔ ∃ h : n < w, l[n] = a :=
|
||||
_root_.some_eq_getElem?_iff
|
||||
theorem getElem?_eq_some_iff {l : BitVec w} : l[n]? = some a ↔ ∃ h : n < w, l[n] = a := by
|
||||
simp only [getElem?_def]
|
||||
split
|
||||
· simp_all
|
||||
· simp; omega
|
||||
|
||||
theorem getElem_of_getElem? {l : BitVec w} : l[n]? = some a → ∃ h : n < w, l[n] = a :=
|
||||
getElem?_eq_some_iff.mp
|
||||
@@ -81,11 +81,11 @@ set_option linter.missingDocs false in
|
||||
@[deprecated getElem?_eq_some_iff (since := "2025-02-17")]
|
||||
abbrev getElem?_eq_some := @getElem?_eq_some_iff
|
||||
|
||||
theorem getElem?_eq_none_iff {l : BitVec w} : l[n]? = none ↔ w ≤ n := by
|
||||
simp
|
||||
|
||||
theorem none_eq_getElem?_iff {l : BitVec w} : none = l[n]? ↔ w ≤ n := by
|
||||
simp
|
||||
@[simp] theorem getElem?_eq_none_iff {l : BitVec w} : l[n]? = none ↔ w ≤ n := by
|
||||
simp only [getElem?_def]
|
||||
split
|
||||
· simp_all
|
||||
· simp; omega
|
||||
|
||||
theorem getElem?_eq_none {l : BitVec w} (h : w ≤ n) : l[n]? = none := getElem?_eq_none_iff.mpr h
|
||||
|
||||
@@ -93,13 +93,13 @@ theorem getElem?_eq (l : BitVec w) (i : Nat) :
|
||||
l[i]? = if h : i < w then some l[i] else none := by
|
||||
split <;> simp_all
|
||||
|
||||
theorem some_getElem_eq_getElem? (l : BitVec w) (i : Nat) (h : i < w) :
|
||||
@[simp] theorem some_getElem_eq_getElem? (l : BitVec w) (i : Nat) (h : i < w) :
|
||||
(some l[i] = l[i]?) ↔ True := by
|
||||
simp
|
||||
simp [h]
|
||||
|
||||
theorem getElem?_eq_some_getElem (l : BitVec w) (i : Nat) (h : i < w) :
|
||||
@[simp] theorem getElem?_eq_some_getElem (l : BitVec w) (i : Nat) (h : i < w) :
|
||||
(l[i]? = some l[i]) ↔ True := by
|
||||
simp
|
||||
simp [h]
|
||||
|
||||
theorem getElem_eq_iff {l : BitVec w} {n : Nat} {h : n < w} : l[n] = x ↔ l[n]? = some x := by
|
||||
simp only [getElem?_eq_some_iff]
|
||||
@@ -125,7 +125,7 @@ theorem getElem_of_getLsbD_eq_true {x : BitVec w} {i : Nat} (h : x.getLsbD i = t
|
||||
This normalized a bitvec using `ofFin` to `ofNat`.
|
||||
-/
|
||||
theorem ofFin_eq_ofNat : @BitVec.ofFin w (Fin.mk x lt) = BitVec.ofNat w x := by
|
||||
simp only [BitVec.ofNat, Fin.ofNat, lt, Nat.mod_eq_of_lt]
|
||||
simp only [BitVec.ofNat, Fin.ofNat', lt, Nat.mod_eq_of_lt]
|
||||
|
||||
/-- Prove equality of bitvectors in terms of nat operations. -/
|
||||
theorem eq_of_toNat_eq {n} : ∀ {x y : BitVec n}, x.toNat = y.toNat → x = y
|
||||
@@ -314,7 +314,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, Nat.and_two_pow_sub_one_eq_mod]
|
||||
|
||||
@[simp] theorem ofFin_neg {x : Fin (2 ^ w)} : ofFin (-x) = -(ofFin x) := by
|
||||
rfl
|
||||
@@ -346,11 +346,11 @@ theorem toFin_one : toFin (1 : BitVec w) = 1 := by
|
||||
@[simp] theorem toInt_ofBool (b : Bool) : (ofBool b).toInt = -b.toInt := by
|
||||
cases b <;> simp
|
||||
|
||||
@[simp] theorem toFin_ofBool (b : Bool) : (ofBool b).toFin = Fin.ofNat 2 (b.toNat) := by
|
||||
@[simp] theorem toFin_ofBool (b : Bool) : (ofBool b).toFin = Fin.ofNat' 2 (b.toNat) := by
|
||||
cases b <;> rfl
|
||||
|
||||
theorem ofNat_one (n : Nat) : BitVec.ofNat 1 n = BitVec.ofBool (n % 2 = 1) := by
|
||||
rcases (Nat.mod_two_eq_zero_or_one n) with h | h <;> simp [h, BitVec.ofNat, Fin.ofNat]
|
||||
rcases (Nat.mod_two_eq_zero_or_one n) with h | h <;> simp [h, BitVec.ofNat, Fin.ofNat']
|
||||
|
||||
theorem ofBool_eq_iff_eq : ∀ {b b' : Bool}, BitVec.ofBool b = BitVec.ofBool b' ↔ b = b' := by
|
||||
decide
|
||||
@@ -390,12 +390,12 @@ theorem getMsbD_ofNatLt {n x i : Nat} (h : x < 2^n) :
|
||||
getMsbD (x#'h) i = (decide (i < n) && x.testBit (n - 1 - i)) := getMsbD_ofNatLT h
|
||||
|
||||
@[simp, bitvec_to_nat] theorem toNat_ofNat (x w : Nat) : (BitVec.ofNat w x).toNat = x % 2^w := by
|
||||
simp [BitVec.toNat, BitVec.ofNat, Fin.ofNat]
|
||||
simp [BitVec.toNat, BitVec.ofNat, Fin.ofNat']
|
||||
|
||||
theorem ofNatLT_eq_ofNat {w : Nat} {n : Nat} (hn) : BitVec.ofNatLT n hn = BitVec.ofNat w n :=
|
||||
eq_of_toNat_eq (by simp [Nat.mod_eq_of_lt hn])
|
||||
|
||||
@[simp] theorem toFin_ofNat (x : Nat) : toFin (BitVec.ofNat w x) = Fin.ofNat (2^w) x := rfl
|
||||
@[simp] theorem toFin_ofNat (x : Nat) : toFin (BitVec.ofNat w x) = Fin.ofNat' (2^w) x := rfl
|
||||
|
||||
@[simp] theorem finMk_toNat (x : BitVec w) : Fin.mk x.toNat x.isLt = x.toFin := rfl
|
||||
|
||||
@@ -415,7 +415,7 @@ theorem ofNatLT_eq_ofNat {w : Nat} {n : Nat} (hn) : BitVec.ofNatLT n hn = BitVec
|
||||
-- If `x` and `n` are not literals, applying this theorem eagerly may not be a good idea.
|
||||
theorem getLsbD_ofNat (n : Nat) (x : Nat) (i : Nat) :
|
||||
getLsbD (BitVec.ofNat n x) i = (i < n && x.testBit i) := by
|
||||
simp [getLsbD, BitVec.ofNat, Fin.val_ofNat]
|
||||
simp [getLsbD, BitVec.ofNat, Fin.val_ofNat']
|
||||
|
||||
@[simp] theorem getLsbD_zero : (0#w).getLsbD i = false := by simp [getLsbD]
|
||||
|
||||
@@ -505,7 +505,7 @@ theorem getLsbD_ofBool (b : Bool) (i : Nat) : (ofBool b).getLsbD i = ((i = 0) &&
|
||||
· simp only [ofBool, ofNat_eq_ofNat, cond_true, getLsbD_ofNat, Bool.and_true]
|
||||
by_cases hi : i = 0 <;> simp [hi] <;> omega
|
||||
|
||||
theorem getElem_ofBool_zero {b : Bool} : (ofBool b)[0] = b := by simp
|
||||
@[simp] theorem getElem_ofBool_zero {b : Bool} : (ofBool b)[0] = b := by simp
|
||||
|
||||
@[simp]
|
||||
theorem getElem_ofBool {b : Bool} {h : i < 1}: (ofBool b)[i] = b := by
|
||||
@@ -909,7 +909,7 @@ theorem zeroExtend_eq_setWidth {v : Nat} {x : BitVec w} :
|
||||
simp [toInt_eq_toNat_bmod, toNat_setWidth, Int.emod_bmod, -Int.natCast_pow]
|
||||
|
||||
@[simp] theorem toFin_setWidth {x : BitVec w} :
|
||||
(x.setWidth v).toFin = Fin.ofNat (2^v) x.toNat := by
|
||||
(x.setWidth v).toFin = Fin.ofNat' (2^v) x.toNat := by
|
||||
ext; simp
|
||||
|
||||
@[simp] theorem setWidth_eq (x : BitVec n) : setWidth n x = x := by
|
||||
@@ -1105,7 +1105,7 @@ theorem toInt_setWidth' {m n : Nat} (p : m ≤ n) {x : BitVec m} :
|
||||
@[simp] theorem toFin_setWidth' {m n : Nat} (p : m ≤ n) (x : BitVec m) :
|
||||
(setWidth' p x).toFin = x.toFin.castLE (Nat.pow_le_pow_right (by omega) (by omega)) := by
|
||||
ext
|
||||
rw [setWidth'_eq, toFin_setWidth, Fin.val_ofNat, Fin.coe_castLE, val_toFin,
|
||||
rw [setWidth'_eq, toFin_setWidth, Fin.val_ofNat', Fin.coe_castLE, val_toFin,
|
||||
Nat.mod_eq_of_lt (by apply BitVec.toNat_lt_twoPow_of_le p)]
|
||||
|
||||
/-! ## extractLsb -/
|
||||
@@ -1135,11 +1135,11 @@ protected theorem extractLsb_ofNat (x n : Nat) (hi lo : Nat) :
|
||||
simp [extractLsb, toInt_ofNat]
|
||||
|
||||
@[simp] theorem toFin_extractLsb' {s m : Nat} {x : BitVec n} :
|
||||
(extractLsb' s m x).toFin = Fin.ofNat (2 ^ m) (x.toNat >>> s) := by
|
||||
(extractLsb' s m x).toFin = Fin.ofNat' (2 ^ m) (x.toNat >>> s) := by
|
||||
simp [extractLsb', toInt_ofNat]
|
||||
|
||||
@[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
|
||||
(extractLsb hi lo x).toFin = Fin.ofNat' (2 ^ (hi - lo + 1)) (x.toNat >>> lo) := by
|
||||
simp [extractLsb, toInt_ofNat]
|
||||
|
||||
@[simp] theorem getElem_extractLsb' {start len : Nat} {x : BitVec n} {i : Nat} (h : i < len) :
|
||||
@@ -1310,7 +1310,7 @@ theorem extractLsb'_eq_zero {x : BitVec w} {start : Nat} :
|
||||
simp [BitVec.toInt, -Int.natCast_pow]
|
||||
omega
|
||||
|
||||
@[simp] theorem toFin_allOnes : (allOnes w).toFin = Fin.ofNat (2^w) (2^w - 1) := by
|
||||
@[simp] theorem toFin_allOnes : (allOnes w).toFin = Fin.ofNat' (2^w) (2^w - 1) := by
|
||||
ext
|
||||
simp
|
||||
|
||||
@@ -1847,7 +1847,7 @@ theorem not_xor_right {x y : BitVec w} : ~~~ (x ^^^ y) = x ^^^ ~~~ y := by
|
||||
simp [-Int.natCast_pow]
|
||||
|
||||
@[simp] theorem toFin_shiftLeft {n : Nat} (x : BitVec w) :
|
||||
(x <<< n).toFin = Fin.ofNat (2^w) (x.toNat <<< n) := rfl
|
||||
(x <<< n).toFin = Fin.ofNat' (2^w) (x.toNat <<< n) := rfl
|
||||
|
||||
@[simp]
|
||||
theorem shiftLeft_zero (x : BitVec w) : x <<< 0 = x := by
|
||||
@@ -2089,7 +2089,7 @@ theorem toInt_ushiftRight {x : BitVec w} {n : Nat} :
|
||||
|
||||
@[simp]
|
||||
theorem toFin_ushiftRight {x : BitVec w} {n : Nat} :
|
||||
(x >>> n).toFin = x.toFin / (Fin.ofNat (2^w) (2^n)) := by
|
||||
(x >>> n).toFin = x.toFin / (Fin.ofNat' (2^w) (2^n)) := by
|
||||
apply Fin.eq_of_val_eq
|
||||
by_cases hn : n < w
|
||||
· simp [Nat.shiftRight_eq_div_pow, Nat.mod_eq_of_lt (Nat.pow_lt_pow_of_lt Nat.one_lt_two hn)]
|
||||
@@ -2340,26 +2340,26 @@ theorem toNat_sshiftRight {x : BitVec w} {n : Nat} :
|
||||
simp [toNat_sshiftRight_of_msb_false, h]
|
||||
|
||||
theorem toFin_sshiftRight_of_msb_true {x : BitVec w} {n : Nat} (h : x.msb = true) :
|
||||
(x.sshiftRight n).toFin = Fin.ofNat (2^w) (2 ^ w - 1 - (2 ^ w - 1 - x.toNat) >>> n) := by
|
||||
(x.sshiftRight n).toFin = Fin.ofNat' (2^w) (2 ^ w - 1 - (2 ^ w - 1 - x.toNat) >>> n) := by
|
||||
apply Fin.eq_of_val_eq
|
||||
simp only [val_toFin, toNat_sshiftRight, h, ↓reduceIte, Fin.val_ofNat]
|
||||
simp only [val_toFin, toNat_sshiftRight, h, ↓reduceIte, Fin.val_ofNat']
|
||||
rw [Nat.mod_eq_of_lt]
|
||||
have := x.isLt
|
||||
have ineq : ∀ y, 2 ^ w - 1 - y < 2 ^ w := by omega
|
||||
exact ineq ((2 ^ w - 1 - x.toNat) >>> n)
|
||||
|
||||
theorem toFin_sshiftRight_of_msb_false {x : BitVec w} {n : Nat} (h : x.msb = false) :
|
||||
(x.sshiftRight n).toFin = Fin.ofNat (2^w) (x.toNat >>> n) := by
|
||||
(x.sshiftRight n).toFin = Fin.ofNat' (2^w) (x.toNat >>> n) := by
|
||||
apply Fin.eq_of_val_eq
|
||||
simp only [val_toFin, toNat_sshiftRight, h, Bool.false_eq_true, ↓reduceIte, Fin.val_ofNat]
|
||||
simp only [val_toFin, toNat_sshiftRight, h, Bool.false_eq_true, ↓reduceIte, Fin.val_ofNat']
|
||||
have := Nat.shiftRight_le x.toNat n
|
||||
rw [Nat.mod_eq_of_lt (by omega)]
|
||||
|
||||
theorem toFin_sshiftRight {x : BitVec w} {n : Nat} :
|
||||
(x.sshiftRight n).toFin =
|
||||
if x.msb
|
||||
then Fin.ofNat (2^w) (2 ^ w - 1 - (2 ^ w - 1 - x.toNat) >>> n)
|
||||
else Fin.ofNat (2^w) (x.toNat >>> n) := by
|
||||
then Fin.ofNat' (2^w) (2 ^ w - 1 - (2 ^ w - 1 - x.toNat) >>> n)
|
||||
else Fin.ofNat' (2^w) (x.toNat >>> n) := by
|
||||
by_cases h : x.msb
|
||||
· simp [toFin_sshiftRight_of_msb_true, h]
|
||||
· simp [toFin_sshiftRight_of_msb_false, h]
|
||||
@@ -2397,18 +2397,18 @@ theorem toNat_sshiftRight' {x y : BitVec w} :
|
||||
rw [sshiftRight_eq', toNat_sshiftRight]
|
||||
|
||||
theorem toFin_sshiftRight'_of_msb_true {x y : BitVec w} (h : x.msb = true) :
|
||||
(x.sshiftRight' y).toFin = Fin.ofNat (2^w) (2 ^ w - 1 - (2 ^ w - 1 - x.toNat) >>> y.toNat) := by
|
||||
(x.sshiftRight' y).toFin = Fin.ofNat' (2^w) (2 ^ w - 1 - (2 ^ w - 1 - x.toNat) >>> y.toNat) := by
|
||||
rw [sshiftRight_eq', toFin_sshiftRight_of_msb_true h]
|
||||
|
||||
theorem toFin_sshiftRight'_of_msb_false {x y : BitVec w} (h : x.msb = false) :
|
||||
(x.sshiftRight' y).toFin = Fin.ofNat (2^w) (x.toNat >>> y.toNat) := by
|
||||
(x.sshiftRight' y).toFin = Fin.ofNat' (2^w) (x.toNat >>> y.toNat) := by
|
||||
rw [sshiftRight_eq', toFin_sshiftRight_of_msb_false h]
|
||||
|
||||
theorem toFin_sshiftRight' {x y : BitVec w} :
|
||||
(x.sshiftRight' y).toFin =
|
||||
if x.msb
|
||||
then Fin.ofNat (2^w) (2 ^ w - 1 - (2 ^ w - 1 - x.toNat) >>> y.toNat)
|
||||
else Fin.ofNat (2^w) (x.toNat >>> y.toNat) := by
|
||||
then Fin.ofNat' (2^w) (2 ^ w - 1 - (2 ^ w - 1 - x.toNat) >>> y.toNat)
|
||||
else Fin.ofNat' (2^w) (x.toNat >>> y.toNat) := by
|
||||
rw [sshiftRight_eq', toFin_sshiftRight]
|
||||
|
||||
theorem toInt_sshiftRight' {x y : BitVec w} :
|
||||
@@ -2614,16 +2614,16 @@ theorem toInt_signExtend_eq_toInt_bmod_of_le (x : BitVec w) (h : v ≤ w) :
|
||||
rw [BitVec.toInt_signExtend, Nat.min_eq_left h]
|
||||
|
||||
theorem toFin_signExtend_of_le {x : BitVec w} (hv : v ≤ w):
|
||||
(x.signExtend v).toFin = Fin.ofNat (2 ^ v) x.toNat := by
|
||||
(x.signExtend v).toFin = Fin.ofNat' (2 ^ v) x.toNat := by
|
||||
simp [signExtend_eq_setWidth_of_le _ hv]
|
||||
|
||||
theorem toFin_signExtend (x : BitVec w) :
|
||||
(x.signExtend v).toFin = Fin.ofNat (2 ^ v) (x.toNat + if x.msb = true then 2 ^ v - 2 ^ w else 0):= by
|
||||
(x.signExtend v).toFin = Fin.ofNat' (2 ^ v) (x.toNat + if x.msb = true then 2 ^ v - 2 ^ w else 0):= by
|
||||
by_cases hv : v ≤ w
|
||||
· simp [toFin_signExtend_of_le hv, show 2 ^ v - 2 ^ w = 0 by rw [@Nat.sub_eq_zero_iff_le]; apply Nat.pow_le_pow_of_le (by decide) (by omega)]
|
||||
· simp only [Nat.not_le] at hv
|
||||
apply Fin.eq_of_val_eq
|
||||
simp only [val_toFin, Fin.val_ofNat]
|
||||
simp only [val_toFin, Fin.val_ofNat']
|
||||
rw [toNat_signExtend_of_le _ (by omega)]
|
||||
have : 2 ^ w < 2 ^ v := by apply Nat.pow_lt_pow_of_lt <;> omega
|
||||
rw [Nat.mod_eq_of_lt]
|
||||
@@ -3179,11 +3179,11 @@ theorem getElem_concat (x : BitVec w) (b : Bool) (i : Nat) (h : i < w + 1) :
|
||||
· simp [Nat.mod_eq_of_lt b.toNat_lt]
|
||||
· simp [Nat.div_eq_of_lt b.toNat_lt, Nat.testBit_add_one]
|
||||
|
||||
@[simp] theorem getElem_concat_zero : (concat x b)[0] = b := by
|
||||
@[simp] theorem getLsbD_concat_zero : (concat x b).getLsbD 0 = b := by
|
||||
simp [getElem_concat]
|
||||
|
||||
theorem getLsbD_concat_zero : (concat x b).getLsbD 0 = b := by
|
||||
simp
|
||||
@[simp] theorem getElem_concat_zero : (concat x b)[0] = b := by
|
||||
simp [getElem_concat]
|
||||
|
||||
@[simp] theorem getLsbD_concat_succ : (concat x b).getLsbD (i + 1) = x.getLsbD i := by
|
||||
simp [getLsbD_concat]
|
||||
@@ -3323,19 +3323,11 @@ Definition of bitvector addition as a nat.
|
||||
|
||||
theorem ofNat_add {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_add]
|
||||
simp [BitVec.ofNat, Fin.ofNat'_add]
|
||||
|
||||
theorem ofNat_add_ofNat {n} (x y : Nat) : BitVec.ofNat n x + BitVec.ofNat n y = BitVec.ofNat n (x + y) :=
|
||||
(ofNat_add x y).symm
|
||||
|
||||
@[simp]
|
||||
theorem toNat_add_of_not_uaddOverflow {x y : BitVec w} (h : ¬ uaddOverflow x y) :
|
||||
(x + y).toNat = x.toNat + y.toNat := by
|
||||
rcases w with _|w
|
||||
· simp [of_length_zero]
|
||||
· simp only [uaddOverflow, ge_iff_le, decide_eq_true_eq, Nat.not_le] at h
|
||||
rw [toNat_add, Nat.mod_eq_of_lt h]
|
||||
|
||||
protected theorem add_assoc (x y z : BitVec n) : x + y + z = x + (y + z) := by
|
||||
apply eq_of_toNat_eq ; simp [Nat.add_assoc]
|
||||
instance : Std.Associative (α := BitVec n) (· + ·) := ⟨BitVec.add_assoc⟩
|
||||
@@ -3365,15 +3357,6 @@ theorem ofInt_add {n} (x y : Int) : BitVec.ofInt n (x + y) =
|
||||
apply eq_of_toInt_eq
|
||||
simp
|
||||
|
||||
@[simp]
|
||||
theorem toInt_add_of_not_saddOverflow {x y : BitVec w} (h : ¬ saddOverflow x y) :
|
||||
(x + y).toInt = x.toInt + y.toInt := by
|
||||
rcases w with _|w
|
||||
· simp [of_length_zero]
|
||||
· simp only [saddOverflow, Nat.add_one_sub_one, ge_iff_le, Bool.or_eq_true, decide_eq_true_eq,
|
||||
_root_.not_or, Int.not_le, Int.not_lt] at h
|
||||
rw [toInt_add, Int.bmod_eq_of_le (by push_cast; omega) (by push_cast; omega)]
|
||||
|
||||
@[simp]
|
||||
theorem shiftLeft_add_distrib {x y : BitVec w} {n : Nat} :
|
||||
(x + y) <<< n = x <<< n + y <<< n := by
|
||||
@@ -3399,24 +3382,6 @@ theorem sub_def {n} (x y : BitVec n) : x - y = .ofNat n ((2^n - y.toNat) + x.toN
|
||||
(x - y).toInt = (x.toInt - y.toInt).bmod (2 ^ w) := by
|
||||
simp [toInt_eq_toNat_bmod, @Int.ofNat_sub y.toNat (2 ^ w) (by omega), -Int.natCast_pow]
|
||||
|
||||
@[simp]
|
||||
theorem toNat_sub_of_not_usubOverflow {x y : BitVec w} (h : ¬ usubOverflow x y) :
|
||||
(x - y).toNat = x.toNat - y.toNat := by
|
||||
rcases w with _|w
|
||||
· simp [of_length_zero]
|
||||
· simp only [usubOverflow, decide_eq_true_eq, Nat.not_lt] at h
|
||||
rw [toNat_sub, ← Nat.sub_add_comm (by omega), Nat.add_sub_assoc h, Nat.add_mod_left,
|
||||
Nat.mod_eq_of_lt (by omega)]
|
||||
|
||||
@[simp]
|
||||
theorem toInt_sub_of_not_ssubOverflow {x y : BitVec w} (h : ¬ ssubOverflow x y) :
|
||||
(x - y).toInt = x.toInt - y.toInt := by
|
||||
rcases w with _|w
|
||||
· simp [of_length_zero]
|
||||
· simp only [ssubOverflow, Nat.add_one_sub_one, ge_iff_le, Bool.or_eq_true, decide_eq_true_eq,
|
||||
_root_.not_or, Int.not_le, Int.not_lt] at h
|
||||
rw [toInt_sub, Int.bmod_eq_of_le (by push_cast; omega) (by push_cast; omega)]
|
||||
|
||||
theorem toInt_sub_toInt_lt_twoPow_iff {x y : BitVec w} :
|
||||
(x.toInt - y.toInt < - 2 ^ (w - 1))
|
||||
↔ (x.toInt < 0 ∧ 0 ≤ y.toInt ∧ 0 ≤ (x.toInt - y.toInt).bmod (2 ^ w)) := by
|
||||
@@ -3468,7 +3433,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, Fin.ofNat'_sub]
|
||||
|
||||
@[simp] protected theorem sub_zero (x : BitVec n) : x - 0#n = x := by apply eq_of_toNat_eq ; simp
|
||||
|
||||
@@ -3495,21 +3460,11 @@ theorem toInt_neg {x : BitVec w} :
|
||||
rw [← BitVec.zero_sub, toInt_sub]
|
||||
simp [BitVec.toInt_ofNat]
|
||||
|
||||
@[simp]
|
||||
theorem toInt_neg_of_not_negOverflow {x : BitVec w} (h : ¬ negOverflow x):
|
||||
(-x).toInt = -x.toInt := by
|
||||
rcases w with _|w
|
||||
· simp [of_length_zero]
|
||||
· have := toInt_lt (x := x); simp only [Nat.add_one_sub_one] at this
|
||||
have := le_toInt (x := x); simp only [Nat.add_one_sub_one] at this
|
||||
simp only [negOverflow, Nat.add_one_sub_one, beq_iff_eq] at h
|
||||
rw [toInt_neg, Int.bmod_eq_of_le (by push_cast; omega) (by push_cast; omega)]
|
||||
|
||||
theorem ofInt_neg {w : Nat} {n : Int} : BitVec.ofInt w (-n) = -BitVec.ofInt w n :=
|
||||
eq_of_toInt_eq (by simp [toInt_neg])
|
||||
|
||||
@[simp] theorem toFin_neg (x : BitVec n) :
|
||||
(-x).toFin = Fin.ofNat (2^n) (2^n - x.toNat) :=
|
||||
(-x).toFin = Fin.ofNat' (2^n) (2^n - x.toNat) :=
|
||||
rfl
|
||||
|
||||
theorem sub_eq_add_neg {n} (x y : BitVec n) : x - y = x + - y := by
|
||||
@@ -3724,7 +3679,7 @@ theorem fill_false {w : Nat} : fill w false = 0#w := by
|
||||
by_cases h : v <;> simp [h]
|
||||
|
||||
@[simp] theorem fill_toFin {w : Nat} {v : Bool} :
|
||||
(fill w v).toFin = if v = true then (allOnes w).toFin else Fin.ofNat (2 ^ w) 0 := by
|
||||
(fill w v).toFin = if v = true then (allOnes w).toFin else Fin.ofNat' (2 ^ w) 0 := by
|
||||
by_cases h : v <;> simp [h]
|
||||
|
||||
/-! ### mul -/
|
||||
@@ -3736,7 +3691,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, Fin.ofNat'_mul]
|
||||
|
||||
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
|
||||
@@ -3794,23 +3749,6 @@ theorem two_mul {x : BitVec w} : 2#w * x = x + x := by rw [BitVec.mul_comm, mul_
|
||||
(x * y).toInt = (x.toInt * y.toInt).bmod (2^w) := by
|
||||
simp [toInt_eq_toNat_bmod, -Int.natCast_pow]
|
||||
|
||||
@[simp]
|
||||
theorem toNat_mul_of_not_umulOverflow {x y : BitVec w} (h : ¬ umulOverflow x y) :
|
||||
(x * y).toNat = x.toNat * y.toNat := by
|
||||
rcases w with _|w
|
||||
· simp [of_length_zero]
|
||||
· simp only [umulOverflow, ge_iff_le, decide_eq_true_eq, Nat.not_le] at h
|
||||
rw [toNat_mul, Nat.mod_eq_of_lt h]
|
||||
|
||||
@[simp]
|
||||
theorem toInt_mul_of_not_smulOverflow {x y : BitVec w} (h : ¬ smulOverflow x y) :
|
||||
(x * y).toInt = x.toInt * y.toInt := by
|
||||
rcases w with _|w
|
||||
· simp [of_length_zero]
|
||||
· simp only [smulOverflow, Nat.add_one_sub_one, ge_iff_le, Bool.or_eq_true, decide_eq_true_eq,
|
||||
_root_.not_or, Int.not_le, Int.not_lt] at h
|
||||
rw [toInt_mul, Int.bmod_eq_of_le (by push_cast; omega) (by push_cast; omega)]
|
||||
|
||||
theorem ofInt_mul {n} (x y : Int) : BitVec.ofInt n (x * y) =
|
||||
BitVec.ofInt n x * BitVec.ofInt n y := by
|
||||
apply eq_of_toInt_eq
|
||||
@@ -4624,7 +4562,7 @@ theorem toInt_rotateLeft {x : BitVec w} {r : Nat} :
|
||||
|
||||
theorem toFin_rotateLeft {x : BitVec w} {r : Nat} :
|
||||
(x.rotateLeft r).toFin =
|
||||
Fin.ofNat (2 ^ w) (x.toNat <<< (r % w)) ||| x.toFin / Fin.ofNat (2 ^ w) (2 ^ (w - r % w)) := by
|
||||
Fin.ofNat' (2 ^ w) (x.toNat <<< (r % w)) ||| x.toFin / Fin.ofNat' (2 ^ w) (2 ^ (w - r % w)) := by
|
||||
simp [rotateLeft_def, toFin_shiftLeft, toFin_ushiftRight, toFin_or]
|
||||
|
||||
/-! ## Rotate Right -/
|
||||
@@ -4786,7 +4724,7 @@ theorem toInt_rotateRight {x : BitVec w} {r : Nat} :
|
||||
simp [rotateRight_def, toInt_shiftLeft, toInt_ushiftRight, 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
|
||||
(x.rotateRight r).toFin = x.toFin / Fin.ofNat' (2 ^ w) (2 ^ (r % w)) ||| Fin.ofNat' (2 ^ w) (x.toNat <<< (w - r % w)) := by
|
||||
simp [rotateRight_def, toFin_shiftLeft, toFin_ushiftRight, toFin_or]
|
||||
|
||||
/- ## twoPow -/
|
||||
@@ -4858,7 +4796,7 @@ theorem toInt_twoPow {w i : Nat} :
|
||||
· simp [h, h', show i < w + 1 by omega, Int.natCast_pow]
|
||||
|
||||
theorem toFin_twoPow {w i : Nat} :
|
||||
(BitVec.twoPow w i).toFin = Fin.ofNat (2^w) (2^i) := by
|
||||
(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]
|
||||
@@ -5502,7 +5440,7 @@ theorem toInt_abs_eq_natAbs_of_ne_intMin {x : BitVec w} (hx : x ≠ intMin w) :
|
||||
simp [toInt_abs_eq_natAbs, hx]
|
||||
|
||||
theorem toFin_abs {x : BitVec w} :
|
||||
x.abs.toFin = if x.msb then Fin.ofNat (2 ^ w) (2 ^ w - x.toNat) else x.toFin := by
|
||||
x.abs.toFin = if x.msb then Fin.ofNat' (2 ^ w) (2 ^ w - x.toNat) else x.toFin := by
|
||||
by_cases h : x.msb <;> simp [BitVec.abs, h]
|
||||
|
||||
/-! ### Reverse -/
|
||||
|
||||
@@ -455,7 +455,7 @@ theorem toNat_lt (b : Bool) : b.toNat < 2 :=
|
||||
/--
|
||||
Converts `true` to `1` and `false` to `0`.
|
||||
-/
|
||||
@[expose] def toInt (b : Bool) : Int := cond b 1 0
|
||||
def toInt (b : Bool) : Int := cond b 1 0
|
||||
|
||||
@[simp] theorem toInt_false : false.toInt = 0 := rfl
|
||||
|
||||
|
||||
@@ -205,7 +205,7 @@ def foldlM {β : Type v} {m : Type v → Type w} [Monad m] (f : β → UInt8 →
|
||||
|
||||
@[inline]
|
||||
def foldl {β : Type v} (f : β → UInt8 → β) (init : β) (as : ByteArray) (start := 0) (stop := as.size) : β :=
|
||||
Id.run <| as.foldlM (pure <| f · ·) init start stop
|
||||
Id.run <| as.foldlM f init start stop
|
||||
|
||||
/-- Iterator over the bytes (`UInt8`) of a `ByteArray`.
|
||||
|
||||
|
||||
@@ -46,12 +46,15 @@ Returns `a` modulo `n` as a `Fin n`.
|
||||
|
||||
The assumption `NeZero n` ensures that `Fin n` is nonempty.
|
||||
-/
|
||||
@[expose] protected def ofNat (n : Nat) [NeZero n] (a : Nat) : Fin n :=
|
||||
@[expose] protected def ofNat' (n : Nat) [NeZero n] (a : Nat) : Fin n :=
|
||||
⟨a % n, Nat.mod_lt _ (pos_of_neZero n)⟩
|
||||
|
||||
@[deprecated Fin.ofNat (since := "2025-05-28")]
|
||||
protected def ofNat' (n : Nat) [NeZero n] (a : Nat) : Fin n :=
|
||||
Fin.ofNat n a
|
||||
/--
|
||||
Returns `a` modulo `n + 1` as a `Fin n.succ`.
|
||||
-/
|
||||
@[deprecated Fin.ofNat' (since := "2024-11-27")]
|
||||
protected def ofNat {n : Nat} (a : Nat) : Fin (n + 1) :=
|
||||
⟨a % (n+1), Nat.mod_lt _ (Nat.zero_lt_succ _)⟩
|
||||
|
||||
-- We provide this because other similar types have a `toNat` function, but `simp` rewrites
|
||||
-- `i.toNat` to `i.val`.
|
||||
@@ -227,7 +230,7 @@ instance : ShiftRight (Fin n) where
|
||||
shiftRight := Fin.shiftRight
|
||||
|
||||
instance instOfNat {n : Nat} [NeZero n] {i : Nat} : OfNat (Fin n) i where
|
||||
ofNat := Fin.ofNat n i
|
||||
ofNat := Fin.ofNat' n i
|
||||
|
||||
/-- If you actually have an element of `Fin n`, then the `n` is always positive -/
|
||||
protected theorem pos (i : Fin n) : 0 < n :=
|
||||
|
||||
@@ -266,7 +266,7 @@ theorem foldl_add (f : α → Fin (n + m) → α) (x) :
|
||||
| succ m ih => simp [foldl_succ_last, ih, ← Nat.add_assoc]
|
||||
|
||||
theorem foldl_eq_foldlM (f : α → Fin n → α) (x) :
|
||||
foldl n f x = (foldlM (m := Id) n (pure <| f · ·) x).run := by
|
||||
foldl n f x = foldlM (m:=Id) n f x := by
|
||||
induction n generalizing x <;> simp [foldl_succ, foldlM_succ, *]
|
||||
|
||||
-- This is not marked `@[simp]` as it would match on every occurrence of `foldlM`.
|
||||
@@ -319,7 +319,7 @@ theorem foldr_add (f : Fin (n + m) → α → α) (x) :
|
||||
| succ m ih => simp [foldr_succ_last, ih, ← Nat.add_assoc]
|
||||
|
||||
theorem foldr_eq_foldrM (f : Fin n → α → α) (x) :
|
||||
foldr n f x = (foldrM (m := Id) n (pure <| f · ·) x).run := by
|
||||
foldr n f x = foldrM (m:=Id) n f x := by
|
||||
induction n <;> simp [foldr_succ, foldrM_succ, *]
|
||||
|
||||
theorem foldl_rev (f : Fin n → α → α) (x) :
|
||||
|
||||
@@ -15,9 +15,10 @@ import Init.Omega
|
||||
|
||||
namespace Fin
|
||||
|
||||
@[simp] theorem ofNat_zero (n : Nat) [NeZero n] : Fin.ofNat n 0 = 0 := rfl
|
||||
@[simp] theorem ofNat'_zero (n : Nat) [NeZero n] : Fin.ofNat' n 0 = 0 := rfl
|
||||
|
||||
@[deprecated ofNat_zero (since := "2025-05-28")] abbrev ofNat'_zero := @ofNat_zero
|
||||
@[deprecated Fin.pos (since := "2024-11-11")]
|
||||
theorem size_pos (i : Fin n) : 0 < n := i.pos
|
||||
|
||||
theorem mod_def (a m : Fin n) : a % m = Fin.mk (a % m) (Nat.lt_of_le_of_lt (Nat.mod_le _ _) a.2) :=
|
||||
rfl
|
||||
@@ -28,6 +29,8 @@ theorem sub_def (a b : Fin n) : a - b = Fin.mk (((n - b) + a) % n) (Nat.mod_lt _
|
||||
|
||||
theorem pos' : ∀ [Nonempty (Fin n)], 0 < n | ⟨i⟩ => i.pos
|
||||
|
||||
@[deprecated pos' (since := "2024-11-11")] abbrev size_pos' := @pos'
|
||||
|
||||
@[simp] theorem is_lt (a : Fin n) : (a : Nat) < n := a.2
|
||||
|
||||
theorem pos_iff_nonempty {n : Nat} : 0 < n ↔ Nonempty (Fin n) :=
|
||||
@@ -63,25 +66,19 @@ theorem mk_val (i : Fin n) : (⟨i, i.isLt⟩ : Fin n) = i := Fin.eta ..
|
||||
0 = (⟨a, ha⟩ : Fin n) ↔ a = 0 := by
|
||||
simp [eq_comm]
|
||||
|
||||
@[simp] theorem val_ofNat (n : Nat) [NeZero n] (a : Nat) :
|
||||
(Fin.ofNat n a).val = a % n := rfl
|
||||
@[simp] theorem val_ofNat' (n : Nat) [NeZero n] (a : Nat) :
|
||||
(Fin.ofNat' n a).val = a % n := rfl
|
||||
|
||||
@[deprecated val_ofNat (since := "2025-05-28")] abbrev val_ofNat' := @val_ofNat
|
||||
|
||||
@[simp] theorem ofNat_self {n : Nat} [NeZero n] : Fin.ofNat n n = 0 := by
|
||||
@[simp] theorem ofNat'_self {n : Nat} [NeZero n] : Fin.ofNat' n n = 0 := by
|
||||
ext
|
||||
simp
|
||||
congr
|
||||
|
||||
@[deprecated ofNat_self (since := "2025-05-28")] abbrev ofNat'_self := @ofNat_self
|
||||
|
||||
@[simp] theorem ofNat_val_eq_self [NeZero n] (x : Fin n) : (Fin.ofNat n x) = x := by
|
||||
@[simp] theorem ofNat'_val_eq_self [NeZero n] (x : Fin n) : (Fin.ofNat' n x) = x := by
|
||||
ext
|
||||
rw [val_ofNat, Nat.mod_eq_of_lt]
|
||||
rw [val_ofNat', Nat.mod_eq_of_lt]
|
||||
exact x.2
|
||||
|
||||
@[deprecated ofNat_val_eq_self (since := "2025-05-28")] abbrev ofNat'_val_eq_self := @ofNat_val_eq_self
|
||||
|
||||
@[simp] theorem mod_val (a b : Fin n) : (a % b).val = a.val % b.val :=
|
||||
rfl
|
||||
|
||||
@@ -103,20 +100,19 @@ theorem dite_val {n : Nat} {c : Prop} [Decidable c] {x y : Fin n} :
|
||||
by_cases c <;> simp [*]
|
||||
|
||||
instance (n : Nat) [NeZero n] : NatCast (Fin n) where
|
||||
natCast a := Fin.ofNat n a
|
||||
natCast a := Fin.ofNat' n a
|
||||
|
||||
@[expose]
|
||||
def intCast [NeZero n] (a : Int) : Fin n :=
|
||||
if 0 ≤ a then
|
||||
Fin.ofNat n a.natAbs
|
||||
Fin.ofNat' n a.natAbs
|
||||
else
|
||||
- Fin.ofNat n a.natAbs
|
||||
- Fin.ofNat' n a.natAbs
|
||||
|
||||
instance (n : Nat) [NeZero n] : IntCast (Fin n) where
|
||||
intCast := Fin.intCast
|
||||
|
||||
theorem intCast_def {n : Nat} [NeZero n] (x : Int) :
|
||||
(x : Fin n) = if 0 ≤ x then Fin.ofNat n x.natAbs else -Fin.ofNat n x.natAbs := rfl
|
||||
(x : Fin n) = if 0 ≤ x then Fin.ofNat' n x.natAbs else -Fin.ofNat' n x.natAbs := rfl
|
||||
|
||||
/-! ### order -/
|
||||
|
||||
@@ -801,7 +797,7 @@ parameter, `Fin.cases` is the corresponding case analysis operator, and `Fin.rev
|
||||
version that starts at the greatest value instead of `0`.
|
||||
-/
|
||||
-- FIXME: Performance review
|
||||
@[elab_as_elim, expose] def induction {motive : Fin (n + 1) → Sort _} (zero : motive 0)
|
||||
@[elab_as_elim] def induction {motive : Fin (n + 1) → Sort _} (zero : motive 0)
|
||||
(succ : ∀ i : Fin n, motive (castSucc i) → motive i.succ) :
|
||||
∀ i : Fin (n + 1), motive i
|
||||
| ⟨i, hi⟩ => go i hi
|
||||
@@ -843,7 +839,7 @@ The two cases are:
|
||||
|
||||
The corresponding induction principle is `Fin.induction`.
|
||||
-/
|
||||
@[elab_as_elim, expose] def cases {motive : Fin (n + 1) → Sort _}
|
||||
@[elab_as_elim] def cases {motive : Fin (n + 1) → Sort _}
|
||||
(zero : motive 0) (succ : ∀ i : Fin n, motive i.succ) :
|
||||
∀ i : Fin (n + 1), motive i := induction zero fun i _ => succ i
|
||||
|
||||
@@ -969,38 +965,30 @@ theorem val_ne_zero_iff [NeZero n] {a : Fin n} : a.val ≠ 0 ↔ a ≠ 0 :=
|
||||
|
||||
/-! ### add -/
|
||||
|
||||
theorem ofNat_add [NeZero n] (x : Nat) (y : Fin n) :
|
||||
Fin.ofNat n x + y = Fin.ofNat n (x + y.val) := by
|
||||
theorem ofNat'_add [NeZero n] (x : Nat) (y : Fin n) :
|
||||
Fin.ofNat' n x + y = Fin.ofNat' n (x + y.val) := by
|
||||
apply Fin.eq_of_val_eq
|
||||
simp [Fin.ofNat, Fin.add_def]
|
||||
simp [Fin.ofNat', Fin.add_def]
|
||||
|
||||
@[deprecated ofNat_add (since := "2025-05-28")] abbrev ofNat_add' := @ofNat_add
|
||||
|
||||
theorem add_ofNat [NeZero n] (x : Fin n) (y : Nat) :
|
||||
x + Fin.ofNat n y = Fin.ofNat n (x.val + y) := by
|
||||
theorem add_ofNat' [NeZero n] (x : Fin n) (y : Nat) :
|
||||
x + Fin.ofNat' n y = Fin.ofNat' n (x.val + y) := by
|
||||
apply Fin.eq_of_val_eq
|
||||
simp [Fin.ofNat, Fin.add_def]
|
||||
|
||||
@[deprecated add_ofNat (since := "2025-05-28")] abbrev add_ofNat' := @add_ofNat
|
||||
simp [Fin.ofNat', Fin.add_def]
|
||||
|
||||
/-! ### sub -/
|
||||
|
||||
protected theorem coe_sub (a b : Fin n) : ((a - b : Fin n) : Nat) = ((n - b) + a) % n := by
|
||||
cases a; cases b; rfl
|
||||
|
||||
theorem ofNat_sub [NeZero n] (x : Nat) (y : Fin n) :
|
||||
Fin.ofNat n x - y = Fin.ofNat n ((n - y.val) + x) := by
|
||||
theorem ofNat'_sub [NeZero n] (x : Nat) (y : Fin n) :
|
||||
Fin.ofNat' n x - y = Fin.ofNat' n ((n - y.val) + x) := by
|
||||
apply Fin.eq_of_val_eq
|
||||
simp [Fin.ofNat, Fin.sub_def]
|
||||
simp [Fin.ofNat', Fin.sub_def]
|
||||
|
||||
@[deprecated ofNat_sub (since := "2025-05-28")] abbrev ofNat_sub' := @ofNat_sub
|
||||
|
||||
theorem sub_ofNat [NeZero n] (x : Fin n) (y : Nat) :
|
||||
x - Fin.ofNat n y = Fin.ofNat n ((n - y % n) + x.val) := by
|
||||
theorem sub_ofNat' [NeZero n] (x : Fin n) (y : Nat) :
|
||||
x - Fin.ofNat' n y = Fin.ofNat' n ((n - y % n) + x.val) := by
|
||||
apply Fin.eq_of_val_eq
|
||||
simp [Fin.ofNat, Fin.sub_def]
|
||||
|
||||
@[deprecated sub_ofNat (since := "2025-05-28")] abbrev sub_ofNat' := @sub_ofNat
|
||||
simp [Fin.ofNat', Fin.sub_def]
|
||||
|
||||
@[simp] protected theorem sub_self [NeZero n] {x : Fin n} : x - x = 0 := by
|
||||
ext
|
||||
@@ -1047,19 +1035,15 @@ theorem val_neg {n : Nat} [NeZero n] (x : Fin n) :
|
||||
|
||||
/-! ### mul -/
|
||||
|
||||
theorem ofNat_mul [NeZero n] (x : Nat) (y : Fin n) :
|
||||
Fin.ofNat n x * y = Fin.ofNat n (x * y.val) := by
|
||||
theorem ofNat'_mul [NeZero n] (x : Nat) (y : Fin n) :
|
||||
Fin.ofNat' n x * y = Fin.ofNat' n (x * y.val) := by
|
||||
apply Fin.eq_of_val_eq
|
||||
simp [Fin.ofNat, Fin.mul_def]
|
||||
simp [Fin.ofNat', Fin.mul_def]
|
||||
|
||||
@[deprecated ofNat_mul (since := "2025-05-28")] abbrev ofNat_mul' := @ofNat_mul
|
||||
|
||||
theorem mul_ofNat [NeZero n] (x : Fin n) (y : Nat) :
|
||||
x * Fin.ofNat n y = Fin.ofNat n (x.val * y) := by
|
||||
theorem mul_ofNat' [NeZero n] (x : Fin n) (y : Nat) :
|
||||
x * Fin.ofNat' n y = Fin.ofNat' n (x.val * y) := by
|
||||
apply Fin.eq_of_val_eq
|
||||
simp [Fin.ofNat, Fin.mul_def]
|
||||
|
||||
@[deprecated mul_ofNat (since := "2025-05-28")] abbrev mul_ofNat' := @mul_ofNat
|
||||
simp [Fin.ofNat', Fin.mul_def]
|
||||
|
||||
theorem val_mul {n : Nat} : ∀ a b : Fin n, (a * b).val = a.val * b.val % n
|
||||
| ⟨_, _⟩, ⟨_, _⟩ => rfl
|
||||
|
||||
@@ -165,7 +165,7 @@ def foldlM {β : Type v} {m : Type v → Type w} [Monad m] (f : β → Float →
|
||||
|
||||
@[inline]
|
||||
def foldl {β : Type v} (f : β → Float → β) (init : β) (as : FloatArray) (start := 0) (stop := as.size) : β :=
|
||||
Id.run <| as.foldlM (pure <| f · ·) init start stop
|
||||
Id.run <| as.foldlM f init start stop
|
||||
|
||||
end FloatArray
|
||||
|
||||
|
||||
@@ -142,36 +142,17 @@ private structure WorkItem where
|
||||
indent : Int
|
||||
activeTags : Nat
|
||||
|
||||
/--
|
||||
A directive indicating whether a given work group is able to be flattened.
|
||||
|
||||
- `allow` indicates that the group is allowed to be flattened; its argument is `true` if
|
||||
there is sufficient space for it to be flattened (and so it should be), or `false` if not.
|
||||
- `disallow` means that this group should not be flattened irrespective of space concerns.
|
||||
This is used at levels of a `Format` outside of any flattening groups. It is necessary to track
|
||||
this so that, after a hard line break, we know whether to try to flatten the next line.
|
||||
-/
|
||||
inductive FlattenAllowability where
|
||||
| allow (fits : Bool)
|
||||
| disallow
|
||||
deriving BEq
|
||||
|
||||
/-- Whether the given directive indicates that flattening should occur. -/
|
||||
def FlattenAllowability.shouldFlatten : FlattenAllowability → Bool
|
||||
| allow true => true
|
||||
| _ => false
|
||||
|
||||
private structure WorkGroup where
|
||||
fla : FlattenAllowability
|
||||
flb : FlattenBehavior
|
||||
items : List WorkItem
|
||||
flatten : Bool
|
||||
flb : FlattenBehavior
|
||||
items : List WorkItem
|
||||
|
||||
private partial def spaceUptoLine' : List WorkGroup → Nat → Nat → SpaceResult
|
||||
| [], _, _ => {}
|
||||
| { items := [], .. }::gs, col, w => spaceUptoLine' gs col w
|
||||
| g@{ items := i::is, .. }::gs, col, w =>
|
||||
merge w
|
||||
(spaceUptoLine i.f g.fla.shouldFlatten (w + col - i.indent) w)
|
||||
(spaceUptoLine i.f g.flatten (w + col - i.indent) w)
|
||||
(spaceUptoLine' ({ g with items := is }::gs) col)
|
||||
|
||||
/-- A monad in which we can pretty-print `Format` objects. -/
|
||||
@@ -188,11 +169,11 @@ open MonadPrettyFormat
|
||||
private def pushGroup (flb : FlattenBehavior) (items : List WorkItem) (gs : List WorkGroup) (w : Nat) [Monad m] [MonadPrettyFormat m] : m (List WorkGroup) := do
|
||||
let k ← currColumn
|
||||
-- Flatten group if it + the remainder (gs) fits in the remaining space. For `fill`, measure only up to the next (ungrouped) line break.
|
||||
let g := { fla := .allow (flb == FlattenBehavior.allOrNone), flb := flb, items := items : WorkGroup }
|
||||
let g := { flatten := flb == FlattenBehavior.allOrNone, flb := flb, items := items : WorkGroup }
|
||||
let r := spaceUptoLine' [g] k (w-k)
|
||||
let r' := merge (w-k) r (spaceUptoLine' gs k)
|
||||
-- Prevent flattening if any item contains a hard line break, except within `fill` if it is ungrouped (=> unflattened)
|
||||
return { g with fla := .allow (!r.foundFlattenedHardLine && r'.space <= w-k) }::gs
|
||||
return { g with flatten := !r.foundFlattenedHardLine && r'.space <= w-k }::gs
|
||||
|
||||
private partial def be (w : Nat) [Monad m] [MonadPrettyFormat m] : List WorkGroup → m Unit
|
||||
| [] => pure ()
|
||||
@@ -219,15 +200,11 @@ private partial def be (w : Nat) [Monad m] [MonadPrettyFormat m] : List WorkGrou
|
||||
pushNewline i.indent.toNat
|
||||
let is := { i with f := text (s.extract (s.next p) s.endPos) }::is
|
||||
-- after a hard line break, re-evaluate whether to flatten the remaining group
|
||||
-- note that we shouldn't start flattening after a hard break outside a group
|
||||
if g.fla == .disallow then
|
||||
be w (gs' is)
|
||||
else
|
||||
pushGroup g.flb is gs w >>= be w
|
||||
pushGroup g.flb is gs w >>= be w
|
||||
| line =>
|
||||
match g.flb with
|
||||
| FlattenBehavior.allOrNone =>
|
||||
if g.fla.shouldFlatten then
|
||||
if g.flatten then
|
||||
-- flatten line = text " "
|
||||
pushOutput " "
|
||||
endTags i.activeTags
|
||||
@@ -243,10 +220,10 @@ private partial def be (w : Nat) [Monad m] [MonadPrettyFormat m] : List WorkGrou
|
||||
endTags i.activeTags
|
||||
pushGroup FlattenBehavior.fill is gs w >>= be w
|
||||
-- if preceding fill item fit in a single line, try to fit next one too
|
||||
if g.fla.shouldFlatten then
|
||||
if g.flatten then
|
||||
let gs'@(g'::_) ← pushGroup FlattenBehavior.fill is gs (w - " ".length)
|
||||
| panic "unreachable"
|
||||
if g'.fla.shouldFlatten then
|
||||
if g'.flatten then
|
||||
pushOutput " "
|
||||
endTags i.activeTags
|
||||
be w gs' -- TODO: use `return`
|
||||
@@ -255,7 +232,7 @@ private partial def be (w : Nat) [Monad m] [MonadPrettyFormat m] : List WorkGrou
|
||||
else
|
||||
breakHere
|
||||
| align force =>
|
||||
if g.fla.shouldFlatten && !force then
|
||||
if g.flatten && !force then
|
||||
-- flatten (align false) = nil
|
||||
endTags i.activeTags
|
||||
be w (gs' is)
|
||||
@@ -270,7 +247,7 @@ private partial def be (w : Nat) [Monad m] [MonadPrettyFormat m] : List WorkGrou
|
||||
endTags i.activeTags
|
||||
be w (gs' is)
|
||||
| group f flb =>
|
||||
if g.fla.shouldFlatten then
|
||||
if g.flatten then
|
||||
-- flatten (group f) = flatten f
|
||||
be w (gs' ({ i with f }::is))
|
||||
else
|
||||
@@ -279,7 +256,7 @@ private partial def be (w : Nat) [Monad m] [MonadPrettyFormat m] : List WorkGrou
|
||||
/-- Render the given `f : Format` with a line width of `w`.
|
||||
`indent` is the starting amount to indent each line by. -/
|
||||
def prettyM (f : Format) (w : Nat) (indent : Nat := 0) [Monad m] [MonadPrettyFormat m] : m Unit :=
|
||||
be w [{ flb := FlattenBehavior.allOrNone, fla := .disallow, items := [{ f := f, indent, activeTags := 0 }]}]
|
||||
be w [{ flb := FlattenBehavior.allOrNone, flatten := false, items := [{ f := f, indent, activeTags := 0 }]}]
|
||||
|
||||
/-- Create a format `l ++ f ++ r` with a flatten group.
|
||||
FlattenBehaviour is `allOrNone`; for `fill` use `bracketFill`. -/
|
||||
|
||||
@@ -41,7 +41,6 @@ Examples:
|
||||
* `(-0b1000 : Int) >>> 1 = -0b0100`
|
||||
* `(-0b0111 : Int) >>> 1 = -0b0100`
|
||||
-/
|
||||
@[expose]
|
||||
protected def shiftRight : Int → Nat → Int
|
||||
| Int.ofNat n, s => Int.ofNat (n >>> s)
|
||||
| Int.negSucc n, s => Int.negSucc (n >>> s)
|
||||
|
||||
@@ -264,8 +264,8 @@ theorem mul_emod (a b n : Int) : (a * b) % n = (a % n) * (b % n) % n := by
|
||||
match k, h with
|
||||
| _, ⟨t, rfl⟩ => rw [Int.mul_assoc, add_mul_emod_self_left]
|
||||
|
||||
theorem emod_emod (a b : Int) : (a % b) % b = a % b := by
|
||||
simp
|
||||
@[simp] theorem emod_emod (a b : Int) : (a % b) % b = a % b := by
|
||||
conv => rhs; rw [← emod_add_ediv a b, add_mul_emod_self_left]
|
||||
|
||||
theorem sub_emod (a b n : Int) : (a - b) % n = (a % n - b % n) % n := by
|
||||
apply (emod_add_cancel_right b).mp
|
||||
|
||||
@@ -1410,7 +1410,8 @@ theorem mul_tmod (a b n : Int) : (a * b).tmod n = (a.tmod n * b.tmod n).tmod n :
|
||||
norm_cast at h
|
||||
rw [Nat.mod_mod_of_dvd _ h]
|
||||
|
||||
theorem tmod_tmod (a b : Int) : (a.tmod b).tmod b = a.tmod b := by simp
|
||||
@[simp] theorem tmod_tmod (a b : Int) : (a.tmod b).tmod b = a.tmod b :=
|
||||
tmod_tmod_of_dvd a (Int.dvd_refl b)
|
||||
|
||||
theorem tmod_eq_zero_of_dvd : ∀ {a b : Int}, a ∣ b → tmod b a = 0
|
||||
| _, _, ⟨_, rfl⟩ => mul_tmod_right ..
|
||||
@@ -1468,8 +1469,9 @@ protected theorem tdiv_mul_cancel {a b : Int} (H : b ∣ a) : a.tdiv b * b = a :
|
||||
protected theorem mul_tdiv_cancel' {a b : Int} (H : a ∣ b) : a * b.tdiv a = b := by
|
||||
rw [Int.mul_comm, Int.tdiv_mul_cancel H]
|
||||
|
||||
theorem neg_tmod_self (a : Int) : (-a).tmod a = 0 := by
|
||||
simp
|
||||
@[simp] theorem neg_tmod_self (a : Int) : (-a).tmod a = 0 := by
|
||||
rw [← dvd_iff_tmod_eq_zero, Int.dvd_neg]
|
||||
exact Int.dvd_refl a
|
||||
|
||||
theorem lt_tdiv_add_one_mul_self (a : Int) {b : Int} (H : 0 < b) : a < (a.tdiv b + 1) * b := by
|
||||
rw [Int.add_mul, Int.one_mul, Int.mul_comm]
|
||||
@@ -1566,11 +1568,13 @@ theorem dvd_tmod_sub_self {x m : Int} : m ∣ x.tmod m - x := by
|
||||
theorem dvd_self_sub_tmod {x m : Int} : m ∣ x - x.tmod m :=
|
||||
Int.dvd_neg.1 (by simpa only [Int.neg_sub] using dvd_tmod_sub_self)
|
||||
|
||||
theorem neg_mul_tmod_right (a b : Int) : (-(a * b)).tmod a = 0 := by
|
||||
simp
|
||||
@[simp] theorem neg_mul_tmod_right (a b : Int) : (-(a * b)).tmod a = 0 := by
|
||||
rw [← dvd_iff_tmod_eq_zero, Int.dvd_neg]
|
||||
exact Int.dvd_mul_right a b
|
||||
|
||||
theorem neg_mul_tmod_left (a b : Int) : (-(a * b)).tmod b = 0 := by
|
||||
simp
|
||||
@[simp] theorem neg_mul_tmod_left (a b : Int) : (-(a * b)).tmod b = 0 := by
|
||||
rw [← dvd_iff_tmod_eq_zero, Int.dvd_neg]
|
||||
exact Int.dvd_mul_left a b
|
||||
|
||||
@[simp] protected theorem tdiv_one : ∀ a : Int, a.tdiv 1 = a
|
||||
| (n:Nat) => congrArg ofNat (Nat.div_one _)
|
||||
@@ -2189,8 +2193,8 @@ theorem mul_fmod (a b n : Int) : (a * b).fmod n = (a.fmod n * b.fmod n).fmod n :
|
||||
match k, h with
|
||||
| _, ⟨t, rfl⟩ => rw [Int.mul_assoc, add_mul_fmod_self_left]
|
||||
|
||||
theorem fmod_fmod (a b : Int) : (a.fmod b).fmod b = a.fmod b := by
|
||||
simp
|
||||
@[simp] theorem fmod_fmod (a b : Int) : (a.fmod b).fmod b = a.fmod b :=
|
||||
fmod_fmod_of_dvd _ (Int.dvd_refl b)
|
||||
|
||||
theorem sub_fmod (a b n : Int) : (a - b).fmod n = (a.fmod n - b.fmod n).fmod n := by
|
||||
apply (fmod_add_cancel_right b).mp
|
||||
|
||||
@@ -35,7 +35,6 @@ Examples:
|
||||
* `Int.gcd 0 5 = 5`
|
||||
* `Int.gcd (-7) 0 = 7`
|
||||
-/
|
||||
@[expose]
|
||||
def gcd (m n : Int) : Nat := m.natAbs.gcd n.natAbs
|
||||
|
||||
theorem gcd_eq_natAbs_gcd_natAbs (m n : Int) : gcd m n = Nat.gcd m.natAbs n.natAbs := rfl
|
||||
@@ -429,7 +428,6 @@ Examples:
|
||||
* `Int.lcm 0 3 = 0`
|
||||
* `Int.lcm (-3) 0 = 0`
|
||||
-/
|
||||
@[expose]
|
||||
def lcm (m n : Int) : Nat := m.natAbs.lcm n.natAbs
|
||||
|
||||
theorem lcm_eq_natAbs_lcm_natAbs (m n : Int) : lcm m n = Nat.lcm m.natAbs n.natAbs := rfl
|
||||
|
||||
@@ -638,7 +638,7 @@ theorem toNat_of_nonneg {a : Int} (h : 0 ≤ a) : (toNat a : Int) = a := by
|
||||
@[simp] theorem toNat_natCast (n : Nat) : toNat ↑n = n := rfl
|
||||
|
||||
@[deprecated toNat_natCast (since := "2025-04-16")]
|
||||
theorem toNat_ofNat (n : Nat) : toNat ↑n = n := rfl
|
||||
theorem toNat_ofNat (n : Nat) : toNat ↑n = n := toNat_natCast n
|
||||
|
||||
@[simp] theorem toNat_negSucc (n : Nat) : (Int.negSucc n).toNat = 0 := by
|
||||
simp [toNat]
|
||||
|
||||
@@ -23,7 +23,6 @@ a list `l : List α`, given a proof that every element of `l` in fact satisfies
|
||||
`O(|l|)`. `List.pmap`, named for “partial map,” is the equivalent of `List.map` for such partial
|
||||
functions.
|
||||
-/
|
||||
@[expose]
|
||||
def pmap {P : α → Prop} (f : ∀ a, P a → β) : ∀ l : List α, (H : ∀ a ∈ l, P a) → List β
|
||||
| [], _ => []
|
||||
| a :: l, H => f a (forall_mem_cons.1 H).1 :: pmap f l (forall_mem_cons.1 H).2
|
||||
@@ -41,7 +40,7 @@ elements in the corresponding subtype `{ x // P x }`.
|
||||
|
||||
`O(1)`.
|
||||
-/
|
||||
@[implemented_by attachWithImpl, expose] def attachWith
|
||||
@[implemented_by attachWithImpl] def attachWith
|
||||
(l : List α) (P : α → Prop) (H : ∀ x ∈ l, P x) : List {x // P x} := pmap Subtype.mk l H
|
||||
|
||||
/--
|
||||
@@ -55,7 +54,7 @@ recursion](lean-manual://section/well-founded-recursion) that use higher-order f
|
||||
`List.map`) to prove that an value taken from a list is smaller than the list. This allows the
|
||||
well-founded recursion mechanism to prove that the function terminates.
|
||||
-/
|
||||
@[inline, expose] def attach (l : List α) : List {x // x ∈ l} := attachWith l _ fun _ => id
|
||||
@[inline] def attach (l : List α) : List {x // x ∈ l} := attachWith l _ fun _ => id
|
||||
|
||||
/-- Implementation of `pmap` using the zero-copy version of `attach`. -/
|
||||
@[inline] private def pmapImpl {P : α → Prop} (f : ∀ a, P a → β) (l : List α) (H : ∀ a ∈ l, P a) :
|
||||
@@ -676,7 +675,6 @@ the elaboration of definitions by [well-founded
|
||||
recursion](lean-manual://section/well-founded-recursion). If this function is encountered in a proof
|
||||
state, the right approach is usually the tactic `simp [List.unattach, -List.map_subtype]`.
|
||||
-/
|
||||
@[expose]
|
||||
def unattach {α : Type _} {p : α → Prop} (l : List { x // p x }) : List α := l.map (·.val)
|
||||
|
||||
@[simp] theorem unattach_nil {p : α → Prop} : ([] : List { x // p x }).unattach = [] := rfl
|
||||
|
||||
@@ -586,7 +586,7 @@ Examples:
|
||||
* `[1, 2, 3, 4].reverse = [4, 3, 2, 1]`
|
||||
* `[].reverse = []`
|
||||
-/
|
||||
@[expose] def reverse (as : List α) : List α :=
|
||||
def reverse (as : List α) : List α :=
|
||||
reverseAux as []
|
||||
|
||||
@[simp, grind] theorem reverse_nil : reverse ([] : List α) = [] := rfl
|
||||
@@ -715,7 +715,7 @@ Examples:
|
||||
* `List.singleton "green" = ["green"]`.
|
||||
* `List.singleton [1, 2, 3] = [[1, 2, 3]]`
|
||||
-/
|
||||
@[inline, expose] protected def singleton {α : Type u} (a : α) : List α := [a]
|
||||
@[inline] protected def singleton {α : Type u} (a : α) : List α := [a]
|
||||
|
||||
/-! ### flatMap -/
|
||||
|
||||
@@ -1190,10 +1190,10 @@ def isPrefixOf [BEq α] : List α → List α → Bool
|
||||
| _, [] => false
|
||||
| a::as, b::bs => a == b && isPrefixOf as bs
|
||||
|
||||
@[simp, grind =] theorem isPrefixOf_nil_left [BEq α] : isPrefixOf ([] : List α) l = true := by
|
||||
@[simp] theorem isPrefixOf_nil_left [BEq α] : isPrefixOf ([] : List α) l = true := by
|
||||
simp [isPrefixOf]
|
||||
@[simp, grind =] theorem isPrefixOf_cons_nil [BEq α] : isPrefixOf (a::as) ([] : List α) = false := rfl
|
||||
@[grind =] theorem isPrefixOf_cons₂ [BEq α] {a : α} :
|
||||
@[simp] theorem isPrefixOf_cons_nil [BEq α] : isPrefixOf (a::as) ([] : List α) = false := rfl
|
||||
theorem isPrefixOf_cons₂ [BEq α] {a : α} :
|
||||
isPrefixOf (a::as) (b::bs) = (a == b && isPrefixOf as bs) := rfl
|
||||
|
||||
/--
|
||||
@@ -1229,7 +1229,7 @@ Examples:
|
||||
def isSuffixOf [BEq α] (l₁ l₂ : List α) : Bool :=
|
||||
isPrefixOf l₁.reverse l₂.reverse
|
||||
|
||||
@[simp, grind =] theorem isSuffixOf_nil_left [BEq α] : isSuffixOf ([] : List α) l = true := by
|
||||
@[simp] theorem isSuffixOf_nil_left [BEq α] : isSuffixOf ([] : List α) l = true := by
|
||||
simp [isSuffixOf]
|
||||
|
||||
/--
|
||||
@@ -1564,8 +1564,8 @@ protected def erase {α} [BEq α] : List α → α → List α
|
||||
| true => as
|
||||
| false => a :: List.erase as b
|
||||
|
||||
@[simp, grind =] theorem erase_nil [BEq α] (a : α) : [].erase a = [] := rfl
|
||||
@[grind =] theorem erase_cons [BEq α] {a b : α} {l : List α} :
|
||||
@[simp] theorem erase_nil [BEq α] (a : α) : [].erase a = [] := rfl
|
||||
theorem erase_cons [BEq α] {a b : α} {l : List α} :
|
||||
(b :: l).erase a = if b == a then l else b :: l.erase a := by
|
||||
simp only [List.erase]; split <;> simp_all
|
||||
|
||||
@@ -2096,7 +2096,7 @@ where
|
||||
| 0, acc => acc
|
||||
| n+1, acc => loop n (n::acc)
|
||||
|
||||
@[simp, grind =] theorem range_zero : range 0 = [] := rfl
|
||||
@[simp] theorem range_zero : range 0 = [] := rfl
|
||||
|
||||
/-! ### range' -/
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ Returns the `i`-th element in the list (zero-based).
|
||||
If the index is out of bounds (`i ≥ as.length`), this function returns `none`.
|
||||
Also see `get`, `getD` and `get!`.
|
||||
-/
|
||||
@[deprecated "Use `a[i]?` instead." (since := "2025-02-12"), expose]
|
||||
@[deprecated "Use `a[i]?` instead." (since := "2025-02-12")]
|
||||
def get? : (as : List α) → (i : Nat) → Option α
|
||||
| a::_, 0 => some a
|
||||
| _::as, n+1 => get? as n
|
||||
@@ -61,7 +61,7 @@ Returns the `i`-th element in the list (zero-based).
|
||||
If the index is out of bounds (`i ≥ as.length`), this function panics when executed, and returns
|
||||
`default`. See `get?` and `getD` for safer alternatives.
|
||||
-/
|
||||
@[deprecated "Use `a[i]!` instead." (since := "2025-02-12"), expose]
|
||||
@[deprecated "Use `a[i]!` instead." (since := "2025-02-12")]
|
||||
def get! [Inhabited α] : (as : List α) → (i : Nat) → α
|
||||
| a::_, 0 => a
|
||||
| _::as, n+1 => get! as n
|
||||
@@ -92,7 +92,7 @@ Examples:
|
||||
* `["spring", "summer", "fall", "winter"].getD 0 "never" = "spring"`
|
||||
* `["spring", "summer", "fall", "winter"].getD 4 "never" = "never"`
|
||||
-/
|
||||
@[expose] def getD (as : List α) (i : Nat) (fallback : α) : α :=
|
||||
def getD (as : List α) (i : Nat) (fallback : α) : α :=
|
||||
as[i]?.getD fallback
|
||||
|
||||
@[simp] theorem getD_nil : getD [] n d = d := rfl
|
||||
@@ -111,7 +111,6 @@ Examples:
|
||||
* `["circle", "rectangle"].getLast! = "rectangle"`
|
||||
* `["circle"].getLast! = "circle"`
|
||||
-/
|
||||
@[expose]
|
||||
def getLast! [Inhabited α] : List α → α
|
||||
| [] => panic! "empty list"
|
||||
| a::as => getLast (a::as) (fun h => List.noConfusion h)
|
||||
@@ -147,7 +146,7 @@ Examples:
|
||||
* `["apple", "banana", "grape"].tail! = ["banana", "grape"]`
|
||||
* `["banana", "grape"].tail! = ["grape"]`
|
||||
-/
|
||||
@[expose] def tail! : List α → List α
|
||||
def tail! : List α → List α
|
||||
| [] => panic! "empty list"
|
||||
| _::as => as
|
||||
|
||||
@@ -255,7 +254,7 @@ pointer-equal to its argument.
|
||||
For verification purposes, `List.mapMono = List.map`.
|
||||
-/
|
||||
def mapMono (as : List α) (f : α → α) : List α :=
|
||||
Id.run <| as.mapMonoM (pure <| f ·)
|
||||
Id.run <| as.mapMonoM f
|
||||
|
||||
/-! ## Additional lemmas required for bootstrapping `Array`. -/
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@ This implementation is tail recursive. `List.mapM'` is a a non-tail-recursive va
|
||||
more convenient to reason about. `List.forM` is the variant that discards the results and
|
||||
`List.mapA` is the variant that works with `Applicative`.
|
||||
-/
|
||||
@[inline, expose]
|
||||
@[inline]
|
||||
def mapM {m : Type u → Type v} [Monad m] {α : Type w} {β : Type u} (f : α → m β) (as : List α) : m (List β) :=
|
||||
let rec @[specialize] loop
|
||||
| [], bs => pure bs.reverse
|
||||
@@ -83,7 +83,7 @@ Applies the monadic action `f` to every element in the list, in order.
|
||||
`List.mapM` is a variant that collects results. `List.forA` is a variant that works on any
|
||||
`Applicative`.
|
||||
-/
|
||||
@[specialize, expose]
|
||||
@[specialize]
|
||||
protected def forM {m : Type u → Type v} [Monad m] {α : Type w} (as : List α) (f : α → m PUnit) : m PUnit :=
|
||||
match as with
|
||||
| [] => pure ⟨⟩
|
||||
@@ -191,7 +191,7 @@ Examining 7
|
||||
[10, 14, 14]
|
||||
```
|
||||
-/
|
||||
@[inline, expose]
|
||||
@[inline]
|
||||
def filterMapM {m : Type u → Type v} [Monad m] {α : Type w} {β : Type u} (f : α → m (Option β)) (as : List α) : m (List β) :=
|
||||
let rec @[specialize] loop
|
||||
| [], bs => pure bs.reverse
|
||||
@@ -205,7 +205,7 @@ def filterMapM {m : Type u → Type v} [Monad m] {α : Type w} {β : Type u} (f
|
||||
Applies a monadic function that returns a list to each element of a list, from left to right, and
|
||||
concatenates the resulting lists.
|
||||
-/
|
||||
@[inline, expose]
|
||||
@[inline]
|
||||
def flatMapM {m : Type u → Type v} [Monad m] {α : Type w} {β : Type u} (f : α → m (List β)) (as : List α) : m (List β) :=
|
||||
let rec @[specialize] loop
|
||||
| [], bs => pure bs.reverse.flatten
|
||||
@@ -230,7 +230,7 @@ example [Monad m] (f : α → β → m α) :
|
||||
:= by rfl
|
||||
```
|
||||
-/
|
||||
@[specialize, expose]
|
||||
@[specialize]
|
||||
def foldlM {m : Type u → Type v} [Monad m] {s : Type u} {α : Type w} : (f : s → α → m s) → (init : s) → List α → m s
|
||||
| _, s, [] => pure s
|
||||
| f, s, a :: as => do
|
||||
@@ -257,7 +257,7 @@ example [Monad m] (f : α → β → m β) :
|
||||
:= by rfl
|
||||
```
|
||||
-/
|
||||
@[inline, expose]
|
||||
@[inline]
|
||||
def foldrM {m : Type u → Type v} [Monad m] {s : Type u} {α : Type w} (f : α → s → m s) (init : s) (l : List α) : m s :=
|
||||
l.reverse.foldlM (fun s a => f a s) init
|
||||
|
||||
@@ -348,16 +348,9 @@ theorem findM?_pure {m} [Monad m] [LawfulMonad m] (p : α → Bool) (as : List
|
||||
| false => simp [ih]
|
||||
|
||||
@[simp]
|
||||
theorem idRun_findM? (p : α → Id Bool) (as : List α) :
|
||||
(findM? p as).run = as.find? (p · |>.run) :=
|
||||
theorem findM?_id (p : α → Bool) (as : List α) : findM? (m := Id) p as = as.find? p :=
|
||||
findM?_pure _ _
|
||||
|
||||
@[deprecated idRun_findM? (since := "2025-05-21")]
|
||||
theorem findM?_id (p : α → Id Bool) (as : List α) :
|
||||
findM? (m := Id) p as = as.find? p :=
|
||||
findM?_pure _ _
|
||||
|
||||
|
||||
/--
|
||||
Returns the first non-`none` result of applying the monadic function `f` to each element of the
|
||||
list, in order. Returns `none` if `f` returns `none` for all elements.
|
||||
@@ -401,13 +394,7 @@ theorem findSomeM?_pure [Monad m] [LawfulMonad m] {f : α → Option β} {as : L
|
||||
| none => simp [ih]
|
||||
|
||||
@[simp]
|
||||
theorem idRun_findSomeM? (f : α → Id (Option β)) (as : List α) :
|
||||
(findSomeM? f as).run = as.findSome? (f · |>.run) :=
|
||||
findSomeM?_pure
|
||||
|
||||
@[deprecated idRun_findSomeM? (since := "2025-05-21")]
|
||||
theorem findSomeM?_id (f : α → Id (Option β)) (as : List α) :
|
||||
findSomeM? (m := Id) f as = as.findSome? f :=
|
||||
theorem findSomeM?_id {f : α → Option β} {as : List α} : findSomeM? (m := Id) f as = as.findSome? f :=
|
||||
findSomeM?_pure
|
||||
|
||||
theorem findM?_eq_findSomeM? [Monad m] [LawfulMonad m] {p : α → m Bool} {as : List α} :
|
||||
@@ -422,7 +409,7 @@ theorem findM?_eq_findSomeM? [Monad m] [LawfulMonad m] {p : α → m Bool} {as :
|
||||
intro b
|
||||
cases b <;> simp
|
||||
|
||||
@[inline, expose] protected def forIn' {α : Type u} {β : Type v} {m : Type v → Type w} [Monad m] (as : List α) (init : β) (f : (a : α) → a ∈ as → β → m (ForInStep β)) : m β :=
|
||||
@[inline] protected def forIn' {α : Type u} {β : Type v} {m : Type v → Type w} [Monad m] (as : List α) (init : β) (f : (a : α) → a ∈ as → β → m (ForInStep β)) : m β :=
|
||||
let rec @[specialize] loop : (as' : List α) → (b : β) → Exists (fun bs => bs ++ as' = as) → m β
|
||||
| [], b, _ => pure b
|
||||
| a::as', b, h => do
|
||||
|
||||
@@ -10,9 +10,6 @@ import Init.Data.List.Sublist
|
||||
|
||||
/-!
|
||||
# Lemmas about `List.countP` and `List.count`.
|
||||
|
||||
Because we mark `countP_eq_length_filter` and `count_eq_countP` with `@[grind _=_]`,
|
||||
we don't need many other `@[grind]` annotations here.
|
||||
-/
|
||||
|
||||
set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
|
||||
@@ -64,7 +61,6 @@ theorem length_eq_countP_add_countP (p : α → Bool) {l : List α} : length l =
|
||||
· rfl
|
||||
· simp [h]
|
||||
|
||||
@[grind =]
|
||||
theorem countP_eq_length_filter {l : List α} : countP p l = length (filter p l) := by
|
||||
induction l with
|
||||
| nil => rfl
|
||||
@@ -73,7 +69,6 @@ theorem countP_eq_length_filter {l : List α} : countP p l = length (filter p l)
|
||||
then rw [countP_cons_of_pos h, ih, filter_cons_of_pos h, length]
|
||||
else rw [countP_cons_of_neg h, ih, filter_cons_of_neg h]
|
||||
|
||||
@[grind =]
|
||||
theorem countP_eq_length_filter' : countP p = length ∘ filter p := by
|
||||
funext l
|
||||
apply countP_eq_length_filter
|
||||
@@ -102,7 +97,6 @@ theorem countP_replicate {p : α → Bool} {a : α} {n : Nat} :
|
||||
simp only [countP_eq_length_filter, filter_replicate]
|
||||
split <;> simp
|
||||
|
||||
@[grind]
|
||||
theorem boole_getElem_le_countP {p : α → Bool} {l : List α} {i : Nat} (h : i < l.length) :
|
||||
(if p l[i] then 1 else 0) ≤ l.countP p := by
|
||||
induction l generalizing i with
|
||||
@@ -126,7 +120,6 @@ theorem IsInfix.countP_le (s : l₁ <:+: l₂) : countP p l₁ ≤ countP p l₂
|
||||
|
||||
-- See `Init.Data.List.Nat.Count` for `Sublist.le_countP : countP p l₂ - (l₂.length - l₁.length) ≤ countP p l₁`.
|
||||
|
||||
@[grind]
|
||||
theorem countP_tail_le (l) : countP p l.tail ≤ countP p l :=
|
||||
(tail_sublist l).countP_le
|
||||
|
||||
@@ -205,21 +198,18 @@ variable [BEq α]
|
||||
|
||||
@[simp] theorem count_nil {a : α} : count a [] = 0 := rfl
|
||||
|
||||
@[grind]
|
||||
theorem count_cons {a b : α} {l : List α} :
|
||||
count a (b :: l) = count a l + if b == a then 1 else 0 := by
|
||||
simp [count, countP_cons]
|
||||
|
||||
@[grind =] theorem count_eq_countP {a : α} {l : List α} : count a l = countP (· == a) l := rfl
|
||||
theorem count_eq_countP {a : α} {l : List α} : count a l = countP (· == a) l := rfl
|
||||
theorem count_eq_countP' {a : α} : count a = countP (· == a) := by
|
||||
funext l
|
||||
apply count_eq_countP
|
||||
|
||||
@[grind]
|
||||
theorem count_tail : ∀ {l : List α} {a : α},
|
||||
l.tail.count a = l.count a - if l.head? == some a then 1 else 0
|
||||
| [], a => by simp
|
||||
| _ :: _, a => by simp [count_cons]
|
||||
theorem count_tail : ∀ {l : List α} (h : l ≠ []) (a : α),
|
||||
l.tail.count a = l.count a - if l.head h == a then 1 else 0
|
||||
| _ :: _, a, _ => by simp [count_cons]
|
||||
|
||||
theorem count_le_length {a : α} {l : List α} : count a l ≤ l.length := countP_le_length
|
||||
|
||||
@@ -242,7 +232,7 @@ theorem count_le_count_cons {a b : α} {l : List α} : count a l ≤ count a (b
|
||||
theorem count_singleton {a b : α} : count a [b] = if b == a then 1 else 0 := by
|
||||
simp [count_cons]
|
||||
|
||||
@[simp, grind =] theorem count_append {a : α} {l₁ l₂ : List α} : count a (l₁ ++ l₂) = count a l₁ + count a l₂ :=
|
||||
@[simp] theorem count_append {a : α} {l₁ l₂ : List α} : count a (l₁ ++ l₂) = count a l₁ + count a l₂ :=
|
||||
countP_append
|
||||
|
||||
theorem count_flatten {a : α} {l : List (List α)} : count a l.flatten = (l.map (count a)).sum := by
|
||||
@@ -251,7 +241,6 @@ theorem count_flatten {a : α} {l : List (List α)} : count a l.flatten = (l.map
|
||||
@[simp] theorem count_reverse {a : α} {l : List α} : count a l.reverse = count a l := by
|
||||
simp only [count_eq_countP, countP_eq_length_filter, filter_reverse, length_reverse]
|
||||
|
||||
@[grind]
|
||||
theorem boole_getElem_le_count {a : α} {l : List α} {i : Nat} (h : i < l.length) :
|
||||
(if l[i] == a then 1 else 0) ≤ l.count a := by
|
||||
rw [count_eq_countP]
|
||||
@@ -294,7 +283,7 @@ theorem count_eq_length {l : List α} : count a l = l.length ↔ ∀ b ∈ l, a
|
||||
@[simp] theorem count_replicate_self {a : α} {n : Nat} : count a (replicate n a) = n :=
|
||||
(count_eq_length.2 <| fun _ h => (eq_of_mem_replicate h).symm).trans (length_replicate ..)
|
||||
|
||||
@[grind =] theorem count_replicate {a b : α} {n : Nat} : count a (replicate n b) = if b == a then n else 0 := by
|
||||
theorem count_replicate {a b : α} {n : Nat} : count a (replicate n b) = if b == a then n else 0 := by
|
||||
split <;> (rename_i h; simp only [beq_iff_eq] at h)
|
||||
· exact ‹b = a› ▸ count_replicate_self ..
|
||||
· exact count_eq_zero.2 <| mt eq_of_mem_replicate (Ne.symm h)
|
||||
@@ -306,18 +295,14 @@ theorem filter_beq {l : List α} (a : α) : l.filter (· == a) = replicate (coun
|
||||
theorem filter_eq [DecidableEq α] {l : List α} (a : α) : l.filter (· = a) = replicate (count a l) a :=
|
||||
funext (Bool.beq_eq_decide_eq · a) ▸ filter_beq a
|
||||
|
||||
@[grind =] theorem replicate_sublist_iff {l : List α} : replicate n a <+ l ↔ n ≤ count a l := by
|
||||
theorem le_count_iff_replicate_sublist {l : List α} : n ≤ count a l ↔ replicate n a <+ l := by
|
||||
refine ⟨fun h => ?_, fun h => ?_⟩
|
||||
· simpa only [count_replicate_self] using h.count_le a
|
||||
· exact ((replicate_sublist_replicate a).2 h).trans <| filter_beq a ▸ filter_sublist
|
||||
|
||||
@[deprecated replicate_sublist_iff (since := "2025-05-26")]
|
||||
theorem le_count_iff_replicate_sublist {l : List α} : n ≤ count a l ↔ replicate n a <+ l :=
|
||||
replicate_sublist_iff.symm
|
||||
· simpa only [count_replicate_self] using h.count_le a
|
||||
|
||||
theorem replicate_count_eq_of_count_eq_length {l : List α} (h : count a l = length l) :
|
||||
replicate (count a l) a = l :=
|
||||
(replicate_sublist_iff.mpr (Nat.le_refl _)).eq_of_length <| length_replicate.trans h
|
||||
(le_count_iff_replicate_sublist.mp (Nat.le_refl _)).eq_of_length <| length_replicate.trans h
|
||||
|
||||
@[simp] theorem count_filter {l : List α} (h : p a) : count a (filter p l) = count a l := by
|
||||
rw [count, countP_filter]; congr; funext b
|
||||
@@ -340,7 +325,6 @@ theorem count_filterMap {α} [BEq β] {b : β} {f : α → Option β} {l : List
|
||||
theorem count_flatMap {α} [BEq β] {l : List α} {f : α → List β} {x : β} :
|
||||
count x (l.flatMap f) = sum (map (count x ∘ f) l) := countP_flatMap
|
||||
|
||||
@[grind]
|
||||
theorem count_erase {a b : α} :
|
||||
∀ {l : List α}, count a (l.erase b) = count a l - if b == a then 1 else 0
|
||||
| [] => by simp
|
||||
|
||||
@@ -243,6 +243,9 @@ theorem find?_eq_some_iff_append :
|
||||
cases h₁
|
||||
simp
|
||||
|
||||
@[deprecated find?_eq_some_iff_append (since := "2024-11-06")]
|
||||
abbrev find?_eq_some := @find?_eq_some_iff_append
|
||||
|
||||
@[simp]
|
||||
theorem find?_cons_eq_some : (a :: xs).find? p = some b ↔ (p a ∧ a = b) ∨ (!p a ∧ xs.find? p = some b) := by
|
||||
rw [find?_cons]
|
||||
@@ -1105,9 +1108,14 @@ theorem isSome_finIdxOf? [BEq α] [LawfulBEq α] {l : List α} {a : α} :
|
||||
simp only [finIdxOf?_cons]
|
||||
split <;> simp_all [@eq_comm _ x a]
|
||||
|
||||
@[simp]
|
||||
theorem isNone_finIdxOf? [BEq α] [LawfulBEq α] {l : List α} {a : α} :
|
||||
(l.finIdxOf? a).isNone = ¬ a ∈ l := by
|
||||
simp
|
||||
induction l with
|
||||
| nil => simp
|
||||
| cons x xs ih =>
|
||||
simp only [finIdxOf?_cons]
|
||||
split <;> simp_all [@eq_comm _ x a]
|
||||
|
||||
/-! ### idxOf?
|
||||
|
||||
@@ -1146,9 +1154,15 @@ theorem isSome_idxOf? [BEq α] [LawfulBEq α] {l : List α} {a : α} :
|
||||
simp only [idxOf?_cons]
|
||||
split <;> simp_all [@eq_comm _ x a]
|
||||
|
||||
@[simp]
|
||||
theorem isNone_idxOf? [BEq α] [LawfulBEq α] {l : List α} {a : α} :
|
||||
(l.idxOf? a).isNone = ¬ a ∈ l := by
|
||||
simp
|
||||
induction l with
|
||||
| nil => simp
|
||||
| cons x xs ih =>
|
||||
simp only [idxOf?_cons]
|
||||
split <;> simp_all [@eq_comm _ x a]
|
||||
|
||||
|
||||
/-! ### lookup -/
|
||||
|
||||
|
||||
@@ -109,7 +109,7 @@ Example:
|
||||
let rec go : ∀ as acc, filterMapTR.go f as acc = acc.toList ++ as.filterMap f
|
||||
| [], acc => by simp [filterMapTR.go, filterMap]
|
||||
| a::as, acc => by
|
||||
simp only [filterMapTR.go, go as, Array.toList_push, append_assoc, singleton_append,
|
||||
simp only [filterMapTR.go, go as, Array.push_toList, append_assoc, singleton_append,
|
||||
filterMap]
|
||||
split <;> simp [*]
|
||||
exact (go l #[]).symm
|
||||
@@ -550,7 +550,7 @@ def zipIdxTR (l : List α) (n : Nat := 0) : List (α × Nat) :=
|
||||
(as.foldr (fun a (n, acc) => (n-1, (a, n-1) :: acc)) (n + as.size, [])).2
|
||||
|
||||
@[csimp] theorem zipIdx_eq_zipIdxTR : @zipIdx = @zipIdxTR := by
|
||||
funext α l n; simp only [zipIdxTR]
|
||||
funext α l n; simp only [zipIdxTR, size_toArray]
|
||||
let f := fun (a : α) (n, acc) => (n-1, (a, n-1) :: acc)
|
||||
let rec go : ∀ l i, l.foldr f (i + l.length, []) = (i, zipIdx l i)
|
||||
| [], n => rfl
|
||||
@@ -571,7 +571,7 @@ def enumFromTR (n : Nat) (l : List α) : List (Nat × α) :=
|
||||
set_option linter.deprecated false in
|
||||
@[deprecated zipIdx_eq_zipIdxTR (since := "2025-01-21"), csimp]
|
||||
theorem enumFrom_eq_enumFromTR : @enumFrom = @enumFromTR := by
|
||||
funext α n l; simp only [enumFromTR]
|
||||
funext α n l; simp only [enumFromTR, size_toArray]
|
||||
let f := fun (a : α) (n, acc) => (n-1, (n-1, a) :: acc)
|
||||
let rec go : ∀ l n, l.foldr f (n + l.length, []) = (n, enumFrom n l)
|
||||
| [], n => rfl
|
||||
|
||||
@@ -272,13 +272,13 @@ theorem getElem_of_getElem? {l : List α} : l[i]? = some a → ∃ h : i < l.len
|
||||
theorem some_eq_getElem?_iff {l : List α} : some a = l[i]? ↔ ∃ h : i < l.length, l[i] = a := by
|
||||
rw [eq_comm, getElem?_eq_some_iff]
|
||||
|
||||
theorem some_getElem_eq_getElem?_iff {xs : List α} {i : Nat} (h : i < xs.length) :
|
||||
@[simp] theorem some_getElem_eq_getElem?_iff {xs : List α} {i : Nat} (h : i < xs.length) :
|
||||
(some xs[i] = xs[i]?) ↔ True := by
|
||||
simp
|
||||
simp [h]
|
||||
|
||||
theorem getElem?_eq_some_getElem_iff {xs : List α} {i : Nat} (h : i < xs.length) :
|
||||
@[simp] theorem getElem?_eq_some_getElem_iff {xs : List α} {i : Nat} (h : i < xs.length) :
|
||||
(xs[i]? = some xs[i]) ↔ True := by
|
||||
simp
|
||||
simp [h]
|
||||
|
||||
theorem getElem_eq_iff {l : List α} {i : Nat} (h : i < l.length) : l[i] = x ↔ l[i]? = some x := by
|
||||
simp only [getElem?_eq_some_iff]
|
||||
@@ -296,7 +296,7 @@ theorem getD_getElem? {l : List α} {i : Nat} {d : α} :
|
||||
have p : i ≥ l.length := Nat.le_of_not_gt h
|
||||
simp [getElem?_eq_none p, h]
|
||||
|
||||
@[simp] theorem getElem_singleton {a : α} {i : Nat} (h : i < 1) : [a][i] = a := by
|
||||
@[simp] theorem getElem_singleton {a : α} {i : Nat} (h : i < 1) : [a][i] = a :=
|
||||
match i, h with
|
||||
| 0, _ => rfl
|
||||
|
||||
@@ -434,8 +434,8 @@ theorem eq_nil_iff_forall_not_mem {l : List α} : l = [] ↔ ∀ a, a ∉ l := b
|
||||
theorem eq_of_mem_singleton : a ∈ [b] → a = b
|
||||
| .head .. => rfl
|
||||
|
||||
theorem mem_singleton {a b : α} : a ∈ [b] ↔ a = b := by
|
||||
simp
|
||||
@[simp] theorem mem_singleton {a b : α} : a ∈ [b] ↔ a = b :=
|
||||
⟨eq_of_mem_singleton, (by simp [·])⟩
|
||||
|
||||
theorem forall_mem_cons {p : α → Prop} {a : α} {l : List α} :
|
||||
(∀ x, x ∈ a :: l → p x) ↔ p a ∧ ∀ x, x ∈ l → p x :=
|
||||
@@ -834,7 +834,7 @@ theorem getElem_length_sub_one_eq_getLast {l : List α} (h : l.length - 1 < l.le
|
||||
rw [← getLast_eq_getElem]
|
||||
|
||||
@[simp, grind] theorem getLast_cons_cons {a : α} {l : List α} :
|
||||
getLast (a :: b :: l) (by simp) = getLast (b :: l) (by simp) :=
|
||||
getLast (a :: b :: l) (by simp) = getLast (b :: l) (by simp) := by
|
||||
rfl
|
||||
|
||||
theorem getLast_cons {a : α} {l : List α} : ∀ (h : l ≠ nil),
|
||||
@@ -1252,7 +1252,7 @@ theorem tailD_map {f : α → β} {l l' : List α} :
|
||||
theorem getLastD_map {f : α → β} {l : List α} {a : α} : (map f l).getLastD (f a) = f (l.getLastD a) := by
|
||||
simp
|
||||
|
||||
@[simp, grind _=_] theorem map_map {g : β → γ} {f : α → β} {l : List α} :
|
||||
@[simp] theorem map_map {g : β → γ} {f : α → β} {l : List α} :
|
||||
map g (map f l) = map (g ∘ f) l := by induction l <;> simp_all
|
||||
|
||||
/-! ### filter -/
|
||||
@@ -1337,7 +1337,7 @@ theorem foldr_filter {p : α → Bool} {f : α → β → β} {l : List α} {ini
|
||||
simp only [filter_cons, foldr_cons]
|
||||
split <;> simp [ih]
|
||||
|
||||
@[grind _=_] theorem filter_map {f : β → α} {p : α → Bool} {l : List β} :
|
||||
theorem filter_map {f : β → α} {p : α → Bool} {l : List β} :
|
||||
filter p (map f l) = map f (filter (p ∘ f) l) := by
|
||||
induction l with
|
||||
| nil => rfl
|
||||
@@ -1572,6 +1572,9 @@ theorem not_mem_append {a : α} {s t : List α} (h₁ : a ∉ s) (h₂ : a ∉ t
|
||||
theorem mem_append_eq {a : α} {s t : List α} : (a ∈ s ++ t) = (a ∈ s ∨ a ∈ t) :=
|
||||
propext mem_append
|
||||
|
||||
@[deprecated mem_append_left (since := "2024-11-20")] abbrev mem_append_of_mem_left := @mem_append_left
|
||||
@[deprecated mem_append_right (since := "2024-11-20")] abbrev mem_append_of_mem_right := @mem_append_right
|
||||
|
||||
/--
|
||||
See also `eq_append_cons_of_mem`, which proves a stronger version
|
||||
in which the initial list must not contain the element.
|
||||
@@ -1682,8 +1685,8 @@ theorem getLast_concat {a : α} : ∀ {l : List α}, getLast (l ++ [a]) (by simp
|
||||
|
||||
@[deprecated append_eq_nil_iff (since := "2025-01-13")] abbrev append_eq_nil := @append_eq_nil_iff
|
||||
|
||||
theorem nil_eq_append_iff : [] = a ++ b ↔ a = [] ∧ b = [] := by
|
||||
simp
|
||||
@[simp] theorem nil_eq_append_iff : [] = a ++ b ↔ a = [] ∧ b = [] := by
|
||||
rw [eq_comm, append_eq_nil_iff]
|
||||
|
||||
@[grind →]
|
||||
theorem eq_nil_of_append_eq_nil {l₁ l₂ : List α} (h : l₁ ++ l₂ = []) : l₁ = [] ∧ l₂ = [] :=
|
||||
@@ -1879,7 +1882,7 @@ theorem eq_nil_or_concat : ∀ l : List α, l = [] ∨ ∃ l' b, l = concat l' b
|
||||
|
||||
/-! ### flatten -/
|
||||
|
||||
@[simp, grind _=_] theorem length_flatten {L : List (List α)} : L.flatten.length = (L.map length).sum := by
|
||||
@[simp] theorem length_flatten {L : List (List α)} : L.flatten.length = (L.map length).sum := by
|
||||
induction L with
|
||||
| nil => rfl
|
||||
| cons =>
|
||||
@@ -1894,8 +1897,8 @@ theorem eq_nil_or_concat : ∀ l : List α, l = [] ∨ ∃ l' b, l = concat l' b
|
||||
@[simp] theorem flatten_eq_nil_iff {L : List (List α)} : L.flatten = [] ↔ ∀ l ∈ L, l = [] := by
|
||||
induction L <;> simp_all
|
||||
|
||||
theorem nil_eq_flatten_iff {L : List (List α)} : [] = L.flatten ↔ ∀ l ∈ L, l = [] := by
|
||||
simp
|
||||
@[simp] theorem nil_eq_flatten_iff {L : List (List α)} : [] = L.flatten ↔ ∀ l ∈ L, l = [] := by
|
||||
rw [eq_comm, flatten_eq_nil_iff]
|
||||
|
||||
theorem flatten_ne_nil_iff {xss : List (List α)} : xss.flatten ≠ [] ↔ ∃ xs, xs ∈ xss ∧ xs ≠ [] := by
|
||||
simp
|
||||
@@ -2049,7 +2052,7 @@ theorem eq_iff_flatten_eq : ∀ {L L' : List (List α)},
|
||||
|
||||
/-! ### flatMap -/
|
||||
|
||||
@[grind _=_] theorem flatMap_def {l : List α} {f : α → List β} : l.flatMap f = flatten (map f l) := rfl
|
||||
theorem flatMap_def {l : List α} {f : α → List β} : l.flatMap f = flatten (map f l) := rfl
|
||||
|
||||
@[simp] theorem flatMap_id {L : List (List α)} : L.flatMap id = L.flatten := by simp [flatMap_def]
|
||||
|
||||
@@ -2538,25 +2541,17 @@ theorem flatten_reverse {L : List (List α)} :
|
||||
induction l generalizing b <;> simp [*]
|
||||
|
||||
theorem foldl_eq_foldlM {f : β → α → β} {b : β} {l : List α} :
|
||||
l.foldl f b = (l.foldlM (m := Id) (pure <| f · ·) b).run := by
|
||||
simp
|
||||
l.foldl f b = l.foldlM (m := Id) f b := by
|
||||
induction l generalizing b <;> simp [*, foldl]
|
||||
|
||||
theorem foldr_eq_foldrM {f : α → β → β} {b : β} {l : List α} :
|
||||
l.foldr f b = (l.foldrM (m := Id) (pure <| f · ·) b).run := by
|
||||
simp
|
||||
l.foldr f b = l.foldrM (m := Id) f b := by
|
||||
induction l <;> simp [*, foldr]
|
||||
|
||||
theorem idRun_foldlM {f : β → α → Id β} {b : β} {l : List α} :
|
||||
Id.run (l.foldlM f b) = l.foldl (f · · |>.run) b := foldl_eq_foldlM.symm
|
||||
|
||||
@[deprecated idRun_foldlM (since := "2025-05-21")]
|
||||
theorem id_run_foldlM {f : β → α → Id β} {b : β} {l : List α} :
|
||||
@[simp] theorem id_run_foldlM {f : β → α → Id β} {b : β} {l : List α} :
|
||||
Id.run (l.foldlM f b) = l.foldl f b := foldl_eq_foldlM.symm
|
||||
|
||||
theorem idRun_foldrM {f : α → β → Id β} {b : β} {l : List α} :
|
||||
Id.run (l.foldrM f b) = l.foldr (f · · |>.run) b := foldr_eq_foldrM.symm
|
||||
|
||||
@[deprecated idRun_foldrM (since := "2025-05-21")]
|
||||
theorem id_run_foldrM {f : α → β → Id β} {b : β} {l : List α} :
|
||||
@[simp] theorem id_run_foldrM {f : α → β → Id β} {b : β} {l : List α} :
|
||||
Id.run (l.foldrM f b) = l.foldr f b := foldr_eq_foldrM.symm
|
||||
|
||||
@[simp] theorem foldlM_reverse [Monad m] {l : List α} {f : β → α → m β} {b : β} :
|
||||
@@ -2582,9 +2577,9 @@ theorem id_run_foldrM {f : α → β → Id β} {b : β} {l : List α} :
|
||||
induction l generalizing l' <;> simp [*]
|
||||
|
||||
/-- Variant of `foldl_flip_cons_eq_append` specalized to `f = id`. -/
|
||||
@[grind] theorem foldl_flip_cons_eq_append' {l l' : List α} :
|
||||
@[simp, grind] theorem foldl_flip_cons_eq_append' {l l' : List α} :
|
||||
l.foldl (fun xs y => y :: xs) l' = l.reverse ++ l' := by
|
||||
simp
|
||||
induction l generalizing l' <;> simp [*]
|
||||
|
||||
@[simp, grind] theorem foldr_append_eq_append {l : List α} {f : α → List β} {l' : List β} :
|
||||
l.foldr (f · ++ ·) l' = (l.map f).flatten ++ l' := by
|
||||
@@ -2651,10 +2646,10 @@ theorem foldr_map_hom {g : α → β} {f : α → α → α} {f' : β → β →
|
||||
induction l <;> simp [*]
|
||||
|
||||
@[simp, grind _=_] theorem foldl_append {β : Type _} {f : β → α → β} {b : β} {l l' : List α} :
|
||||
(l ++ l').foldl f b = l'.foldl f (l.foldl f b) := by simp [foldl_eq_foldlM, -foldlM_pure]
|
||||
(l ++ l').foldl f b = l'.foldl f (l.foldl f b) := by simp [foldl_eq_foldlM]
|
||||
|
||||
@[simp, grind _=_] theorem foldr_append {f : α → β → β} {b : β} {l l' : List α} :
|
||||
(l ++ l').foldr f b = l.foldr f (l'.foldr f b) := by simp [foldr_eq_foldrM, -foldrM_pure]
|
||||
(l ++ l').foldr f b = l.foldr f (l'.foldr f b) := by simp [foldr_eq_foldrM]
|
||||
|
||||
@[grind] theorem foldl_flatten {f : β → α → β} {b : β} {L : List (List α)} :
|
||||
(flatten L).foldl f b = L.foldl (fun b l => l.foldl f b) b := by
|
||||
@@ -2665,8 +2660,7 @@ theorem foldr_map_hom {g : α → β} {f : α → α → α} {f' : β → β →
|
||||
induction L <;> simp_all
|
||||
|
||||
@[simp, grind] theorem foldl_reverse {l : List α} {f : β → α → β} {b : β} :
|
||||
l.reverse.foldl f b = l.foldr (fun x y => f y x) b := by
|
||||
simp [foldl_eq_foldlM, foldr_eq_foldrM, -foldrM_pure]
|
||||
l.reverse.foldl f b = l.foldr (fun x y => f y x) b := by simp [foldl_eq_foldlM, foldr_eq_foldrM]
|
||||
|
||||
@[simp, grind] theorem foldr_reverse {l : List α} {f : α → β → β} {b : β} :
|
||||
l.reverse.foldr f b = l.foldl (fun x y => f y x) b :=
|
||||
@@ -2718,7 +2712,6 @@ example {xs : List Nat} : xs.foldl (· + ·) 1 > 0 := by
|
||||
intros; omega
|
||||
```
|
||||
-/
|
||||
@[expose]
|
||||
def foldlRecOn {motive : β → Sort _} : ∀ (l : List α) (op : β → α → β) {b : β} (_ : motive b)
|
||||
(_ : ∀ (b : β) (_ : motive b) (a : α) (_ : a ∈ l), motive (op b a)), motive (List.foldl op b l)
|
||||
| [], _, _, hb, _ => hb
|
||||
@@ -2753,7 +2746,6 @@ example {xs : List Nat} : xs.foldr (· + ·) 1 > 0 := by
|
||||
intros; omega
|
||||
```
|
||||
-/
|
||||
@[expose]
|
||||
def foldrRecOn {motive : β → Sort _} : ∀ (l : List α) (op : α → β → β) {b : β} (_ : motive b)
|
||||
(_ : ∀ (b : β) (_ : motive b) (a : α) (_ : a ∈ l), motive (op a b)), motive (List.foldr op b l)
|
||||
| nil, _, _, hb, _ => hb
|
||||
@@ -2951,7 +2943,7 @@ theorem contains_iff_exists_mem_beq [BEq α] {l : List α} {a : α} :
|
||||
l.contains a ↔ ∃ a' ∈ l, a == a' := by
|
||||
induction l <;> simp_all
|
||||
|
||||
@[grind _=_]
|
||||
@[grind]
|
||||
theorem contains_iff_mem [BEq α] [LawfulBEq α] {l : List α} {a : α} :
|
||||
l.contains a ↔ a ∈ l := by
|
||||
simp
|
||||
@@ -3426,8 +3418,8 @@ variable [LawfulBEq α]
|
||||
| Or.inr h' => exact h'
|
||||
else rw [insert_of_not_mem h, mem_cons]
|
||||
|
||||
theorem mem_insert_self {a : α} {l : List α} : a ∈ l.insert a := by
|
||||
simp
|
||||
@[simp] theorem mem_insert_self {a : α} {l : List α} : a ∈ l.insert a :=
|
||||
mem_insert_iff.2 (Or.inl rfl)
|
||||
|
||||
theorem mem_insert_of_mem {l : List α} (h : a ∈ l) : a ∈ l.insert b :=
|
||||
mem_insert_iff.2 (Or.inr h)
|
||||
@@ -3703,6 +3695,17 @@ theorem mem_iff_get? {a} {l : List α} : a ∈ l ↔ ∃ n, l.get? n = some a :=
|
||||
|
||||
/-! ### Deprecations -/
|
||||
|
||||
@[deprecated get?_eq_none (since := "2024-11-29")] abbrev get?_len_le := @getElem?_eq_none
|
||||
@[deprecated getElem?_eq_some_iff (since := "2024-11-29")]
|
||||
abbrev getElem?_eq_some := @getElem?_eq_some_iff
|
||||
@[deprecated get?_eq_some_iff (since := "2024-11-29")]
|
||||
abbrev get?_eq_some := @getElem?_eq_some_iff
|
||||
@[deprecated LawfulGetElem.getElem?_def (since := "2024-11-29")]
|
||||
theorem getElem?_eq (l : List α) (i : Nat) :
|
||||
l[i]? = if h : i < l.length then some l[i] else none :=
|
||||
getElem?_def _ _
|
||||
@[deprecated getElem?_eq_none (since := "2024-11-29")] abbrev getElem?_len_le := @getElem?_eq_none
|
||||
|
||||
@[deprecated _root_.isSome_getElem? (since := "2024-12-09")]
|
||||
theorem isSome_getElem? {l : List α} {i : Nat} : l[i]?.isSome ↔ i < l.length := by
|
||||
simp
|
||||
|
||||
@@ -27,7 +27,7 @@ that the index is valid.
|
||||
|
||||
`List.mapIdx` is a variant that does not provide the function with evidence that the index is valid.
|
||||
-/
|
||||
@[inline, expose] def mapFinIdx (as : List α) (f : (i : Nat) → α → (h : i < as.length) → β) : List β :=
|
||||
@[inline] def mapFinIdx (as : List α) (f : (i : Nat) → α → (h : i < as.length) → β) : List β :=
|
||||
go as #[] (by simp)
|
||||
where
|
||||
/-- Auxiliary for `mapFinIdx`:
|
||||
@@ -44,7 +44,7 @@ returning the list of results.
|
||||
`List.mapFinIdx` is a variant that additionally provides the function with a proof that the index
|
||||
is valid.
|
||||
-/
|
||||
@[inline, expose] def mapIdx (f : Nat → α → β) (as : List α) : List β := go as #[] where
|
||||
@[inline] def mapIdx (f : Nat → α → β) (as : List α) : List β := go as #[] where
|
||||
/-- Auxiliary for `mapIdx`:
|
||||
`mapIdx.go [a₀, a₁, ...] acc = acc.toList ++ [f acc.size a₀, f (acc.size + 1) a₁, ...]` -/
|
||||
@[specialize] go : List α → Array β → List β
|
||||
@@ -320,7 +320,7 @@ theorem mapIdx_nil {f : Nat → α → β} : mapIdx f [] = [] :=
|
||||
theorem mapIdx_go_length {acc : Array β} :
|
||||
length (mapIdx.go f l acc) = length l + acc.size := by
|
||||
induction l generalizing acc with
|
||||
| nil => simp [mapIdx.go]
|
||||
| nil => simp only [mapIdx.go, length_nil, Nat.zero_add]
|
||||
| cons _ _ ih =>
|
||||
simp only [mapIdx.go, ih, Array.size_push, Nat.add_succ, length_cons, Nat.add_comm]
|
||||
|
||||
@@ -348,7 +348,7 @@ theorem getElem?_mapIdx_go : ∀ {l : List α} {acc : Array β} {i : Nat},
|
||||
split <;> split
|
||||
· simp only [Option.some.injEq]
|
||||
rw [← Array.getElem_toList]
|
||||
simp only [Array.toList_push]
|
||||
simp only [Array.push_toList]
|
||||
rw [getElem_append_left, ← Array.getElem_toList]
|
||||
· have : i = acc.size := by omega
|
||||
simp_all
|
||||
|
||||
@@ -44,7 +44,6 @@ This is a non-tail-recursive variant of `List.mapM` that's easier to reason abou
|
||||
as the main definition and replaced by the tail-recursive version because they can only be proved
|
||||
equal when `m` is a `LawfulMonad`.
|
||||
-/
|
||||
@[expose]
|
||||
def mapM' [Monad m] (f : α → m β) : List α → m (List β)
|
||||
| [] => pure []
|
||||
| a :: l => return (← f a) :: (← l.mapM' f)
|
||||
@@ -69,11 +68,7 @@ theorem mapM'_eq_mapM [Monad m] [LawfulMonad m] {f : α → m β} {l : List α}
|
||||
l.mapM (m := m) (pure <| f ·) = pure (l.map f) := by
|
||||
induction l <;> simp_all
|
||||
|
||||
@[simp] theorem idRun_mapM {l : List α} {f : α → Id β} : (l.mapM f).run = l.map (f · |>.run) :=
|
||||
mapM_pure
|
||||
|
||||
@[deprecated idRun_mapM (since := "2025-05-21")]
|
||||
theorem mapM_id {l : List α} {f : α → Id β} : (l.mapM f).run = l.map (f · |>.run) :=
|
||||
@[simp] theorem mapM_id {l : List α} {f : α → Id β} : l.mapM f = l.map f :=
|
||||
mapM_pure
|
||||
|
||||
@[simp] theorem mapM_map [Monad m] [LawfulMonad m] {f : α → β} {g : β → m γ} {l : List α} :
|
||||
@@ -350,18 +345,12 @@ theorem forIn'_eq_foldlM [Monad m] [LawfulMonad m]
|
||||
simp only [forIn'_eq_foldlM]
|
||||
induction l.attach generalizing init <;> simp_all
|
||||
|
||||
@[simp] theorem idRun_forIn'_yield_eq_foldl
|
||||
(l : List α) (f : (a : α) → a ∈ l → β → Id β) (init : β) :
|
||||
(forIn' l init (fun a m b => .yield <$> f a m b)).run =
|
||||
l.attach.foldl (fun b ⟨a, h⟩ => f a h b |>.run) init :=
|
||||
forIn'_pure_yield_eq_foldl _ _
|
||||
|
||||
@[deprecated idRun_forIn'_yield_eq_foldl (since := "2025-05-21")]
|
||||
theorem forIn'_yield_eq_foldl
|
||||
@[simp] theorem forIn'_yield_eq_foldl
|
||||
{l : List α} (f : (a : α) → a ∈ l → β → β) (init : β) :
|
||||
forIn' (m := Id) l init (fun a m b => .yield (f a m b)) =
|
||||
l.attach.foldl (fun b ⟨a, h⟩ => f a h b) init :=
|
||||
forIn'_pure_yield_eq_foldl _ _
|
||||
l.attach.foldl (fun b ⟨a, h⟩ => f a h b) init := by
|
||||
simp only [forIn'_eq_foldlM]
|
||||
induction l.attach generalizing init <;> simp_all
|
||||
|
||||
@[simp] theorem forIn'_map [Monad m] [LawfulMonad m]
|
||||
{l : List α} (g : α → β) (f : (b : β) → b ∈ l.map g → γ → m (ForInStep γ)) :
|
||||
@@ -409,18 +398,12 @@ theorem forIn_eq_foldlM [Monad m] [LawfulMonad m]
|
||||
simp only [forIn_eq_foldlM]
|
||||
induction l generalizing init <;> simp_all
|
||||
|
||||
@[simp] theorem idRun_forIn_yield_eq_foldl
|
||||
(l : List α) (f : α → β → Id β) (init : β) :
|
||||
(forIn l init (fun a b => .yield <$> f a b)).run =
|
||||
l.foldl (fun b a => f a b |>.run) init :=
|
||||
forIn_pure_yield_eq_foldl _ _
|
||||
|
||||
@[deprecated idRun_forIn_yield_eq_foldl (since := "2025-05-21")]
|
||||
theorem forIn_yield_eq_foldl
|
||||
@[simp] theorem forIn_yield_eq_foldl
|
||||
{l : List α} (f : α → β → β) (init : β) :
|
||||
forIn (m := Id) l init (fun a b => .yield (f a b)) =
|
||||
l.foldl (fun b a => f a b) init :=
|
||||
forIn_pure_yield_eq_foldl _ _
|
||||
l.foldl (fun b a => f a b) init := by
|
||||
simp only [forIn_eq_foldlM]
|
||||
induction l generalizing init <;> simp_all
|
||||
|
||||
@[simp] theorem forIn_map [Monad m] [LawfulMonad m]
|
||||
{l : List α} {g : α → β} {f : β → γ → m (ForInStep γ)} :
|
||||
|
||||
@@ -617,6 +617,9 @@ set_option linter.deprecated false
|
||||
@[deprecated zipIdx_eq_nil_iff (since := "2025-01-21"), simp]
|
||||
theorem enum_eq_nil_iff {l : List α} : List.enum l = [] ↔ l = [] := enumFrom_eq_nil
|
||||
|
||||
@[deprecated zipIdx_eq_nil_iff (since := "2024-11-04")]
|
||||
theorem enum_eq_nil {l : List α} : List.enum l = [] ↔ l = [] := enum_eq_nil_iff
|
||||
|
||||
@[deprecated zipIdx_singleton (since := "2025-01-21"), simp]
|
||||
theorem enum_singleton (x : α) : enum [x] = [(0, x)] := rfl
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ theorem IsSuffix.getElem {xs ys : List α} (h : xs <:+ ys) {i} (hn : i < xs.leng
|
||||
have := h.length_le
|
||||
omega
|
||||
|
||||
theorem suffix_iff_getElem? : l₁ <:+ l₂ ↔
|
||||
theorem isSuffix_iff : l₁ <:+ l₂ ↔
|
||||
l₁.length ≤ l₂.length ∧ ∀ i (h : i < l₁.length), l₂[i + l₂.length - l₁.length]? = some l₁[i] := by
|
||||
suffices l₁.length ≤ l₂.length ∧ l₁ <:+ l₂ ↔
|
||||
l₁.length ≤ l₂.length ∧ ∀ i (h : i < l₁.length), l₂[i + l₂.length - l₁.length]? = some l₁[i] by
|
||||
@@ -41,7 +41,7 @@ theorem suffix_iff_getElem? : l₁ <:+ l₂ ↔
|
||||
exact (this.mpr h).2
|
||||
simp only [and_congr_right_iff]
|
||||
intro le
|
||||
rw [← reverse_prefix, prefix_iff_getElem?]
|
||||
rw [← reverse_prefix, isPrefix_iff]
|
||||
simp only [length_reverse]
|
||||
constructor
|
||||
· intro w i h
|
||||
@@ -60,33 +60,15 @@ theorem suffix_iff_getElem? : l₁ <:+ l₂ ↔
|
||||
rw [w, getElem_reverse]
|
||||
exact Nat.lt_of_lt_of_le h le
|
||||
|
||||
@[deprecated suffix_iff_getElem? (since := "2025-05-27")]
|
||||
abbrev isSuffix_iff := @suffix_iff_getElem?
|
||||
|
||||
theorem suffix_iff_getElem {l₁ l₂ : List α} :
|
||||
l₁ <:+ l₂ ↔ ∃ (_ : l₁.length ≤ l₂.length), ∀ i (_ : i < l₁.length), l₂[i + l₂.length - l₁.length] = l₁[i] := by
|
||||
rw [suffix_iff_getElem?]
|
||||
constructor
|
||||
· rintro ⟨h, w⟩
|
||||
refine ⟨h, fun i h => ?_⟩
|
||||
specialize w i h
|
||||
rw [getElem?_eq_getElem] at w
|
||||
simpa using w
|
||||
· rintro ⟨h, w⟩
|
||||
refine ⟨h, fun i h => ?_⟩
|
||||
specialize w i h
|
||||
rw [getElem?_eq_getElem]
|
||||
simpa using w
|
||||
|
||||
theorem infix_iff_getElem? : l₁ <:+: l₂ ↔
|
||||
theorem isInfix_iff : l₁ <:+: l₂ ↔
|
||||
∃ k, l₁.length + k ≤ l₂.length ∧ ∀ i (h : i < l₁.length), l₂[i + k]? = some l₁[i] := by
|
||||
constructor
|
||||
· intro h
|
||||
obtain ⟨t, p, s⟩ := infix_iff_suffix_prefix.mp h
|
||||
refine ⟨t.length - l₁.length, by have := p.length_le; have := s.length_le; omega, ?_⟩
|
||||
rw [suffix_iff_getElem?] at p
|
||||
rw [isSuffix_iff] at p
|
||||
obtain ⟨p', p⟩ := p
|
||||
rw [prefix_iff_getElem?] at s
|
||||
rw [isPrefix_iff] at s
|
||||
intro i h
|
||||
rw [s _ (by omega)]
|
||||
specialize p i (by omega)
|
||||
@@ -111,9 +93,6 @@ theorem infix_iff_getElem? : l₁ <:+: l₂ ↔
|
||||
simp_all
|
||||
omega
|
||||
|
||||
@[deprecated infix_iff_getElem? (since := "2025-05-27")]
|
||||
abbrev isInfix_iff := @infix_iff_getElem?
|
||||
|
||||
theorem suffix_iff_eq_append : l₁ <:+ l₂ ↔ take (length l₂ - length l₁) l₂ ++ l₁ = l₂ :=
|
||||
⟨by rintro ⟨r, rfl⟩; simp only [length_append, Nat.add_sub_cancel_right, take_left], fun e =>
|
||||
⟨_, e⟩⟩
|
||||
@@ -136,7 +115,7 @@ theorem suffix_iff_eq_drop : l₁ <:+ l₂ ↔ l₁ = drop (length l₂ - length
|
||||
⟨fun h => append_cancel_left <| (suffix_iff_eq_append.1 h).trans (take_append_drop _ _).symm,
|
||||
fun e => e.symm ▸ drop_suffix _ _⟩
|
||||
|
||||
@[grind =] theorem prefix_take_le_iff {xs : List α} (hm : i < xs.length) :
|
||||
theorem prefix_take_le_iff {xs : List α} (hm : i < xs.length) :
|
||||
xs.take i <+: xs.take j ↔ i ≤ j := by
|
||||
simp only [prefix_iff_eq_take, length_take]
|
||||
induction i generalizing xs j with
|
||||
|
||||
@@ -56,7 +56,7 @@ theorem getElem?_take_eq_none {l : List α} {i j : Nat} (h : i ≤ j) :
|
||||
(l.take i)[j]? = none :=
|
||||
getElem?_eq_none <| Nat.le_trans (length_take_le _ _) h
|
||||
|
||||
@[grind =] theorem getElem?_take {l : List α} {i j : Nat} :
|
||||
@[grind =]theorem getElem?_take {l : List α} {i j : Nat} :
|
||||
(l.take i)[j]? = if j < i then l[j]? else none := by
|
||||
split
|
||||
· next h => exact getElem?_take_of_lt h
|
||||
@@ -199,7 +199,7 @@ theorem take_eq_dropLast {l : List α} {i : Nat} (h : i + 1 = l.length) :
|
||||
simpa using h
|
||||
|
||||
theorem take_prefix_take_left {l : List α} {i j : Nat} (h : i ≤ j) : take i l <+: take j l := by
|
||||
rw [prefix_iff_getElem?]
|
||||
rw [isPrefix_iff]
|
||||
intro i w
|
||||
rw [getElem?_take_of_lt, getElem_take, getElem?_eq_getElem]
|
||||
simp only [length_take] at w
|
||||
|
||||
@@ -173,6 +173,7 @@ theorem ofFnM_pure [Monad m] [LawfulMonad m] {n} {f : Fin n → α} :
|
||||
|
||||
@[simp, grind =] theorem idRun_ofFnM {f : Fin n → Id α} :
|
||||
Id.run (ofFnM f) = ofFn (fun i => Id.run (f i)) := by
|
||||
unfold Id.run
|
||||
induction n with
|
||||
| zero => simp
|
||||
| succ n ih => simp [-ofFn_succ, ofFnM_succ_last, ofFn_succ_last, ih]
|
||||
|
||||
@@ -24,7 +24,7 @@ open Nat
|
||||
|
||||
/-! ### Pairwise -/
|
||||
|
||||
@[grind →] theorem Pairwise.sublist : l₁ <+ l₂ → l₂.Pairwise R → l₁.Pairwise R
|
||||
theorem Pairwise.sublist : l₁ <+ l₂ → l₂.Pairwise R → l₁.Pairwise R
|
||||
| .slnil, h => h
|
||||
| .cons _ s, .cons _ h₂ => h₂.sublist s
|
||||
| .cons₂ _ s, .cons h₁ h₂ => (h₂.sublist s).cons fun _ h => h₁ _ (s.subset h)
|
||||
@@ -37,11 +37,11 @@ theorem Pairwise.imp {α R S} (H : ∀ {a b}, R a b → S a b) :
|
||||
theorem rel_of_pairwise_cons (p : (a :: l).Pairwise R) : ∀ {a'}, a' ∈ l → R a a' :=
|
||||
(pairwise_cons.1 p).1 _
|
||||
|
||||
@[grind →] theorem Pairwise.of_cons (p : (a :: l).Pairwise R) : Pairwise R l :=
|
||||
theorem Pairwise.of_cons (p : (a :: l).Pairwise R) : Pairwise R l :=
|
||||
(pairwise_cons.1 p).2
|
||||
|
||||
set_option linter.unusedVariables false in
|
||||
@[grind] theorem Pairwise.tail : ∀ {l : List α} (h : Pairwise R l), Pairwise R l.tail
|
||||
theorem Pairwise.tail : ∀ {l : List α} (h : Pairwise R l), Pairwise R l.tail
|
||||
| [], h => h
|
||||
| _ :: _, h => h.of_cons
|
||||
|
||||
@@ -101,11 +101,11 @@ theorem Pairwise.forall_of_forall_of_flip (h₁ : ∀ x ∈ l, R x x) (h₂ : Pa
|
||||
· exact h₃.1 _ hx
|
||||
· exact ih (fun x hx => h₁ _ <| mem_cons_of_mem _ hx) h₂.2 h₃.2 hx hy
|
||||
|
||||
@[grind] theorem pairwise_singleton (R) (a : α) : Pairwise R [a] := by simp
|
||||
theorem pairwise_singleton (R) (a : α) : Pairwise R [a] := by simp
|
||||
|
||||
@[grind =] theorem pairwise_pair {a b : α} : Pairwise R [a, b] ↔ R a b := by simp
|
||||
theorem pairwise_pair {a b : α} : Pairwise R [a, b] ↔ R a b := by simp
|
||||
|
||||
@[grind =] theorem pairwise_map {l : List α} :
|
||||
theorem pairwise_map {l : List α} :
|
||||
(l.map f).Pairwise R ↔ l.Pairwise fun a b => R (f a) (f b) := by
|
||||
induction l
|
||||
· simp
|
||||
@@ -115,11 +115,11 @@ theorem Pairwise.of_map {S : β → β → Prop} (f : α → β) (H : ∀ a b :
|
||||
(p : Pairwise S (map f l)) : Pairwise R l :=
|
||||
(pairwise_map.1 p).imp (H _ _)
|
||||
|
||||
@[grind] theorem Pairwise.map {S : β → β → Prop} (f : α → β) (H : ∀ a b : α, R a b → S (f a) (f b))
|
||||
theorem Pairwise.map {S : β → β → Prop} (f : α → β) (H : ∀ a b : α, R a b → S (f a) (f b))
|
||||
(p : Pairwise R l) : Pairwise S (map f l) :=
|
||||
pairwise_map.2 <| p.imp (H _ _)
|
||||
|
||||
@[grind =] theorem pairwise_filterMap {f : β → Option α} {l : List β} :
|
||||
theorem pairwise_filterMap {f : β → Option α} {l : List β} :
|
||||
Pairwise R (filterMap f l) ↔ Pairwise (fun a a' : β => ∀ b, f a = some b → ∀ b', f a' = some b' → R b b') l := by
|
||||
let _S (a a' : β) := ∀ b, f a = some b → ∀ b', f a' = some b' → R b b'
|
||||
induction l with
|
||||
@@ -134,20 +134,20 @@ theorem Pairwise.of_map {S : β → β → Prop} (f : α → β) (H : ∀ a b :
|
||||
simpa [IH, e] using fun _ =>
|
||||
⟨fun h a ha b hab => h _ _ ha hab, fun h a b ha hab => h _ ha _ hab⟩
|
||||
|
||||
@[grind] theorem Pairwise.filterMap {S : β → β → Prop} (f : α → Option β)
|
||||
theorem Pairwise.filterMap {S : β → β → Prop} (f : α → Option β)
|
||||
(H : ∀ a a' : α, R a a' → ∀ b, f a = some b → ∀ b', f a' = some b' → S b b') {l : List α} (p : Pairwise R l) :
|
||||
Pairwise S (filterMap f l) :=
|
||||
pairwise_filterMap.2 <| p.imp (H _ _)
|
||||
|
||||
@[grind =] theorem pairwise_filter {p : α → Bool} {l : List α} :
|
||||
theorem pairwise_filter {p : α → Prop} [DecidablePred p] {l : List α} :
|
||||
Pairwise R (filter p l) ↔ Pairwise (fun x y => p x → p y → R x y) l := by
|
||||
rw [← filterMap_eq_filter, pairwise_filterMap]
|
||||
simp
|
||||
|
||||
@[grind] theorem Pairwise.filter (p : α → Bool) : Pairwise R l → Pairwise R (filter p l) :=
|
||||
theorem Pairwise.filter (p : α → Bool) : Pairwise R l → Pairwise R (filter p l) :=
|
||||
Pairwise.sublist filter_sublist
|
||||
|
||||
@[grind =] theorem pairwise_append {l₁ l₂ : List α} :
|
||||
theorem pairwise_append {l₁ l₂ : List α} :
|
||||
(l₁ ++ l₂).Pairwise R ↔ l₁.Pairwise R ∧ l₂.Pairwise R ∧ ∀ a ∈ l₁, ∀ b ∈ l₂, R a b := by
|
||||
induction l₁ <;> simp [*, or_imp, forall_and, and_assoc, and_left_comm]
|
||||
|
||||
@@ -157,13 +157,13 @@ theorem pairwise_append_comm {R : α → α → Prop} (s : ∀ {x y}, R x y →
|
||||
(x : α) (xm : x ∈ l₂) (y : α) (ym : y ∈ l₁) : R x y := s (H y ym x xm)
|
||||
simp only [pairwise_append, and_left_comm]; rw [Iff.intro (this l₁ l₂) (this l₂ l₁)]
|
||||
|
||||
@[grind =] theorem pairwise_middle {R : α → α → Prop} (s : ∀ {x y}, R x y → R y x) {a : α} {l₁ l₂ : List α} :
|
||||
theorem pairwise_middle {R : α → α → Prop} (s : ∀ {x y}, R x y → R y x) {a : α} {l₁ l₂ : List α} :
|
||||
Pairwise R (l₁ ++ a :: l₂) ↔ Pairwise R (a :: (l₁ ++ l₂)) := by
|
||||
show Pairwise R (l₁ ++ ([a] ++ l₂)) ↔ Pairwise R ([a] ++ l₁ ++ l₂)
|
||||
rw [← append_assoc, pairwise_append, @pairwise_append _ _ ([a] ++ l₁), pairwise_append_comm s]
|
||||
simp only [mem_append, or_comm]
|
||||
|
||||
@[grind =] theorem pairwise_flatten {L : List (List α)} :
|
||||
theorem pairwise_flatten {L : List (List α)} :
|
||||
Pairwise R (flatten L) ↔
|
||||
(∀ l ∈ L, Pairwise R l) ∧ Pairwise (fun l₁ l₂ => ∀ x ∈ l₁, ∀ y ∈ l₂, R x y) L := by
|
||||
induction L with
|
||||
@@ -174,16 +174,16 @@ theorem pairwise_append_comm {R : α → α → Prop} (s : ∀ {x y}, R x y →
|
||||
rw [and_comm, and_congr_left_iff]
|
||||
intros; exact ⟨fun h l' b c d e => h c d e l' b, fun h c d e l' b => h l' b c d e⟩
|
||||
|
||||
@[grind =] theorem pairwise_flatMap {R : β → β → Prop} {l : List α} {f : α → List β} :
|
||||
theorem pairwise_flatMap {R : β → β → Prop} {l : List α} {f : α → List β} :
|
||||
List.Pairwise R (l.flatMap f) ↔
|
||||
(∀ a ∈ l, Pairwise R (f a)) ∧ Pairwise (fun a₁ a₂ => ∀ x ∈ f a₁, ∀ y ∈ f a₂, R x y) l := by
|
||||
simp [List.flatMap, pairwise_flatten, pairwise_map]
|
||||
|
||||
@[grind =] theorem pairwise_reverse {l : List α} :
|
||||
theorem pairwise_reverse {l : List α} :
|
||||
l.reverse.Pairwise R ↔ l.Pairwise (fun a b => R b a) := by
|
||||
induction l <;> simp [*, pairwise_append, and_comm]
|
||||
|
||||
@[simp, grind =] theorem pairwise_replicate {n : Nat} {a : α} :
|
||||
@[simp] theorem pairwise_replicate {n : Nat} {a : α} :
|
||||
(replicate n a).Pairwise R ↔ n ≤ 1 ∨ R a a := by
|
||||
induction n with
|
||||
| zero => simp
|
||||
@@ -205,10 +205,10 @@ theorem pairwise_append_comm {R : α → α → Prop} (s : ∀ {x y}, R x y →
|
||||
simp
|
||||
· exact ⟨fun _ => h, Or.inr h⟩
|
||||
|
||||
@[grind] theorem Pairwise.drop {l : List α} {i : Nat} (h : List.Pairwise R l) : List.Pairwise R (l.drop i) :=
|
||||
theorem Pairwise.drop {l : List α} {i : Nat} (h : List.Pairwise R l) : List.Pairwise R (l.drop i) :=
|
||||
h.sublist (drop_sublist _ _)
|
||||
|
||||
@[grind] theorem Pairwise.take {l : List α} {i : Nat} (h : List.Pairwise R l) : List.Pairwise R (l.take i) :=
|
||||
theorem Pairwise.take {l : List α} {i : Nat} (h : List.Pairwise R l) : List.Pairwise R (l.take i) :=
|
||||
h.sublist (take_sublist _ _)
|
||||
|
||||
theorem pairwise_iff_forall_sublist : l.Pairwise R ↔ (∀ {a b}, [a,b] <+ l → R a b) := by
|
||||
@@ -247,7 +247,7 @@ theorem pairwise_of_forall_mem_list {l : List α} {r : α → α → Prop} (h :
|
||||
intro a b hab
|
||||
apply h <;> (apply hab.subset; simp)
|
||||
|
||||
@[grind =] theorem pairwise_pmap {p : β → Prop} {f : ∀ b, p b → α} {l : List β} (h : ∀ x ∈ l, p x) :
|
||||
theorem pairwise_pmap {p : β → Prop} {f : ∀ b, p b → α} {l : List β} (h : ∀ x ∈ l, p x) :
|
||||
Pairwise R (l.pmap f h) ↔
|
||||
Pairwise (fun b₁ b₂ => ∀ (h₁ : p b₁) (h₂ : p b₂), R (f b₁ h₁) (f b₂ h₂)) l := by
|
||||
induction l with
|
||||
@@ -259,7 +259,7 @@ theorem pairwise_of_forall_mem_list {l : List α} {r : α → α → Prop} (h :
|
||||
rintro H _ b hb rfl
|
||||
exact H b hb _ _
|
||||
|
||||
@[grind] theorem Pairwise.pmap {l : List α} (hl : Pairwise R l) {p : α → Prop} {f : ∀ a, p a → β}
|
||||
theorem Pairwise.pmap {l : List α} (hl : Pairwise R l) {p : α → Prop} {f : ∀ a, p a → β}
|
||||
(h : ∀ x ∈ l, p x) {S : β → β → Prop}
|
||||
(hS : ∀ ⦃x⦄ (hx : p x) ⦃y⦄ (hy : p y), R x y → S (f x hx) (f y hy)) :
|
||||
Pairwise S (l.pmap f h) := by
|
||||
@@ -268,20 +268,17 @@ theorem pairwise_of_forall_mem_list {l : List α} {r : α → α → Prop} (h :
|
||||
|
||||
/-! ### Nodup -/
|
||||
|
||||
@[simp, grind]
|
||||
@[simp]
|
||||
theorem nodup_nil : @Nodup α [] :=
|
||||
Pairwise.nil
|
||||
|
||||
@[simp, grind =]
|
||||
@[simp]
|
||||
theorem nodup_cons {a : α} {l : List α} : Nodup (a :: l) ↔ a ∉ l ∧ Nodup l := by
|
||||
simp only [Nodup, pairwise_cons, forall_mem_ne]
|
||||
|
||||
theorem Nodup.sublist : l₁ <+ l₂ → Nodup l₂ → Nodup l₁ :=
|
||||
Pairwise.sublist
|
||||
|
||||
grind_pattern Nodup.sublist => l₁ <+ l₂, Nodup l₁
|
||||
grind_pattern Nodup.sublist => l₁ <+ l₂, Nodup l₂
|
||||
|
||||
theorem Sublist.nodup : l₁ <+ l₂ → Nodup l₂ → Nodup l₁ :=
|
||||
Nodup.sublist
|
||||
|
||||
@@ -306,7 +303,7 @@ theorem getElem?_inj {xs : List α}
|
||||
rw [mem_iff_getElem?]
|
||||
exact ⟨_, h₂⟩; exact ⟨_ , h₂.symm⟩
|
||||
|
||||
@[simp, grind =] theorem nodup_replicate {n : Nat} {a : α} :
|
||||
@[simp] theorem nodup_replicate {n : Nat} {a : α} :
|
||||
(replicate n a).Nodup ↔ n ≤ 1 := by simp [Nodup]
|
||||
|
||||
end List
|
||||
|
||||
@@ -142,8 +142,6 @@ theorem range'_eq_cons_iff : range' s n = a :: xs ↔ s = a ∧ 0 < n ∧ xs = r
|
||||
|
||||
/-! ### range -/
|
||||
|
||||
@[simp, grind =] theorem range_one : range 1 = [0] := rfl
|
||||
|
||||
theorem range_loop_range' : ∀ s n, range.loop s (range' s n) = range' 0 (n + s)
|
||||
| 0, _ => rfl
|
||||
| s + 1, n => by rw [← Nat.add_assoc, Nat.add_right_comm n s 1]; exact range_loop_range' s (n + 1)
|
||||
|
||||
@@ -24,14 +24,14 @@ open Nat
|
||||
section isPrefixOf
|
||||
variable [BEq α]
|
||||
|
||||
@[simp, grind =] theorem isPrefixOf_cons₂_self [LawfulBEq α] {a : α} :
|
||||
@[simp] theorem isPrefixOf_cons₂_self [LawfulBEq α] {a : α} :
|
||||
isPrefixOf (a::as) (a::bs) = isPrefixOf as bs := by simp [isPrefixOf_cons₂]
|
||||
|
||||
@[simp] theorem isPrefixOf_length_pos_nil {l : List α} (h : 0 < l.length) : isPrefixOf l [] = false := by
|
||||
cases l <;> simp_all [isPrefixOf]
|
||||
|
||||
@[simp, grind =] theorem isPrefixOf_replicate {a : α} :
|
||||
isPrefixOf l (replicate n a) = ((l.length ≤ n) && l.all (· == a)) := by
|
||||
@[simp] theorem isPrefixOf_replicate {a : α} :
|
||||
isPrefixOf l (replicate n a) = (decide (l.length ≤ n) && l.all (· == a)) := by
|
||||
induction l generalizing n with
|
||||
| nil => simp
|
||||
| cons _ _ ih =>
|
||||
@@ -45,10 +45,10 @@ end isPrefixOf
|
||||
section isSuffixOf
|
||||
variable [BEq α]
|
||||
|
||||
@[simp, grind =] theorem isSuffixOf_cons_nil : isSuffixOf (a::as) ([] : List α) = false := by
|
||||
@[simp] theorem isSuffixOf_cons_nil : isSuffixOf (a::as) ([] : List α) = false := by
|
||||
simp [isSuffixOf]
|
||||
|
||||
@[simp, grind =] theorem isSuffixOf_replicate {a : α} :
|
||||
@[simp] theorem isSuffixOf_replicate {a : α} :
|
||||
isSuffixOf l (replicate n a) = (decide (l.length ≤ n) && l.all (· == a)) := by
|
||||
simp [isSuffixOf, all_eq]
|
||||
|
||||
@@ -58,8 +58,7 @@ end isSuffixOf
|
||||
|
||||
/-! ### List subset -/
|
||||
|
||||
-- For now we don't annotate lemmas about `Subset` for `grind`, but instead just unfold the definition.
|
||||
@[grind =] theorem subset_def {l₁ l₂ : List α} : l₁ ⊆ l₂ ↔ ∀ {a : α}, a ∈ l₁ → a ∈ l₂ := .rfl
|
||||
theorem subset_def {l₁ l₂ : List α} : l₁ ⊆ l₂ ↔ ∀ {a : α}, a ∈ l₁ → a ∈ l₂ := .rfl
|
||||
|
||||
@[simp] theorem nil_subset (l : List α) : [] ⊆ l := nofun
|
||||
|
||||
@@ -96,15 +95,9 @@ theorem eq_nil_of_subset_nil {l : List α} : l ⊆ [] → l = [] := subset_nil.m
|
||||
theorem map_subset {l₁ l₂ : List α} (f : α → β) (h : l₁ ⊆ l₂) : map f l₁ ⊆ map f l₂ :=
|
||||
fun x => by simp only [mem_map]; exact .imp fun a => .imp_left (@h _)
|
||||
|
||||
grind_pattern map_subset => l₁ ⊆ l₂, map f l₁
|
||||
grind_pattern map_subset => l₁ ⊆ l₂, map f l₂
|
||||
|
||||
theorem filter_subset {l₁ l₂ : List α} (p : α → Bool) (H : l₁ ⊆ l₂) : filter p l₁ ⊆ filter p l₂ :=
|
||||
fun x => by simp_all [mem_filter, subset_def.1 H]
|
||||
|
||||
grind_pattern filter_subset => l₁ ⊆ l₂, filter p l₁
|
||||
grind_pattern filter_subset => l₁ ⊆ l₂, filter p l₂
|
||||
|
||||
theorem filterMap_subset {l₁ l₂ : List α} (f : α → Option β) (H : l₁ ⊆ l₂) :
|
||||
filterMap f l₁ ⊆ filterMap f l₂ := by
|
||||
intro x
|
||||
@@ -112,9 +105,6 @@ theorem filterMap_subset {l₁ l₂ : List α} (f : α → Option β) (H : l₁
|
||||
rintro ⟨a, h, w⟩
|
||||
exact ⟨a, H h, w⟩
|
||||
|
||||
grind_pattern filterMap_subset => l₁ ⊆ l₂, filterMap f l₁
|
||||
grind_pattern filterMap_subset => l₁ ⊆ l₂, filterMap f l₂
|
||||
|
||||
theorem subset_append_left (l₁ l₂ : List α) : l₁ ⊆ l₁ ++ l₂ := fun _ => mem_append_left _
|
||||
|
||||
theorem subset_append_right (l₁ l₂ : List α) : l₂ ⊆ l₁ ++ l₂ := fun _ => mem_append_right _
|
||||
@@ -149,11 +139,11 @@ theorem subset_replicate {n : Nat} {a : α} {l : List α} (h : n ≠ 0) : l ⊆
|
||||
|
||||
/-! ### Sublist and isSublist -/
|
||||
|
||||
@[simp, grind] theorem nil_sublist : ∀ l : List α, [] <+ l
|
||||
@[simp] theorem nil_sublist : ∀ l : List α, [] <+ l
|
||||
| [] => .slnil
|
||||
| a :: l => (nil_sublist l).cons a
|
||||
|
||||
@[simp, grind] theorem Sublist.refl : ∀ l : List α, l <+ l
|
||||
@[simp] theorem Sublist.refl : ∀ l : List α, l <+ l
|
||||
| [] => .slnil
|
||||
| a :: l => (Sublist.refl l).cons₂ a
|
||||
|
||||
@@ -170,14 +160,14 @@ theorem Sublist.trans {l₁ l₂ l₃ : List α} (h₁ : l₁ <+ l₂) (h₂ : l
|
||||
|
||||
instance : Trans (@Sublist α) Sublist Sublist := ⟨Sublist.trans⟩
|
||||
|
||||
attribute [simp, grind] Sublist.cons
|
||||
attribute [simp] Sublist.cons
|
||||
|
||||
theorem sublist_cons_self (a : α) (l : List α) : l <+ a :: l := (Sublist.refl l).cons _
|
||||
|
||||
theorem sublist_of_cons_sublist : a :: l₁ <+ l₂ → l₁ <+ l₂ :=
|
||||
(sublist_cons_self a l₁).trans
|
||||
|
||||
@[simp, grind =]
|
||||
@[simp]
|
||||
theorem cons_sublist_cons : a :: l₁ <+ a :: l₂ ↔ l₁ <+ l₂ :=
|
||||
⟨fun | .cons _ s => sublist_of_cons_sublist s | .cons₂ _ s => s, .cons₂ _⟩
|
||||
|
||||
@@ -191,7 +181,7 @@ theorem sublist_or_mem_of_sublist (h : l <+ l₁ ++ a :: l₂) : l <+ l₁ ++ l
|
||||
| .cons _ h => exact (IH h).imp_left (Sublist.cons _)
|
||||
| .cons₂ _ h => exact (IH h).imp (Sublist.cons₂ _) (.tail _)
|
||||
|
||||
@[grind →] theorem Sublist.subset : l₁ <+ l₂ → l₁ ⊆ l₂
|
||||
theorem Sublist.subset : l₁ <+ l₂ → l₁ ⊆ l₂
|
||||
| .slnil, _, h => h
|
||||
| .cons _ s, _, h => .tail _ (s.subset h)
|
||||
| .cons₂ .., _, .head .. => .head ..
|
||||
@@ -200,10 +190,10 @@ theorem sublist_or_mem_of_sublist (h : l <+ l₁ ++ a :: l₂) : l <+ l₁ ++ l
|
||||
protected theorem Sublist.mem (hx : a ∈ l₁) (hl : l₁ <+ l₂) : a ∈ l₂ :=
|
||||
hl.subset hx
|
||||
|
||||
@[grind] theorem Sublist.head_mem (s : ys <+ xs) (h) : ys.head h ∈ xs :=
|
||||
theorem Sublist.head_mem (s : ys <+ xs) (h) : ys.head h ∈ xs :=
|
||||
s.mem (List.head_mem h)
|
||||
|
||||
@[grind] theorem Sublist.getLast_mem (s : ys <+ xs) (h) : ys.getLast h ∈ xs :=
|
||||
theorem Sublist.getLast_mem (s : ys <+ xs) (h) : ys.getLast h ∈ xs :=
|
||||
s.mem (List.getLast_mem h)
|
||||
|
||||
instance : Trans (@Sublist α) Subset Subset :=
|
||||
@@ -218,7 +208,7 @@ instance : Trans (fun l₁ l₂ => Sublist l₂ l₁) (Membership.mem : List α
|
||||
theorem mem_of_cons_sublist {a : α} {l₁ l₂ : List α} (s : a :: l₁ <+ l₂) : a ∈ l₂ :=
|
||||
(cons_subset.1 s.subset).1
|
||||
|
||||
@[simp, grind =] theorem sublist_nil {l : List α} : l <+ [] ↔ l = [] :=
|
||||
@[simp] theorem sublist_nil {l : List α} : l <+ [] ↔ l = [] :=
|
||||
⟨fun s => subset_nil.1 s.subset, fun H => H ▸ Sublist.refl _⟩
|
||||
|
||||
theorem eq_nil_of_sublist_nil {l : List α} (s : l <+ []) : l = [] :=
|
||||
@@ -229,39 +219,29 @@ theorem Sublist.length_le : l₁ <+ l₂ → length l₁ ≤ length l₂
|
||||
| .cons _l s => le_succ_of_le (length_le s)
|
||||
| .cons₂ _ s => succ_le_succ (length_le s)
|
||||
|
||||
grind_pattern Sublist.length_le => l₁ <+ l₂, length l₁
|
||||
grind_pattern Sublist.length_le => l₁ <+ l₂, length l₂
|
||||
|
||||
theorem Sublist.eq_of_length : l₁ <+ l₂ → length l₁ = length l₂ → l₁ = l₂
|
||||
| .slnil, _ => rfl
|
||||
| .cons a s, h => nomatch Nat.not_lt.2 s.length_le (h ▸ lt_succ_self _)
|
||||
| .cons₂ a s, h => by rw [s.eq_of_length (succ.inj h)]
|
||||
|
||||
-- Only activative `eq_of_length` if we're already thinking about lengths.
|
||||
grind_pattern Sublist.eq_of_length => l₁ <+ l₂, length l₁, length l₂
|
||||
|
||||
theorem Sublist.eq_of_length_le (s : l₁ <+ l₂) (h : length l₂ ≤ length l₁) : l₁ = l₂ :=
|
||||
s.eq_of_length <| Nat.le_antisymm s.length_le h
|
||||
|
||||
theorem Sublist.length_eq (s : l₁ <+ l₂) : length l₁ = length l₂ ↔ l₁ = l₂ :=
|
||||
⟨s.eq_of_length, congrArg _⟩
|
||||
|
||||
@[grind]
|
||||
theorem tail_sublist : ∀ l : List α, tail l <+ l
|
||||
| [] => .slnil
|
||||
| a::l => sublist_cons_self a l
|
||||
|
||||
@[grind]
|
||||
protected theorem Sublist.tail : ∀ {l₁ l₂ : List α}, l₁ <+ l₂ → tail l₁ <+ tail l₂
|
||||
| _, _, slnil => .slnil
|
||||
| _, _, Sublist.cons _ h => (tail_sublist _).trans h
|
||||
| _, _, Sublist.cons₂ _ h => h
|
||||
|
||||
@[grind →]
|
||||
theorem Sublist.of_cons_cons {l₁ l₂ : List α} {a b : α} (h : a :: l₁ <+ b :: l₂) : l₁ <+ l₂ :=
|
||||
h.tail
|
||||
|
||||
@[grind]
|
||||
protected theorem Sublist.map (f : α → β) {l₁ l₂} (s : l₁ <+ l₂) : map f l₁ <+ map f l₂ := by
|
||||
induction s with
|
||||
| slnil => simp
|
||||
@@ -270,31 +250,19 @@ protected theorem Sublist.map (f : α → β) {l₁ l₂} (s : l₁ <+ l₂) : m
|
||||
| cons₂ a s ih =>
|
||||
simpa using cons₂ (f a) ih
|
||||
|
||||
grind_pattern Sublist.map => l₁ <+ l₂, map f l₁
|
||||
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₂]
|
||||
|
||||
grind_pattern Sublist.filterMap => l₁ <+ l₂, filterMap f l₁
|
||||
grind_pattern Sublist.filterMap => l₁ <+ l₂, filterMap f l₂
|
||||
|
||||
@[grind]
|
||||
protected theorem Sublist.filter (p : α → Bool) {l₁ l₂} (s : l₁ <+ l₂) : filter p l₁ <+ filter p l₂ := by
|
||||
rw [← filterMap_eq_filter]; apply s.filterMap
|
||||
|
||||
grind_pattern Sublist.filter => l₁ <+ l₂, l₁.filter p
|
||||
grind_pattern Sublist.filter => l₁ <+ l₂, l₂.filter p
|
||||
|
||||
theorem head_filter_mem (xs : List α) (p : α → Bool) (h) : (xs.filter p).head h ∈ xs :=
|
||||
filter_sublist.head_mem h
|
||||
|
||||
theorem getLast_filter_mem (xs : List α) (p : α → Bool) (h) : (xs.filter p).getLast h ∈ xs :=
|
||||
filter_sublist.getLast_mem h
|
||||
|
||||
@[grind =]
|
||||
theorem sublist_filterMap_iff {l₁ : List β} {f : α → Option β} :
|
||||
l₁ <+ l₂.filterMap f ↔ ∃ l', l' <+ l₂ ∧ l₁ = l'.filterMap f := by
|
||||
induction l₂ generalizing l₁ with
|
||||
@@ -329,12 +297,10 @@ theorem sublist_filterMap_iff {l₁ : List β} {f : α → Option β} :
|
||||
rwa [filterMap_cons_some] at h
|
||||
assumption
|
||||
|
||||
@[grind =]
|
||||
theorem sublist_map_iff {l₁ : List β} {f : α → β} :
|
||||
l₁ <+ l₂.map f ↔ ∃ l', l' <+ l₂ ∧ l₁ = l'.map f := by
|
||||
simp only [← filterMap_eq_map, sublist_filterMap_iff]
|
||||
|
||||
@[grind =]
|
||||
theorem sublist_filter_iff {l₁ : List α} {p : α → Bool} :
|
||||
l₁ <+ l₂.filter p ↔ ∃ l', l' <+ l₂ ∧ l₁ = l'.filter p := by
|
||||
simp only [← filterMap_eq_filter, sublist_filterMap_iff]
|
||||
@@ -343,15 +309,11 @@ theorem sublist_append_left : ∀ l₁ l₂ : List α, l₁ <+ l₁ ++ l₂
|
||||
| [], _ => nil_sublist _
|
||||
| _ :: l₁, l₂ => (sublist_append_left l₁ l₂).cons₂ _
|
||||
|
||||
grind_pattern sublist_append_left => Sublist, l₁ ++ l₂
|
||||
|
||||
theorem sublist_append_right : ∀ l₁ l₂ : List α, l₂ <+ l₁ ++ l₂
|
||||
| [], _ => Sublist.refl _
|
||||
| _ :: l₁, l₂ => (sublist_append_right l₁ l₂).cons _
|
||||
|
||||
grind_pattern sublist_append_right => Sublist, l₁ ++ l₂
|
||||
|
||||
@[simp, grind =] theorem singleton_sublist {a : α} {l} : [a] <+ l ↔ a ∈ l := by
|
||||
@[simp] theorem singleton_sublist {a : α} {l} : [a] <+ l ↔ a ∈ l := by
|
||||
refine ⟨fun h => h.subset (mem_singleton_self _), fun h => ?_⟩
|
||||
obtain ⟨_, _, rfl⟩ := append_of_mem h
|
||||
exact ((nil_sublist _).cons₂ _).trans (sublist_append_right ..)
|
||||
@@ -359,14 +321,10 @@ grind_pattern sublist_append_right => Sublist, l₁ ++ l₂
|
||||
@[simp] theorem sublist_append_of_sublist_left (s : l <+ l₁) : l <+ l₁ ++ l₂ :=
|
||||
s.trans <| sublist_append_left ..
|
||||
|
||||
grind_pattern sublist_append_of_sublist_left => l <+ l₁, l₁ ++ l₂
|
||||
|
||||
@[simp] theorem sublist_append_of_sublist_right (s : l <+ l₂) : l <+ l₁ ++ l₂ :=
|
||||
s.trans <| sublist_append_right ..
|
||||
|
||||
grind_pattern sublist_append_of_sublist_right => l <+ l₂, l₁ ++ l₂
|
||||
|
||||
@[simp, grind =] theorem append_sublist_append_left : ∀ l, l ++ l₁ <+ l ++ l₂ ↔ l₁ <+ l₂
|
||||
@[simp] theorem append_sublist_append_left : ∀ l, l ++ l₁ <+ l ++ l₂ ↔ l₁ <+ l₂
|
||||
| [] => Iff.rfl
|
||||
| _ :: l => cons_sublist_cons.trans (append_sublist_append_left l)
|
||||
|
||||
@@ -381,9 +339,6 @@ theorem Sublist.append_right : l₁ <+ l₂ → ∀ l, l₁ ++ l <+ l₂ ++ l
|
||||
theorem Sublist.append (hl : l₁ <+ l₂) (hr : r₁ <+ r₂) : l₁ ++ r₁ <+ l₂ ++ r₂ :=
|
||||
(hl.append_right _).trans ((append_sublist_append_left _).2 hr)
|
||||
|
||||
grind_pattern Sublist.append => l₁ <+ l₂, r₁ <+ r₂, l₁ ++ r₁, l₂ ++ r₂
|
||||
|
||||
@[grind =]
|
||||
theorem sublist_cons_iff {a : α} {l l'} :
|
||||
l <+ a :: l' ↔ l <+ l' ∨ ∃ r, l = a :: r ∧ r <+ l' := by
|
||||
constructor
|
||||
@@ -395,7 +350,6 @@ theorem sublist_cons_iff {a : α} {l l'} :
|
||||
· exact h.cons _
|
||||
· exact h.cons₂ _
|
||||
|
||||
@[grind =]
|
||||
theorem cons_sublist_iff {a : α} {l l'} :
|
||||
a :: l <+ l' ↔ ∃ r₁ r₂, l' = r₁ ++ r₂ ∧ a ∈ r₁ ∧ l <+ r₂ := by
|
||||
induction l' with
|
||||
@@ -479,7 +433,6 @@ theorem Sublist.of_sublist_append_right (w : ∀ a, a ∈ l → a ∉ l₁) (h :
|
||||
exact fun x m => w x (mem_append_left l₂' m) (h₁.mem m)
|
||||
simp_all
|
||||
|
||||
@[grind]
|
||||
theorem Sublist.middle {l : List α} (h : l <+ l₁ ++ l₂) (a : α) : l <+ l₁ ++ a :: l₂ := by
|
||||
rw [sublist_append_iff] at h
|
||||
obtain ⟨l₁', l₂', rfl, h₁, h₂⟩ := h
|
||||
@@ -490,14 +443,13 @@ theorem Sublist.reverse : l₁ <+ l₂ → l₁.reverse <+ l₂.reverse
|
||||
| .cons _ h => by rw [reverse_cons]; exact sublist_append_of_sublist_left h.reverse
|
||||
| .cons₂ _ h => by rw [reverse_cons, reverse_cons]; exact h.reverse.append_right _
|
||||
|
||||
@[simp, grind =] theorem reverse_sublist : l₁.reverse <+ l₂.reverse ↔ l₁ <+ l₂ :=
|
||||
@[simp] theorem reverse_sublist : l₁.reverse <+ l₂.reverse ↔ l₁ <+ l₂ :=
|
||||
⟨fun h => l₁.reverse_reverse ▸ l₂.reverse_reverse ▸ h.reverse, Sublist.reverse⟩
|
||||
|
||||
@[grind _=_]
|
||||
theorem sublist_reverse_iff : l₁ <+ l₂.reverse ↔ l₁.reverse <+ l₂ :=
|
||||
by rw [← reverse_sublist, reverse_reverse]
|
||||
|
||||
@[simp, grind =] theorem append_sublist_append_right (l) : l₁ ++ l <+ l₂ ++ l ↔ l₁ <+ l₂ :=
|
||||
@[simp] theorem append_sublist_append_right (l) : l₁ ++ l <+ l₂ ++ l ↔ l₁ <+ l₂ :=
|
||||
⟨fun h => by
|
||||
have := h.reverse
|
||||
simp only [reverse_append, append_sublist_append_left, reverse_sublist] at this
|
||||
@@ -512,7 +464,6 @@ theorem sublist_reverse_iff : l₁ <+ l₂.reverse ↔ l₁.reverse <+ l₂ :=
|
||||
| refl => apply Sublist.refl
|
||||
| step => simp [*, replicate, Sublist.cons]
|
||||
|
||||
@[grind =]
|
||||
theorem sublist_replicate_iff : l <+ replicate m a ↔ ∃ n, n ≤ m ∧ l = replicate n a := by
|
||||
induction l generalizing m with
|
||||
| nil =>
|
||||
@@ -600,7 +551,7 @@ theorem flatten_sublist_iff {L : List (List α)} {l} :
|
||||
exact ⟨l₁, L'.flatten, by simp, by simpa using h 0 (by simp), L', rfl,
|
||||
fun i lt => by simpa using h (i+1) (Nat.add_lt_add_right lt 1)⟩
|
||||
|
||||
@[simp, grind =] theorem isSublist_iff_sublist [BEq α] [LawfulBEq α] {l₁ l₂ : List α} :
|
||||
@[simp] theorem isSublist_iff_sublist [BEq α] [LawfulBEq α] {l₁ l₂ : List α} :
|
||||
l₁.isSublist l₂ ↔ l₁ <+ l₂ := by
|
||||
cases l₁ <;> cases l₂ <;> simp [isSublist]
|
||||
case cons.cons hd₁ tl₁ hd₂ tl₂ =>
|
||||
@@ -622,49 +573,41 @@ theorem flatten_sublist_iff {L : List (List α)} {l} :
|
||||
instance [DecidableEq α] (l₁ l₂ : List α) : Decidable (l₁ <+ l₂) :=
|
||||
decidable_of_iff (l₁.isSublist l₂) isSublist_iff_sublist
|
||||
|
||||
@[grind]
|
||||
protected theorem Sublist.drop : ∀ {l₁ l₂ : List α}, l₁ <+ l₂ → ∀ i, l₁.drop i <+ l₂.drop i
|
||||
| _, _, h, 0 => h
|
||||
| _, _, h, i + 1 => by rw [← drop_tail, ← drop_tail]; exact h.tail.drop i
|
||||
|
||||
/-! ### IsPrefix / IsSuffix / IsInfix -/
|
||||
|
||||
@[simp, grind] theorem prefix_append (l₁ l₂ : List α) : l₁ <+: l₁ ++ l₂ := ⟨l₂, rfl⟩
|
||||
@[simp] theorem prefix_append (l₁ l₂ : List α) : l₁ <+: l₁ ++ l₂ := ⟨l₂, rfl⟩
|
||||
|
||||
@[simp, grind] theorem suffix_append (l₁ l₂ : List α) : l₂ <:+ l₁ ++ l₂ := ⟨l₁, rfl⟩
|
||||
@[simp] theorem suffix_append (l₁ l₂ : List α) : l₂ <:+ l₁ ++ l₂ := ⟨l₁, rfl⟩
|
||||
|
||||
theorem infix_append (l₁ l₂ l₃ : List α) : l₂ <:+: l₁ ++ l₂ ++ l₃ := ⟨l₁, l₃, rfl⟩
|
||||
|
||||
@[simp, grind] theorem infix_append' (l₁ l₂ l₃ : List α) : l₂ <:+: l₁ ++ (l₂ ++ l₃) := by
|
||||
@[simp] theorem infix_append' (l₁ l₂ l₃ : List α) : l₂ <:+: l₁ ++ (l₂ ++ l₃) := by
|
||||
rw [← List.append_assoc]; apply infix_append
|
||||
|
||||
theorem infix_append_left : l₁ <:+: l₁ ++ l₂ := ⟨[], l₂, rfl⟩
|
||||
theorem infix_append_right : l₂ <:+: l₁ ++ l₂ := ⟨l₁, [], by simp⟩
|
||||
|
||||
theorem IsPrefix.isInfix : l₁ <+: l₂ → l₁ <:+: l₂ := fun ⟨t, h⟩ => ⟨[], t, h⟩
|
||||
|
||||
grind_pattern IsPrefix.isInfix => l₁ <+: l₂, IsInfix
|
||||
|
||||
theorem IsSuffix.isInfix : l₁ <:+ l₂ → l₁ <:+: l₂ := fun ⟨t, h⟩ => ⟨t, [], by rw [h, append_nil]⟩
|
||||
|
||||
grind_pattern IsSuffix.isInfix => l₁ <:+ l₂, IsInfix
|
||||
@[simp] theorem nil_prefix {l : List α} : [] <+: l := ⟨l, rfl⟩
|
||||
|
||||
@[simp, grind] theorem nil_prefix {l : List α} : [] <+: l := ⟨l, rfl⟩
|
||||
@[simp] theorem nil_suffix {l : List α} : [] <:+ l := ⟨l, append_nil _⟩
|
||||
|
||||
@[simp, grind] theorem nil_suffix {l : List α} : [] <:+ l := ⟨l, append_nil _⟩
|
||||
|
||||
@[simp, grind] theorem nil_infix {l : List α} : [] <:+: l := nil_prefix.isInfix
|
||||
@[simp] theorem nil_infix {l : List α} : [] <:+: l := nil_prefix.isInfix
|
||||
|
||||
theorem prefix_refl (l : List α) : l <+: l := ⟨[], append_nil _⟩
|
||||
@[simp, grind] theorem prefix_rfl {l : List α} : l <+: l := prefix_refl l
|
||||
@[simp] theorem prefix_rfl {l : List α} : l <+: l := prefix_refl l
|
||||
|
||||
theorem suffix_refl (l : List α) : l <:+ l := ⟨[], rfl⟩
|
||||
@[simp, grind] theorem suffix_rfl {l : List α} : l <:+ l := suffix_refl l
|
||||
@[simp] theorem suffix_rfl {l : List α} : l <:+ l := suffix_refl l
|
||||
|
||||
theorem infix_refl (l : List α) : l <:+: l := prefix_rfl.isInfix
|
||||
@[simp, grind] theorem infix_rfl {l : List α} : l <:+: l := infix_refl l
|
||||
@[simp] theorem infix_rfl {l : List α} : l <:+: l := infix_refl l
|
||||
|
||||
@[simp, grind] theorem suffix_cons (a : α) : ∀ l, l <:+ a :: l := suffix_append [a]
|
||||
@[simp] theorem suffix_cons (a : α) : ∀ l, l <:+ a :: l := suffix_append [a]
|
||||
|
||||
theorem infix_cons : l₁ <:+: l₂ → l₁ <:+: a :: l₂ := fun ⟨l₁', l₂', h⟩ => ⟨a :: l₁', l₂', h ▸ rfl⟩
|
||||
|
||||
@@ -674,38 +617,12 @@ theorem infix_concat : l₁ <:+: l₂ → l₁ <:+: concat l₂ a := fun ⟨l₁
|
||||
theorem IsPrefix.trans : ∀ {l₁ l₂ l₃ : List α}, l₁ <+: l₂ → l₂ <+: l₃ → l₁ <+: l₃
|
||||
| _, _, _, ⟨r₁, rfl⟩, ⟨r₂, rfl⟩ => ⟨r₁ ++ r₂, (append_assoc _ _ _).symm⟩
|
||||
|
||||
grind_pattern IsPrefix.trans => l₁ <+: l₂, l₂ <+: l₃
|
||||
|
||||
theorem IsSuffix.trans : ∀ {l₁ l₂ l₃ : List α}, l₁ <:+ l₂ → l₂ <:+ l₃ → l₁ <:+ l₃
|
||||
| _, _, _, ⟨l₁, rfl⟩, ⟨l₂, rfl⟩ => ⟨l₂ ++ l₁, append_assoc _ _ _⟩
|
||||
|
||||
grind_pattern IsSuffix.trans => l₁ <:+ l₂, l₂ <:+ l₃
|
||||
|
||||
theorem IsInfix.trans : ∀ {l₁ l₂ l₃ : List α}, l₁ <:+: l₂ → l₂ <:+: l₃ → l₁ <:+: l₃
|
||||
| l, _, _, ⟨l₁, r₁, rfl⟩, ⟨l₂, r₂, rfl⟩ => ⟨l₂ ++ l₁, r₁ ++ r₂, by simp only [append_assoc]⟩
|
||||
|
||||
grind_pattern IsInfix.trans => l₁ <:+: l₂, l₂ <:+: l₃
|
||||
|
||||
theorem prefix_append_of_prefix (h : l₁ <+: l₂) : l₁ <+: l₂ ++ l₃ :=
|
||||
h.trans (prefix_append l₂ l₃)
|
||||
|
||||
grind_pattern prefix_append_of_prefix => l₁ <+: l₂, l₂ ++ l₃
|
||||
|
||||
theorem suffix_append_of_suffix (h : l₁ <:+ l₃) : l₁ <:+ l₂ ++ l₃ :=
|
||||
h.trans (suffix_append l₂ l₃)
|
||||
|
||||
grind_pattern suffix_append_of_suffix => l₁ <:+ l₃, l₂ ++ l₃
|
||||
|
||||
theorem infix_append_of_infix_left (h : l₁ <:+: l₂) : l₁ <:+: l₂ ++ l₃ :=
|
||||
h.trans infix_append_left
|
||||
|
||||
grind_pattern infix_append_of_infix_left => l₁ <:+: l₂, l₂ ++ l₃
|
||||
|
||||
theorem infix_append_of_infix_right (h : l₁ <:+: l₃) : l₁ <:+: l₂ ++ l₃ :=
|
||||
h.trans infix_append_right
|
||||
|
||||
grind_pattern infix_append_of_infix_right => l₁ <:+: l₃, l₂ ++ l₃
|
||||
|
||||
protected theorem IsInfix.sublist : l₁ <:+: l₂ → l₁ <+ l₂
|
||||
| ⟨_, _, h⟩ => h ▸ (sublist_append_right ..).trans (sublist_append_left ..)
|
||||
|
||||
@@ -724,11 +641,11 @@ protected theorem IsSuffix.sublist (h : l₁ <:+ l₂) : l₁ <+ l₂ :=
|
||||
protected theorem IsSuffix.subset (hl : l₁ <:+ l₂) : l₁ ⊆ l₂ :=
|
||||
hl.sublist.subset
|
||||
|
||||
@[simp, grind =] theorem infix_nil : l <:+: [] ↔ l = [] := ⟨(sublist_nil.1 ·.sublist), (· ▸ infix_rfl)⟩
|
||||
@[simp] theorem infix_nil : l <:+: [] ↔ l = [] := ⟨(sublist_nil.1 ·.sublist), (· ▸ infix_rfl)⟩
|
||||
|
||||
@[simp, grind =] theorem prefix_nil : l <+: [] ↔ l = [] := ⟨(sublist_nil.1 ·.sublist), (· ▸ prefix_rfl)⟩
|
||||
@[simp] theorem prefix_nil : l <+: [] ↔ l = [] := ⟨(sublist_nil.1 ·.sublist), (· ▸ prefix_rfl)⟩
|
||||
|
||||
@[simp, grind =] theorem suffix_nil : l <:+ [] ↔ l = [] := ⟨(sublist_nil.1 ·.sublist), (· ▸ suffix_rfl)⟩
|
||||
@[simp] theorem suffix_nil : l <:+ [] ↔ l = [] := ⟨(sublist_nil.1 ·.sublist), (· ▸ suffix_rfl)⟩
|
||||
|
||||
theorem eq_nil_of_infix_nil (h : l <:+: []) : l = [] := infix_nil.mp h
|
||||
theorem eq_nil_of_prefix_nil (h : l <+: []) : l = [] := prefix_nil.mp h
|
||||
@@ -746,21 +663,12 @@ theorem IsInfix.ne_nil {xs ys : List α} (h : xs <:+: ys) (hx : xs ≠ []) : ys
|
||||
theorem IsInfix.length_le (h : l₁ <:+: l₂) : l₁.length ≤ l₂.length :=
|
||||
h.sublist.length_le
|
||||
|
||||
grind_pattern IsInfix.length_le => l₁ <:+: l₂, l₁.length
|
||||
grind_pattern IsInfix.length_le => l₁ <:+: l₂, l₂.length
|
||||
|
||||
theorem IsPrefix.length_le (h : l₁ <+: l₂) : l₁.length ≤ l₂.length :=
|
||||
h.sublist.length_le
|
||||
|
||||
grind_pattern IsPrefix.length_le => l₁ <+: l₂, l₁.length
|
||||
grind_pattern IsPrefix.length_le => l₁ <+: l₂, l₂.length
|
||||
|
||||
theorem IsSuffix.length_le (h : l₁ <:+ l₂) : l₁.length ≤ l₂.length :=
|
||||
h.sublist.length_le
|
||||
|
||||
grind_pattern IsSuffix.length_le => l₁ <:+ l₂, l₁.length
|
||||
grind_pattern IsSuffix.length_le => l₁ <:+ l₂, l₂.length
|
||||
|
||||
theorem IsPrefix.getElem {xs ys : List α} (h : xs <+: ys) {i} (hi : i < xs.length) :
|
||||
xs[i] = ys[i]'(Nat.le_trans hi h.length_le) := by
|
||||
obtain ⟨_, rfl⟩ := h
|
||||
@@ -768,23 +676,23 @@ theorem IsPrefix.getElem {xs ys : List α} (h : xs <+: ys) {i} (hi : i < xs.leng
|
||||
|
||||
-- See `Init.Data.List.Nat.Sublist` for `IsSuffix.getElem`.
|
||||
|
||||
@[grind →] theorem IsPrefix.mem (hx : a ∈ l₁) (hl : l₁ <+: l₂) : a ∈ l₂ :=
|
||||
theorem IsPrefix.mem (hx : a ∈ l₁) (hl : l₁ <+: l₂) : a ∈ l₂ :=
|
||||
hl.subset hx
|
||||
|
||||
@[grind →] theorem IsSuffix.mem (hx : a ∈ l₁) (hl : l₁ <:+ l₂) : a ∈ l₂ :=
|
||||
theorem IsSuffix.mem (hx : a ∈ l₁) (hl : l₁ <:+ l₂) : a ∈ l₂ :=
|
||||
hl.subset hx
|
||||
|
||||
@[grind →] theorem IsInfix.mem (hx : a ∈ l₁) (hl : l₁ <:+: l₂) : a ∈ l₂ :=
|
||||
theorem IsInfix.mem (hx : a ∈ l₁) (hl : l₁ <:+: l₂) : a ∈ l₂ :=
|
||||
hl.subset hx
|
||||
|
||||
@[simp, grind =] theorem reverse_suffix : reverse l₁ <:+ reverse l₂ ↔ l₁ <+: l₂ :=
|
||||
@[simp] theorem reverse_suffix : reverse l₁ <:+ reverse l₂ ↔ l₁ <+: l₂ :=
|
||||
⟨fun ⟨r, e⟩ => ⟨reverse r, by rw [← reverse_reverse l₁, ← reverse_append, e, reverse_reverse]⟩,
|
||||
fun ⟨r, e⟩ => ⟨reverse r, by rw [← reverse_append, e]⟩⟩
|
||||
|
||||
@[simp, grind =] theorem reverse_prefix : reverse l₁ <+: reverse l₂ ↔ l₁ <:+ l₂ := by
|
||||
@[simp] theorem reverse_prefix : reverse l₁ <+: reverse l₂ ↔ l₁ <:+ l₂ := by
|
||||
rw [← reverse_suffix]; simp only [reverse_reverse]
|
||||
|
||||
@[simp, grind =] theorem reverse_infix : reverse l₁ <:+: reverse l₂ ↔ l₁ <:+: l₂ := by
|
||||
@[simp] theorem reverse_infix : reverse l₁ <:+: reverse l₂ ↔ l₁ <:+: l₂ := by
|
||||
refine ⟨fun ⟨s, t, e⟩ => ⟨reverse t, reverse s, ?_⟩, fun ⟨s, t, e⟩ => ⟨reverse t, reverse s, ?_⟩⟩
|
||||
· rw [← reverse_reverse l₁, append_assoc, ← reverse_append, ← reverse_append, e,
|
||||
reverse_reverse]
|
||||
@@ -793,21 +701,12 @@ theorem IsPrefix.getElem {xs ys : List α} (h : xs <+: ys) {i} (hi : i < xs.leng
|
||||
theorem IsInfix.reverse : l₁ <:+: l₂ → reverse l₁ <:+: reverse l₂ :=
|
||||
reverse_infix.2
|
||||
|
||||
grind_pattern IsInfix.reverse => l₁ <:+: l₂, l₁.reverse
|
||||
grind_pattern IsInfix.reverse => l₁ <:+: l₂, l₂.reverse
|
||||
|
||||
theorem IsSuffix.reverse : l₁ <:+ l₂ → reverse l₁ <+: reverse l₂ :=
|
||||
reverse_prefix.2
|
||||
|
||||
grind_pattern IsSuffix.reverse => l₁ <:+ l₂, l₁.reverse
|
||||
grind_pattern IsSuffix.reverse => l₁ <:+ l₂, l₂.reverse
|
||||
|
||||
theorem IsPrefix.reverse : l₁ <+: l₂ → reverse l₁ <:+ reverse l₂ :=
|
||||
reverse_suffix.2
|
||||
|
||||
grind_pattern IsPrefix.reverse => l₁ <+: l₂, l₁.reverse
|
||||
grind_pattern IsPrefix.reverse => l₁ <+: l₂, l₂.reverse
|
||||
|
||||
theorem IsPrefix.head {l₁ l₂ : List α} (h : l₁ <+: l₂) (hx : l₁ ≠ []) :
|
||||
l₁.head hx = l₂.head (h.ne_nil hx) := by
|
||||
cases l₁ <;> cases l₂ <;> simp only [head_cons, ne_eq, not_true_eq_false] at hx ⊢
|
||||
@@ -881,7 +780,7 @@ theorem prefix_cons_iff : l₁ <+: a :: l₂ ↔ l₁ = [] ∨ ∃ t, l₁ = a :
|
||||
· simp only [w]
|
||||
refine ⟨s, by simp [h']⟩
|
||||
|
||||
@[simp, grind =] theorem cons_prefix_cons : a :: l₁ <+: b :: l₂ ↔ a = b ∧ l₁ <+: l₂ := by
|
||||
@[simp] theorem cons_prefix_cons : a :: l₁ <+: b :: l₂ ↔ a = b ∧ l₁ <+: l₂ := by
|
||||
simp only [prefix_cons_iff, cons.injEq, false_or, List.cons_ne_nil]
|
||||
constructor
|
||||
· rintro ⟨t, ⟨rfl, rfl⟩, h⟩
|
||||
@@ -932,7 +831,7 @@ theorem infix_concat_iff {l₁ l₂ : List α} {a : α} :
|
||||
rw [← reverse_infix, reverse_concat, infix_cons_iff, reverse_infix,
|
||||
← reverse_prefix, reverse_concat]
|
||||
|
||||
theorem prefix_iff_getElem? : l₁ <+: l₂ ↔ ∀ i (h : i < l₁.length), l₂[i]? = some l₁[i] := by
|
||||
theorem isPrefix_iff : l₁ <+: l₂ ↔ ∀ i (h : i < l₁.length), l₂[i]? = some l₁[i] := by
|
||||
induction l₁ generalizing l₂ with
|
||||
| nil => simp
|
||||
| cons a l₁ ih =>
|
||||
@@ -944,12 +843,7 @@ theorem prefix_iff_getElem? : l₁ <+: l₂ ↔ ∀ i (h : i < l₁.length), l
|
||||
rw (occs := [2]) [← Nat.and_forall_add_one]
|
||||
simp [Nat.succ_lt_succ_iff, eq_comm]
|
||||
|
||||
-- See `Init.Data.List.Nat.Sublist` for `isSuffix_iff` and `ifInfix_iff`.
|
||||
|
||||
@[deprecated prefix_iff_getElem? (since := "2025-05-27")]
|
||||
abbrev isPrefix_iff := @prefix_iff_getElem?
|
||||
|
||||
theorem prefix_iff_getElem {l₁ l₂ : List α} :
|
||||
theorem isPrefix_iff_getElem {l₁ l₂ : List α} :
|
||||
l₁ <+: l₂ ↔ ∃ (h : l₁.length ≤ l₂.length), ∀ i (hx : i < l₁.length),
|
||||
l₁[i] = l₂[i]'(Nat.lt_of_lt_of_le hx h) where
|
||||
mp h := ⟨h.length_le, fun _ h' ↦ h.getElem h'⟩
|
||||
@@ -967,16 +861,9 @@ theorem prefix_iff_getElem {l₁ l₂ : List α} :
|
||||
simp only [cons_prefix_cons]
|
||||
exact ⟨h 0 (zero_lt_succ _), tail_ih hl fun a ha ↦ h a.succ (succ_lt_succ ha)⟩
|
||||
|
||||
@[deprecated prefix_iff_getElem (since := "2025-05-27")]
|
||||
abbrev isPrefix_iff_getElem := @prefix_iff_getElem
|
||||
-- See `Init.Data.List.Nat.Sublist` for `isSuffix_iff` and `ifInfix_iff`.
|
||||
|
||||
theorem cons_prefix_iff {a : α} {l₁ l₂ : List α} :
|
||||
a :: l₁ <+: l₂ ↔ ∃ l', l₂ = a :: l' ∧ l₁ <+: l' := by
|
||||
match l₂ with
|
||||
| nil => simp
|
||||
| cons b l₂ => simp [and_assoc, eq_comm]
|
||||
|
||||
theorem prefix_filterMap_iff {β} {f : α → Option β} {l₁ : List α} {l₂ : List β} :
|
||||
theorem isPrefix_filterMap_iff {β} {f : α → Option β} {l₁ : List α} {l₂ : List β} :
|
||||
l₂ <+: filterMap f l₁ ↔ ∃ l, l <+: l₁ ∧ l₂ = filterMap f l := by
|
||||
simp only [IsPrefix, append_eq_filterMap_iff]
|
||||
constructor
|
||||
@@ -985,10 +872,7 @@ theorem prefix_filterMap_iff {β} {f : α → Option β} {l₁ : List α} {l₂
|
||||
· rintro ⟨l₁, ⟨l₂, rfl⟩, rfl⟩
|
||||
exact ⟨_, l₁, l₂, rfl, rfl, rfl⟩
|
||||
|
||||
@[deprecated prefix_filterMap_iff (since := "2025-05-27")]
|
||||
abbrev isPrefix_filterMap_iff := @prefix_filterMap_iff
|
||||
|
||||
theorem suffix_filterMap_iff {β} {f : α → Option β} {l₁ : List α} {l₂ : List β} :
|
||||
theorem isSuffix_filterMap_iff {β} {f : α → Option β} {l₁ : List α} {l₂ : List β} :
|
||||
l₂ <:+ filterMap f l₁ ↔ ∃ l, l <:+ l₁ ∧ l₂ = filterMap f l := by
|
||||
simp only [IsSuffix, append_eq_filterMap_iff]
|
||||
constructor
|
||||
@@ -997,10 +881,7 @@ theorem suffix_filterMap_iff {β} {f : α → Option β} {l₁ : List α} {l₂
|
||||
· rintro ⟨l₁, ⟨l₂, rfl⟩, rfl⟩
|
||||
exact ⟨_, l₂, l₁, rfl, rfl, rfl⟩
|
||||
|
||||
@[deprecated suffix_filterMap_iff (since := "2025-05-27")]
|
||||
abbrev isSuffix_filterMap_iff := @suffix_filterMap_iff
|
||||
|
||||
theorem infix_filterMap_iff {β} {f : α → Option β} {l₁ : List α} {l₂ : List β} :
|
||||
theorem isInfix_filterMap_iff {β} {f : α → Option β} {l₁ : List α} {l₂ : List β} :
|
||||
l₂ <:+: filterMap f l₁ ↔ ∃ l, l <:+: l₁ ∧ l₂ = filterMap f l := by
|
||||
simp only [IsInfix, append_eq_filterMap_iff, filterMap_eq_append_iff]
|
||||
constructor
|
||||
@@ -1009,52 +890,31 @@ theorem infix_filterMap_iff {β} {f : α → Option β} {l₁ : List α} {l₂ :
|
||||
· rintro ⟨l₃, ⟨l₂, l₁, rfl⟩, rfl⟩
|
||||
exact ⟨_, _, _, l₁, rfl, ⟨⟨l₂, l₃, rfl, rfl, rfl⟩, rfl⟩⟩
|
||||
|
||||
@[deprecated infix_filterMap_iff (since := "2025-05-27")]
|
||||
abbrev isInfix_filterMap_iff := @infix_filterMap_iff
|
||||
|
||||
theorem prefix_filter_iff {p : α → Bool} {l₁ l₂ : List α} :
|
||||
theorem isPrefix_filter_iff {p : α → Bool} {l₁ l₂ : List α} :
|
||||
l₂ <+: l₁.filter p ↔ ∃ l, l <+: l₁ ∧ l₂ = l.filter p := by
|
||||
rw [← filterMap_eq_filter, prefix_filterMap_iff]
|
||||
rw [← filterMap_eq_filter, isPrefix_filterMap_iff]
|
||||
|
||||
@[deprecated prefix_filter_iff (since := "2025-05-27")]
|
||||
abbrev isPrefix_filter_iff := @prefix_filter_iff
|
||||
|
||||
theorem suffix_filter_iff {p : α → Bool} {l₁ l₂ : List α} :
|
||||
theorem isSuffix_filter_iff {p : α → Bool} {l₁ l₂ : List α} :
|
||||
l₂ <:+ l₁.filter p ↔ ∃ l, l <:+ l₁ ∧ l₂ = l.filter p := by
|
||||
rw [← filterMap_eq_filter, suffix_filterMap_iff]
|
||||
rw [← filterMap_eq_filter, isSuffix_filterMap_iff]
|
||||
|
||||
@[deprecated suffix_filter_iff (since := "2025-05-27")]
|
||||
abbrev isSuffix_filter_iff := @suffix_filter_iff
|
||||
|
||||
theorem infix_filter_iff {p : α → Bool} {l₁ l₂ : List α} :
|
||||
theorem isInfix_filter_iff {p : α → Bool} {l₁ l₂ : List α} :
|
||||
l₂ <:+: l₁.filter p ↔ ∃ l, l <:+: l₁ ∧ l₂ = l.filter p := by
|
||||
rw [← filterMap_eq_filter, infix_filterMap_iff]
|
||||
rw [← filterMap_eq_filter, isInfix_filterMap_iff]
|
||||
|
||||
@[deprecated infix_filter_iff (since := "2025-05-27")]
|
||||
abbrev isInfix_filter_iff := @infix_filter_iff
|
||||
|
||||
theorem prefix_map_iff {β} {f : α → β} {l₁ : List α} {l₂ : List β} :
|
||||
theorem isPrefix_map_iff {β} {f : α → β} {l₁ : List α} {l₂ : List β} :
|
||||
l₂ <+: l₁.map f ↔ ∃ l, l <+: l₁ ∧ l₂ = l.map f := by
|
||||
rw [← filterMap_eq_map, prefix_filterMap_iff]
|
||||
rw [← filterMap_eq_map, isPrefix_filterMap_iff]
|
||||
|
||||
@[deprecated prefix_map_iff (since := "2025-05-27")]
|
||||
abbrev isPrefix_map_iff := @prefix_map_iff
|
||||
|
||||
theorem suffix_map_iff {β} {f : α → β} {l₁ : List α} {l₂ : List β} :
|
||||
theorem isSuffix_map_iff {β} {f : α → β} {l₁ : List α} {l₂ : List β} :
|
||||
l₂ <:+ l₁.map f ↔ ∃ l, l <:+ l₁ ∧ l₂ = l.map f := by
|
||||
rw [← filterMap_eq_map, suffix_filterMap_iff]
|
||||
rw [← filterMap_eq_map, isSuffix_filterMap_iff]
|
||||
|
||||
@[deprecated suffix_map_iff (since := "2025-05-27")]
|
||||
abbrev isSuffix_map_iff := @suffix_map_iff
|
||||
|
||||
theorem infix_map_iff {β} {f : α → β} {l₁ : List α} {l₂ : List β} :
|
||||
theorem isInfix_map_iff {β} {f : α → β} {l₁ : List α} {l₂ : List β} :
|
||||
l₂ <:+: l₁.map f ↔ ∃ l, l <:+: l₁ ∧ l₂ = l.map f := by
|
||||
rw [← filterMap_eq_map, infix_filterMap_iff]
|
||||
rw [← filterMap_eq_map, isInfix_filterMap_iff]
|
||||
|
||||
@[deprecated infix_map_iff (since := "2025-05-27")]
|
||||
abbrev isInfix_map_iff := @infix_map_iff
|
||||
|
||||
@[grind =] theorem prefix_replicate_iff {n} {a : α} {l : List α} :
|
||||
theorem isPrefix_replicate_iff {n} {a : α} {l : List α} :
|
||||
l <+: List.replicate n a ↔ l.length ≤ n ∧ l = List.replicate l.length a := by
|
||||
rw [IsPrefix]
|
||||
simp only [append_eq_replicate_iff]
|
||||
@@ -1066,18 +926,12 @@ abbrev isInfix_map_iff := @infix_map_iff
|
||||
· simpa using add_sub_of_le h
|
||||
· simpa using w
|
||||
|
||||
@[deprecated prefix_replicate_iff (since := "2025-05-27")]
|
||||
abbrev isPrefix_replicate_iff := @prefix_replicate_iff
|
||||
|
||||
@[grind =] theorem suffix_replicate_iff {n} {a : α} {l : List α} :
|
||||
theorem isSuffix_replicate_iff {n} {a : α} {l : List α} :
|
||||
l <:+ List.replicate n a ↔ l.length ≤ n ∧ l = List.replicate l.length a := by
|
||||
rw [← reverse_prefix, reverse_replicate, prefix_replicate_iff]
|
||||
rw [← reverse_prefix, reverse_replicate, isPrefix_replicate_iff]
|
||||
simp [reverse_eq_iff]
|
||||
|
||||
@[deprecated suffix_replicate_iff (since := "2025-05-27")]
|
||||
abbrev isSuffix_replicate_iff := @suffix_replicate_iff
|
||||
|
||||
@[grind =] theorem infix_replicate_iff {n} {a : α} {l : List α} :
|
||||
theorem isInfix_replicate_iff {n} {a : α} {l : List α} :
|
||||
l <:+: List.replicate n a ↔ l.length ≤ n ∧ l = List.replicate l.length a := by
|
||||
rw [IsInfix]
|
||||
simp only [append_eq_replicate_iff, length_append]
|
||||
@@ -1089,9 +943,6 @@ abbrev isSuffix_replicate_iff := @suffix_replicate_iff
|
||||
· simpa using Nat.sub_add_cancel h
|
||||
· simpa using w
|
||||
|
||||
@[deprecated infix_replicate_iff (since := "2025-05-27")]
|
||||
abbrev isInfix_replicate_iff := @infix_replicate_iff
|
||||
|
||||
theorem infix_of_mem_flatten : ∀ {L : List (List α)}, l ∈ L → l <:+: flatten L
|
||||
| l' :: _, h =>
|
||||
match h with
|
||||
@@ -1105,16 +956,16 @@ theorem infix_of_mem_flatten : ∀ {L : List (List α)}, l ∈ L → l <:+: flat
|
||||
theorem prefix_cons_inj (a) : a :: l₁ <+: a :: l₂ ↔ l₁ <+: l₂ :=
|
||||
prefix_append_right_inj [a]
|
||||
|
||||
@[grind] theorem take_prefix (i) (l : List α) : take i l <+: l :=
|
||||
theorem take_prefix (i) (l : List α) : take i l <+: l :=
|
||||
⟨_, take_append_drop _ _⟩
|
||||
|
||||
@[grind] theorem drop_suffix (i) (l : List α) : drop i l <:+ l :=
|
||||
theorem drop_suffix (i) (l : List α) : drop i l <:+ l :=
|
||||
⟨_, take_append_drop _ _⟩
|
||||
|
||||
@[grind] theorem take_sublist (i) (l : List α) : take i l <+ l :=
|
||||
theorem take_sublist (i) (l : List α) : take i l <+ l :=
|
||||
(take_prefix i l).sublist
|
||||
|
||||
@[grind] theorem drop_sublist (i) (l : List α) : drop i l <+ l :=
|
||||
theorem drop_sublist (i) (l : List α) : drop i l <+ l :=
|
||||
(drop_suffix i l).sublist
|
||||
|
||||
theorem take_subset (i) (l : List α) : take i l ⊆ l :=
|
||||
@@ -1135,22 +986,22 @@ theorem drop_suffix_drop_left (l : List α) {i j : Nat} (h : i ≤ j) : drop j l
|
||||
|
||||
-- See `Init.Data.List.Nat.TakeDrop` for `take_prefix_take_left`.
|
||||
|
||||
@[grind] theorem drop_sublist_drop_left (l : List α) {i j : Nat} (h : i ≤ j) : drop j l <+ drop i l :=
|
||||
theorem drop_sublist_drop_left (l : List α) {i j : Nat} (h : i ≤ j) : drop j l <+ drop i l :=
|
||||
(drop_suffix_drop_left l h).sublist
|
||||
|
||||
@[grind] theorem drop_subset_drop_left (l : List α) {i j : Nat} (h : i ≤ j) : drop j l ⊆ drop i l :=
|
||||
theorem drop_subset_drop_left (l : List α) {i j : Nat} (h : i ≤ j) : drop j l ⊆ drop i l :=
|
||||
(drop_sublist_drop_left l h).subset
|
||||
|
||||
@[grind] theorem takeWhile_prefix (p : α → Bool) : l.takeWhile p <+: l :=
|
||||
theorem takeWhile_prefix (p : α → Bool) : l.takeWhile p <+: l :=
|
||||
⟨l.dropWhile p, takeWhile_append_dropWhile⟩
|
||||
|
||||
@[grind] theorem dropWhile_suffix (p : α → Bool) : l.dropWhile p <:+ l :=
|
||||
theorem dropWhile_suffix (p : α → Bool) : l.dropWhile p <:+ l :=
|
||||
⟨l.takeWhile p, takeWhile_append_dropWhile⟩
|
||||
|
||||
@[grind] theorem takeWhile_sublist (p : α → Bool) : l.takeWhile p <+ l :=
|
||||
theorem takeWhile_sublist (p : α → Bool) : l.takeWhile p <+ l :=
|
||||
(takeWhile_prefix p).sublist
|
||||
|
||||
@[grind] theorem dropWhile_sublist (p : α → Bool) : l.dropWhile p <+ l :=
|
||||
theorem dropWhile_sublist (p : α → Bool) : l.dropWhile p <+ l :=
|
||||
(dropWhile_suffix p).sublist
|
||||
|
||||
theorem takeWhile_subset {l : List α} (p : α → Bool) : l.takeWhile p ⊆ l :=
|
||||
@@ -1159,88 +1010,61 @@ theorem takeWhile_subset {l : List α} (p : α → Bool) : l.takeWhile p ⊆ l :
|
||||
theorem dropWhile_subset {l : List α} (p : α → Bool) : l.dropWhile p ⊆ l :=
|
||||
(dropWhile_sublist p).subset
|
||||
|
||||
@[grind] theorem dropLast_prefix : ∀ l : List α, l.dropLast <+: l
|
||||
theorem dropLast_prefix : ∀ l : List α, l.dropLast <+: l
|
||||
| [] => ⟨nil, by rw [dropLast, List.append_nil]⟩
|
||||
| a :: l => ⟨_, dropLast_concat_getLast (cons_ne_nil a l)⟩
|
||||
|
||||
@[grind] theorem dropLast_sublist (l : List α) : l.dropLast <+ l :=
|
||||
theorem dropLast_sublist (l : List α) : l.dropLast <+ l :=
|
||||
(dropLast_prefix l).sublist
|
||||
|
||||
theorem dropLast_subset (l : List α) : l.dropLast ⊆ l :=
|
||||
(dropLast_sublist l).subset
|
||||
|
||||
@[grind] theorem tail_suffix (l : List α) : tail l <:+ l := by rw [← drop_one]; apply drop_suffix
|
||||
theorem tail_suffix (l : List α) : tail l <:+ l := by rw [← drop_one]; apply drop_suffix
|
||||
|
||||
@[grind] theorem IsPrefix.map {β} (f : α → β) ⦃l₁ l₂ : List α⦄ (h : l₁ <+: l₂) : l₁.map f <+: l₂.map f := by
|
||||
theorem IsPrefix.map {β} (f : α → β) ⦃l₁ l₂ : List α⦄ (h : l₁ <+: l₂) : l₁.map f <+: l₂.map f := by
|
||||
obtain ⟨r, rfl⟩ := h
|
||||
rw [map_append]; apply prefix_append
|
||||
|
||||
grind_pattern IsPrefix.map => l₁ <+: l₂, l₁.map f
|
||||
grind_pattern IsPrefix.map => l₁ <+: l₂, l₂.map f
|
||||
|
||||
@[grind] theorem IsSuffix.map {β} (f : α → β) ⦃l₁ l₂ : List α⦄ (h : l₁ <:+ l₂) : l₁.map f <:+ l₂.map f := by
|
||||
theorem IsSuffix.map {β} (f : α → β) ⦃l₁ l₂ : List α⦄ (h : l₁ <:+ l₂) : l₁.map f <:+ l₂.map f := by
|
||||
obtain ⟨r, rfl⟩ := h
|
||||
rw [map_append]; apply suffix_append
|
||||
|
||||
grind_pattern IsSuffix.map => l₁ <:+ l₂, l₁.map f
|
||||
grind_pattern IsSuffix.map => l₁ <:+ l₂, l₂.map f
|
||||
|
||||
@[grind] theorem IsInfix.map {β} (f : α → β) ⦃l₁ l₂ : List α⦄ (h : l₁ <:+: l₂) : l₁.map f <:+: l₂.map f := by
|
||||
theorem IsInfix.map {β} (f : α → β) ⦃l₁ l₂ : List α⦄ (h : l₁ <:+: l₂) : l₁.map f <:+: l₂.map f := by
|
||||
obtain ⟨r₁, r₂, rfl⟩ := h
|
||||
rw [map_append, map_append]; apply infix_append
|
||||
|
||||
grind_pattern IsInfix.map => l₁ <:+: l₂, l₁.map f
|
||||
grind_pattern IsInfix.map => l₁ <:+: l₂, l₂.map f
|
||||
|
||||
@[grind] theorem IsPrefix.filter (p : α → Bool) ⦃l₁ l₂ : List α⦄ (h : l₁ <+: l₂) :
|
||||
theorem IsPrefix.filter (p : α → Bool) ⦃l₁ l₂ : List α⦄ (h : l₁ <+: l₂) :
|
||||
l₁.filter p <+: l₂.filter p := by
|
||||
obtain ⟨xs, rfl⟩ := h
|
||||
rw [filter_append]; apply prefix_append
|
||||
|
||||
grind_pattern IsPrefix.filter => l₁ <+: l₂, l₁.filter p
|
||||
grind_pattern IsPrefix.filter => l₁ <+: l₂, l₂.filter p
|
||||
|
||||
@[grind] theorem IsSuffix.filter (p : α → Bool) ⦃l₁ l₂ : List α⦄ (h : l₁ <:+ l₂) :
|
||||
theorem IsSuffix.filter (p : α → Bool) ⦃l₁ l₂ : List α⦄ (h : l₁ <:+ l₂) :
|
||||
l₁.filter p <:+ l₂.filter p := by
|
||||
obtain ⟨xs, rfl⟩ := h
|
||||
rw [filter_append]; apply suffix_append
|
||||
|
||||
grind_pattern IsSuffix.filter => l₁ <:+ l₂, l₁.filter p
|
||||
grind_pattern IsSuffix.filter => l₁ <:+ l₂, l₂.filter p
|
||||
|
||||
@[grind] theorem IsInfix.filter (p : α → Bool) ⦃l₁ l₂ : List α⦄ (h : l₁ <:+: l₂) :
|
||||
theorem IsInfix.filter (p : α → Bool) ⦃l₁ l₂ : List α⦄ (h : l₁ <:+: l₂) :
|
||||
l₁.filter p <:+: l₂.filter p := by
|
||||
obtain ⟨xs, ys, rfl⟩ := h
|
||||
rw [filter_append, filter_append]; apply infix_append _
|
||||
|
||||
grind_pattern IsInfix.filter => l₁ <:+: l₂, l₁.filter p
|
||||
grind_pattern IsInfix.filter => l₁ <:+: l₂, l₂.filter p
|
||||
|
||||
@[grind] theorem IsPrefix.filterMap {β} (f : α → Option β) ⦃l₁ l₂ : List α⦄ (h : l₁ <+: l₂) :
|
||||
theorem IsPrefix.filterMap {β} (f : α → Option β) ⦃l₁ l₂ : List α⦄ (h : l₁ <+: l₂) :
|
||||
filterMap f l₁ <+: filterMap f l₂ := by
|
||||
obtain ⟨xs, rfl⟩ := h
|
||||
rw [filterMap_append]; apply prefix_append
|
||||
|
||||
grind_pattern IsPrefix.filterMap => l₁ <+: l₂, filterMap f l₁
|
||||
grind_pattern IsPrefix.filterMap => l₁ <+: l₂, filterMap f l₂
|
||||
|
||||
@[grind] theorem IsSuffix.filterMap {β} (f : α → Option β) ⦃l₁ l₂ : List α⦄ (h : l₁ <:+ l₂) :
|
||||
theorem IsSuffix.filterMap {β} (f : α → Option β) ⦃l₁ l₂ : List α⦄ (h : l₁ <:+ l₂) :
|
||||
filterMap f l₁ <:+ filterMap f l₂ := by
|
||||
obtain ⟨xs, rfl⟩ := h
|
||||
rw [filterMap_append]; apply suffix_append
|
||||
|
||||
grind_pattern IsSuffix.filterMap => l₁ <:+ l₂, filterMap f l₁
|
||||
grind_pattern IsSuffix.filterMap => l₁ <:+ l₂, filterMap f l₂
|
||||
|
||||
@[grind] theorem IsInfix.filterMap {β} (f : α → Option β) ⦃l₁ l₂ : List α⦄ (h : l₁ <:+: l₂) :
|
||||
theorem IsInfix.filterMap {β} (f : α → Option β) ⦃l₁ l₂ : List α⦄ (h : l₁ <:+: l₂) :
|
||||
filterMap f l₁ <:+: filterMap f l₂ := by
|
||||
obtain ⟨xs, ys, rfl⟩ := h
|
||||
rw [filterMap_append, filterMap_append]; apply infix_append
|
||||
|
||||
grind_pattern IsInfix.filterMap => l₁ <:+: l₂, filterMap f l₁
|
||||
grind_pattern IsInfix.filterMap => l₁ <:+: l₂, filterMap f l₂
|
||||
|
||||
@[simp, grind =] theorem isPrefixOf_iff_prefix [BEq α] [LawfulBEq α] {l₁ l₂ : List α} :
|
||||
@[simp] theorem isPrefixOf_iff_prefix [BEq α] [LawfulBEq α] {l₁ l₂ : List α} :
|
||||
l₁.isPrefixOf l₂ ↔ l₁ <+: l₂ := by
|
||||
induction l₁ generalizing l₂ with
|
||||
| nil => simp
|
||||
@@ -1252,7 +1076,7 @@ grind_pattern IsInfix.filterMap => l₁ <:+: l₂, filterMap f l₂
|
||||
instance [DecidableEq α] (l₁ l₂ : List α) : Decidable (l₁ <+: l₂) :=
|
||||
decidable_of_iff (l₁.isPrefixOf l₂) isPrefixOf_iff_prefix
|
||||
|
||||
@[simp, grind =] theorem isSuffixOf_iff_suffix [BEq α] [LawfulBEq α] {l₁ l₂ : List α} :
|
||||
@[simp] theorem isSuffixOf_iff_suffix [BEq α] [LawfulBEq α] {l₁ l₂ : List α} :
|
||||
l₁.isSuffixOf l₂ ↔ l₁ <:+ l₂ := by
|
||||
simp [isSuffixOf]
|
||||
|
||||
|
||||
@@ -256,16 +256,16 @@ theorem findRevM?_toArray [Monad m] [LawfulMonad m] (f : α → m Bool) (l : Lis
|
||||
|
||||
@[simp, grind =] theorem findSome?_toArray (f : α → Option β) (l : List α) :
|
||||
l.toArray.findSome? f = l.findSome? f := by
|
||||
rw [Array.findSome?, findSomeM?_toArray, findSomeM?_pure, Id.run_pure]
|
||||
rw [Array.findSome?, ← findSomeM?_id, findSomeM?_toArray, Id.run]
|
||||
|
||||
@[simp, grind =] theorem find?_toArray (f : α → Bool) (l : List α) :
|
||||
l.toArray.find? f = l.find? f := by
|
||||
rw [Array.find?]
|
||||
simp only [forIn_toArray]
|
||||
simp only [Id.run, Id, Id.pure_eq, Id.bind_eq, forIn_toArray]
|
||||
induction l with
|
||||
| nil => simp
|
||||
| cons a l ih =>
|
||||
simp only [forIn_cons, find?]
|
||||
simp only [forIn_cons, Id.pure_eq, Id.bind_eq, find?]
|
||||
by_cases f a <;> simp_all
|
||||
|
||||
private theorem findFinIdx?_loop_toArray (w : l' = l.drop j) :
|
||||
@@ -302,7 +302,7 @@ termination_by l.length - j
|
||||
@[simp, grind =] theorem findIdx?_toArray (p : α → Bool) (l : List α) :
|
||||
l.toArray.findIdx? p = l.findIdx? p := by
|
||||
rw [Array.findIdx?_eq_map_findFinIdx?_val, findIdx?_eq_map_findFinIdx?_val]
|
||||
simp [Array.size]
|
||||
simp
|
||||
|
||||
private theorem idxAuxOf_toArray [BEq α] (a : α) (l : List α) (j : Nat) (w : l' = l.drop j) (h) :
|
||||
l.toArray.idxOfAux a j = findFinIdx?.go (fun x => x == a) l l' j h := by
|
||||
@@ -339,11 +339,11 @@ termination_by l.length - j
|
||||
@[simp, grind =] theorem idxOf?_toArray [BEq α] (a : α) (l : List α) :
|
||||
l.toArray.idxOf? a = l.idxOf? a := by
|
||||
rw [Array.idxOf?, idxOf?]
|
||||
simp [finIdxOf?, findIdx?_eq_map_findFinIdx?_val, Array.size]
|
||||
simp [finIdxOf?, findIdx?_eq_map_findFinIdx?_val]
|
||||
|
||||
@[simp, grind =] theorem findIdx_toArray {as : List α} {p : α → Bool} :
|
||||
as.toArray.findIdx p = as.findIdx p := by
|
||||
rw [Array.findIdx, findIdx?_toArray, findIdx_eq_getD_findIdx?, Array.size]
|
||||
rw [Array.findIdx, findIdx?_toArray, findIdx_eq_getD_findIdx?]
|
||||
|
||||
@[simp, grind =] theorem idxOf_toArray [BEq α] {as : List α} {a : α} :
|
||||
as.toArray.idxOf a = as.idxOf a := by
|
||||
@@ -670,9 +670,9 @@ theorem replace_toArray [BEq α] [LawfulBEq α] (l : List α) (a b : α) :
|
||||
split <;> rename_i i h
|
||||
· simp only [finIdxOf?_toArray, finIdxOf?_eq_none_iff] at h
|
||||
rw [replace_of_not_mem]
|
||||
exact finIdxOf?_eq_none_iff.mp h
|
||||
simpa
|
||||
· simp_all only [finIdxOf?_toArray, finIdxOf?_eq_some_iff, Fin.getElem_fin, set_toArray,
|
||||
mk.injEq, Array.size]
|
||||
mk.injEq]
|
||||
apply List.ext_getElem
|
||||
· simp
|
||||
· intro j h₁ h₂
|
||||
|
||||
@@ -150,7 +150,7 @@ theorem add_one (n : Nat) : n + 1 = succ n :=
|
||||
@[simp] theorem succ_eq_add_one (n : Nat) : succ n = n + 1 :=
|
||||
rfl
|
||||
|
||||
theorem add_one_ne_zero (n : Nat) : n + 1 ≠ 0 := nofun
|
||||
@[simp] theorem add_one_ne_zero (n : Nat) : n + 1 ≠ 0 := nofun
|
||||
theorem zero_ne_add_one (n : Nat) : 0 ≠ n + 1 := by simp
|
||||
|
||||
protected theorem add_comm : ∀ (n m : Nat), n + m = m + n
|
||||
@@ -731,12 +731,13 @@ theorem exists_eq_add_one_of_ne_zero : ∀ {n}, n ≠ 0 → Exists fun k => n =
|
||||
theorem ctor_eq_zero : Nat.zero = 0 :=
|
||||
rfl
|
||||
|
||||
protected theorem one_ne_zero : 1 ≠ (0 : Nat) := by simp
|
||||
@[simp] protected theorem one_ne_zero : 1 ≠ (0 : Nat) :=
|
||||
fun h => Nat.noConfusion h
|
||||
|
||||
@[simp] protected theorem zero_ne_one : 0 ≠ (1 : Nat) :=
|
||||
fun h => Nat.noConfusion h
|
||||
|
||||
theorem succ_ne_zero (n : Nat) : succ n ≠ 0 := by simp
|
||||
@[simp] theorem succ_ne_zero (n : Nat) : succ n ≠ 0 := by simp
|
||||
|
||||
instance instNeZeroSucc {n : Nat} : NeZero (n + 1) := ⟨succ_ne_zero n⟩
|
||||
|
||||
|
||||
@@ -72,7 +72,7 @@ Examples:
|
||||
* `0 <<< 3 = 0`
|
||||
* `0xf1 <<< 4 = 0xf10`
|
||||
-/
|
||||
@[extern "lean_nat_shiftl", expose]
|
||||
@[extern "lean_nat_shiftl"]
|
||||
def shiftLeft : @& Nat → @& Nat → Nat
|
||||
| n, 0 => n
|
||||
| n, succ m => shiftLeft (2*n) m
|
||||
@@ -88,7 +88,7 @@ Examples:
|
||||
* `0 >>> 3 = 0`
|
||||
* `0xf13a >>> 8 = 0xf1`
|
||||
-/
|
||||
@[extern "lean_nat_shiftr", expose]
|
||||
@[extern "lean_nat_shiftr"]
|
||||
def shiftRight : @& Nat → @& Nat → Nat
|
||||
| n, 0 => n
|
||||
| n, succ m => shiftRight n m / 2
|
||||
|
||||
@@ -26,7 +26,6 @@ Examples:
|
||||
* `Nat.lcm 0 3 = 0`
|
||||
* `Nat.lcm 3 0 = 0`
|
||||
-/
|
||||
@[expose]
|
||||
def lcm (m n : Nat) : Nat := m * n / gcd m n
|
||||
|
||||
theorem lcm_eq_mul_div (m n : Nat) : lcm m n = m * n / gcd m n := rfl
|
||||
|
||||
@@ -415,7 +415,7 @@ theorem succ_min_succ (x y) : min (succ x) (succ y) = succ (min x y) := by
|
||||
| inl h => rw [Nat.min_eq_left h, Nat.min_eq_left (Nat.succ_le_succ h)]
|
||||
| inr h => rw [Nat.min_eq_right h, Nat.min_eq_right (Nat.succ_le_succ h)]
|
||||
|
||||
protected theorem min_self (a : Nat) : min a a = a := by simp
|
||||
@[simp] protected theorem min_self (a : Nat) : min a a = a := Nat.min_eq_left (Nat.le_refl _)
|
||||
instance : Std.IdempotentOp (α := Nat) min := ⟨Nat.min_self⟩
|
||||
|
||||
@[simp] protected theorem min_assoc : ∀ (a b c : Nat), min (min a b) c = min a (min b c)
|
||||
@@ -431,14 +431,16 @@ instance : Std.Associative (α := Nat) min := ⟨Nat.min_assoc⟩
|
||||
@[simp] protected theorem min_self_assoc' {m n : Nat} : min n (min m n) = min n m := by
|
||||
rw [Nat.min_comm m n, ← Nat.min_assoc, Nat.min_self]
|
||||
|
||||
theorem min_add_left_self {a b : Nat} : min a (b + a) = a := by
|
||||
@[simp] theorem min_add_left_self {a b : Nat} : min a (b + a) = a := by
|
||||
rw [Nat.min_def]
|
||||
simp
|
||||
theorem min_add_right_self {a b : Nat} : min a (a + b) = a := by
|
||||
simp
|
||||
theorem add_left_min_self {a b : Nat} : min (b + a) a = a := by
|
||||
simp
|
||||
theorem add_right_min_self {a b : Nat} : min (a + b) a = a := by
|
||||
@[simp] theorem min_add_right_self {a b : Nat} : min a (a + b) = a := by
|
||||
rw [Nat.min_def]
|
||||
simp
|
||||
@[simp] theorem add_left_min_self {a b : Nat} : min (b + a) a = a := by
|
||||
rw [Nat.min_comm, min_add_left_self]
|
||||
@[simp] theorem add_right_min_self {a b : Nat} : min (a + b) a = a := by
|
||||
rw [Nat.min_comm, min_add_right_self]
|
||||
|
||||
protected theorem sub_sub_eq_min : ∀ (a b : Nat), a - (a - b) = min a b
|
||||
| 0, _ => by rw [Nat.zero_sub, Nat.zero_min]
|
||||
@@ -460,7 +462,7 @@ protected theorem succ_max_succ (x y) : max (succ x) (succ y) = succ (max x y) :
|
||||
| inl h => rw [Nat.max_eq_right h, Nat.max_eq_right (Nat.succ_le_succ h)]
|
||||
| inr h => rw [Nat.max_eq_left h, Nat.max_eq_left (Nat.succ_le_succ h)]
|
||||
|
||||
protected theorem max_self (a : Nat) : max a a = a := by simp
|
||||
@[simp] protected theorem max_self (a : Nat) : max a a = a := Nat.max_eq_right (Nat.le_refl _)
|
||||
instance : Std.IdempotentOp (α := Nat) max := ⟨Nat.max_self⟩
|
||||
|
||||
instance : Std.LawfulIdentity (α := Nat) max 0 where
|
||||
@@ -474,14 +476,16 @@ instance : Std.LawfulIdentity (α := Nat) max 0 where
|
||||
| _+1, _+1, _+1 => by simp only [Nat.succ_max_succ]; exact congrArg succ <| Nat.max_assoc ..
|
||||
instance : Std.Associative (α := Nat) max := ⟨Nat.max_assoc⟩
|
||||
|
||||
theorem max_add_left_self {a b : Nat} : max a (b + a) = b + a := by
|
||||
@[simp] theorem max_add_left_self {a b : Nat} : max a (b + a) = b + a := by
|
||||
rw [Nat.max_def]
|
||||
simp
|
||||
theorem max_add_right_self {a b : Nat} : max a (a + b) = a + b := by
|
||||
simp
|
||||
theorem add_left_max_self {a b : Nat} : max (b + a) a = b + a := by
|
||||
simp
|
||||
theorem add_right_max_self {a b : Nat} : max (a + b) a = a + b := by
|
||||
@[simp] theorem max_add_right_self {a b : Nat} : max a (a + b) = a + b := by
|
||||
rw [Nat.max_def]
|
||||
simp
|
||||
@[simp] theorem add_left_max_self {a b : Nat} : max (b + a) a = b + a := by
|
||||
rw [Nat.max_comm, max_add_left_self]
|
||||
@[simp] theorem add_right_max_self {a b : Nat} : max (a + b) a = a + b := by
|
||||
rw [Nat.max_comm, max_add_right_self]
|
||||
|
||||
protected theorem sub_add_eq_max (a b : Nat) : a - b + b = max a b := by
|
||||
match Nat.le_total a b with
|
||||
@@ -810,8 +814,10 @@ theorem sub_mul_mod {x k n : Nat} (h₁ : n*k ≤ x) : (x - n*k) % n = x % n :=
|
||||
simp [mul_succ, Nat.add_comm] at h₁; simp [h₁]
|
||||
rw [mul_succ, ← Nat.sub_sub, ← mod_eq_sub_mod h₄, sub_mul_mod h₂]
|
||||
|
||||
theorem mod_mod (a n : Nat) : (a % n) % n = a % n := by
|
||||
simp
|
||||
@[simp] theorem mod_mod (a n : Nat) : (a % n) % n = a % n :=
|
||||
match eq_zero_or_pos n with
|
||||
| .inl n0 => by simp [n0, mod_zero]
|
||||
| .inr npos => Nat.mod_eq_of_lt (mod_lt _ npos)
|
||||
|
||||
theorem mul_mod (a b n : Nat) : a * b % n = (a % n) * (b % n) % n := by
|
||||
rw (occs := [1]) [← mod_add_div a n]
|
||||
|
||||
@@ -39,11 +39,11 @@ namespace Option
|
||||
o.toArray.foldr f a = o.elim a (fun b => f b a) := by
|
||||
cases o <;> simp
|
||||
|
||||
@[simp, grind =]
|
||||
@[simp]
|
||||
theorem toList_toArray {o : Option α} : o.toArray.toList = o.toList := by
|
||||
cases o <;> simp
|
||||
|
||||
@[simp, grind =]
|
||||
@[simp]
|
||||
theorem toArray_toList {o : Option α} : o.toList.toArray = o.toArray := by
|
||||
cases o <;> simp
|
||||
|
||||
@@ -69,8 +69,7 @@ theorem toArray_min [Min α] {o o' : Option α} :
|
||||
theorem size_toArray_le {o : Option α} : o.toArray.size ≤ 1 := by
|
||||
cases o <;> simp
|
||||
|
||||
@[grind =]
|
||||
theorem size_toArray {o : Option α} :
|
||||
theorem size_toArray_eq_ite {o : Option α} :
|
||||
o.toArray.size = if o.isSome then 1 else 0 := by
|
||||
cases o <;> simp
|
||||
|
||||
@@ -82,9 +81,10 @@ theorem toArray_eq_empty_iff {o : Option α} : o.toArray = #[] ↔ o = none := b
|
||||
theorem toArray_eq_singleton_iff {o : Option α} : o.toArray = #[a] ↔ o = some a := by
|
||||
cases o <;> simp
|
||||
|
||||
@[simp]
|
||||
theorem size_toArray_eq_zero_iff {o : Option α} :
|
||||
o.toArray.size = 0 ↔ o = none := by
|
||||
simp [Array.size]
|
||||
cases o <;> simp
|
||||
|
||||
@[simp]
|
||||
theorem size_toArray_eq_one_iff {o : Option α} :
|
||||
|
||||
@@ -34,7 +34,7 @@ well-founded recursion that use iteration operators (such as `Option.map`) to pr
|
||||
value drawn from a parameter is smaller than the parameter. This allows the well-founded recursion
|
||||
mechanism to prove that the function terminates.
|
||||
-/
|
||||
@[implemented_by attachWithImpl, expose] def attachWith
|
||||
@[implemented_by attachWithImpl] def attachWith
|
||||
(xs : Option α) (P : α → Prop) (H : ∀ x, xs = some x → P x) : Option {x // P x} :=
|
||||
match xs with
|
||||
| none => none
|
||||
@@ -49,14 +49,14 @@ operators (such as `Option.map`) to prove that an optional value drawn from a pa
|
||||
than the parameter. This allows the well-founded recursion mechanism to prove that the function
|
||||
terminates.
|
||||
-/
|
||||
@[inline, expose] def attach (xs : Option α) : Option {x // xs = some x} := xs.attachWith _ fun _ => id
|
||||
@[inline] def attach (xs : Option α) : Option {x // xs = some x} := xs.attachWith _ fun _ => id
|
||||
|
||||
@[simp, grind =] theorem attach_none : (none : Option α).attach = none := rfl
|
||||
@[simp, grind =] theorem attachWith_none : (none : Option α).attachWith P H = none := rfl
|
||||
@[simp] theorem attach_none : (none : Option α).attach = none := rfl
|
||||
@[simp] theorem attachWith_none : (none : Option α).attachWith P H = none := rfl
|
||||
|
||||
@[simp, grind =] theorem attach_some {x : α} :
|
||||
@[simp] theorem attach_some {x : α} :
|
||||
(some x).attach = some ⟨x, rfl⟩ := rfl
|
||||
@[simp, grind =] theorem attachWith_some {x : α} {P : α → Prop} (h : ∀ (b : α), some x = some b → P b) :
|
||||
@[simp] theorem attachWith_some {x : α} {P : α → Prop} (h : ∀ (b : α), some x = some b → P b) :
|
||||
(some x).attachWith P h = some ⟨x, by simpa using h⟩ := rfl
|
||||
|
||||
theorem attach_congr {o₁ o₂ : Option α} (h : o₁ = o₂) :
|
||||
@@ -76,7 +76,7 @@ theorem attach_map_val (o : Option α) (f : α → β) :
|
||||
@[deprecated attach_map_val (since := "2025-02-17")]
|
||||
abbrev attach_map_coe := @attach_map_val
|
||||
|
||||
@[simp, grind =]theorem attach_map_subtype_val (o : Option α) :
|
||||
theorem attach_map_subtype_val (o : Option α) :
|
||||
o.attach.map Subtype.val = o :=
|
||||
(attach_map_val _ _).trans (congrFun Option.map_id _)
|
||||
|
||||
@@ -87,7 +87,7 @@ theorem attachWith_map_val {p : α → Prop} (f : α → β) (o : Option α) (H
|
||||
@[deprecated attachWith_map_val (since := "2025-02-17")]
|
||||
abbrev attachWith_map_coe := @attachWith_map_val
|
||||
|
||||
@[simp, grind =] theorem attachWith_map_subtype_val {p : α → Prop} (o : Option α) (H : ∀ a, o = some a → p a) :
|
||||
theorem attachWith_map_subtype_val {p : α → Prop} (o : Option α) (H : ∀ a, o = some a → p a) :
|
||||
(o.attachWith p H).map Subtype.val = o :=
|
||||
(attachWith_map_val _ _ _).trans (congrFun Option.map_id _)
|
||||
|
||||
@@ -98,17 +98,17 @@ theorem attach_eq_some : ∀ (o : Option α) (x : {x // o = some x}), o.attach =
|
||||
theorem mem_attach : ∀ (o : Option α) (x : {x // o = some x}), x ∈ o.attach :=
|
||||
attach_eq_some
|
||||
|
||||
@[simp, grind =] theorem isNone_attach (o : Option α) : o.attach.isNone = o.isNone := by
|
||||
@[simp] theorem isNone_attach (o : Option α) : o.attach.isNone = o.isNone := by
|
||||
cases o <;> simp
|
||||
|
||||
@[simp, grind =] theorem isNone_attachWith {p : α → Prop} (o : Option α) (H : ∀ a, o = some a → p a) :
|
||||
@[simp] theorem isNone_attachWith {p : α → Prop} (o : Option α) (H : ∀ a, o = some a → p a) :
|
||||
(o.attachWith p H).isNone = o.isNone := by
|
||||
cases o <;> simp
|
||||
|
||||
@[simp, grind =] theorem isSome_attach (o : Option α) : o.attach.isSome = o.isSome := by
|
||||
@[simp] theorem isSome_attach (o : Option α) : o.attach.isSome = o.isSome := by
|
||||
cases o <;> simp
|
||||
|
||||
@[simp, grind =] theorem isSome_attachWith {p : α → Prop} (o : Option α) (H : ∀ a, o = some a → p a) :
|
||||
@[simp] theorem isSome_attachWith {p : α → Prop} (o : Option α) (H : ∀ a, o = some a → p a) :
|
||||
(o.attachWith p H).isSome = o.isSome := by
|
||||
cases o <;> simp
|
||||
|
||||
@@ -127,28 +127,25 @@ theorem mem_attach : ∀ (o : Option α) (x : {x // o = some x}), x ∈ o.attach
|
||||
o.attachWith p H = some x ↔ o = some x.val := by
|
||||
cases o <;> cases x <;> simp
|
||||
|
||||
@[simp, grind =] theorem get_attach {o : Option α} (h : o.attach.isSome = true) :
|
||||
@[simp] theorem get_attach {o : Option α} (h : o.attach.isSome = true) :
|
||||
o.attach.get h = ⟨o.get (by simpa using h), by simp⟩ :=
|
||||
Subsingleton.elim _ _
|
||||
|
||||
@[simp, grind =] theorem getD_attach {o : Option α} {fallback} :
|
||||
@[simp] theorem getD_attach {o : Option α} {fallback} :
|
||||
o.attach.getD fallback = fallback :=
|
||||
Subsingleton.elim _ _
|
||||
|
||||
@[simp, grind =] theorem get!_attach {o : Option α} [Inhabited { x // o = some x }] :
|
||||
@[simp] theorem get!_attach {o : Option α} [Inhabited { x // o = some x }] :
|
||||
o.attach.get! = default :=
|
||||
Subsingleton.elim _ _
|
||||
|
||||
@[simp, grind =] theorem get_attachWith {p : α → Prop} {o : Option α} (H : ∀ a, o = some a → p a) (h : (o.attachWith p H).isSome) :
|
||||
@[simp] theorem get_attachWith {p : α → Prop} {o : Option α} (H : ∀ a, o = some a → p a) (h : (o.attachWith p H).isSome) :
|
||||
(o.attachWith p H).get h = ⟨o.get (by simpa using h), H _ (by simp)⟩ := by
|
||||
cases o <;> simp
|
||||
|
||||
@[simp, grind =] theorem getD_attachWith {p : α → Prop} {o : Option α} {h} {fallback} :
|
||||
@[simp] theorem getD_attachWith {p : α → Prop} {o : Option α} {h} {fallback} :
|
||||
(o.attachWith p h).getD fallback =
|
||||
⟨o.getD fallback.val, by
|
||||
cases o
|
||||
· exact fallback.property
|
||||
· exact h _ (by simp)⟩ := by
|
||||
⟨o.getD fallback.1, by cases o <;> (try exact fallback.2) <;> exact h _ (by simp)⟩ := by
|
||||
cases o <;> simp
|
||||
|
||||
theorem toList_attach (o : Option α) :
|
||||
@@ -171,23 +168,23 @@ theorem toArray_attachWith {p : α → Prop} {o : Option α} {h} :
|
||||
o.toList.attach = (o.attach.map fun ⟨a, h⟩ => ⟨a, by simpa using h⟩).toList := by
|
||||
cases o <;> simp [toList]
|
||||
|
||||
@[grind =] theorem attach_map {o : Option α} (f : α → β) :
|
||||
theorem attach_map {o : Option α} (f : α → β) :
|
||||
(o.map f).attach = o.attach.map (fun ⟨x, h⟩ => ⟨f x, map_eq_some_iff.2 ⟨_, h, rfl⟩⟩) := by
|
||||
cases o <;> simp
|
||||
|
||||
@[grind =] theorem attachWith_map {o : Option α} (f : α → β) {P : β → Prop} {H : ∀ (b : β), o.map f = some b → P b} :
|
||||
theorem attachWith_map {o : Option α} (f : α → β) {P : β → Prop} {H : ∀ (b : β), o.map f = some b → P b} :
|
||||
(o.map f).attachWith P H = (o.attachWith (P ∘ f) (fun _ h => H _ (map_eq_some_iff.2 ⟨_, h, rfl⟩))).map
|
||||
fun ⟨x, h⟩ => ⟨f x, h⟩ := by
|
||||
cases o <;> simp
|
||||
|
||||
@[grind =] theorem map_attach_eq_pmap {o : Option α} (f : { x // o = some x } → β) :
|
||||
theorem map_attach_eq_pmap {o : Option α} (f : { x // o = some x } → β) :
|
||||
o.attach.map f = o.pmap (fun a (h : o = some a) => f ⟨a, h⟩) (fun _ h => h) := by
|
||||
cases o <;> simp
|
||||
|
||||
@[deprecated map_attach_eq_pmap (since := "2025-02-09")]
|
||||
abbrev map_attach := @map_attach_eq_pmap
|
||||
|
||||
@[simp, grind =] theorem map_attachWith {l : Option α} {P : α → Prop} {H : ∀ (a : α), l = some a → P a}
|
||||
@[simp] theorem map_attachWith {l : Option α} {P : α → Prop} {H : ∀ (a : α), l = some a → P a}
|
||||
(f : { x // P x } → β) :
|
||||
(l.attachWith P H).map f = l.attach.map fun ⟨x, h⟩ => f ⟨x, H _ h⟩ := by
|
||||
cases l <;> simp_all
|
||||
@@ -203,12 +200,12 @@ theorem map_attach_eq_attachWith {o : Option α} {p : α → Prop} (f : ∀ a, o
|
||||
o.attach.map (fun x => ⟨x.1, f x.1 x.2⟩) = o.attachWith p f := by
|
||||
cases o <;> simp_all [Function.comp_def]
|
||||
|
||||
@[grind =] theorem attach_bind {o : Option α} {f : α → Option β} :
|
||||
theorem attach_bind {o : Option α} {f : α → Option β} :
|
||||
(o.bind f).attach =
|
||||
o.attach.bind fun ⟨x, h⟩ => (f x).attach.map fun ⟨y, h'⟩ => ⟨y, bind_eq_some_iff.2 ⟨_, h, h'⟩⟩ := by
|
||||
cases o <;> simp
|
||||
|
||||
@[grind =] theorem bind_attach {o : Option α} {f : {x // o = some x} → Option β} :
|
||||
theorem bind_attach {o : Option α} {f : {x // o = some x} → Option β} :
|
||||
o.attach.bind f = o.pbind fun a h => f ⟨a, h⟩ := by
|
||||
cases o <;> simp
|
||||
|
||||
@@ -216,7 +213,7 @@ theorem pbind_eq_bind_attach {o : Option α} {f : (a : α) → o = some a → Op
|
||||
o.pbind f = o.attach.bind fun ⟨x, h⟩ => f x h := by
|
||||
cases o <;> simp
|
||||
|
||||
@[grind =] theorem attach_filter {o : Option α} {p : α → Bool} :
|
||||
theorem attach_filter {o : Option α} {p : α → Bool} :
|
||||
(o.filter p).attach =
|
||||
o.attach.bind fun ⟨x, h⟩ => if h' : p x then some ⟨x, by simp_all⟩ else none := by
|
||||
cases o with
|
||||
@@ -232,12 +229,12 @@ theorem pbind_eq_bind_attach {o : Option α} {f : (a : α) → o = some a → Op
|
||||
· rintro ⟨h, rfl⟩
|
||||
simp [h]
|
||||
|
||||
@[grind =] theorem filter_attachWith {P : α → Prop} {o : Option α} {h : ∀ x, o = some x → P x} {q : α → Bool} :
|
||||
theorem filter_attachWith {P : α → Prop} {o : Option α} {h : ∀ x, o = some x → P x} {q : α → Bool} :
|
||||
(o.attachWith P h).filter q =
|
||||
(o.filter q).attachWith P (fun _ h' => h _ (eq_some_of_filter_eq_some h')) := by
|
||||
cases o <;> simp [filter_some] <;> split <;> simp
|
||||
|
||||
@[grind =] theorem filter_attach {o : Option α} {p : {x // o = some x} → Bool} :
|
||||
theorem filter_attach {o : Option α} {p : {x // o = some x} → Bool} :
|
||||
o.attach.filter p = o.pbind fun a h => if p ⟨a, h⟩ then some ⟨a, h⟩ else none := by
|
||||
cases o <;> simp [filter_some]
|
||||
|
||||
@@ -281,7 +278,7 @@ theorem toArray_pmap {p : α → Prop} {o : Option α} {f : (a : α) → p a →
|
||||
(o.pmap f h).toArray = o.attach.toArray.map (fun x => f x.1 (h _ x.2)) := by
|
||||
cases o <;> simp
|
||||
|
||||
@[grind =] theorem attach_pfilter {o : Option α} {p : (a : α) → o = some a → Bool} :
|
||||
theorem attach_pfilter {o : Option α} {p : (a : α) → o = some a → Bool} :
|
||||
(o.pfilter p).attach =
|
||||
o.attach.pbind fun x h => if h' : p x (by simp_all) then
|
||||
some ⟨x.1, by simpa [pfilter_eq_some_iff] using ⟨_, h'⟩⟩ else none := by
|
||||
@@ -325,7 +322,6 @@ If this function is encountered in a proof state, the right approach is usually
|
||||
|
||||
It is a synonym for `Option.map Subtype.val`.
|
||||
-/
|
||||
@[expose]
|
||||
def unattach {α : Type _} {p : α → Prop} (o : Option { x // p x }) := o.map (·.val)
|
||||
|
||||
@[simp] theorem unattach_none {p : α → Prop} : (none : Option { x // p x }).unattach = none := rfl
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace Option
|
||||
/--
|
||||
Extracts the value from an `Option`, panicking on `none`.
|
||||
-/
|
||||
@[inline, expose] def get! {α : Type u} [Inhabited α] : Option α → α
|
||||
@[inline] def get! {α : Type u} [Inhabited α] : Option α → α
|
||||
| some x => x
|
||||
| none => panic! "value is none"
|
||||
|
||||
|
||||
@@ -87,7 +87,7 @@ some ⟨3, ⋯⟩
|
||||
none
|
||||
```
|
||||
-/
|
||||
@[inline, expose]
|
||||
@[inline]
|
||||
def pbind : (o : Option α) → (f : (a : α) → o = some a → Option β) → Option β
|
||||
| none, _ => none
|
||||
| some a, f => f a rfl
|
||||
@@ -114,7 +114,7 @@ some ⟨3, ⋯⟩
|
||||
none
|
||||
```
|
||||
-/
|
||||
@[inline, expose] def pmap {p : α → Prop}
|
||||
@[inline] def pmap {p : α → Prop}
|
||||
(f : ∀ a : α, p a → β) :
|
||||
(o : Option α) → (∀ a, o = some a → p a) → Option β
|
||||
| none, _ => none
|
||||
@@ -147,14 +147,14 @@ some ⟨3, ⋯⟩
|
||||
none
|
||||
```
|
||||
-/
|
||||
@[inline, expose] def pelim (o : Option α) (b : β) (f : (a : α) → o = some a → β) : β :=
|
||||
@[inline] def pelim (o : Option α) (b : β) (f : (a : α) → o = some a → β) : β :=
|
||||
match o with
|
||||
| none => b
|
||||
| some a => f a rfl
|
||||
|
||||
/-- Partial filter. If `o : Option α`, `p : (a : α) → o = some a → Bool`, then `o.pfilter p` is
|
||||
the same as `o.filter p` but `p` is passed the proof that `o = some a`. -/
|
||||
@[inline, expose] def pfilter (o : Option α) (p : (a : α) → o = some a → Bool) : Option α :=
|
||||
@[inline] def pfilter (o : Option α) (p : (a : α) → o = some a → Bool) : Option α :=
|
||||
match o with
|
||||
| none => none
|
||||
| some a => bif p a rfl then o else none
|
||||
@@ -177,7 +177,7 @@ Examples:
|
||||
((), 0)
|
||||
```
|
||||
-/
|
||||
@[inline, expose] protected def forM [Pure m] : Option α → (α → m PUnit) → m PUnit
|
||||
@[inline] protected def forM [Pure m] : Option α → (α → m PUnit) → m PUnit
|
||||
| none , _ => pure ⟨⟩
|
||||
| some a, f => f a
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ import Init.Ext
|
||||
|
||||
namespace Option
|
||||
|
||||
@[grind =] theorem default_eq_none : (default : Option α) = none := rfl
|
||||
theorem default_eq_none : (default : Option α) = none := rfl
|
||||
|
||||
@[deprecated mem_def (since := "2025-04-07")]
|
||||
theorem mem_iff {a : α} {b : Option α} : a ∈ b ↔ b = some a := .rfl
|
||||
@@ -70,6 +70,8 @@ theorem some_get! [Inhabited α] : (o : Option α) → o.isSome → some (o.get!
|
||||
|
||||
theorem get!_eq_getD [Inhabited α] (o : Option α) : o.get! = o.getD default := rfl
|
||||
|
||||
@[deprecated get!_eq_getD (since := "2024-11-18")] abbrev get!_eq_getD_default := @get!_eq_getD
|
||||
|
||||
theorem get_congr {o o' : Option α} {ho : o.isSome} (h : o = o') :
|
||||
o.get ho = o'.get (h ▸ ho) := by
|
||||
cases h; rfl
|
||||
@@ -252,11 +254,11 @@ theorem isSome_apply_of_isSome_bind {α β : Type _} {x : Option α} {f : α →
|
||||
(isSome_apply_of_isSome_bind h) := by
|
||||
cases x <;> trivial
|
||||
|
||||
@[grind =] theorem any_bind {p : β → Bool} {f : α → Option β} {o : Option α} :
|
||||
theorem any_bind {p : β → Bool} {f : α → Option β} {o : Option α} :
|
||||
(o.bind f).any p = o.any (Option.any p ∘ f) := by
|
||||
cases o <;> simp
|
||||
|
||||
@[grind =] theorem all_bind {p : β → Bool} {f : α → Option β} {o : Option α} :
|
||||
theorem all_bind {p : β → Bool} {f : α → Option β} {o : Option α} :
|
||||
(o.bind f).all p = o.all (Option.all p ∘ f) := by
|
||||
cases o <;> simp
|
||||
|
||||
@@ -429,7 +431,7 @@ theorem filter_eq_bind (x : Option α) (p : α → Bool) :
|
||||
x.filter p = x.bind (Option.guard p) :=
|
||||
(bind_guard x p).symm
|
||||
|
||||
@[simp, grind =] theorem any_filter : (o : Option α) →
|
||||
@[simp] theorem any_filter : (o : Option α) →
|
||||
(Option.filter p o).any q = Option.any (fun a => p a && q a) o
|
||||
| none => rfl
|
||||
| some a =>
|
||||
@@ -437,7 +439,7 @@ theorem filter_eq_bind (x : Option α) (p : α → Bool) :
|
||||
| false => by simp [filter_some_neg h, h]
|
||||
| true => by simp [filter_some_pos h, h]
|
||||
|
||||
@[simp, grind =] theorem all_filter : (o : Option α) →
|
||||
@[simp] theorem all_filter : (o : Option α) →
|
||||
(Option.filter p o).all q = Option.all (fun a => !p a || q a) o
|
||||
| none => rfl
|
||||
| some a =>
|
||||
@@ -445,7 +447,7 @@ theorem filter_eq_bind (x : Option α) (p : α → Bool) :
|
||||
| false => by simp [filter_some_neg h, h]
|
||||
| true => by simp [filter_some_pos h, h]
|
||||
|
||||
@[simp, grind =] theorem isNone_filter :
|
||||
@[simp] theorem isNone_filter :
|
||||
Option.isNone (Option.filter p o) = Option.all (fun a => !p a) o :=
|
||||
match o with
|
||||
| none => rfl
|
||||
@@ -466,7 +468,7 @@ theorem filter_eq_bind (x : Option α) (p : α → Bool) :
|
||||
Option.filter q (Option.filter p o) = Option.filter (fun x => p x && q x) o := by
|
||||
cases o <;> repeat (simp_all [filter_some]; try split)
|
||||
|
||||
@[grind =] theorem filter_bind {f : α → Option β} :
|
||||
theorem filter_bind {f : α → Option β} :
|
||||
(Option.bind x f).filter p = (x.filter (fun a => (f a).any p)).bind f := by
|
||||
cases x with
|
||||
| none => simp
|
||||
@@ -481,16 +483,16 @@ theorem filter_eq_bind (x : Option α) (p : α → Bool) :
|
||||
theorem eq_some_of_filter_eq_some {o : Option α} {a : α} (h : o.filter p = some a) : o = some a :=
|
||||
filter_eq_some_iff.1 h |>.1
|
||||
|
||||
@[grind =] theorem filter_map {f : α → β} {p : β → Bool} :
|
||||
theorem filter_map {f : α → β} {p : β → Bool} :
|
||||
(Option.map f x).filter p = (x.filter (p ∘ f)).map f := by
|
||||
cases x <;> simp [filter_some]
|
||||
|
||||
@[simp] theorem all_guard (a : α) :
|
||||
@[simp, grind] theorem all_guard (a : α) :
|
||||
Option.all q (guard p a) = (!p a || q a) := by
|
||||
simp only [guard]
|
||||
split <;> simp_all
|
||||
|
||||
@[simp] theorem any_guard (a : α) : Option.any q (guard p a) = (p a && q a) := by
|
||||
@[simp, grind] theorem any_guard (a : α) : Option.any q (guard p a) = (p a && q a) := by
|
||||
simp only [guard]
|
||||
split <;> simp_all
|
||||
|
||||
@@ -561,21 +563,21 @@ theorem bind_map_comm {α β} {x : Option (Option α)} {f : α → β} :
|
||||
theorem mem_of_mem_join {a : α} {x : Option (Option α)} (h : a ∈ x.join) : some a ∈ x :=
|
||||
h.symm ▸ join_eq_some_iff.1 h
|
||||
|
||||
@[grind _=_] theorem any_join {p : α → Bool} {x : Option (Option α)} :
|
||||
theorem any_join {p : α → Bool} {x : Option (Option α)} :
|
||||
x.join.any p = x.any (Option.any p) := by
|
||||
cases x <;> simp
|
||||
|
||||
@[grind _=_] theorem all_join {p : α → Bool} {x : Option (Option α)} :
|
||||
theorem all_join {p : α → Bool} {x : Option (Option α)} :
|
||||
x.join.all p = x.all (Option.all p) := by
|
||||
cases x <;> simp
|
||||
|
||||
@[grind =] theorem isNone_join {x : Option (Option α)} : x.join.isNone = x.all Option.isNone := by
|
||||
theorem isNone_join {x : Option (Option α)} : x.join.isNone = x.all Option.isNone := by
|
||||
cases x <;> simp
|
||||
|
||||
@[grind =]theorem isSome_join {x : Option (Option α)} : x.join.isSome = x.any Option.isSome := by
|
||||
theorem isSome_join {x : Option (Option α)} : x.join.isSome = x.any Option.isSome := by
|
||||
cases x <;> simp
|
||||
|
||||
@[grind =] theorem get_join {x : Option (Option α)} {h} : x.join.get h =
|
||||
theorem get_join {x : Option (Option α)} {h} : x.join.get h =
|
||||
(x.get (Option.isSome_of_any (Option.isSome_join ▸ h))).get (get_of_any_eq_true _ _ (Option.isSome_join ▸ h)) := by
|
||||
cases x with
|
||||
| none => simp at h
|
||||
@@ -586,11 +588,11 @@ theorem join_eq_get {x : Option (Option α)} {h} : x.join = x.get h := by
|
||||
| none => simp at h
|
||||
| some _ => simp
|
||||
|
||||
@[grind =] theorem getD_join {x : Option (Option α)} {default : α} :
|
||||
theorem getD_join {x : Option (Option α)} {default : α} :
|
||||
x.join.getD default = (x.getD (some default)).getD default := by
|
||||
cases x <;> simp
|
||||
|
||||
@[grind =] theorem get!_join [Inhabited α] {x : Option (Option α)} :
|
||||
theorem get!_join [Inhabited α] {x : Option (Option α)} :
|
||||
x.join.get! = x.get!.get! := by
|
||||
cases x <;> simp [default_eq_none]
|
||||
|
||||
@@ -600,13 +602,13 @@ theorem join_eq_get {x : Option (Option α)} {h} : x.join = x.get h := by
|
||||
@[deprecated guard_eq_some_iff (since := "2025-04-10")]
|
||||
abbrev guard_eq_some := @guard_eq_some_iff
|
||||
|
||||
@[simp, grind =] theorem isSome_guard : (Option.guard p a).isSome = p a :=
|
||||
@[simp] theorem isSome_guard : (Option.guard p a).isSome = p a :=
|
||||
if h : p a then by simp [Option.guard, h] else by simp [Option.guard, h]
|
||||
|
||||
@[deprecated isSome_guard (since := "2025-03-18")]
|
||||
abbrev guard_isSome := @isSome_guard
|
||||
|
||||
@[simp, grind =] theorem isNone_guard : (Option.guard p a).isNone = !p a := by
|
||||
@[simp] theorem isNone_guard : (Option.guard p a).isNone = !p a := by
|
||||
rw [← not_isSome, isSome_guard]
|
||||
|
||||
@[simp] theorem guard_eq_none_iff : Option.guard p a = none ↔ p a = false :=
|
||||
@@ -641,7 +643,7 @@ theorem get_none (a : α) {h} : none.get h = a := by
|
||||
theorem get_none_eq_iff_true {h} : (none : Option α).get h = a ↔ True := by
|
||||
simp at h
|
||||
|
||||
@[simp, grind =] theorem get_guard : (guard p a).get h = a := by
|
||||
theorem get_guard : (guard p a).get h = a := by
|
||||
simp only [guard]
|
||||
split <;> simp
|
||||
|
||||
@@ -670,7 +672,7 @@ theorem map_guard {p : α → Bool} {f : α → β} {x : α} :
|
||||
(Option.guard p x).map f = if p x then some (f x) else none := by
|
||||
simp [guard_eq_ite]
|
||||
|
||||
@[grind =] theorem join_filter {p : Option α → Bool} : {o : Option (Option α)} →
|
||||
theorem join_filter {p : Option α → Bool} : {o : Option (Option α)} →
|
||||
(o.filter p).join = o.join.filter (fun a => p (some a))
|
||||
| none => by simp
|
||||
| some none => by
|
||||
@@ -680,7 +682,7 @@ theorem map_guard {p : α → Bool} {f : α → β} {x : α} :
|
||||
simp only [join_some, filter_some]
|
||||
split <;> simp
|
||||
|
||||
@[grind =] theorem filter_join {p : α → Bool} : {o : Option (Option α)} →
|
||||
theorem filter_join {p : α → Bool} : {o : Option (Option α)} →
|
||||
o.join.filter p = (o.filter (Option.any p)).join
|
||||
| none => by simp
|
||||
| some none => by
|
||||
@@ -752,22 +754,22 @@ theorem merge_eq_some_iff {o o' : Option α} {f : α → α → α} {a : α} :
|
||||
theorem merge_eq_none_iff {o o' : Option α} : o.merge f o' = none ↔ o = none ∧ o' = none := by
|
||||
cases o <;> cases o' <;> simp
|
||||
|
||||
@[simp, grind =]
|
||||
@[simp]
|
||||
theorem any_merge {p : α → Bool} {f : α → α → α} (hpf : ∀ a b, p (f a b) = (p a || p b))
|
||||
{o o' : Option α} : (o.merge f o').any p = (o.any p || o'.any p) := by
|
||||
cases o <;> cases o' <;> simp [*]
|
||||
|
||||
@[simp, grind =]
|
||||
@[simp]
|
||||
theorem all_merge {p : α → Bool} {f : α → α → α} (hpf : ∀ a b, p (f a b) = (p a && p b))
|
||||
{o o' : Option α} : (o.merge f o').all p = (o.all p && o'.all p) := by
|
||||
cases o <;> cases o' <;> simp [*]
|
||||
|
||||
@[simp, grind =]
|
||||
@[simp]
|
||||
theorem isSome_merge {o o' : Option α} {f : α → α → α} :
|
||||
(o.merge f o').isSome = (o.isSome || o'.isSome) := by
|
||||
simp [← any_true]
|
||||
|
||||
@[simp, grind =]
|
||||
@[simp]
|
||||
theorem isNone_merge {o o' : Option α} {f : α → α → α} :
|
||||
(o.merge f o').isNone = (o.isNone && o'.isNone) := by
|
||||
simp [← all_false]
|
||||
@@ -781,7 +783,7 @@ theorem get_merge {o o' : Option α} {f : α → α → α} {i : α} [Std.Lawful
|
||||
|
||||
@[simp, grind] theorem elim_some (x : β) (f : α → β) (a : α) : (some a).elim x f = f a := rfl
|
||||
|
||||
@[grind =] theorem elim_filter {o : Option α} {b : β} :
|
||||
theorem elim_filter {o : Option α} {b : β} :
|
||||
Option.elim (Option.filter p o) b f = Option.elim o b (fun a => if p a then f a else b) :=
|
||||
match o with
|
||||
| none => rfl
|
||||
@@ -790,7 +792,7 @@ theorem get_merge {o o' : Option α} {f : α → α → α} {i : α} [Std.Lawful
|
||||
| false => by simp [filter_some_neg h, h]
|
||||
| true => by simp [filter_some_pos, h]
|
||||
|
||||
@[grind =] theorem elim_join {o : Option (Option α)} {b : β} {f : α → β} :
|
||||
theorem elim_join {o : Option (Option α)} {b : β} {f : α → β} :
|
||||
o.join.elim b f = o.elim b (·.elim b f) := by
|
||||
cases o <;> simp
|
||||
|
||||
@@ -828,16 +830,9 @@ theorem choice_eq_default [Subsingleton α] [Inhabited α] : choice α = some de
|
||||
theorem choice_eq_none_iff_not_nonempty : choice α = none ↔ ¬Nonempty α := by
|
||||
simp [choice]
|
||||
|
||||
theorem isNone_choice_iff_not_nonempty : (choice α).isNone ↔ ¬Nonempty α := by
|
||||
rw [isNone_iff_eq_none, choice_eq_none_iff_not_nonempty]
|
||||
|
||||
grind_pattern isNone_choice_iff_not_nonempty => (choice α).isNone
|
||||
|
||||
theorem isSome_choice_iff_nonempty : (choice α).isSome ↔ Nonempty α :=
|
||||
⟨fun h => ⟨(choice α).get h⟩, fun h => by simp only [choice, dif_pos h, isSome_some]⟩
|
||||
|
||||
grind_pattern isSome_choice_iff_nonempty => (choice α).isSome
|
||||
|
||||
@[simp]
|
||||
theorem isSome_choice [Nonempty α] : (choice α).isSome :=
|
||||
isSome_choice_iff_nonempty.2 inferInstance
|
||||
@@ -845,16 +840,19 @@ theorem isSome_choice [Nonempty α] : (choice α).isSome :=
|
||||
@[deprecated isSome_choice_iff_nonempty (since := "2025-03-18")]
|
||||
abbrev choice_isSome_iff_nonempty := @isSome_choice_iff_nonempty
|
||||
|
||||
theorem isNone_choice_iff_not_nonempty : (choice α).isNone ↔ ¬Nonempty α := by
|
||||
rw [isNone_iff_eq_none, choice_eq_none_iff_not_nonempty]
|
||||
|
||||
@[simp]
|
||||
theorem isNone_choice_eq_false [Nonempty α] : (choice α).isNone = false := by
|
||||
simp [← not_isSome]
|
||||
|
||||
@[simp, grind =]
|
||||
@[simp]
|
||||
theorem getD_choice {a} :
|
||||
(choice α).getD a = (choice α).get (isSome_choice_iff_nonempty.2 ⟨a⟩) := by
|
||||
rw [get_eq_getD]
|
||||
|
||||
@[simp, grind =]
|
||||
@[simp]
|
||||
theorem get!_choice [Inhabited α] : (choice α).get! = (choice α).get isSome_choice := by
|
||||
rw [get_eq_get!]
|
||||
|
||||
@@ -935,16 +933,16 @@ theorem or_of_isNone {o o' : Option α} (h : o.isNone) : o.or o' = o' := by
|
||||
match o, h with
|
||||
| none, _ => simp
|
||||
|
||||
@[simp, grind =]
|
||||
@[simp, grind]
|
||||
theorem getD_or {o o' : Option α} {fallback : α} :
|
||||
(o.or o').getD fallback = o.getD (o'.getD fallback) := by
|
||||
cases o <;> simp
|
||||
|
||||
@[simp, grind =]
|
||||
@[simp]
|
||||
theorem get!_or {o o' : Option α} [Inhabited α] : (o.or o').get! = o.getD o'.get! := by
|
||||
cases o <;> simp
|
||||
|
||||
@[simp, grind =] theorem filter_or_filter {o o' : Option α} {f : α → Bool} :
|
||||
@[simp] theorem filter_or_filter {o o' : Option α} {f : α → Bool} :
|
||||
(o.or (o'.filter f)).filter f = (o.or o').filter f := by
|
||||
cases o <;> cases o' <;> simp
|
||||
|
||||
@@ -1028,16 +1026,16 @@ variable [BEq α]
|
||||
|
||||
@[simp] theorem beq_none {o : Option α} : (o == none) = o.isNone := by cases o <;> simp
|
||||
|
||||
@[simp, grind =]
|
||||
theorem filter_beq_self [ReflBEq α] {p : α → Bool} {o : Option α} : (o.filter p == o) = o.all p := by
|
||||
@[simp]
|
||||
theorem filter_beq_self [ReflBEq α] {p : α → Bool} {o : Option α} : (o.filter p == o) = (o.all p) := by
|
||||
cases o with
|
||||
| none => simp
|
||||
| some _ =>
|
||||
simp only [filter_some]
|
||||
split <;> simp [*]
|
||||
|
||||
@[simp, grind =]
|
||||
theorem self_beq_filter [ReflBEq α] {p : α → Bool} {o : Option α} : (o == o.filter p) = o.all p := by
|
||||
@[simp]
|
||||
theorem self_beq_filter [ReflBEq α] {p : α → Bool} {o : Option α} : (o == o.filter p) = (o.all p) := by
|
||||
cases o with
|
||||
| none => simp
|
||||
| some _ =>
|
||||
@@ -1206,7 +1204,7 @@ theorem pbind_eq_some_iff {o : Option α} {f : (a : α) → o = some a → Optio
|
||||
o.pbind f = some b ↔ ∃ a h, f a h = some b := by
|
||||
cases o <;> simp
|
||||
|
||||
@[grind =] theorem pbind_join {o : Option (Option α)} {f : (a : α) → o.join = some a → Option β} :
|
||||
theorem pbind_join {o : Option (Option α)} {f : (a : α) → o.join = some a → Option β} :
|
||||
o.join.pbind f = o.pbind (fun o' ho' => o'.pbind (fun a ha => f a (by simp_all))) := by
|
||||
cases o <;> simp <;> congr
|
||||
|
||||
@@ -1220,7 +1218,7 @@ theorem isSome_get_of_isSome_pbind {o : Option α} {f : (a : α) → o = some a
|
||||
| none => simp at h
|
||||
| some a => simp [← h]
|
||||
|
||||
@[simp, grind =]
|
||||
@[simp]
|
||||
theorem get_pbind {o : Option α} {f : (a : α) → o = some a → Option β} {h} :
|
||||
(o.pbind f).get h = (f (o.get (isSome_of_isSome_pbind h)) (by simp)).get (isSome_get_of_isSome_pbind h) := by
|
||||
cases o <;> simp
|
||||
@@ -1258,7 +1256,7 @@ theorem get_pbind {o : Option α} {f : (a : α) → o = some a → Option β} {h
|
||||
· rintro ⟨h, rfl⟩
|
||||
rfl
|
||||
|
||||
@[simp]
|
||||
@[simp, grind]
|
||||
theorem pmap_eq_map (p : α → Prop) (f : α → β) (o : Option α) (H) :
|
||||
@pmap _ _ p (fun a _ => f a) o H = Option.map f o := by
|
||||
cases o <;> simp
|
||||
@@ -1307,7 +1305,7 @@ theorem pmap_guard {q : α → Bool} {p : α → Prop} (f : (x : α) → p x →
|
||||
simp only [guard_eq_ite]
|
||||
split <;> simp_all
|
||||
|
||||
@[simp, grind =]
|
||||
@[simp]
|
||||
theorem get_pmap {p : α → Bool} {f : (x : α) → p x → β} {o : Option α}
|
||||
{h : ∀ a, o = some a → p a} {h'} :
|
||||
(o.pmap f h).get h' = f (o.get (by simpa using h')) (h _ (by simp)) := by
|
||||
@@ -1318,7 +1316,7 @@ theorem get_pmap {p : α → Bool} {f : (x : α) → p x → β} {o : Option α}
|
||||
@[simp, grind] theorem pelim_none : pelim none b f = b := rfl
|
||||
@[simp, grind] theorem pelim_some : pelim (some a) b f = f a rfl := rfl
|
||||
|
||||
@[simp] theorem pelim_eq_elim : pelim o b (fun a _ => f a) = o.elim b f := by
|
||||
@[simp, grind] theorem pelim_eq_elim : pelim o b (fun a _ => f a) = o.elim b f := by
|
||||
cases o <;> simp
|
||||
|
||||
@[simp, grind] theorem elim_pmap {p : α → Prop} (f : (a : α) → p a → β) (o : Option α)
|
||||
@@ -1331,7 +1329,7 @@ theorem pelim_congr_left {o o' : Option α } {b : β} {f : (a : α) → (a ∈ o
|
||||
pelim o b f = pelim o' b (fun a ha => f a (h ▸ ha)) := by
|
||||
cases h; rfl
|
||||
|
||||
@[grind =] theorem pelim_filter {o : Option α} {b : β} {f : (a : α) → a ∈ o.filter p → β} :
|
||||
theorem pelim_filter {o : Option α} {b : β} {f : (a : α) → a ∈ o.filter p → β} :
|
||||
Option.pelim (Option.filter p o) b f =
|
||||
Option.pelim o b (fun a h => if hp : p a then f a (Option.mem_filter_iff.2 ⟨h, hp⟩) else b) :=
|
||||
match o with
|
||||
@@ -1341,7 +1339,7 @@ theorem pelim_congr_left {o o' : Option α } {b : β} {f : (a : α) → (a ∈ o
|
||||
| false => by simp [pelim_congr_left (filter_some_neg h), h]
|
||||
| true => by simp [pelim_congr_left (filter_some_pos h), h]
|
||||
|
||||
@[grind =] theorem pelim_join {o : Option (Option α)} {b : β} {f : (a : α) → a ∈ o.join → β} :
|
||||
theorem pelim_join {o : Option (Option α)} {b : β} {f : (a : α) → a ∈ o.join → β} :
|
||||
o.join.pelim b f = o.pelim b (fun o' ho' => o'.pelim b (fun a ha => f a (by simp_all))) := by
|
||||
cases o <;> simp <;> congr
|
||||
|
||||
@@ -1419,7 +1417,7 @@ theorem eq_some_of_pfilter_eq_some {o : Option α} {p : (a : α) → o = some a
|
||||
{a : α} (h : o.pfilter p = some a) : o = some a :=
|
||||
pfilter_eq_some_iff.1 h |>.1
|
||||
|
||||
@[grind =] theorem filter_pbind {f : (a : α) → o = some a → Option β} :
|
||||
theorem filter_pbind {f : (a : α) → o = some a → Option β} :
|
||||
(Option.pbind o f).filter p =
|
||||
(o.pfilter (fun a h => (f a h).any p)).pbind (fun a h => f a (eq_some_of_pfilter_eq_some h)) := by
|
||||
cases o with
|
||||
@@ -1431,7 +1429,7 @@ theorem eq_some_of_pfilter_eq_some {o : Option α} {p : (a : α) → o = some a
|
||||
· simp only [h, filter_some, any_some]
|
||||
split <;> simp [h]
|
||||
|
||||
@[simp] theorem pfilter_eq_filter {α : Type _} {o : Option α} {p : α → Bool} :
|
||||
@[simp, grind] theorem pfilter_eq_filter {α : Type _} {o : Option α} {p : α → Bool} :
|
||||
o.pfilter (fun a _ => p a) = o.filter p := by
|
||||
cases o with
|
||||
| none => rfl
|
||||
@@ -1470,7 +1468,7 @@ theorem pfilter_eq_pbind_ite {α : Type _} {o : Option α}
|
||||
· rfl
|
||||
· simp only [Option.pfilter, Bool.cond_eq_ite, Option.pbind_some]
|
||||
|
||||
@[grind =] theorem filter_pmap {p : α → Prop} {f : (a : α) → p a → β} {h : ∀ (a : α), o = some a → p a}
|
||||
theorem filter_pmap {p : α → Prop} {f : (a : α) → p a → β} {h : ∀ (a : α), o = some a → p a}
|
||||
{q : β → Bool} : (o.pmap f h).filter q = (o.pfilter (fun a h' => q (f a (h _ h')))).pmap f
|
||||
(fun _ h' => h _ (eq_some_of_pfilter_eq_some h')) := by
|
||||
cases o with
|
||||
@@ -1479,7 +1477,7 @@ theorem pfilter_eq_pbind_ite {α : Type _} {o : Option α}
|
||||
simp only [pmap_some, filter_some, pfilter_some]
|
||||
split <;> simp
|
||||
|
||||
@[grind =] theorem pfilter_join {o : Option (Option α)} {p : (a : α) → o.join = some a → Bool} :
|
||||
theorem pfilter_join {o : Option (Option α)} {p : (a : α) → o.join = some a → Bool} :
|
||||
o.join.pfilter p = (o.pfilter (fun o' h => o'.pelim false (fun a ha => p a (by simp_all)))).join := by
|
||||
cases o with
|
||||
| none => simp
|
||||
@@ -1490,11 +1488,11 @@ theorem pfilter_eq_pbind_ite {α : Type _} {o : Option α}
|
||||
simp only [join_some, pfilter_some, pelim_some]
|
||||
split <;> simp
|
||||
|
||||
@[grind =] theorem join_pfilter {o : Option (Option α)} {p : (o' : Option α) → o = some o' → Bool} :
|
||||
theorem join_pfilter {o : Option (Option α)} {p : (o' : Option α) → o = some o' → Bool} :
|
||||
(o.pfilter p).join = o.pbind (fun o' ho' => if p o' ho' then o' else none) := by
|
||||
cases o <;> simp <;> split <;> simp
|
||||
|
||||
@[grind =] theorem elim_pfilter {o : Option α} {b : β} {f : α → β} {p : (a : α) → o = some a → Bool} :
|
||||
theorem elim_pfilter {o : Option α} {b : β} {f : α → β} {p : (a : α) → o = some a → Bool} :
|
||||
(o.pfilter p).elim b f = o.pelim b (fun a ha => if p a ha then f a else b) := by
|
||||
cases o with
|
||||
| none => simp
|
||||
@@ -1502,7 +1500,7 @@ theorem pfilter_eq_pbind_ite {α : Type _} {o : Option α}
|
||||
simp only [pfilter_some, pelim_some]
|
||||
split <;> simp
|
||||
|
||||
@[grind =] theorem pelim_pfilter {o : Option α} {b : β} {p : (a : α) → o = some a → Bool}
|
||||
theorem pelim_pfilter {o : Option α} {b : β} {p : (a : α) → o = some a → Bool}
|
||||
{f : (a : α) → o.pfilter p = some a → β} :
|
||||
(o.pfilter p).pelim b f = o.pelim b
|
||||
(fun a ha => if hp : p a ha then f a (pfilter_eq_some_iff.2 ⟨_, hp⟩) else b) := by
|
||||
@@ -1520,13 +1518,13 @@ theorem pfilter_guard {a : α} {p : α → Bool} {q : (a' : α) → guard p a =
|
||||
/-! ### LT and LE -/
|
||||
|
||||
@[simp, grind] theorem not_lt_none [LT α] {a : Option α} : ¬ a < none := by cases a <;> simp [LT.lt, Option.lt]
|
||||
@[grind] theorem none_lt_some [LT α] {a : α} : none < some a := by simp [LT.lt, Option.lt]
|
||||
@[simp] theorem none_lt [LT α] {a : Option α} : none < a ↔ a.isSome := by cases a <;> simp [none_lt_some]
|
||||
@[simp, grind] theorem none_lt_some [LT α] {a : α} : none < some a := by simp [LT.lt, Option.lt]
|
||||
@[simp] theorem none_lt [LT α] {a : Option α} : none < a ↔ a.isSome := by cases a <;> simp
|
||||
@[simp, grind] theorem some_lt_some [LT α] {a b : α} : some a < some b ↔ a < b := by simp [LT.lt, Option.lt]
|
||||
|
||||
@[simp, grind] theorem none_le [LE α] {a : Option α} : none ≤ a := by cases a <;> simp [LE.le, Option.le]
|
||||
@[grind] theorem not_some_le_none [LE α] {a : α} : ¬ some a ≤ none := by simp [LE.le, Option.le]
|
||||
@[simp] theorem le_none [LE α] {a : Option α} : a ≤ none ↔ a = none := by cases a <;> simp [not_some_le_none]
|
||||
@[simp, grind] theorem not_some_le_none [LE α] {a : α} : ¬ some a ≤ none := by simp [LE.le, Option.le]
|
||||
@[simp] theorem le_none [LE α] {a : Option α} : a ≤ none ↔ a = none := by cases a <;> simp
|
||||
@[simp, grind] theorem some_le_some [LE α] {a b : α} : some a ≤ some b ↔ a ≤ b := by simp [LE.le, Option.le]
|
||||
|
||||
@[simp]
|
||||
@@ -1791,19 +1789,19 @@ theorem min_pfilter_right [Min α] [Std.IdempotentOp (α := α) min] {o : Option
|
||||
simp only [pfilter_some]
|
||||
split <;> simp [Std.IdempotentOp.idempotent]
|
||||
|
||||
@[simp, grind =]
|
||||
@[simp]
|
||||
theorem isSome_max [Max α] {o o' : Option α} : (max o o').isSome = (o.isSome || o'.isSome) := by
|
||||
cases o <;> cases o' <;> simp
|
||||
|
||||
@[simp, grind =]
|
||||
@[simp]
|
||||
theorem isNone_max [Max α] {o o' : Option α} : (max o o').isNone = (o.isNone && o'.isNone) := by
|
||||
cases o <;> cases o' <;> simp
|
||||
|
||||
@[simp, grind =]
|
||||
@[simp]
|
||||
theorem isSome_min [Min α] {o o' : Option α} : (min o o').isSome = (o.isSome && o'.isSome) := by
|
||||
cases o <;> cases o' <;> simp
|
||||
|
||||
@[simp, grind =]
|
||||
@[simp]
|
||||
theorem isNone_min [Min α] {o o' : Option α} : (min o o').isNone = (o.isNone || o'.isNone) := by
|
||||
cases o <;> cases o' <;> simp
|
||||
|
||||
@@ -1815,7 +1813,7 @@ theorem max_join_right [Max α] {o : Option α} {o' : Option (Option α)} :
|
||||
max o o'.join = (max (some o) o').get (by simp) := by
|
||||
cases o' <;> simp
|
||||
|
||||
@[grind _=_] theorem join_max [Max α] {o o' : Option (Option α)} :
|
||||
theorem join_max [Max α] {o o' : Option (Option α)} :
|
||||
(max o o').join = max o.join o'.join := by
|
||||
cases o <;> cases o' <;> simp
|
||||
|
||||
@@ -1827,7 +1825,7 @@ theorem min_join_right [Min α] {o : Option α} {o' : Option (Option α)} :
|
||||
min o o'.join = (min (some o) o').join := by
|
||||
cases o' <;> simp
|
||||
|
||||
@[grind _=_] theorem join_min [Min α] {o o' : Option (Option α)} :
|
||||
theorem join_min [Min α] {o o' : Option (Option α)} :
|
||||
(min o o').join = min o.join o'.join := by
|
||||
cases o <;> cases o' <;> simp
|
||||
|
||||
@@ -1875,12 +1873,12 @@ theorem min_eq_none_iff [Min α] {o o' : Option α} :
|
||||
min o o' = none ↔ o = none ∨ o' = none := by
|
||||
cases o <;> cases o' <;> simp
|
||||
|
||||
@[simp, grind =]
|
||||
@[simp]
|
||||
theorem any_max [Max α] {o o' : Option α} {p : α → Bool} (hp : ∀ a b, p (max a b) = (p a || p b)) :
|
||||
(max o o').any p = (o.any p || o'.any p) := by
|
||||
cases o <;> cases o' <;> simp [hp]
|
||||
|
||||
@[simp, grind =]
|
||||
@[simp]
|
||||
theorem all_min [Min α] {o o' : Option α} {p : α → Bool} (hp : ∀ a b, p (min a b) = (p a || p b)) :
|
||||
(min o o').all p = (o.all p || o'.all p) := by
|
||||
cases o <;> cases o' <;> simp [hp]
|
||||
@@ -1891,7 +1889,7 @@ theorem isSome_left_of_isSome_min [Min α] {o o' : Option α} : (min o o').isSom
|
||||
theorem isSome_right_of_isSome_min [Min α] {o o' : Option α} : (min o o').isSome → o'.isSome := by
|
||||
cases o' <;> simp
|
||||
|
||||
@[simp, grind =]
|
||||
@[simp]
|
||||
theorem get_min [Min α] {o o' : Option α} {h} :
|
||||
(min o o').get h = min (o.get (isSome_left_of_isSome_min h)) (o'.get (isSome_right_of_isSome_min h)) := by
|
||||
cases o <;> cases o' <;> simp
|
||||
|
||||
@@ -73,8 +73,7 @@ theorem toList_min [Min α] {o o' : Option α} :
|
||||
theorem length_toList_le {o : Option α} : o.toList.length ≤ 1 := by
|
||||
cases o <;> simp
|
||||
|
||||
@[grind =]
|
||||
theorem length_toList {o : Option α} :
|
||||
theorem length_toList_eq_ite {o : Option α} :
|
||||
o.toList.length = if o.isSome then 1 else 0 := by
|
||||
cases o <;> simp
|
||||
|
||||
@@ -86,9 +85,10 @@ theorem toList_eq_nil_iff {o : Option α} : o.toList = [] ↔ o = none := by
|
||||
theorem toList_eq_singleton_iff {o : Option α} : o.toList = [a] ↔ o = some a := by
|
||||
cases o <;> simp
|
||||
|
||||
@[simp]
|
||||
theorem length_toList_eq_zero_iff {o : Option α} :
|
||||
o.toList.length = 0 ↔ o = none := by
|
||||
simp
|
||||
cases o <;> simp
|
||||
|
||||
@[simp]
|
||||
theorem length_toList_eq_one_iff {o : Option α} :
|
||||
|
||||
@@ -90,18 +90,11 @@ theorem forIn'_eq_pelim [Monad m] [LawfulMonad m]
|
||||
pure (f := m) (o.pelim b (fun a h => f a h b)) := by
|
||||
cases o <;> simp
|
||||
|
||||
@[simp] theorem idRun_forIn'_yield_eq_pelim
|
||||
(o : Option α) (f : (a : α) → a ∈ o → β → Id β) (b : β) :
|
||||
(forIn' o b (fun a m b => .yield <$> f a m b)).run =
|
||||
o.pelim b (fun a h => f a h b |>.run) :=
|
||||
forIn'_pure_yield_eq_pelim _ _ _
|
||||
|
||||
@[deprecated idRun_forIn'_yield_eq_pelim (since := "2025-05-21")]
|
||||
theorem forIn'_id_yield_eq_pelim
|
||||
@[simp] theorem forIn'_id_yield_eq_pelim
|
||||
(o : Option α) (f : (a : α) → a ∈ o → β → β) (b : β) :
|
||||
forIn' (m := Id) o b (fun a m b => .yield (f a m b)) =
|
||||
o.pelim b (fun a h => f a h b) :=
|
||||
forIn'_pure_yield_eq_pelim _ _ _
|
||||
o.pelim b (fun a h => f a h b) := by
|
||||
cases o <;> simp
|
||||
|
||||
@[simp, grind] theorem forIn'_map [Monad m] [LawfulMonad m]
|
||||
(o : Option α) (g : α → β) (f : (b : β) → b ∈ o.map g → γ → m (ForInStep γ)) :
|
||||
@@ -133,18 +126,11 @@ theorem forIn_eq_elim [Monad m] [LawfulMonad m]
|
||||
pure (f := m) (o.elim b (fun a => f a b)) := by
|
||||
cases o <;> simp
|
||||
|
||||
@[simp] theorem idRun_forIn_yield_eq_elim
|
||||
(o : Option α) (f : (a : α) → β → Id β) (b : β) :
|
||||
(forIn o b (fun a b => .yield <$> f a b)).run =
|
||||
o.elim b (fun a => f a b |>.run) :=
|
||||
forIn_pure_yield_eq_elim _ _ _
|
||||
|
||||
@[deprecated idRun_forIn_yield_eq_elim (since := "2025-05-21")]
|
||||
theorem forIn_id_yield_eq_elim
|
||||
@[simp] theorem forIn_id_yield_eq_elim
|
||||
(o : Option α) (f : (a : α) → β → β) (b : β) :
|
||||
forIn (m := Id) o b (fun a b => .yield (f a b)) =
|
||||
o.elim b (fun a => f a b) :=
|
||||
forIn_pure_yield_eq_elim _ _ _
|
||||
o.elim b (fun a => f a b) := by
|
||||
cases o <;> simp
|
||||
|
||||
@[simp, grind] theorem forIn_map [Monad m] [LawfulMonad m]
|
||||
(o : Option α) (g : α → β) (f : β → γ → m (ForInStep γ)) :
|
||||
@@ -156,26 +142,26 @@ theorem forIn_join [Monad m] [LawfulMonad m]
|
||||
forIn o.join init f = forIn o init (fun o' b => ForInStep.yield <$> forIn o' b f) := by
|
||||
cases o <;> simp
|
||||
|
||||
@[simp, grind =] theorem elimM_pure [Monad m] [LawfulMonad m] (x : Option α) (y : m β) (z : α → m β) :
|
||||
@[simp] theorem elimM_pure [Monad m] [LawfulMonad m] (x : Option α) (y : m β) (z : α → m β) :
|
||||
Option.elimM (pure x : m (Option α)) y z = x.elim y z := by
|
||||
simp [Option.elimM]
|
||||
|
||||
@[simp, grind =] theorem elimM_bind [Monad m] [LawfulMonad m] (x : m α) (f : α → m (Option β))
|
||||
@[simp] theorem elimM_bind [Monad m] [LawfulMonad m] (x : m α) (f : α → m (Option β))
|
||||
(y : m γ) (z : β → m γ) : Option.elimM (x >>= f) y z = (do Option.elimM (f (← x)) y z) := by
|
||||
simp [Option.elimM]
|
||||
|
||||
@[simp, grind =] theorem elimM_map [Monad m] [LawfulMonad m] (x : m α) (f : α → Option β)
|
||||
@[simp] theorem elimM_map [Monad m] [LawfulMonad m] (x : m α) (f : α → Option β)
|
||||
(y : m γ) (z : β → m γ) : Option.elimM (f <$> x) y z = (do Option.elim (f (← x)) y z) := by
|
||||
simp [Option.elimM]
|
||||
|
||||
@[simp, grind =] theorem tryCatch_eq_or (o : Option α) (alternative : Unit → Option α) :
|
||||
@[simp] theorem tryCatch_eq_or (o : Option α) (alternative : Unit → Option α) :
|
||||
tryCatch o alternative = o.or (alternative ()) := by cases o <;> rfl
|
||||
|
||||
@[simp, grind =] theorem throw_eq_none : throw () = (none : Option α) := rfl
|
||||
@[simp] theorem throw_eq_none : throw () = (none : Option α) := rfl
|
||||
|
||||
@[simp, grind =] theorem filterM_none [Applicative m] (p : α → m Bool) :
|
||||
@[simp, grind] theorem filterM_none [Applicative m] (p : α → m Bool) :
|
||||
none.filterM p = pure none := rfl
|
||||
@[grind =] theorem filterM_some [Applicative m] (p : α → m Bool) (a : α) :
|
||||
theorem filterM_some [Applicative m] (p : α → m Bool) (a : α) :
|
||||
(some a).filterM p = (fun b => if b then some a else none) <$> p a := rfl
|
||||
|
||||
theorem sequence_join [Applicative m] [LawfulApplicative m] {o : Option (Option (m α))} :
|
||||
|
||||
@@ -3,6 +3,7 @@ Copyright (c) 2021 Microsoft Corporation. All rights reserved.
|
||||
Released under Apache 2.0 license as described in the file LICENSE.
|
||||
Authors: Dany Fabian, Sebastian Ullrich
|
||||
-/
|
||||
|
||||
module
|
||||
|
||||
prelude
|
||||
@@ -20,13 +21,13 @@ The relationship between the compared items may be:
|
||||
* `Ordering.gt`: greater than
|
||||
-/
|
||||
inductive Ordering where
|
||||
/-- Less than. -/
|
||||
| lt
|
||||
/-- Equal. -/
|
||||
| eq
|
||||
/-- Greater than. -/
|
||||
| gt
|
||||
deriving Inhabited, DecidableEq, Repr
|
||||
| /-- Less than. -/
|
||||
lt
|
||||
| /-- Equal. -/
|
||||
eq
|
||||
| /-- Greater than. -/
|
||||
gt
|
||||
deriving Inhabited, DecidableEq
|
||||
|
||||
namespace Ordering
|
||||
|
||||
@@ -38,7 +39,6 @@ Examples:
|
||||
* `Ordering.eq.swap = Ordering.eq`
|
||||
* `Ordering.gt.swap = Ordering.lt`
|
||||
-/
|
||||
@[inline, expose]
|
||||
def swap : Ordering → Ordering
|
||||
| .lt => .gt
|
||||
| .eq => .eq
|
||||
@@ -96,7 +96,6 @@ Ordering.lt
|
||||
/--
|
||||
Checks whether the ordering is `eq`.
|
||||
-/
|
||||
@[inline, expose]
|
||||
def isEq : Ordering → Bool
|
||||
| eq => true
|
||||
| _ => false
|
||||
@@ -104,7 +103,6 @@ def isEq : Ordering → Bool
|
||||
/--
|
||||
Checks whether the ordering is not `eq`.
|
||||
-/
|
||||
@[inline, expose]
|
||||
def isNe : Ordering → Bool
|
||||
| eq => false
|
||||
| _ => true
|
||||
@@ -112,7 +110,6 @@ def isNe : Ordering → Bool
|
||||
/--
|
||||
Checks whether the ordering is `lt` or `eq`.
|
||||
-/
|
||||
@[inline, expose]
|
||||
def isLE : Ordering → Bool
|
||||
| gt => false
|
||||
| _ => true
|
||||
@@ -120,7 +117,6 @@ def isLE : Ordering → Bool
|
||||
/--
|
||||
Checks whether the ordering is `lt`.
|
||||
-/
|
||||
@[inline, expose]
|
||||
def isLT : Ordering → Bool
|
||||
| lt => true
|
||||
| _ => false
|
||||
@@ -128,7 +124,6 @@ def isLT : Ordering → Bool
|
||||
/--
|
||||
Checks whether the ordering is `gt`.
|
||||
-/
|
||||
@[inline, expose]
|
||||
def isGT : Ordering → Bool
|
||||
| gt => true
|
||||
| _ => false
|
||||
@@ -136,158 +131,203 @@ def isGT : Ordering → Bool
|
||||
/--
|
||||
Checks whether the ordering is `gt` or `eq`.
|
||||
-/
|
||||
@[inline, expose]
|
||||
def isGE : Ordering → Bool
|
||||
| lt => false
|
||||
| _ => true
|
||||
|
||||
section Lemmas
|
||||
|
||||
protected theorem «forall» {p : Ordering → Prop} : (∀ o, p o) ↔ p .lt ∧ p .eq ∧ p .gt := by
|
||||
constructor
|
||||
· intro h
|
||||
exact ⟨h _, h _, h _⟩
|
||||
· rintro ⟨h₁, h₂, h₃⟩ (_ | _ | _) <;> assumption
|
||||
@[simp]
|
||||
theorem isLT_lt : lt.isLT := rfl
|
||||
|
||||
protected theorem «exists» {p : Ordering → Prop} : (∃ o, p o) ↔ p .lt ∨ p .eq ∨ p .gt := by
|
||||
constructor
|
||||
· rintro ⟨(_ | _ | _), h⟩
|
||||
· exact .inl h
|
||||
· exact .inr (.inl h)
|
||||
· exact .inr (.inr h)
|
||||
· rintro (h | h | h) <;> exact ⟨_, h⟩
|
||||
@[simp]
|
||||
theorem isLE_lt : lt.isLE := rfl
|
||||
|
||||
instance [DecidablePred p] : Decidable (∀ o : Ordering, p o) :=
|
||||
decidable_of_decidable_of_iff Ordering.«forall».symm
|
||||
@[simp]
|
||||
theorem isEq_lt : lt.isEq = false := rfl
|
||||
|
||||
instance [DecidablePred p] : Decidable (∃ o : Ordering, p o) :=
|
||||
decidable_of_decidable_of_iff Ordering.«exists».symm
|
||||
@[simp]
|
||||
theorem isNe_lt : lt.isNe = true := rfl
|
||||
|
||||
@[simp] theorem isLT_lt : lt.isLT := rfl
|
||||
@[simp] theorem isLE_lt : lt.isLE := rfl
|
||||
@[simp] theorem isEq_lt : lt.isEq = false := rfl
|
||||
@[simp] theorem isNe_lt : lt.isNe = true := rfl
|
||||
@[simp] theorem isGE_lt : lt.isGE = false := rfl
|
||||
@[simp] theorem isGT_lt : lt.isGT = false := rfl
|
||||
@[simp]
|
||||
theorem isGE_lt : lt.isGE = false := rfl
|
||||
|
||||
@[simp] theorem isLT_eq : eq.isLT = false := rfl
|
||||
@[simp] theorem isLE_eq : eq.isLE := rfl
|
||||
@[simp] theorem isEq_eq : eq.isEq := rfl
|
||||
@[simp] theorem isNe_eq : eq.isNe = false := rfl
|
||||
@[simp] theorem isGE_eq : eq.isGE := rfl
|
||||
@[simp] theorem isGT_eq : eq.isGT = false := rfl
|
||||
@[simp]
|
||||
theorem isGT_lt : lt.isGT = false := rfl
|
||||
|
||||
@[simp] theorem isLT_gt : gt.isLT = false := rfl
|
||||
@[simp] theorem isLE_gt : gt.isLE = false := rfl
|
||||
@[simp] theorem isEq_gt : gt.isEq = false := rfl
|
||||
@[simp] theorem isNe_gt : gt.isNe = true := rfl
|
||||
@[simp] theorem isGE_gt : gt.isGE := rfl
|
||||
@[simp] theorem isGT_gt : gt.isGT := rfl
|
||||
@[simp]
|
||||
theorem isLT_eq : eq.isLT = false := rfl
|
||||
|
||||
@[simp] theorem lt_beq_eq : (lt == eq) = false := rfl
|
||||
@[simp] theorem lt_beq_gt : (lt == gt) = false := rfl
|
||||
@[simp] theorem eq_beq_lt : (eq == lt) = false := rfl
|
||||
@[simp] theorem eq_beq_gt : (eq == gt) = false := rfl
|
||||
@[simp] theorem gt_beq_lt : (gt == lt) = false := rfl
|
||||
@[simp] theorem gt_beq_eq : (gt == eq) = false := rfl
|
||||
@[simp]
|
||||
theorem isLE_eq : eq.isLE := rfl
|
||||
|
||||
@[simp] theorem swap_lt : lt.swap = .gt := rfl
|
||||
@[simp] theorem swap_eq : eq.swap = .eq := rfl
|
||||
@[simp] theorem swap_gt : gt.swap = .lt := rfl
|
||||
@[simp]
|
||||
theorem isEq_eq : eq.isEq := rfl
|
||||
|
||||
theorem eq_eq_of_isLE_of_isLE_swap : ∀ {o : Ordering}, o.isLE → o.swap.isLE → o = .eq := by decide
|
||||
theorem eq_eq_of_isGE_of_isGE_swap : ∀ {o : Ordering}, o.isGE → o.swap.isGE → o = .eq := by decide
|
||||
theorem eq_eq_of_isLE_of_isGE : ∀ {o : Ordering}, o.isLE → o.isGE → o = .eq := by decide
|
||||
theorem eq_swap_iff_eq_eq : ∀ {o : Ordering}, o = o.swap ↔ o = .eq := by decide
|
||||
theorem eq_eq_of_eq_swap : ∀ {o : Ordering}, o = o.swap → o = .eq := eq_swap_iff_eq_eq.mp
|
||||
@[simp]
|
||||
theorem isNe_eq : eq.isNe = false := rfl
|
||||
|
||||
@[simp] theorem isLE_eq_false : ∀ {o : Ordering}, o.isLE = false ↔ o = .gt := by decide
|
||||
@[simp] theorem isGE_eq_false : ∀ {o : Ordering}, o.isGE = false ↔ o = .lt := by decide
|
||||
@[simp] theorem isNe_eq_false : ∀ {o : Ordering}, o.isNe = false ↔ o = .eq := by decide
|
||||
@[simp] theorem isEq_eq_false : ∀ {o : Ordering}, o.isEq = false ↔ ¬o = .eq := by decide
|
||||
@[simp]
|
||||
theorem isGE_eq : eq.isGE := rfl
|
||||
|
||||
@[simp] theorem swap_eq_gt : ∀ {o : Ordering}, o.swap = .gt ↔ o = .lt := by decide
|
||||
@[simp] theorem swap_eq_lt : ∀ {o : Ordering}, o.swap = .lt ↔ o = .gt := by decide
|
||||
@[simp] theorem swap_eq_eq : ∀ {o : Ordering}, o.swap = .eq ↔ o = .eq := by decide
|
||||
@[simp]
|
||||
theorem isGT_eq : eq.isGT = false := rfl
|
||||
|
||||
@[simp] theorem isLT_swap : ∀ {o : Ordering}, o.swap.isLT = o.isGT := by decide
|
||||
@[simp] theorem isLE_swap : ∀ {o : Ordering}, o.swap.isLE = o.isGE := by decide
|
||||
@[simp] theorem isEq_swap : ∀ {o : Ordering}, o.swap.isEq = o.isEq := by decide
|
||||
@[simp] theorem isNe_swap : ∀ {o : Ordering}, o.swap.isNe = o.isNe := by decide
|
||||
@[simp] theorem isGE_swap : ∀ {o : Ordering}, o.swap.isGE = o.isLE := by decide
|
||||
@[simp] theorem isGT_swap : ∀ {o : Ordering}, o.swap.isGT = o.isLT := by decide
|
||||
@[simp]
|
||||
theorem isLT_gt : gt.isLT = false := rfl
|
||||
|
||||
theorem isLE_of_eq_lt : ∀ {o : Ordering}, o = .lt → o.isLE := by decide
|
||||
theorem isLE_of_eq_eq : ∀ {o : Ordering}, o = .eq → o.isLE := by decide
|
||||
theorem isGE_of_eq_gt : ∀ {o : Ordering}, o = .gt → o.isGE := by decide
|
||||
theorem isGE_of_eq_eq : ∀ {o : Ordering}, o = .eq → o.isGE := by decide
|
||||
@[simp]
|
||||
theorem isLE_gt : gt.isLE = false := rfl
|
||||
|
||||
theorem ne_eq_of_eq_lt : ∀ {o : Ordering}, o = .lt → o ≠ .eq := by decide
|
||||
theorem ne_eq_of_eq_gt : ∀ {o : Ordering}, o = .gt → o ≠ .eq := by decide
|
||||
@[simp]
|
||||
theorem isEq_gt : gt.isEq = false := rfl
|
||||
|
||||
@[simp] theorem isLT_iff_eq_lt : ∀ {o : Ordering}, o.isLT ↔ o = .lt := by decide
|
||||
@[simp] theorem isGT_iff_eq_gt : ∀ {o : Ordering}, o.isGT ↔ o = .gt := by decide
|
||||
@[simp] theorem isEq_iff_eq_eq : ∀ {o : Ordering}, o.isEq ↔ o = .eq := by decide
|
||||
@[simp] theorem isNe_iff_ne_eq : ∀ {o : Ordering}, o.isNe ↔ ¬o = .eq := by decide
|
||||
@[simp]
|
||||
theorem isNe_gt : gt.isNe = true := rfl
|
||||
|
||||
theorem isLE_iff_ne_gt : ∀ {o : Ordering}, o.isLE ↔ ¬o = .gt := by decide
|
||||
theorem isGE_iff_ne_lt : ∀ {o : Ordering}, o.isGE ↔ ¬o = .lt := by decide
|
||||
theorem isLE_iff_eq_lt_or_eq_eq : ∀ {o : Ordering}, o.isLE ↔ o = .lt ∨ o = .eq := by decide
|
||||
theorem isGE_iff_eq_gt_or_eq_eq : ∀ {o : Ordering}, o.isGE ↔ o = .gt ∨ o = .eq := by decide
|
||||
@[simp]
|
||||
theorem isGE_gt : gt.isGE := rfl
|
||||
|
||||
theorem isLT_eq_beq_lt : ∀ {o : Ordering}, o.isLT = (o == .lt) := by decide
|
||||
theorem isLE_eq_not_beq_gt : ∀ {o : Ordering}, o.isLE = (!o == .gt) := by decide
|
||||
theorem isLE_eq_isLT_or_isEq : ∀ {o : Ordering}, o.isLE = (o.isLT || o.isEq) := by decide
|
||||
theorem isGT_eq_beq_gt : ∀ {o : Ordering}, o.isGT = (o == .gt) := by decide
|
||||
theorem isGE_eq_not_beq_lt : ∀ {o : Ordering}, o.isGE = (!o == .lt) := by decide
|
||||
theorem isGE_eq_isGT_or_isEq : ∀ {o : Ordering}, o.isGE = (o.isGT || o.isEq) := by decide
|
||||
theorem isEq_eq_beq_eq : ∀ {o : Ordering}, o.isEq = (o == .eq) := by decide
|
||||
theorem isNe_eq_not_beq_eq : ∀ {o : Ordering}, o.isNe = (!o == .eq) := by decide
|
||||
theorem isNe_eq_isLT_or_isGT : ∀ {o : Ordering}, o.isNe = (o.isLT || o.isGT) := by decide
|
||||
@[simp]
|
||||
theorem isGT_gt : gt.isGT := rfl
|
||||
|
||||
@[simp] theorem not_isLT_eq_isGE : ∀ {o : Ordering}, !o.isLT = o.isGE := by decide
|
||||
@[simp] theorem not_isLE_eq_isGT : ∀ {o : Ordering}, !o.isLE = o.isGT := by decide
|
||||
@[simp] theorem not_isGT_eq_isLE : ∀ {o : Ordering}, !o.isGT = o.isLE := by decide
|
||||
@[simp] theorem not_isGE_eq_isLT : ∀ {o : Ordering}, !o.isGE = o.isLT := by decide
|
||||
@[simp] theorem not_isNe_eq_isEq : ∀ {o : Ordering}, !o.isNe = o.isEq := by decide
|
||||
theorem not_isEq_eq_isNe : ∀ {o : Ordering}, !o.isEq = o.isNe := by decide
|
||||
@[simp]
|
||||
theorem swap_lt : lt.swap = .gt := rfl
|
||||
|
||||
theorem ne_lt_iff_isGE : ∀ {o : Ordering}, ¬o = .lt ↔ o.isGE := by decide
|
||||
theorem ne_gt_iff_isLE : ∀ {o : Ordering}, ¬o = .gt ↔ o.isLE := by decide
|
||||
@[simp]
|
||||
theorem swap_eq : eq.swap = .eq := rfl
|
||||
|
||||
@[simp] theorem swap_swap : ∀ {o : Ordering}, o.swap.swap = o := by decide
|
||||
@[simp] theorem swap_inj : ∀ {o₁ o₂ : Ordering}, o₁.swap = o₂.swap ↔ o₁ = o₂ := by decide
|
||||
@[simp]
|
||||
theorem swap_gt : gt.swap = .lt := rfl
|
||||
|
||||
theorem swap_then : ∀ (o₁ o₂ : Ordering), (o₁.then o₂).swap = o₁.swap.then o₂.swap := by decide
|
||||
theorem eq_eq_of_isLE_of_isLE_swap {o : Ordering} : o.isLE → o.swap.isLE → o = .eq := by
|
||||
cases o <;> simp
|
||||
|
||||
theorem then_eq_lt : ∀ {o₁ o₂ : Ordering}, o₁.then o₂ = lt ↔ o₁ = lt ∨ o₁ = eq ∧ o₂ = lt := by decide
|
||||
theorem then_eq_gt : ∀ {o₁ o₂ : Ordering}, o₁.then o₂ = gt ↔ o₁ = gt ∨ o₁ = eq ∧ o₂ = gt := by decide
|
||||
@[simp] theorem then_eq_eq : ∀ {o₁ o₂ : Ordering}, o₁.then o₂ = eq ↔ o₁ = eq ∧ o₂ = eq := by decide
|
||||
theorem eq_eq_of_isGE_of_isGE_swap {o : Ordering} : o.isGE → o.swap.isGE → o = .eq := by
|
||||
cases o <;> simp
|
||||
|
||||
theorem isLT_then : ∀ {o₁ o₂ : Ordering}, (o₁.then o₂).isLT = (o₁.isLT || o₁.isEq && o₂.isLT) := by decide
|
||||
theorem isEq_then : ∀ {o₁ o₂ : Ordering}, (o₁.then o₂).isEq = (o₁.isEq && o₂.isEq) := by decide
|
||||
theorem isNe_then : ∀ {o₁ o₂ : Ordering}, (o₁.then o₂).isNe = (o₁.isNe || o₂.isNe) := by decide
|
||||
theorem isGT_then : ∀ {o₁ o₂ : Ordering}, (o₁.then o₂).isGT = (o₁.isGT || o₁.isEq && o₂.isGT) := by decide
|
||||
theorem eq_eq_of_isLE_of_isGE {o : Ordering} : o.isLE → o.isGE → o = .eq := by
|
||||
cases o <;> simp
|
||||
|
||||
@[simp] theorem lt_then {o : Ordering} : lt.then o = lt := rfl
|
||||
@[simp] theorem gt_then {o : Ordering} : gt.then o = gt := rfl
|
||||
@[simp] theorem eq_then {o : Ordering} : eq.then o = o := rfl
|
||||
theorem eq_swap_iff_eq_eq {o : Ordering} : o = o.swap ↔ o = .eq := by
|
||||
cases o <;> simp
|
||||
|
||||
@[simp] theorem then_eq : ∀ {o : Ordering}, o.then eq = o := by decide
|
||||
@[simp] theorem then_self : ∀ {o : Ordering}, o.then o = o := by decide
|
||||
theorem then_assoc : ∀ (o₁ o₂ o₃ : Ordering), (o₁.then o₂).then o₃ = o₁.then (o₂.then o₃) := by decide
|
||||
theorem eq_eq_of_eq_swap {o : Ordering} : o = o.swap → o = .eq :=
|
||||
eq_swap_iff_eq_eq.mp
|
||||
|
||||
theorem isLE_then_iff_or : ∀ {o₁ o₂ : Ordering}, (o₁.then o₂).isLE ↔ o₁ = lt ∨ (o₁ = eq ∧ o₂.isLE) := by decide
|
||||
theorem isLE_then_iff_and : ∀ {o₁ o₂ : Ordering}, (o₁.then o₂).isLE ↔ o₁.isLE ∧ (o₁ = lt ∨ o₂.isLE) := by decide
|
||||
theorem isLE_left_of_isLE_then : ∀ {o₁ o₂ : Ordering}, (o₁.then o₂).isLE → o₁.isLE := by decide
|
||||
theorem isGE_left_of_isGE_then : ∀ {o₁ o₂ : Ordering}, (o₁.then o₂).isGE → o₁.isGE := by decide
|
||||
@[simp]
|
||||
theorem isLE_eq_false {o : Ordering} : o.isLE = false ↔ o = .gt := by
|
||||
cases o <;> simp
|
||||
|
||||
instance : Std.Associative Ordering.then := ⟨then_assoc⟩
|
||||
instance : Std.IdempotentOp Ordering.then := ⟨fun _ => then_self⟩
|
||||
@[simp]
|
||||
theorem isGE_eq_false {o : Ordering} : o.isGE = false ↔ o = .lt := by
|
||||
cases o <;> simp
|
||||
|
||||
instance : Std.LawfulIdentity Ordering.then eq where
|
||||
left_id _ := eq_then
|
||||
right_id _ := then_eq
|
||||
@[simp]
|
||||
theorem swap_eq_gt {o : Ordering} : o.swap = .gt ↔ o = .lt := by
|
||||
cases o <;> simp
|
||||
|
||||
@[simp]
|
||||
theorem swap_eq_lt {o : Ordering} : o.swap = .lt ↔ o = .gt := by
|
||||
cases o <;> simp
|
||||
|
||||
@[simp]
|
||||
theorem swap_eq_eq {o : Ordering} : o.swap = .eq ↔ o = .eq := by
|
||||
cases o <;> simp
|
||||
|
||||
@[simp]
|
||||
theorem isLT_swap {o : Ordering} : o.swap.isLT = o.isGT := by
|
||||
cases o <;> simp
|
||||
|
||||
@[simp]
|
||||
theorem isLE_swap {o : Ordering} : o.swap.isLE = o.isGE := by
|
||||
cases o <;> simp
|
||||
|
||||
@[simp]
|
||||
theorem isEq_swap {o : Ordering} : o.swap.isEq = o.isEq := by
|
||||
cases o <;> simp
|
||||
|
||||
@[simp]
|
||||
theorem isNe_swap {o : Ordering} : o.swap.isNe = o.isNe := by
|
||||
cases o <;> simp
|
||||
|
||||
@[simp]
|
||||
theorem isGE_swap {o : Ordering} : o.swap.isGE = o.isLE := by
|
||||
cases o <;> simp
|
||||
|
||||
@[simp]
|
||||
theorem isGT_swap {o : Ordering} : o.swap.isGT = o.isLT := by
|
||||
cases o <;> simp
|
||||
|
||||
theorem isLT_iff_eq_lt {o : Ordering} : o.isLT ↔ o = .lt := by
|
||||
cases o <;> simp
|
||||
|
||||
theorem isLE_iff_eq_lt_or_eq_eq {o : Ordering} : o.isLE ↔ o = .lt ∨ o = .eq := by
|
||||
cases o <;> simp
|
||||
|
||||
theorem isLE_of_eq_lt {o : Ordering} : o = .lt → o.isLE := by
|
||||
rintro rfl; rfl
|
||||
|
||||
theorem isLE_of_eq_eq {o : Ordering} : o = .eq → o.isLE := by
|
||||
rintro rfl; rfl
|
||||
|
||||
theorem isEq_iff_eq_eq {o : Ordering} : o.isEq ↔ o = .eq := by
|
||||
cases o <;> simp
|
||||
|
||||
theorem isNe_iff_ne_eq {o : Ordering} : o.isNe ↔ o ≠ .eq := by
|
||||
cases o <;> simp
|
||||
|
||||
theorem isGE_iff_eq_gt_or_eq_eq {o : Ordering} : o.isGE ↔ o = .gt ∨ o = .eq := by
|
||||
cases o <;> simp
|
||||
|
||||
theorem isGE_of_eq_gt {o : Ordering} : o = .gt → o.isGE := by
|
||||
rintro rfl; rfl
|
||||
|
||||
theorem isGE_of_eq_eq {o : Ordering} : o = .eq → o.isGE := by
|
||||
rintro rfl; rfl
|
||||
|
||||
theorem isGT_iff_eq_gt {o : Ordering} : o.isGT ↔ o = .gt := by
|
||||
cases o <;> simp
|
||||
|
||||
@[simp]
|
||||
theorem swap_swap {o : Ordering} : o.swap.swap = o := by
|
||||
cases o <;> simp
|
||||
|
||||
@[simp] theorem swap_inj {o₁ o₂ : Ordering} : o₁.swap = o₂.swap ↔ o₁ = o₂ :=
|
||||
⟨fun h => by simpa using congrArg swap h, congrArg _⟩
|
||||
|
||||
theorem swap_then (o₁ o₂ : Ordering) : (o₁.then o₂).swap = o₁.swap.then o₂.swap := by
|
||||
cases o₁ <;> rfl
|
||||
|
||||
theorem then_eq_lt {o₁ o₂ : Ordering} : o₁.then o₂ = lt ↔ o₁ = lt ∨ o₁ = eq ∧ o₂ = lt := by
|
||||
cases o₁ <;> cases o₂ <;> decide
|
||||
|
||||
theorem then_eq_eq {o₁ o₂ : Ordering} : o₁.then o₂ = eq ↔ o₁ = eq ∧ o₂ = eq := by
|
||||
cases o₁ <;> simp [«then»]
|
||||
|
||||
theorem then_eq_gt {o₁ o₂ : Ordering} : o₁.then o₂ = gt ↔ o₁ = gt ∨ o₁ = eq ∧ o₂ = gt := by
|
||||
cases o₁ <;> cases o₂ <;> decide
|
||||
|
||||
@[simp]
|
||||
theorem lt_then {o : Ordering} : lt.then o = lt := rfl
|
||||
|
||||
@[simp]
|
||||
theorem gt_then {o : Ordering} : gt.then o = gt := rfl
|
||||
|
||||
@[simp]
|
||||
theorem eq_then {o : Ordering} : eq.then o = o := rfl
|
||||
|
||||
theorem isLE_then_iff_or {o₁ o₂ : Ordering} : (o₁.then o₂).isLE ↔ o₁ = lt ∨ (o₁ = eq ∧ o₂.isLE) := by
|
||||
cases o₁ <;> simp
|
||||
|
||||
theorem isLE_then_iff_and {o₁ o₂ : Ordering} : (o₁.then o₂).isLE ↔ o₁.isLE ∧ (o₁ = lt ∨ o₂.isLE) := by
|
||||
cases o₁ <;> simp
|
||||
|
||||
theorem isLE_left_of_isLE_then {o₁ o₂ : Ordering} (h : (o₁.then o₂).isLE) : o₁.isLE := by
|
||||
cases o₁ <;> simp_all
|
||||
|
||||
theorem isGE_left_of_isGE_then {o₁ o₂ : Ordering} (h : (o₁.then o₂).isGE) : o₁.isGE := by
|
||||
cases o₁ <;> simp_all
|
||||
|
||||
end Lemmas
|
||||
|
||||
@@ -335,7 +375,7 @@ section Lemmas
|
||||
@[simp]
|
||||
theorem compareLex_eq_eq {α} {cmp₁ cmp₂} {a b : α} :
|
||||
compareLex cmp₁ cmp₂ a b = .eq ↔ cmp₁ a b = .eq ∧ cmp₂ a b = .eq := by
|
||||
simp [compareLex]
|
||||
simp [compareLex, Ordering.then_eq_eq]
|
||||
|
||||
theorem compareOfLessAndEq_eq_swap_of_lt_iff_not_gt_and_ne {α : Type u} [LT α] [DecidableLT α] [DecidableEq α]
|
||||
(h : ∀ x y : α, x < y ↔ ¬ y < x ∧ x ≠ y) {x y : α} :
|
||||
@@ -344,14 +384,14 @@ theorem compareOfLessAndEq_eq_swap_of_lt_iff_not_gt_and_ne {α : Type u} [LT α]
|
||||
split
|
||||
· rename_i h'
|
||||
rw [h] at h'
|
||||
simp only [h'.1, h'.2.symm, ↓reduceIte, Ordering.swap_gt]
|
||||
simp only [h'.1, h'.2.symm, reduceIte, Ordering.swap_gt]
|
||||
· split
|
||||
· rename_i h'
|
||||
have : ¬ y < y := Not.imp (·.2 rfl) <| (h y y).mp
|
||||
simp only [h', this, ↓reduceIte, Ordering.swap_eq]
|
||||
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', Ne.symm 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 α]
|
||||
@@ -438,13 +478,13 @@ but this is not enforced by the typeclass.
|
||||
There is a derive handler, so appending `deriving Ord` to an inductive type or structure
|
||||
will attempt to create an `Ord` instance.
|
||||
-/
|
||||
@[ext]
|
||||
class Ord (α : Type u) where
|
||||
/-- Compare two elements in `α` using the comparator contained in an `[Ord α]` instance. -/
|
||||
compare : α → α → Ordering
|
||||
|
||||
export Ord (compare)
|
||||
|
||||
set_option linter.unusedVariables false in -- allow specifying `ord` explicitly
|
||||
/--
|
||||
Compares two values by comparing the results of applying a function.
|
||||
|
||||
@@ -524,7 +564,7 @@ instance : Ord Ordering where
|
||||
|
||||
namespace List
|
||||
|
||||
@[specialize, expose]
|
||||
@[specialize]
|
||||
protected def compareLex {α} (cmp : α → α → Ordering) :
|
||||
List α → List α → Ordering
|
||||
| [], [] => .eq
|
||||
@@ -696,7 +736,6 @@ end Array
|
||||
|
||||
namespace Vector
|
||||
|
||||
@[expose]
|
||||
protected def compareLex {α n} (cmp : α → α → Ordering) (a b : Vector α n) : Ordering :=
|
||||
Array.compareLex cmp a.toArray b.toArray
|
||||
|
||||
@@ -725,13 +764,6 @@ end Vector
|
||||
def lexOrd [Ord α] [Ord β] : Ord (α × β) where
|
||||
compare := compareLex (compareOn (·.1)) (compareOn (·.2))
|
||||
|
||||
/--
|
||||
Constructs an `BEq` instance from an `Ord` instance that asserts that the result of `compare` is
|
||||
`Ordering.eq`.
|
||||
-/
|
||||
@[expose] def beqOfOrd [Ord α] : BEq α where
|
||||
beq a b := (compare a b).isEq
|
||||
|
||||
/--
|
||||
Constructs an `LT` instance from an `Ord` instance that asserts that the result of `compare` is
|
||||
`Ordering.lt`.
|
||||
@@ -739,9 +771,8 @@ Constructs an `LT` instance from an `Ord` instance that asserts that the result
|
||||
@[expose] def ltOfOrd [Ord α] : LT α where
|
||||
lt a b := compare a b = Ordering.lt
|
||||
|
||||
@[inline]
|
||||
instance [Ord α] : DecidableRel (@LT.lt α ltOfOrd) := fun a b =>
|
||||
decidable_of_bool (compare a b).isLT Ordering.isLT_iff_eq_lt
|
||||
instance [Ord α] : DecidableRel (@LT.lt α ltOfOrd) :=
|
||||
inferInstanceAs (DecidableRel (fun a b => compare a b = Ordering.lt))
|
||||
|
||||
/--
|
||||
Constructs an `LT` instance from an `Ord` instance that asserts that the result of `compare`
|
||||
@@ -750,29 +781,35 @@ satisfies `Ordering.isLE`.
|
||||
@[expose] def leOfOrd [Ord α] : LE α where
|
||||
le a b := (compare a b).isLE
|
||||
|
||||
@[inline]
|
||||
instance [Ord α] : DecidableRel (@LE.le α leOfOrd) := fun _ _ => instDecidableEqBool ..
|
||||
instance [Ord α] : DecidableRel (@LE.le α leOfOrd) :=
|
||||
inferInstanceAs (DecidableRel (fun a b => (compare a b).isLE))
|
||||
|
||||
namespace Ord
|
||||
|
||||
/--
|
||||
Constructs a `BEq` instance from an `Ord` instance.
|
||||
-/
|
||||
@[expose] protected abbrev toBEq (ord : Ord α) : BEq α :=
|
||||
beqOfOrd
|
||||
protected def toBEq (ord : Ord α) : BEq α where
|
||||
beq x y := ord.compare x y == .eq
|
||||
|
||||
/--
|
||||
Constructs an `LT` instance from an `Ord` instance.
|
||||
-/
|
||||
@[expose] protected abbrev toLT (ord : Ord α) : LT α :=
|
||||
@[expose] protected def toLT (ord : Ord α) : LT α :=
|
||||
ltOfOrd
|
||||
|
||||
instance [i : Ord α] : DecidableRel (@LT.lt _ (Ord.toLT i)) :=
|
||||
inferInstanceAs (DecidableRel (fun a b => compare a b = Ordering.lt))
|
||||
|
||||
/--
|
||||
Constructs an `LE` instance from an `Ord` instance.
|
||||
-/
|
||||
@[expose] protected abbrev toLE (ord : Ord α) : LE α :=
|
||||
@[expose] protected def toLE (ord : Ord α) : LE α :=
|
||||
leOfOrd
|
||||
|
||||
instance [i : Ord α] : DecidableRel (@LE.le _ (Ord.toLE i)) :=
|
||||
inferInstanceAs (DecidableRel (fun a b => (compare a b).isLE))
|
||||
|
||||
/--
|
||||
Inverts the order of an `Ord` instance.
|
||||
|
||||
@@ -796,7 +833,7 @@ protected def on (_ : Ord β) (f : α → β) : Ord α where
|
||||
/--
|
||||
Constructs the lexicographic order on products `α × β` from orders for `α` and `β`.
|
||||
-/
|
||||
protected abbrev lex (_ : Ord α) (_ : Ord β) : Ord (α × β) :=
|
||||
protected def lex (_ : Ord α) (_ : Ord β) : Ord (α × β) :=
|
||||
lexOrd
|
||||
|
||||
/--
|
||||
|
||||
@@ -54,7 +54,7 @@ Examples:
|
||||
* `(1, 2).swap = (2, 1)`
|
||||
* `("orange", -87).swap = (-87, "orange")`
|
||||
-/
|
||||
@[expose] def swap : α × β → β × α := fun p => (p.2, p.1)
|
||||
def swap : α × β → β × α := fun p => (p.2, p.1)
|
||||
|
||||
@[simp]
|
||||
theorem swap_swap : ∀ x : α × β, swap (swap x) = x
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace Range
|
||||
universe u v
|
||||
|
||||
/-- The number of elements in the range. -/
|
||||
@[simp, expose] def size (r : Range) : Nat := (r.stop - r.start + r.step - 1) / r.step
|
||||
@[simp] def size (r : Range) : Nat := (r.stop - r.start + r.step - 1) / r.step
|
||||
|
||||
@[inline] protected def forIn' [Monad m] (range : Range) (init : β)
|
||||
(f : (i : Nat) → i ∈ range → β → m (ForInStep β)) : m β :=
|
||||
|
||||
@@ -18,13 +18,13 @@ macro "declare_bitwise_int_theorems" typeName:ident bits:term:arg : command =>
|
||||
`(
|
||||
namespace $typeName
|
||||
|
||||
@[simp, int_toBitVec] protected theorem toBitVec_not {a : $typeName} : (~~~a).toBitVec = ~~~a.toBitVec := (rfl)
|
||||
@[simp, int_toBitVec] protected theorem toBitVec_and (a b : $typeName) : (a &&& b).toBitVec = a.toBitVec &&& b.toBitVec := (rfl)
|
||||
@[simp, int_toBitVec] protected theorem toBitVec_or (a b : $typeName) : (a ||| b).toBitVec = a.toBitVec ||| b.toBitVec := (rfl)
|
||||
@[simp, int_toBitVec] protected theorem toBitVec_xor (a b : $typeName) : (a ^^^ b).toBitVec = a.toBitVec ^^^ b.toBitVec := (rfl)
|
||||
@[simp, int_toBitVec] protected theorem toBitVec_shiftLeft (a b : $typeName) : (a <<< b).toBitVec = a.toBitVec <<< (b.toBitVec.smod $bits) := (rfl)
|
||||
@[simp, int_toBitVec] protected theorem toBitVec_shiftRight (a b : $typeName) : (a >>> b).toBitVec = a.toBitVec.sshiftRight' (b.toBitVec.smod $bits) := (rfl)
|
||||
@[simp, int_toBitVec] protected theorem toBitVec_abs (a : $typeName) : a.abs.toBitVec = a.toBitVec.abs := (rfl)
|
||||
@[simp, int_toBitVec] protected theorem toBitVec_not {a : $typeName} : (~~~a).toBitVec = ~~~a.toBitVec := rfl
|
||||
@[simp, int_toBitVec] protected theorem toBitVec_and (a b : $typeName) : (a &&& b).toBitVec = a.toBitVec &&& b.toBitVec := rfl
|
||||
@[simp, int_toBitVec] protected theorem toBitVec_or (a b : $typeName) : (a ||| b).toBitVec = a.toBitVec ||| b.toBitVec := rfl
|
||||
@[simp, int_toBitVec] protected theorem toBitVec_xor (a b : $typeName) : (a ^^^ b).toBitVec = a.toBitVec ^^^ b.toBitVec := rfl
|
||||
@[simp, int_toBitVec] protected theorem toBitVec_shiftLeft (a b : $typeName) : (a <<< b).toBitVec = a.toBitVec <<< (b.toBitVec.smod $bits) := rfl
|
||||
@[simp, int_toBitVec] protected theorem toBitVec_shiftRight (a b : $typeName) : (a >>> b).toBitVec = a.toBitVec.sshiftRight' (b.toBitVec.smod $bits) := rfl
|
||||
@[simp, int_toBitVec] protected theorem toBitVec_abs (a : $typeName) : a.abs.toBitVec = a.toBitVec.abs := rfl
|
||||
|
||||
end $typeName
|
||||
)
|
||||
@@ -58,53 +58,53 @@ theorem Bool.toBitVec_toISize {b : Bool} :
|
||||
· apply BitVec.eq_of_toNat_eq
|
||||
simp [toISize]
|
||||
|
||||
@[simp] theorem UInt8.toInt8_and (a b : UInt8) : (a &&& b).toInt8 = a.toInt8 &&& b.toInt8 := (rfl)
|
||||
@[simp] theorem UInt16.toInt16_and (a b : UInt16) : (a &&& b).toInt16 = a.toInt16 &&& b.toInt16 := (rfl)
|
||||
@[simp] theorem UInt32.toInt32_and (a b : UInt32) : (a &&& b).toInt32 = a.toInt32 &&& b.toInt32 := (rfl)
|
||||
@[simp] theorem UInt64.toInt64_and (a b : UInt64) : (a &&& b).toInt64 = a.toInt64 &&& b.toInt64 := (rfl)
|
||||
@[simp] theorem USize.toISize_and (a b : USize) : (a &&& b).toISize = a.toISize &&& b.toISize := (rfl)
|
||||
@[simp] theorem UInt8.toInt8_and (a b : UInt8) : (a &&& b).toInt8 = a.toInt8 &&& b.toInt8 := rfl
|
||||
@[simp] theorem UInt16.toInt16_and (a b : UInt16) : (a &&& b).toInt16 = a.toInt16 &&& b.toInt16 := rfl
|
||||
@[simp] theorem UInt32.toInt32_and (a b : UInt32) : (a &&& b).toInt32 = a.toInt32 &&& b.toInt32 := rfl
|
||||
@[simp] theorem UInt64.toInt64_and (a b : UInt64) : (a &&& b).toInt64 = a.toInt64 &&& b.toInt64 := rfl
|
||||
@[simp] theorem USize.toISize_and (a b : USize) : (a &&& b).toISize = a.toISize &&& b.toISize := rfl
|
||||
|
||||
@[simp] theorem UInt8.toInt8_or (a b : UInt8) : (a ||| b).toInt8 = a.toInt8 ||| b.toInt8 := (rfl)
|
||||
@[simp] theorem UInt16.toInt16_or (a b : UInt16) : (a ||| b).toInt16 = a.toInt16 ||| b.toInt16 := (rfl)
|
||||
@[simp] theorem UInt32.toInt32_or (a b : UInt32) : (a ||| b).toInt32 = a.toInt32 ||| b.toInt32 := (rfl)
|
||||
@[simp] theorem UInt64.toInt64_or (a b : UInt64) : (a ||| b).toInt64 = a.toInt64 ||| b.toInt64 := (rfl)
|
||||
@[simp] theorem USize.toISize_or (a b : USize) : (a ||| b).toISize = a.toISize ||| b.toISize := (rfl)
|
||||
@[simp] theorem UInt8.toInt8_or (a b : UInt8) : (a ||| b).toInt8 = a.toInt8 ||| b.toInt8 := rfl
|
||||
@[simp] theorem UInt16.toInt16_or (a b : UInt16) : (a ||| b).toInt16 = a.toInt16 ||| b.toInt16 := rfl
|
||||
@[simp] theorem UInt32.toInt32_or (a b : UInt32) : (a ||| b).toInt32 = a.toInt32 ||| b.toInt32 := rfl
|
||||
@[simp] theorem UInt64.toInt64_or (a b : UInt64) : (a ||| b).toInt64 = a.toInt64 ||| b.toInt64 := rfl
|
||||
@[simp] theorem USize.toISize_or (a b : USize) : (a ||| b).toISize = a.toISize ||| b.toISize := rfl
|
||||
|
||||
@[simp] theorem UInt8.toInt8_xor (a b : UInt8) : (a ^^^ b).toInt8 = a.toInt8 ^^^ b.toInt8 := (rfl)
|
||||
@[simp] theorem UInt16.toInt16_xor (a b : UInt16) : (a ^^^ b).toInt16 = a.toInt16 ^^^ b.toInt16 := (rfl)
|
||||
@[simp] theorem UInt32.toInt32_xor (a b : UInt32) : (a ^^^ b).toInt32 = a.toInt32 ^^^ b.toInt32 := (rfl)
|
||||
@[simp] theorem UInt64.toInt64_xor (a b : UInt64) : (a ^^^ b).toInt64 = a.toInt64 ^^^ b.toInt64 := (rfl)
|
||||
@[simp] theorem USize.toISize_xor (a b : USize) : (a ^^^ b).toISize = a.toISize ^^^ b.toISize := (rfl)
|
||||
@[simp] theorem UInt8.toInt8_xor (a b : UInt8) : (a ^^^ b).toInt8 = a.toInt8 ^^^ b.toInt8 := rfl
|
||||
@[simp] theorem UInt16.toInt16_xor (a b : UInt16) : (a ^^^ b).toInt16 = a.toInt16 ^^^ b.toInt16 := rfl
|
||||
@[simp] theorem UInt32.toInt32_xor (a b : UInt32) : (a ^^^ b).toInt32 = a.toInt32 ^^^ b.toInt32 := rfl
|
||||
@[simp] theorem UInt64.toInt64_xor (a b : UInt64) : (a ^^^ b).toInt64 = a.toInt64 ^^^ b.toInt64 := rfl
|
||||
@[simp] theorem USize.toISize_xor (a b : USize) : (a ^^^ b).toISize = a.toISize ^^^ b.toISize := rfl
|
||||
|
||||
@[simp] theorem UInt8.toInt8_not (a : UInt8) : (~~~a).toInt8 = ~~~a.toInt8 := (rfl)
|
||||
@[simp] theorem UInt16.toInt16_not (a : UInt16) : (~~~a).toInt16 = ~~~a.toInt16 := (rfl)
|
||||
@[simp] theorem UInt32.toInt32_not (a : UInt32) : (~~~a).toInt32 = ~~~a.toInt32 := (rfl)
|
||||
@[simp] theorem UInt64.toInt64_not (a : UInt64) : (~~~a).toInt64 = ~~~a.toInt64 := (rfl)
|
||||
@[simp] theorem USize.toISize_not (a : USize) : (~~~a).toISize = ~~~a.toISize := (rfl)
|
||||
@[simp] theorem UInt8.toInt8_not (a : UInt8) : (~~~a).toInt8 = ~~~a.toInt8 := rfl
|
||||
@[simp] theorem UInt16.toInt16_not (a : UInt16) : (~~~a).toInt16 = ~~~a.toInt16 := rfl
|
||||
@[simp] theorem UInt32.toInt32_not (a : UInt32) : (~~~a).toInt32 = ~~~a.toInt32 := rfl
|
||||
@[simp] theorem UInt64.toInt64_not (a : UInt64) : (~~~a).toInt64 = ~~~a.toInt64 := rfl
|
||||
@[simp] theorem USize.toISize_not (a : USize) : (~~~a).toISize = ~~~a.toISize := rfl
|
||||
|
||||
@[simp] theorem Int8.toUInt8_and (a b : Int8) : (a &&& b).toUInt8 = a.toUInt8 &&& b.toUInt8 := (rfl)
|
||||
@[simp] theorem Int16.toUInt16_and (a b : Int16) : (a &&& b).toUInt16 = a.toUInt16 &&& b.toUInt16 := (rfl)
|
||||
@[simp] theorem Int32.toUInt32_and (a b : Int32) : (a &&& b).toUInt32 = a.toUInt32 &&& b.toUInt32 := (rfl)
|
||||
@[simp] theorem Int64.toUInt64_and (a b : Int64) : (a &&& b).toUInt64 = a.toUInt64 &&& b.toUInt64 := (rfl)
|
||||
@[simp] theorem ISize.toUSize_and (a b : ISize) : (a &&& b).toUSize = a.toUSize &&& b.toUSize := (rfl)
|
||||
@[simp] theorem Int8.toUInt8_and (a b : Int8) : (a &&& b).toUInt8 = a.toUInt8 &&& b.toUInt8 := rfl
|
||||
@[simp] theorem Int16.toUInt16_and (a b : Int16) : (a &&& b).toUInt16 = a.toUInt16 &&& b.toUInt16 := rfl
|
||||
@[simp] theorem Int32.toUInt32_and (a b : Int32) : (a &&& b).toUInt32 = a.toUInt32 &&& b.toUInt32 := rfl
|
||||
@[simp] theorem Int64.toUInt64_and (a b : Int64) : (a &&& b).toUInt64 = a.toUInt64 &&& b.toUInt64 := rfl
|
||||
@[simp] theorem ISize.toUSize_and (a b : ISize) : (a &&& b).toUSize = a.toUSize &&& b.toUSize := rfl
|
||||
|
||||
@[simp] theorem Int8.toUInt8_or (a b : Int8) : (a ||| b).toUInt8 = a.toUInt8 ||| b.toUInt8 := (rfl)
|
||||
@[simp] theorem Int16.toUInt16_or (a b : Int16) : (a ||| b).toUInt16 = a.toUInt16 ||| b.toUInt16 := (rfl)
|
||||
@[simp] theorem Int32.toUInt32_or (a b : Int32) : (a ||| b).toUInt32 = a.toUInt32 ||| b.toUInt32 := (rfl)
|
||||
@[simp] theorem Int64.toUInt64_or (a b : Int64) : (a ||| b).toUInt64 = a.toUInt64 ||| b.toUInt64 := (rfl)
|
||||
@[simp] theorem ISize.toUSize_or (a b : ISize) : (a ||| b).toUSize = a.toUSize ||| b.toUSize := (rfl)
|
||||
@[simp] theorem Int8.toUInt8_or (a b : Int8) : (a ||| b).toUInt8 = a.toUInt8 ||| b.toUInt8 := rfl
|
||||
@[simp] theorem Int16.toUInt16_or (a b : Int16) : (a ||| b).toUInt16 = a.toUInt16 ||| b.toUInt16 := rfl
|
||||
@[simp] theorem Int32.toUInt32_or (a b : Int32) : (a ||| b).toUInt32 = a.toUInt32 ||| b.toUInt32 := rfl
|
||||
@[simp] theorem Int64.toUInt64_or (a b : Int64) : (a ||| b).toUInt64 = a.toUInt64 ||| b.toUInt64 := rfl
|
||||
@[simp] theorem ISize.toUSize_or (a b : ISize) : (a ||| b).toUSize = a.toUSize ||| b.toUSize := rfl
|
||||
|
||||
@[simp] theorem Int8.toUInt8_xor (a b : Int8) : (a ^^^ b).toUInt8 = a.toUInt8 ^^^ b.toUInt8 := (rfl)
|
||||
@[simp] theorem Int16.toUInt16_xor (a b : Int16) : (a ^^^ b).toUInt16 = a.toUInt16 ^^^ b.toUInt16 := (rfl)
|
||||
@[simp] theorem Int32.toUInt32_xor (a b : Int32) : (a ^^^ b).toUInt32 = a.toUInt32 ^^^ b.toUInt32 := (rfl)
|
||||
@[simp] theorem Int64.toUInt64_xor (a b : Int64) : (a ^^^ b).toUInt64 = a.toUInt64 ^^^ b.toUInt64 := (rfl)
|
||||
@[simp] theorem ISize.toUSize_xor (a b : ISize) : (a ^^^ b).toUSize = a.toUSize ^^^ b.toUSize := (rfl)
|
||||
@[simp] theorem Int8.toUInt8_xor (a b : Int8) : (a ^^^ b).toUInt8 = a.toUInt8 ^^^ b.toUInt8 := rfl
|
||||
@[simp] theorem Int16.toUInt16_xor (a b : Int16) : (a ^^^ b).toUInt16 = a.toUInt16 ^^^ b.toUInt16 := rfl
|
||||
@[simp] theorem Int32.toUInt32_xor (a b : Int32) : (a ^^^ b).toUInt32 = a.toUInt32 ^^^ b.toUInt32 := rfl
|
||||
@[simp] theorem Int64.toUInt64_xor (a b : Int64) : (a ^^^ b).toUInt64 = a.toUInt64 ^^^ b.toUInt64 := rfl
|
||||
@[simp] theorem ISize.toUSize_xor (a b : ISize) : (a ^^^ b).toUSize = a.toUSize ^^^ b.toUSize := rfl
|
||||
|
||||
@[simp] theorem Int8.toUInt8_not (a : Int8) : (~~~a).toUInt8 = ~~~a.toUInt8 := (rfl)
|
||||
@[simp] theorem Int16.toUInt16_not (a : Int16) : (~~~a).toUInt16 = ~~~a.toUInt16 := (rfl)
|
||||
@[simp] theorem Int32.toUInt32_not (a : Int32) : (~~~a).toUInt32 = ~~~a.toUInt32 := (rfl)
|
||||
@[simp] theorem Int64.toUInt64_not (a : Int64) : (~~~a).toUInt64 = ~~~a.toUInt64 := (rfl)
|
||||
@[simp] theorem ISize.toUSize_not (a : ISize) : (~~~a).toUSize = ~~~a.toUSize := (rfl)
|
||||
@[simp] theorem Int8.toUInt8_not (a : Int8) : (~~~a).toUInt8 = ~~~a.toUInt8 := rfl
|
||||
@[simp] theorem Int16.toUInt16_not (a : Int16) : (~~~a).toUInt16 = ~~~a.toUInt16 := rfl
|
||||
@[simp] theorem Int32.toUInt32_not (a : Int32) : (~~~a).toUInt32 = ~~~a.toUInt32 := rfl
|
||||
@[simp] theorem Int64.toUInt64_not (a : Int64) : (~~~a).toUInt64 = ~~~a.toUInt64 := rfl
|
||||
@[simp] theorem ISize.toUSize_not (a : ISize) : (~~~a).toUSize = ~~~a.toUSize := rfl
|
||||
|
||||
@[simp] theorem Int8.toInt16_and (a b : Int8) : (a &&& b).toInt16 = a.toInt16 &&& b.toInt16 := Int16.toBitVec_inj.1 (by simp)
|
||||
@[simp] theorem Int8.toInt32_and (a b : Int8) : (a &&& b).toInt32 = a.toInt32 &&& b.toInt32 := Int32.toBitVec_inj.1 (by simp)
|
||||
@@ -208,41 +208,41 @@ theorem ISize.not_eq_neg_add (a : ISize) : ~~~a = -a - 1 := ISize.toBitVec_inj.1
|
||||
|
||||
@[simp] theorem Int64.toISize_not (a : Int64) : (~~~a).toISize = ~~~a.toISize := ISize.toBitVec_inj.1 (by simp)
|
||||
|
||||
@[simp] theorem Int8.ofBitVec_and (a b : BitVec 8) : Int8.ofBitVec (a &&& b) = Int8.ofBitVec a &&& Int8.ofBitVec b := (rfl)
|
||||
@[simp] theorem Int16.ofBitVec_and (a b : BitVec 16) : Int16.ofBitVec (a &&& b) = Int16.ofBitVec a &&& Int16.ofBitVec b := (rfl)
|
||||
@[simp] theorem Int32.ofBitVec_and (a b : BitVec 32) : Int32.ofBitVec (a &&& b) = Int32.ofBitVec a &&& Int32.ofBitVec b := (rfl)
|
||||
@[simp] theorem Int64.ofBitVec_and (a b : BitVec 64) : Int64.ofBitVec (a &&& b) = Int64.ofBitVec a &&& Int64.ofBitVec b := (rfl)
|
||||
@[simp] theorem ISize.ofBitVec_and (a b : BitVec System.Platform.numBits) : ISize.ofBitVec (a &&& b) = ISize.ofBitVec a &&& ISize.ofBitVec b := (rfl)
|
||||
@[simp] theorem Int8.ofBitVec_and (a b : BitVec 8) : Int8.ofBitVec (a &&& b) = Int8.ofBitVec a &&& Int8.ofBitVec b := rfl
|
||||
@[simp] theorem Int16.ofBitVec_and (a b : BitVec 16) : Int16.ofBitVec (a &&& b) = Int16.ofBitVec a &&& Int16.ofBitVec b := rfl
|
||||
@[simp] theorem Int32.ofBitVec_and (a b : BitVec 32) : Int32.ofBitVec (a &&& b) = Int32.ofBitVec a &&& Int32.ofBitVec b := rfl
|
||||
@[simp] theorem Int64.ofBitVec_and (a b : BitVec 64) : Int64.ofBitVec (a &&& b) = Int64.ofBitVec a &&& Int64.ofBitVec b := rfl
|
||||
@[simp] theorem ISize.ofBitVec_and (a b : BitVec System.Platform.numBits) : ISize.ofBitVec (a &&& b) = ISize.ofBitVec a &&& ISize.ofBitVec b := rfl
|
||||
|
||||
@[simp] theorem Int8.ofBitVec_or (a b : BitVec 8) : Int8.ofBitVec (a ||| b) = Int8.ofBitVec a ||| Int8.ofBitVec b := (rfl)
|
||||
@[simp] theorem Int16.ofBitVec_or (a b : BitVec 16) : Int16.ofBitVec (a ||| b) = Int16.ofBitVec a ||| Int16.ofBitVec b := (rfl)
|
||||
@[simp] theorem Int32.ofBitVec_or (a b : BitVec 32) : Int32.ofBitVec (a ||| b) = Int32.ofBitVec a ||| Int32.ofBitVec b := (rfl)
|
||||
@[simp] theorem Int64.ofBitVec_or (a b : BitVec 64) : Int64.ofBitVec (a ||| b) = Int64.ofBitVec a ||| Int64.ofBitVec b := (rfl)
|
||||
@[simp] theorem ISize.ofBitVec_or (a b : BitVec System.Platform.numBits) : ISize.ofBitVec (a ||| b) = ISize.ofBitVec a ||| ISize.ofBitVec b := (rfl)
|
||||
@[simp] theorem Int8.ofBitVec_or (a b : BitVec 8) : Int8.ofBitVec (a ||| b) = Int8.ofBitVec a ||| Int8.ofBitVec b := rfl
|
||||
@[simp] theorem Int16.ofBitVec_or (a b : BitVec 16) : Int16.ofBitVec (a ||| b) = Int16.ofBitVec a ||| Int16.ofBitVec b := rfl
|
||||
@[simp] theorem Int32.ofBitVec_or (a b : BitVec 32) : Int32.ofBitVec (a ||| b) = Int32.ofBitVec a ||| Int32.ofBitVec b := rfl
|
||||
@[simp] theorem Int64.ofBitVec_or (a b : BitVec 64) : Int64.ofBitVec (a ||| b) = Int64.ofBitVec a ||| Int64.ofBitVec b := rfl
|
||||
@[simp] theorem ISize.ofBitVec_or (a b : BitVec System.Platform.numBits) : ISize.ofBitVec (a ||| b) = ISize.ofBitVec a ||| ISize.ofBitVec b := rfl
|
||||
|
||||
@[simp] theorem Int8.ofBitVec_xor (a b : BitVec 8) : Int8.ofBitVec (a ^^^ b) = Int8.ofBitVec a ^^^ Int8.ofBitVec b := (rfl)
|
||||
@[simp] theorem Int16.ofBitVec_xor (a b : BitVec 16) : Int16.ofBitVec (a ^^^ b) = Int16.ofBitVec a ^^^ Int16.ofBitVec b := (rfl)
|
||||
@[simp] theorem Int32.ofBitVec_xor (a b : BitVec 32) : Int32.ofBitVec (a ^^^ b) = Int32.ofBitVec a ^^^ Int32.ofBitVec b := (rfl)
|
||||
@[simp] theorem Int64.ofBitVec_xor (a b : BitVec 64) : Int64.ofBitVec (a ^^^ b) = Int64.ofBitVec a ^^^ Int64.ofBitVec b := (rfl)
|
||||
@[simp] theorem ISize.ofBitVec_xor (a b : BitVec System.Platform.numBits) : ISize.ofBitVec (a ^^^ b) = ISize.ofBitVec a ^^^ ISize.ofBitVec b := (rfl)
|
||||
@[simp] theorem Int8.ofBitVec_xor (a b : BitVec 8) : Int8.ofBitVec (a ^^^ b) = Int8.ofBitVec a ^^^ Int8.ofBitVec b := rfl
|
||||
@[simp] theorem Int16.ofBitVec_xor (a b : BitVec 16) : Int16.ofBitVec (a ^^^ b) = Int16.ofBitVec a ^^^ Int16.ofBitVec b := rfl
|
||||
@[simp] theorem Int32.ofBitVec_xor (a b : BitVec 32) : Int32.ofBitVec (a ^^^ b) = Int32.ofBitVec a ^^^ Int32.ofBitVec b := rfl
|
||||
@[simp] theorem Int64.ofBitVec_xor (a b : BitVec 64) : Int64.ofBitVec (a ^^^ b) = Int64.ofBitVec a ^^^ Int64.ofBitVec b := rfl
|
||||
@[simp] theorem ISize.ofBitVec_xor (a b : BitVec System.Platform.numBits) : ISize.ofBitVec (a ^^^ b) = ISize.ofBitVec a ^^^ ISize.ofBitVec b := rfl
|
||||
|
||||
@[simp] theorem Int8.ofBitVec_not (a : BitVec 8) : Int8.ofBitVec (~~~a) = ~~~Int8.ofBitVec a := (rfl)
|
||||
@[simp] theorem Int16.ofBitVec_not (a : BitVec 16) : Int16.ofBitVec (~~~a) = ~~~Int16.ofBitVec a := (rfl)
|
||||
@[simp] theorem Int32.ofBitVec_not (a : BitVec 32) : Int32.ofBitVec (~~~a) = ~~~Int32.ofBitVec a := (rfl)
|
||||
@[simp] theorem Int64.ofBitVec_not (a : BitVec 64) : Int64.ofBitVec (~~~a) = ~~~Int64.ofBitVec a := (rfl)
|
||||
@[simp] theorem ISize.ofBitVec_not (a : BitVec System.Platform.numBits) : ISize.ofBitVec (~~~a) = ~~~ISize.ofBitVec a := (rfl)
|
||||
@[simp] theorem Int8.ofBitVec_not (a : BitVec 8) : Int8.ofBitVec (~~~a) = ~~~Int8.ofBitVec a := rfl
|
||||
@[simp] theorem Int16.ofBitVec_not (a : BitVec 16) : Int16.ofBitVec (~~~a) = ~~~Int16.ofBitVec a := rfl
|
||||
@[simp] theorem Int32.ofBitVec_not (a : BitVec 32) : Int32.ofBitVec (~~~a) = ~~~Int32.ofBitVec a := rfl
|
||||
@[simp] theorem Int64.ofBitVec_not (a : BitVec 64) : Int64.ofBitVec (~~~a) = ~~~Int64.ofBitVec a := rfl
|
||||
@[simp] theorem ISize.ofBitVec_not (a : BitVec System.Platform.numBits) : ISize.ofBitVec (~~~a) = ~~~ISize.ofBitVec a := rfl
|
||||
|
||||
@[simp] theorem Int8.ofBitVec_intMin : Int8.ofBitVec (BitVec.intMin 8) = Int8.minValue := (rfl)
|
||||
@[simp] theorem Int16.ofBitVec_intMin : Int16.ofBitVec (BitVec.intMin 16) = Int16.minValue := (rfl)
|
||||
@[simp] theorem Int32.ofBitVec_intMin : Int32.ofBitVec (BitVec.intMin 32) = Int32.minValue := (rfl)
|
||||
@[simp] theorem Int64.ofBitVec_intMin : Int64.ofBitVec (BitVec.intMin 64) = Int64.minValue := (rfl)
|
||||
@[simp] theorem Int8.ofBitVec_intMin : Int8.ofBitVec (BitVec.intMin 8) = Int8.minValue := rfl
|
||||
@[simp] theorem Int16.ofBitVec_intMin : Int16.ofBitVec (BitVec.intMin 16) = Int16.minValue := rfl
|
||||
@[simp] theorem Int32.ofBitVec_intMin : Int32.ofBitVec (BitVec.intMin 32) = Int32.minValue := rfl
|
||||
@[simp] theorem Int64.ofBitVec_intMin : Int64.ofBitVec (BitVec.intMin 64) = Int64.minValue := rfl
|
||||
@[simp] theorem ISize.ofBitVec_intMin : ISize.ofBitVec (BitVec.intMin System.Platform.numBits) = ISize.minValue :=
|
||||
ISize.toBitVec_inj.1 (by simp [BitVec.intMin_eq_neg_two_pow])
|
||||
|
||||
@[simp] theorem Int8.ofBitVec_intMax : Int8.ofBitVec (BitVec.intMax 8) = Int8.maxValue := (rfl)
|
||||
@[simp] theorem Int16.ofBitVec_intMax : Int16.ofBitVec (BitVec.intMax 16) = Int16.maxValue := (rfl)
|
||||
@[simp] theorem Int32.ofBitVec_intMax : Int32.ofBitVec (BitVec.intMax 32) = Int32.maxValue := (rfl)
|
||||
@[simp] theorem Int64.ofBitVec_intMax : Int64.ofBitVec (BitVec.intMax 64) = Int64.maxValue := (rfl)
|
||||
@[simp] theorem Int8.ofBitVec_intMax : Int8.ofBitVec (BitVec.intMax 8) = Int8.maxValue := rfl
|
||||
@[simp] theorem Int16.ofBitVec_intMax : Int16.ofBitVec (BitVec.intMax 16) = Int16.maxValue := rfl
|
||||
@[simp] theorem Int32.ofBitVec_intMax : Int32.ofBitVec (BitVec.intMax 32) = Int32.maxValue := rfl
|
||||
@[simp] theorem Int64.ofBitVec_intMax : Int64.ofBitVec (BitVec.intMax 64) = Int64.maxValue := rfl
|
||||
@[simp] theorem ISize.ofBitVec_intMax : ISize.ofBitVec (BitVec.intMax System.Platform.numBits) = ISize.maxValue :=
|
||||
ISize.toInt_inj.1 (by rw [toInt_ofBitVec, BitVec.toInt_intMax, toInt_maxValue])
|
||||
|
||||
@@ -550,16 +550,16 @@ instance : Std.LawfulCommIdentity (α := ISize) (· ^^^ ·) 0 where
|
||||
@[simp] theorem ISize.xor_right_inj {a b : ISize} (c : ISize) : (c ^^^ a = c ^^^ b) ↔ a = b := by
|
||||
simp [← ISize.toBitVec_inj]
|
||||
|
||||
@[simp] theorem Int8.not_zero : ~~~(0 : Int8) = -1 := (rfl)
|
||||
@[simp] theorem Int16.not_zero : ~~~(0 : Int16) = -1 := (rfl)
|
||||
@[simp] theorem Int32.not_zero : ~~~(0 : Int32) = -1 := (rfl)
|
||||
@[simp] theorem Int64.not_zero : ~~~(0 : Int64) = -1 := (rfl)
|
||||
@[simp] theorem Int8.not_zero : ~~~(0 : Int8) = -1 := rfl
|
||||
@[simp] theorem Int16.not_zero : ~~~(0 : Int16) = -1 := rfl
|
||||
@[simp] theorem Int32.not_zero : ~~~(0 : Int32) = -1 := rfl
|
||||
@[simp] theorem Int64.not_zero : ~~~(0 : Int64) = -1 := rfl
|
||||
@[simp] theorem ISize.not_zero : ~~~(0 : ISize) = -1 := by simp [ISize.not_eq_neg_sub]
|
||||
|
||||
@[simp] theorem Int8.not_neg_one : ~~~(-1 : Int8) = 0 := (rfl)
|
||||
@[simp] theorem Int16.not_neg_one : ~~~(-1 : Int16) = 0 := (rfl)
|
||||
@[simp] theorem Int32.not_neg_one : ~~~(-1 : Int32) = 0 := (rfl)
|
||||
@[simp] theorem Int64.not_neg_one : ~~~(-1 : Int64) = 0 := (rfl)
|
||||
@[simp] theorem Int8.not_neg_one : ~~~(-1 : Int8) = 0 := rfl
|
||||
@[simp] theorem Int16.not_neg_one : ~~~(-1 : Int16) = 0 := rfl
|
||||
@[simp] theorem Int32.not_neg_one : ~~~(-1 : Int32) = 0 := rfl
|
||||
@[simp] theorem Int64.not_neg_one : ~~~(-1 : Int64) = 0 := rfl
|
||||
@[simp] theorem ISize.not_neg_one : ~~~(-1 : ISize) = 0 := by simp [ISize.not_eq_neg_sub]
|
||||
|
||||
@[simp] theorem Int8.not_not {a : Int8} : ~~~(~~~a) = a := by simp [← Int8.toBitVec_inj]
|
||||
|
||||
@@ -31,14 +31,14 @@ macro "declare_int_theorems" typeName:ident _bits:term:arg : command => do
|
||||
toBitVec_inj.symm
|
||||
@[int_toBitVec] theorem ne_iff_toBitVec_ne {a b : $typeName} : a ≠ b ↔ a.toBitVec ≠ b.toBitVec :=
|
||||
Decidable.not_iff_not.2 eq_iff_toBitVec_eq
|
||||
@[simp] theorem toBitVec_ofNat' {n : Nat} : toBitVec (ofNat n) = BitVec.ofNat _ n := (rfl)
|
||||
@[simp, int_toBitVec] theorem toBitVec_ofNat {n : Nat} : toBitVec (no_index (OfNat.ofNat n)) = OfNat.ofNat n := (rfl)
|
||||
@[simp] theorem toBitVec_ofNat' {n : Nat} : toBitVec (ofNat n) = BitVec.ofNat _ n := rfl
|
||||
@[simp, int_toBitVec] theorem toBitVec_ofNat {n : Nat} : toBitVec (no_index (OfNat.ofNat n)) = OfNat.ofNat n := rfl
|
||||
|
||||
@[simp, int_toBitVec] protected theorem toBitVec_add {a b : $typeName} : (a + b).toBitVec = a.toBitVec + b.toBitVec := (rfl)
|
||||
@[simp, int_toBitVec] protected theorem toBitVec_sub {a b : $typeName} : (a - b).toBitVec = a.toBitVec - b.toBitVec := (rfl)
|
||||
@[simp, int_toBitVec] protected theorem toBitVec_mul {a b : $typeName} : (a * b).toBitVec = a.toBitVec * b.toBitVec := (rfl)
|
||||
@[simp, int_toBitVec] protected theorem toBitVec_div {a b : $typeName} : (a / b).toBitVec = a.toBitVec.sdiv b.toBitVec := (rfl)
|
||||
@[simp, int_toBitVec] protected theorem toBitVec_mod {a b : $typeName} : (a % b).toBitVec = a.toBitVec.srem b.toBitVec := (rfl)
|
||||
@[simp, int_toBitVec] protected theorem toBitVec_add {a b : $typeName} : (a + b).toBitVec = a.toBitVec + b.toBitVec := rfl
|
||||
@[simp, int_toBitVec] protected theorem toBitVec_sub {a b : $typeName} : (a - b).toBitVec = a.toBitVec - b.toBitVec := rfl
|
||||
@[simp, int_toBitVec] protected theorem toBitVec_mul {a b : $typeName} : (a * b).toBitVec = a.toBitVec * b.toBitVec := rfl
|
||||
@[simp, int_toBitVec] protected theorem toBitVec_div {a b : $typeName} : (a / b).toBitVec = a.toBitVec.sdiv b.toBitVec := rfl
|
||||
@[simp, int_toBitVec] protected theorem toBitVec_mod {a b : $typeName} : (a % b).toBitVec = a.toBitVec.srem b.toBitVec := rfl
|
||||
|
||||
end $typeName
|
||||
)
|
||||
@@ -83,34 +83,34 @@ theorem Int64.toInt_inj {x y : Int64} : x.toInt = y.toInt ↔ x = y := ⟨Int64.
|
||||
theorem ISize.toInt.inj {x y : ISize} (h : x.toInt = y.toInt) : x = y := ISize.toBitVec.inj (BitVec.eq_of_toInt_eq h)
|
||||
theorem ISize.toInt_inj {x y : ISize} : x.toInt = y.toInt ↔ x = y := ⟨ISize.toInt.inj, fun h => h ▸ rfl⟩
|
||||
|
||||
@[simp] theorem Int8.toBitVec_neg (x : Int8) : (-x).toBitVec = -x.toBitVec := (rfl)
|
||||
@[simp] theorem Int16.toBitVec_neg (x : Int16) : (-x).toBitVec = -x.toBitVec := (rfl)
|
||||
@[simp] theorem Int32.toBitVec_neg (x : Int32) : (-x).toBitVec = -x.toBitVec := (rfl)
|
||||
@[simp] theorem Int64.toBitVec_neg (x : Int64) : (-x).toBitVec = -x.toBitVec := (rfl)
|
||||
@[simp] theorem ISize.toBitVec_neg (x : ISize) : (-x).toBitVec = -x.toBitVec := (rfl)
|
||||
@[simp] theorem Int8.toBitVec_neg (x : Int8) : (-x).toBitVec = -x.toBitVec := rfl
|
||||
@[simp] theorem Int16.toBitVec_neg (x : Int16) : (-x).toBitVec = -x.toBitVec := rfl
|
||||
@[simp] theorem Int32.toBitVec_neg (x : Int32) : (-x).toBitVec = -x.toBitVec := rfl
|
||||
@[simp] theorem Int64.toBitVec_neg (x : Int64) : (-x).toBitVec = -x.toBitVec := rfl
|
||||
@[simp] theorem ISize.toBitVec_neg (x : ISize) : (-x).toBitVec = -x.toBitVec := rfl
|
||||
|
||||
@[simp] theorem Int8.toBitVec_zero : toBitVec 0 = 0#8 := (rfl)
|
||||
@[simp] theorem Int16.toBitVec_zero : toBitVec 0 = 0#16 := (rfl)
|
||||
@[simp] theorem Int32.toBitVec_zero : toBitVec 0 = 0#32 := (rfl)
|
||||
@[simp] theorem Int64.toBitVec_zero : toBitVec 0 = 0#64 := (rfl)
|
||||
@[simp] theorem ISize.toBitVec_zero : toBitVec 0 = 0#System.Platform.numBits := (rfl)
|
||||
@[simp] theorem Int8.toBitVec_zero : toBitVec 0 = 0#8 := rfl
|
||||
@[simp] theorem Int16.toBitVec_zero : toBitVec 0 = 0#16 := rfl
|
||||
@[simp] theorem Int32.toBitVec_zero : toBitVec 0 = 0#32 := rfl
|
||||
@[simp] theorem Int64.toBitVec_zero : toBitVec 0 = 0#64 := rfl
|
||||
@[simp] theorem ISize.toBitVec_zero : toBitVec 0 = 0#System.Platform.numBits := rfl
|
||||
|
||||
theorem Int8.toBitVec_one : (1 : Int8).toBitVec = 1#8 := (rfl)
|
||||
theorem Int16.toBitVec_one : (1 : Int16).toBitVec = 1#16 := (rfl)
|
||||
theorem Int32.toBitVec_one : (1 : Int32).toBitVec = 1#32 := (rfl)
|
||||
theorem Int64.toBitVec_one : (1 : Int64).toBitVec = 1#64 := (rfl)
|
||||
theorem ISize.toBitVec_one : (1 : ISize).toBitVec = 1#System.Platform.numBits := (rfl)
|
||||
theorem Int8.toBitVec_one : (1 : Int8).toBitVec = 1#8 := rfl
|
||||
theorem Int16.toBitVec_one : (1 : Int16).toBitVec = 1#16 := rfl
|
||||
theorem Int32.toBitVec_one : (1 : Int32).toBitVec = 1#32 := rfl
|
||||
theorem Int64.toBitVec_one : (1 : Int64).toBitVec = 1#64 := rfl
|
||||
theorem ISize.toBitVec_one : (1 : ISize).toBitVec = 1#System.Platform.numBits := rfl
|
||||
|
||||
@[simp] theorem Int8.toBitVec_ofInt (i : Int) : (ofInt i).toBitVec = BitVec.ofInt _ i := (rfl)
|
||||
@[simp] theorem Int16.toBitVec_ofInt (i : Int) : (ofInt i).toBitVec = BitVec.ofInt _ i := (rfl)
|
||||
@[simp] theorem Int32.toBitVec_ofInt (i : Int) : (ofInt i).toBitVec = BitVec.ofInt _ i := (rfl)
|
||||
@[simp] theorem Int64.toBitVec_ofInt (i : Int) : (ofInt i).toBitVec = BitVec.ofInt _ i := (rfl)
|
||||
@[simp] theorem ISize.toBitVec_ofInt (i : Int) : (ofInt i).toBitVec = BitVec.ofInt _ i := (rfl)
|
||||
@[simp] theorem Int8.toBitVec_ofInt (i : Int) : (ofInt i).toBitVec = BitVec.ofInt _ i := rfl
|
||||
@[simp] theorem Int16.toBitVec_ofInt (i : Int) : (ofInt i).toBitVec = BitVec.ofInt _ i := rfl
|
||||
@[simp] theorem Int32.toBitVec_ofInt (i : Int) : (ofInt i).toBitVec = BitVec.ofInt _ i := rfl
|
||||
@[simp] theorem Int64.toBitVec_ofInt (i : Int) : (ofInt i).toBitVec = BitVec.ofInt _ i := rfl
|
||||
@[simp] theorem ISize.toBitVec_ofInt (i : Int) : (ofInt i).toBitVec = BitVec.ofInt _ i := rfl
|
||||
|
||||
@[simp] protected theorem Int8.neg_zero : -(0 : Int8) = 0 := (rfl)
|
||||
@[simp] protected theorem Int16.neg_zero : -(0 : Int16) = 0 := (rfl)
|
||||
@[simp] protected theorem Int32.neg_zero : -(0 : Int32) = 0 := (rfl)
|
||||
@[simp] protected theorem Int64.neg_zero : -(0 : Int64) = 0 := (rfl)
|
||||
@[simp] protected theorem Int8.neg_zero : -(0 : Int8) = 0 := rfl
|
||||
@[simp] protected theorem Int16.neg_zero : -(0 : Int16) = 0 := rfl
|
||||
@[simp] protected theorem Int32.neg_zero : -(0 : Int32) = 0 := rfl
|
||||
@[simp] protected theorem Int64.neg_zero : -(0 : Int64) = 0 := rfl
|
||||
@[simp] protected theorem ISize.neg_zero : -(0 : ISize) = 0 := ISize.toBitVec.inj (by simp)
|
||||
|
||||
theorem ISize.toNat_toBitVec_ofNat_of_lt {n : Nat} (h : n < 2^32) :
|
||||
@@ -234,84 +234,84 @@ theorem Int32.toInt_zero : toInt 0 = 0 := by simp
|
||||
theorem Int64.toInt_zero : toInt 0 = 0 := by simp
|
||||
theorem ISize.toInt_zero : toInt 0 = 0 := by simp
|
||||
|
||||
theorem Int8.toInt_minValue : Int8.minValue.toInt = -2^7 := (rfl)
|
||||
theorem Int16.toInt_minValue : Int16.minValue.toInt = -2^15 := (rfl)
|
||||
theorem Int32.toInt_minValue : Int32.minValue.toInt = -2^31 := (rfl)
|
||||
theorem Int64.toInt_minValue : Int64.minValue.toInt = -2^63 := (rfl)
|
||||
theorem Int8.toInt_minValue : Int8.minValue.toInt = -2^7 := rfl
|
||||
theorem Int16.toInt_minValue : Int16.minValue.toInt = -2^15 := rfl
|
||||
theorem Int32.toInt_minValue : Int32.minValue.toInt = -2^31 := rfl
|
||||
theorem Int64.toInt_minValue : Int64.minValue.toInt = -2^63 := rfl
|
||||
theorem ISize.toInt_minValue : ISize.minValue.toInt = -2 ^ (System.Platform.numBits - 1) := by
|
||||
rw [minValue, toInt_ofInt_of_two_pow_numBits_le] <;> cases System.Platform.numBits_eq
|
||||
<;> simp_all
|
||||
|
||||
theorem Int8.toInt_maxValue : Int8.maxValue.toInt = 2 ^ 7 - 1 := (rfl)
|
||||
theorem Int16.toInt_maxValue : Int16.maxValue.toInt = 2 ^ 15 - 1 := (rfl)
|
||||
theorem Int32.toInt_maxValue : Int32.maxValue.toInt = 2 ^ 31 - 1 := (rfl)
|
||||
theorem Int64.toInt_maxValue : Int64.maxValue.toInt = 2 ^ 63 - 1 := (rfl)
|
||||
theorem Int8.toInt_maxValue : Int8.maxValue.toInt = 2 ^ 7 - 1 := rfl
|
||||
theorem Int16.toInt_maxValue : Int16.maxValue.toInt = 2 ^ 15 - 1 := rfl
|
||||
theorem Int32.toInt_maxValue : Int32.maxValue.toInt = 2 ^ 31 - 1 := rfl
|
||||
theorem Int64.toInt_maxValue : Int64.maxValue.toInt = 2 ^ 63 - 1 := rfl
|
||||
theorem ISize.toInt_maxValue : ISize.maxValue.toInt = 2 ^ (System.Platform.numBits - 1) - 1:= by
|
||||
rw [maxValue, toInt_ofInt_of_two_pow_numBits_le] <;> cases System.Platform.numBits_eq
|
||||
<;> simp_all
|
||||
|
||||
@[simp] theorem Int8.toNatClampNeg_minValue : Int8.minValue.toNatClampNeg = 0 := (rfl)
|
||||
@[simp] theorem Int16.toNatClampNeg_minValue : Int16.minValue.toNatClampNeg = 0 := (rfl)
|
||||
@[simp] theorem Int32.toNatClampNeg_minValue : Int32.minValue.toNatClampNeg = 0 := (rfl)
|
||||
@[simp] theorem Int64.toNatClampNeg_minValue : Int64.minValue.toNatClampNeg = 0 := (rfl)
|
||||
@[simp] theorem Int8.toNatClampNeg_minValue : Int8.minValue.toNatClampNeg = 0 := rfl
|
||||
@[simp] theorem Int16.toNatClampNeg_minValue : Int16.minValue.toNatClampNeg = 0 := rfl
|
||||
@[simp] theorem Int32.toNatClampNeg_minValue : Int32.minValue.toNatClampNeg = 0 := rfl
|
||||
@[simp] theorem Int64.toNatClampNeg_minValue : Int64.minValue.toNatClampNeg = 0 := rfl
|
||||
@[simp] theorem ISize.toNatClampNeg_minValue : ISize.minValue.toNatClampNeg = 0 := by
|
||||
rw [toNatClampNeg, toInt_minValue]
|
||||
cases System.Platform.numBits_eq <;> simp_all
|
||||
|
||||
@[simp] theorem UInt8.toBitVec_toInt8 (x : UInt8) : x.toInt8.toBitVec = x.toBitVec := (rfl)
|
||||
@[simp] theorem UInt16.toBitVec_toInt16 (x : UInt16) : x.toInt16.toBitVec = x.toBitVec := (rfl)
|
||||
@[simp] theorem UInt32.toBitVec_toInt32 (x : UInt32) : x.toInt32.toBitVec = x.toBitVec := (rfl)
|
||||
@[simp] theorem UInt64.toBitVec_toInt64 (x : UInt64) : x.toInt64.toBitVec = x.toBitVec := (rfl)
|
||||
@[simp] theorem USize.toBitVec_toISize (x : USize) : x.toISize.toBitVec = x.toBitVec := (rfl)
|
||||
@[simp] theorem UInt8.toBitVec_toInt8 (x : UInt8) : x.toInt8.toBitVec = x.toBitVec := rfl
|
||||
@[simp] theorem UInt16.toBitVec_toInt16 (x : UInt16) : x.toInt16.toBitVec = x.toBitVec := rfl
|
||||
@[simp] theorem UInt32.toBitVec_toInt32 (x : UInt32) : x.toInt32.toBitVec = x.toBitVec := rfl
|
||||
@[simp] theorem UInt64.toBitVec_toInt64 (x : UInt64) : x.toInt64.toBitVec = x.toBitVec := rfl
|
||||
@[simp] theorem USize.toBitVec_toISize (x : USize) : x.toISize.toBitVec = x.toBitVec := rfl
|
||||
|
||||
@[simp] theorem Int8.ofBitVec_uInt8ToBitVec (x : UInt8) : Int8.ofBitVec x.toBitVec = x.toInt8 := (rfl)
|
||||
@[simp] theorem Int16.ofBitVec_uInt16ToBitVec (x : UInt16) : Int16.ofBitVec x.toBitVec = x.toInt16 := (rfl)
|
||||
@[simp] theorem Int32.ofBitVec_uInt32ToBitVec (x : UInt32) : Int32.ofBitVec x.toBitVec = x.toInt32 := (rfl)
|
||||
@[simp] theorem Int64.ofBitVec_uInt64ToBitVec (x : UInt64) : Int64.ofBitVec x.toBitVec = x.toInt64 := (rfl)
|
||||
@[simp] theorem ISize.ofBitVec_uSizeToBitVec (x : USize) : ISize.ofBitVec x.toBitVec = x.toISize := (rfl)
|
||||
@[simp] theorem Int8.ofBitVec_uInt8ToBitVec (x : UInt8) : Int8.ofBitVec x.toBitVec = x.toInt8 := rfl
|
||||
@[simp] theorem Int16.ofBitVec_uInt16ToBitVec (x : UInt16) : Int16.ofBitVec x.toBitVec = x.toInt16 := rfl
|
||||
@[simp] theorem Int32.ofBitVec_uInt32ToBitVec (x : UInt32) : Int32.ofBitVec x.toBitVec = x.toInt32 := rfl
|
||||
@[simp] theorem Int64.ofBitVec_uInt64ToBitVec (x : UInt64) : Int64.ofBitVec x.toBitVec = x.toInt64 := rfl
|
||||
@[simp] theorem ISize.ofBitVec_uSizeToBitVec (x : USize) : ISize.ofBitVec x.toBitVec = x.toISize := rfl
|
||||
|
||||
@[simp] theorem UInt8.toUInt8_toInt8 (x : UInt8) : x.toInt8.toUInt8 = x := (rfl)
|
||||
@[simp] theorem UInt16.toUInt16_toInt16 (x : UInt16) : x.toInt16.toUInt16 = x := (rfl)
|
||||
@[simp] theorem UInt32.toUInt32_toInt32 (x : UInt32) : x.toInt32.toUInt32 = x := (rfl)
|
||||
@[simp] theorem UInt64.toUInt64_toInt64 (x : UInt64) : x.toInt64.toUInt64 = x := (rfl)
|
||||
@[simp] theorem USize.toUSize_toISize (x : USize) : x.toISize.toUSize = x := (rfl)
|
||||
@[simp] theorem UInt8.toUInt8_toInt8 (x : UInt8) : x.toInt8.toUInt8 = x := rfl
|
||||
@[simp] theorem UInt16.toUInt16_toInt16 (x : UInt16) : x.toInt16.toUInt16 = x := rfl
|
||||
@[simp] theorem UInt32.toUInt32_toInt32 (x : UInt32) : x.toInt32.toUInt32 = x := rfl
|
||||
@[simp] theorem UInt64.toUInt64_toInt64 (x : UInt64) : x.toInt64.toUInt64 = x := rfl
|
||||
@[simp] theorem USize.toUSize_toISize (x : USize) : x.toISize.toUSize = x := rfl
|
||||
|
||||
@[simp] theorem Int8.toNat_toInt (x : Int8) : x.toInt.toNat = x.toNatClampNeg := (rfl)
|
||||
@[simp] theorem Int16.toNat_toInt (x : Int16) : x.toInt.toNat = x.toNatClampNeg := (rfl)
|
||||
@[simp] theorem Int32.toNat_toInt (x : Int32) : x.toInt.toNat = x.toNatClampNeg := (rfl)
|
||||
@[simp] theorem Int64.toNat_toInt (x : Int64) : x.toInt.toNat = x.toNatClampNeg := (rfl)
|
||||
@[simp] theorem ISize.toNat_toInt (x : ISize) : x.toInt.toNat = x.toNatClampNeg := (rfl)
|
||||
@[simp] theorem Int8.toNat_toInt (x : Int8) : x.toInt.toNat = x.toNatClampNeg := rfl
|
||||
@[simp] theorem Int16.toNat_toInt (x : Int16) : x.toInt.toNat = x.toNatClampNeg := rfl
|
||||
@[simp] theorem Int32.toNat_toInt (x : Int32) : x.toInt.toNat = x.toNatClampNeg := rfl
|
||||
@[simp] theorem Int64.toNat_toInt (x : Int64) : x.toInt.toNat = x.toNatClampNeg := rfl
|
||||
@[simp] theorem ISize.toNat_toInt (x : ISize) : x.toInt.toNat = x.toNatClampNeg := rfl
|
||||
|
||||
@[simp] theorem Int8.toInt_toBitVec (x : Int8) : x.toBitVec.toInt = x.toInt := (rfl)
|
||||
@[simp] theorem Int16.toInt_toBitVec (x : Int16) : x.toBitVec.toInt = x.toInt := (rfl)
|
||||
@[simp] theorem Int32.toInt_toBitVec (x : Int32) : x.toBitVec.toInt = x.toInt := (rfl)
|
||||
@[simp] theorem Int64.toInt_toBitVec (x : Int64) : x.toBitVec.toInt = x.toInt := (rfl)
|
||||
@[simp] theorem ISize.toInt_toBitVec (x : ISize) : x.toBitVec.toInt = x.toInt := (rfl)
|
||||
@[simp] theorem Int8.toInt_toBitVec (x : Int8) : x.toBitVec.toInt = x.toInt := rfl
|
||||
@[simp] theorem Int16.toInt_toBitVec (x : Int16) : x.toBitVec.toInt = x.toInt := rfl
|
||||
@[simp] theorem Int32.toInt_toBitVec (x : Int32) : x.toBitVec.toInt = x.toInt := rfl
|
||||
@[simp] theorem Int64.toInt_toBitVec (x : Int64) : x.toBitVec.toInt = x.toInt := rfl
|
||||
@[simp] theorem ISize.toInt_toBitVec (x : ISize) : x.toBitVec.toInt = x.toInt := rfl
|
||||
|
||||
@[simp] theorem Int8.toBitVec_toInt16 (x : Int8) : x.toInt16.toBitVec = x.toBitVec.signExtend 16 := (rfl)
|
||||
@[simp] theorem Int8.toBitVec_toInt32 (x : Int8) : x.toInt32.toBitVec = x.toBitVec.signExtend 32 := (rfl)
|
||||
@[simp] theorem Int8.toBitVec_toInt64 (x : Int8) : x.toInt64.toBitVec = x.toBitVec.signExtend 64 := (rfl)
|
||||
@[simp] theorem Int8.toBitVec_toISize (x : Int8) : x.toISize.toBitVec = x.toBitVec.signExtend System.Platform.numBits := (rfl)
|
||||
@[simp] theorem Int8.toBitVec_toInt16 (x : Int8) : x.toInt16.toBitVec = x.toBitVec.signExtend 16 := rfl
|
||||
@[simp] theorem Int8.toBitVec_toInt32 (x : Int8) : x.toInt32.toBitVec = x.toBitVec.signExtend 32 := rfl
|
||||
@[simp] theorem Int8.toBitVec_toInt64 (x : Int8) : x.toInt64.toBitVec = x.toBitVec.signExtend 64 := rfl
|
||||
@[simp] theorem Int8.toBitVec_toISize (x : Int8) : x.toISize.toBitVec = x.toBitVec.signExtend System.Platform.numBits := rfl
|
||||
|
||||
@[simp] theorem Int16.toBitVec_toInt8 (x : Int16) : x.toInt8.toBitVec = x.toBitVec.signExtend 8 := (rfl)
|
||||
@[simp] theorem Int16.toBitVec_toInt32 (x : Int16) : x.toInt32.toBitVec = x.toBitVec.signExtend 32 := (rfl)
|
||||
@[simp] theorem Int16.toBitVec_toInt64 (x : Int16) : x.toInt64.toBitVec = x.toBitVec.signExtend 64 := (rfl)
|
||||
@[simp] theorem Int16.toBitVec_toISize (x : Int16) : x.toISize.toBitVec = x.toBitVec.signExtend System.Platform.numBits := (rfl)
|
||||
@[simp] theorem Int16.toBitVec_toInt8 (x : Int16) : x.toInt8.toBitVec = x.toBitVec.signExtend 8 := rfl
|
||||
@[simp] theorem Int16.toBitVec_toInt32 (x : Int16) : x.toInt32.toBitVec = x.toBitVec.signExtend 32 := rfl
|
||||
@[simp] theorem Int16.toBitVec_toInt64 (x : Int16) : x.toInt64.toBitVec = x.toBitVec.signExtend 64 := rfl
|
||||
@[simp] theorem Int16.toBitVec_toISize (x : Int16) : x.toISize.toBitVec = x.toBitVec.signExtend System.Platform.numBits := rfl
|
||||
|
||||
@[simp] theorem Int32.toBitVec_toInt8 (x : Int32) : x.toInt8.toBitVec = x.toBitVec.signExtend 8 := (rfl)
|
||||
@[simp] theorem Int32.toBitVec_toInt16 (x : Int32) : x.toInt16.toBitVec = x.toBitVec.signExtend 16 := (rfl)
|
||||
@[simp] theorem Int32.toBitVec_toInt64 (x : Int32) : x.toInt64.toBitVec = x.toBitVec.signExtend 64 := (rfl)
|
||||
@[simp] theorem Int32.toBitVec_toISize (x : Int32) : x.toISize.toBitVec = x.toBitVec.signExtend System.Platform.numBits := (rfl)
|
||||
@[simp] theorem Int32.toBitVec_toInt8 (x : Int32) : x.toInt8.toBitVec = x.toBitVec.signExtend 8 := rfl
|
||||
@[simp] theorem Int32.toBitVec_toInt16 (x : Int32) : x.toInt16.toBitVec = x.toBitVec.signExtend 16 := rfl
|
||||
@[simp] theorem Int32.toBitVec_toInt64 (x : Int32) : x.toInt64.toBitVec = x.toBitVec.signExtend 64 := rfl
|
||||
@[simp] theorem Int32.toBitVec_toISize (x : Int32) : x.toISize.toBitVec = x.toBitVec.signExtend System.Platform.numBits := rfl
|
||||
|
||||
@[simp] theorem Int64.toBitVec_toInt8 (x : Int64) : x.toInt8.toBitVec = x.toBitVec.signExtend 8 := (rfl)
|
||||
@[simp] theorem Int64.toBitVec_toInt16 (x : Int64) : x.toInt16.toBitVec = x.toBitVec.signExtend 16 := (rfl)
|
||||
@[simp] theorem Int64.toBitVec_toInt32 (x : Int64) : x.toInt32.toBitVec = x.toBitVec.signExtend 32 := (rfl)
|
||||
@[simp] theorem Int64.toBitVec_toISize (x : Int64) : x.toISize.toBitVec = x.toBitVec.signExtend System.Platform.numBits := (rfl)
|
||||
@[simp] theorem Int64.toBitVec_toInt8 (x : Int64) : x.toInt8.toBitVec = x.toBitVec.signExtend 8 := rfl
|
||||
@[simp] theorem Int64.toBitVec_toInt16 (x : Int64) : x.toInt16.toBitVec = x.toBitVec.signExtend 16 := rfl
|
||||
@[simp] theorem Int64.toBitVec_toInt32 (x : Int64) : x.toInt32.toBitVec = x.toBitVec.signExtend 32 := rfl
|
||||
@[simp] theorem Int64.toBitVec_toISize (x : Int64) : x.toISize.toBitVec = x.toBitVec.signExtend System.Platform.numBits := rfl
|
||||
|
||||
@[simp] theorem ISize.toBitVec_toInt8 (x : ISize) : x.toInt8.toBitVec = x.toBitVec.signExtend 8 := (rfl)
|
||||
@[simp] theorem ISize.toBitVec_toInt16 (x : ISize) : x.toInt16.toBitVec = x.toBitVec.signExtend 16 := (rfl)
|
||||
@[simp] theorem ISize.toBitVec_toInt32 (x : ISize) : x.toInt32.toBitVec = x.toBitVec.signExtend 32 := (rfl)
|
||||
@[simp] theorem ISize.toBitVec_toInt64 (x : ISize) : x.toInt64.toBitVec = x.toBitVec.signExtend 64 := (rfl)
|
||||
@[simp] theorem ISize.toBitVec_toInt8 (x : ISize) : x.toInt8.toBitVec = x.toBitVec.signExtend 8 := rfl
|
||||
@[simp] theorem ISize.toBitVec_toInt16 (x : ISize) : x.toInt16.toBitVec = x.toBitVec.signExtend 16 := rfl
|
||||
@[simp] theorem ISize.toBitVec_toInt32 (x : ISize) : x.toInt32.toBitVec = x.toBitVec.signExtend 32 := rfl
|
||||
@[simp] theorem ISize.toBitVec_toInt64 (x : ISize) : x.toInt64.toBitVec = x.toBitVec.signExtend 64 := rfl
|
||||
|
||||
theorem Int8.toInt_lt (x : Int8) : x.toInt < 2 ^ 7 := Int.lt_of_mul_lt_mul_left BitVec.two_mul_toInt_lt (by decide)
|
||||
theorem Int8.le_toInt (x : Int8) : -2 ^ 7 ≤ x.toInt := Int.le_of_mul_le_mul_left BitVec.le_two_mul_toInt (by decide)
|
||||
@@ -454,17 +454,17 @@ theorem ISize.toNatClampNeg_lt (x : ISize) : x.toNatClampNeg < 2 ^ 63 := (Int.to
|
||||
@[simp] theorem ISize.toNatClampNeg_toInt64 (x : ISize) : x.toInt64.toNatClampNeg = x.toNatClampNeg :=
|
||||
congrArg Int.toNat x.toInt_toInt64
|
||||
|
||||
@[simp] theorem Int8.toInt8_toUInt8 (x : Int8) : x.toUInt8.toInt8 = x := (rfl)
|
||||
@[simp] theorem Int16.toInt16_toUInt16 (x : Int16) : x.toUInt16.toInt16 = x := (rfl)
|
||||
@[simp] theorem Int32.toInt32_toUInt32 (x : Int32) : x.toUInt32.toInt32 = x := (rfl)
|
||||
@[simp] theorem Int64.toInt64_toUInt64 (x : Int64) : x.toUInt64.toInt64 = x := (rfl)
|
||||
@[simp] theorem ISize.toISize_toUSize (x : ISize) : x.toUSize.toISize = x := (rfl)
|
||||
@[simp] theorem Int8.toInt8_toUInt8 (x : Int8) : x.toUInt8.toInt8 = x := rfl
|
||||
@[simp] theorem Int16.toInt16_toUInt16 (x : Int16) : x.toUInt16.toInt16 = x := rfl
|
||||
@[simp] theorem Int32.toInt32_toUInt32 (x : Int32) : x.toUInt32.toInt32 = x := rfl
|
||||
@[simp] theorem Int64.toInt64_toUInt64 (x : Int64) : x.toUInt64.toInt64 = x := rfl
|
||||
@[simp] theorem ISize.toISize_toUSize (x : ISize) : x.toUSize.toISize = x := rfl
|
||||
|
||||
theorem Int8.toNat_toBitVec (x : Int8) : x.toBitVec.toNat = x.toUInt8.toNat := (rfl)
|
||||
theorem Int16.toNat_toBitVec (x : Int16) : x.toBitVec.toNat = x.toUInt16.toNat := (rfl)
|
||||
theorem Int32.toNat_toBitVec (x : Int32) : x.toBitVec.toNat = x.toUInt32.toNat := (rfl)
|
||||
theorem Int64.toNat_toBitVec (x : Int64) : x.toBitVec.toNat = x.toUInt64.toNat := (rfl)
|
||||
theorem ISize.toNat_toBitVec (x : ISize) : x.toBitVec.toNat = x.toUSize.toNat := (rfl)
|
||||
theorem Int8.toNat_toBitVec (x : Int8) : x.toBitVec.toNat = x.toUInt8.toNat := rfl
|
||||
theorem Int16.toNat_toBitVec (x : Int16) : x.toBitVec.toNat = x.toUInt16.toNat := rfl
|
||||
theorem Int32.toNat_toBitVec (x : Int32) : x.toBitVec.toNat = x.toUInt32.toNat := rfl
|
||||
theorem Int64.toNat_toBitVec (x : Int64) : x.toBitVec.toNat = x.toUInt64.toNat := rfl
|
||||
theorem ISize.toNat_toBitVec (x : ISize) : x.toBitVec.toNat = x.toUSize.toNat := rfl
|
||||
|
||||
theorem Int8.toNat_toBitVec_of_le {x : Int8} (hx : 0 ≤ x) : x.toBitVec.toNat = x.toNatClampNeg :=
|
||||
(x.toBitVec.toNat_toInt_of_sle hx).symm
|
||||
@@ -488,60 +488,60 @@ theorem Int64.toNat_toUInt64_of_le {x : Int64} (hx : 0 ≤ x) : x.toUInt64.toNat
|
||||
theorem ISize.toNat_toUSize_of_le {x : ISize} (hx : 0 ≤ x) : x.toUSize.toNat = x.toNatClampNeg := by
|
||||
rw [← toNat_toBitVec, toNat_toBitVec_of_le hx]
|
||||
|
||||
theorem Int8.toFin_toBitVec (x : Int8) : x.toBitVec.toFin = x.toUInt8.toFin := (rfl)
|
||||
theorem Int16.toFin_toBitVec (x : Int16) : x.toBitVec.toFin = x.toUInt16.toFin := (rfl)
|
||||
theorem Int32.toFin_toBitVec (x : Int32) : x.toBitVec.toFin = x.toUInt32.toFin := (rfl)
|
||||
theorem Int64.toFin_toBitVec (x : Int64) : x.toBitVec.toFin = x.toUInt64.toFin := (rfl)
|
||||
theorem ISize.toFin_toBitVec (x : ISize) : x.toBitVec.toFin = x.toUSize.toFin := (rfl)
|
||||
theorem Int8.toFin_toBitVec (x : Int8) : x.toBitVec.toFin = x.toUInt8.toFin := rfl
|
||||
theorem Int16.toFin_toBitVec (x : Int16) : x.toBitVec.toFin = x.toUInt16.toFin := rfl
|
||||
theorem Int32.toFin_toBitVec (x : Int32) : x.toBitVec.toFin = x.toUInt32.toFin := rfl
|
||||
theorem Int64.toFin_toBitVec (x : Int64) : x.toBitVec.toFin = x.toUInt64.toFin := rfl
|
||||
theorem ISize.toFin_toBitVec (x : ISize) : x.toBitVec.toFin = x.toUSize.toFin := rfl
|
||||
|
||||
@[simp] theorem Int8.toBitVec_toUInt8 (x : Int8) : x.toUInt8.toBitVec = x.toBitVec := (rfl)
|
||||
@[simp] theorem Int16.toBitVec_toUInt16 (x : Int16) : x.toUInt16.toBitVec = x.toBitVec := (rfl)
|
||||
@[simp] theorem Int32.toBitVec_toUInt32 (x : Int32) : x.toUInt32.toBitVec = x.toBitVec := (rfl)
|
||||
@[simp] theorem Int64.toBitVec_toUInt64 (x : Int64) : x.toUInt64.toBitVec = x.toBitVec := (rfl)
|
||||
@[simp] theorem ISize.toBitVec_toUSize (x : ISize) : x.toUSize.toBitVec = x.toBitVec := (rfl)
|
||||
@[simp] theorem Int8.toBitVec_toUInt8 (x : Int8) : x.toUInt8.toBitVec = x.toBitVec := rfl
|
||||
@[simp] theorem Int16.toBitVec_toUInt16 (x : Int16) : x.toUInt16.toBitVec = x.toBitVec := rfl
|
||||
@[simp] theorem Int32.toBitVec_toUInt32 (x : Int32) : x.toUInt32.toBitVec = x.toBitVec := rfl
|
||||
@[simp] theorem Int64.toBitVec_toUInt64 (x : Int64) : x.toUInt64.toBitVec = x.toBitVec := rfl
|
||||
@[simp] theorem ISize.toBitVec_toUSize (x : ISize) : x.toUSize.toBitVec = x.toBitVec := rfl
|
||||
|
||||
@[simp] theorem UInt8.ofBitVec_int8ToBitVec (x : Int8) : UInt8.ofBitVec x.toBitVec = x.toUInt8 := (rfl)
|
||||
@[simp] theorem UInt16.ofBitVec_int16ToBitVec (x : Int16) : UInt16.ofBitVec x.toBitVec = x.toUInt16 := (rfl)
|
||||
@[simp] theorem UInt32.ofBitVec_int32ToBitVec (x : Int32) : UInt32.ofBitVec x.toBitVec = x.toUInt32 := (rfl)
|
||||
@[simp] theorem UInt64.ofBitVec_int64ToBitVec (x : Int64) : UInt64.ofBitVec x.toBitVec = x.toUInt64 := (rfl)
|
||||
@[simp] theorem USize.ofBitVec_iSizeToBitVec (x : ISize) : USize.ofBitVec x.toBitVec = x.toUSize := (rfl)
|
||||
@[simp] theorem UInt8.ofBitVec_int8ToBitVec (x : Int8) : UInt8.ofBitVec x.toBitVec = x.toUInt8 := rfl
|
||||
@[simp] theorem UInt16.ofBitVec_int16ToBitVec (x : Int16) : UInt16.ofBitVec x.toBitVec = x.toUInt16 := rfl
|
||||
@[simp] theorem UInt32.ofBitVec_int32ToBitVec (x : Int32) : UInt32.ofBitVec x.toBitVec = x.toUInt32 := rfl
|
||||
@[simp] theorem UInt64.ofBitVec_int64ToBitVec (x : Int64) : UInt64.ofBitVec x.toBitVec = x.toUInt64 := rfl
|
||||
@[simp] theorem USize.ofBitVec_iSizeToBitVec (x : ISize) : USize.ofBitVec x.toBitVec = x.toUSize := rfl
|
||||
|
||||
@[simp] theorem Int8.ofBitVec_toBitVec (x : Int8) : Int8.ofBitVec x.toBitVec = x := (rfl)
|
||||
@[simp] theorem Int16.ofBitVec_toBitVec (x : Int16) : Int16.ofBitVec x.toBitVec = x := (rfl)
|
||||
@[simp] theorem Int32.ofBitVec_toBitVec (x : Int32) : Int32.ofBitVec x.toBitVec = x := (rfl)
|
||||
@[simp] theorem Int64.ofBitVec_toBitVec (x : Int64) : Int64.ofBitVec x.toBitVec = x := (rfl)
|
||||
@[simp] theorem ISize.ofBitVec_toBitVec (x : ISize) : ISize.ofBitVec x.toBitVec = x := (rfl)
|
||||
@[simp] theorem Int8.ofBitVec_toBitVec (x : Int8) : Int8.ofBitVec x.toBitVec = x := rfl
|
||||
@[simp] theorem Int16.ofBitVec_toBitVec (x : Int16) : Int16.ofBitVec x.toBitVec = x := rfl
|
||||
@[simp] theorem Int32.ofBitVec_toBitVec (x : Int32) : Int32.ofBitVec x.toBitVec = x := rfl
|
||||
@[simp] theorem Int64.ofBitVec_toBitVec (x : Int64) : Int64.ofBitVec x.toBitVec = x := rfl
|
||||
@[simp] theorem ISize.ofBitVec_toBitVec (x : ISize) : ISize.ofBitVec x.toBitVec = x := rfl
|
||||
|
||||
@[simp] theorem Int8.ofBitVec_int16ToBitVec (x : Int16) : Int8.ofBitVec (x.toBitVec.signExtend 8) = x.toInt8 := (rfl)
|
||||
@[simp] theorem Int8.ofBitVec_int32ToBitVec (x : Int32) : Int8.ofBitVec (x.toBitVec.signExtend 8) = x.toInt8 := (rfl)
|
||||
@[simp] theorem Int8.ofBitVec_int64ToBitVec (x : Int64) : Int8.ofBitVec (x.toBitVec.signExtend 8) = x.toInt8 := (rfl)
|
||||
@[simp] theorem Int8.ofBitVec_iSizeToBitVec (x : ISize) : Int8.ofBitVec (x.toBitVec.signExtend 8) = x.toInt8 := (rfl)
|
||||
@[simp] theorem Int8.ofBitVec_int16ToBitVec (x : Int16) : Int8.ofBitVec (x.toBitVec.signExtend 8) = x.toInt8 := rfl
|
||||
@[simp] theorem Int8.ofBitVec_int32ToBitVec (x : Int32) : Int8.ofBitVec (x.toBitVec.signExtend 8) = x.toInt8 := rfl
|
||||
@[simp] theorem Int8.ofBitVec_int64ToBitVec (x : Int64) : Int8.ofBitVec (x.toBitVec.signExtend 8) = x.toInt8 := rfl
|
||||
@[simp] theorem Int8.ofBitVec_iSizeToBitVec (x : ISize) : Int8.ofBitVec (x.toBitVec.signExtend 8) = x.toInt8 := rfl
|
||||
|
||||
@[simp] theorem Int16.ofBitVec_int8ToBitVec (x : Int8) : Int16.ofBitVec (x.toBitVec.signExtend 16) = x.toInt16 := (rfl)
|
||||
@[simp] theorem Int16.ofBitVec_int32ToBitVec (x : Int32) : Int16.ofBitVec (x.toBitVec.signExtend 16) = x.toInt16 := (rfl)
|
||||
@[simp] theorem Int16.ofBitVec_int64ToBitVec (x : Int64) : Int16.ofBitVec (x.toBitVec.signExtend 16) = x.toInt16 := (rfl)
|
||||
@[simp] theorem Int16.ofBitVec_iSizeToBitVec (x : ISize) : Int16.ofBitVec (x.toBitVec.signExtend 16) = x.toInt16 := (rfl)
|
||||
@[simp] theorem Int16.ofBitVec_int8ToBitVec (x : Int8) : Int16.ofBitVec (x.toBitVec.signExtend 16) = x.toInt16 := rfl
|
||||
@[simp] theorem Int16.ofBitVec_int32ToBitVec (x : Int32) : Int16.ofBitVec (x.toBitVec.signExtend 16) = x.toInt16 := rfl
|
||||
@[simp] theorem Int16.ofBitVec_int64ToBitVec (x : Int64) : Int16.ofBitVec (x.toBitVec.signExtend 16) = x.toInt16 := rfl
|
||||
@[simp] theorem Int16.ofBitVec_iSizeToBitVec (x : ISize) : Int16.ofBitVec (x.toBitVec.signExtend 16) = x.toInt16 := rfl
|
||||
|
||||
@[simp] theorem Int32.ofBitVec_int8ToBitVec (x : Int8) : Int32.ofBitVec (x.toBitVec.signExtend 32) = x.toInt32 := (rfl)
|
||||
@[simp] theorem Int32.ofBitVec_int16ToBitVec (x : Int16) : Int32.ofBitVec (x.toBitVec.signExtend 32) = x.toInt32 := (rfl)
|
||||
@[simp] theorem Int32.ofBitVec_int64ToBitVec (x : Int64) : Int32.ofBitVec (x.toBitVec.signExtend 32) = x.toInt32 := (rfl)
|
||||
@[simp] theorem Int32.ofBitVec_iSizeToBitVec (x : ISize) : Int32.ofBitVec (x.toBitVec.signExtend 32) = x.toInt32 := (rfl)
|
||||
@[simp] theorem Int32.ofBitVec_int8ToBitVec (x : Int8) : Int32.ofBitVec (x.toBitVec.signExtend 32) = x.toInt32 := rfl
|
||||
@[simp] theorem Int32.ofBitVec_int16ToBitVec (x : Int16) : Int32.ofBitVec (x.toBitVec.signExtend 32) = x.toInt32 := rfl
|
||||
@[simp] theorem Int32.ofBitVec_int64ToBitVec (x : Int64) : Int32.ofBitVec (x.toBitVec.signExtend 32) = x.toInt32 := rfl
|
||||
@[simp] theorem Int32.ofBitVec_iSizeToBitVec (x : ISize) : Int32.ofBitVec (x.toBitVec.signExtend 32) = x.toInt32 := rfl
|
||||
|
||||
@[simp] theorem Int64.ofBitVec_int8ToBitVec (x : Int8) : Int64.ofBitVec (x.toBitVec.signExtend 64) = x.toInt64 := (rfl)
|
||||
@[simp] theorem Int64.ofBitVec_int16ToBitVec (x : Int16) : Int64.ofBitVec (x.toBitVec.signExtend 64) = x.toInt64 := (rfl)
|
||||
@[simp] theorem Int64.ofBitVec_int32ToBitVec (x : Int32) : Int64.ofBitVec (x.toBitVec.signExtend 64) = x.toInt64 := (rfl)
|
||||
@[simp] theorem Int64.ofBitVec_iSizeToBitVec (x : ISize) : Int64.ofBitVec (x.toBitVec.signExtend 64) = x.toInt64 := (rfl)
|
||||
@[simp] theorem Int64.ofBitVec_int8ToBitVec (x : Int8) : Int64.ofBitVec (x.toBitVec.signExtend 64) = x.toInt64 := rfl
|
||||
@[simp] theorem Int64.ofBitVec_int16ToBitVec (x : Int16) : Int64.ofBitVec (x.toBitVec.signExtend 64) = x.toInt64 := rfl
|
||||
@[simp] theorem Int64.ofBitVec_int32ToBitVec (x : Int32) : Int64.ofBitVec (x.toBitVec.signExtend 64) = x.toInt64 := rfl
|
||||
@[simp] theorem Int64.ofBitVec_iSizeToBitVec (x : ISize) : Int64.ofBitVec (x.toBitVec.signExtend 64) = x.toInt64 := rfl
|
||||
|
||||
@[simp] theorem ISize.ofBitVec_int8ToBitVec (x : Int8) : ISize.ofBitVec (x.toBitVec.signExtend System.Platform.numBits) = x.toISize := (rfl)
|
||||
@[simp] theorem ISize.ofBitVec_int16ToBitVec (x : Int16) : ISize.ofBitVec (x.toBitVec.signExtend System.Platform.numBits) = x.toISize := (rfl)
|
||||
@[simp] theorem ISize.ofBitVec_int32ToBitVec (x : Int32) : ISize.ofBitVec (x.toBitVec.signExtend System.Platform.numBits) = x.toISize := (rfl)
|
||||
@[simp] theorem ISize.ofBitVec_int64ToBitVec (x : Int64) : ISize.ofBitVec (x.toBitVec.signExtend System.Platform.numBits) = x.toISize := (rfl)
|
||||
@[simp] theorem ISize.ofBitVec_int8ToBitVec (x : Int8) : ISize.ofBitVec (x.toBitVec.signExtend System.Platform.numBits) = x.toISize := rfl
|
||||
@[simp] theorem ISize.ofBitVec_int16ToBitVec (x : Int16) : ISize.ofBitVec (x.toBitVec.signExtend System.Platform.numBits) = x.toISize := rfl
|
||||
@[simp] theorem ISize.ofBitVec_int32ToBitVec (x : Int32) : ISize.ofBitVec (x.toBitVec.signExtend System.Platform.numBits) = x.toISize := rfl
|
||||
@[simp] theorem ISize.ofBitVec_int64ToBitVec (x : Int64) : ISize.ofBitVec (x.toBitVec.signExtend System.Platform.numBits) = x.toISize := rfl
|
||||
|
||||
@[simp] theorem Int8.toBitVec_ofIntLE (x : Int) (h₁ h₂) : (Int8.ofIntLE x h₁ h₂).toBitVec = BitVec.ofInt 8 x := (rfl)
|
||||
@[simp] theorem Int16.toBitVec_ofIntLE (x : Int) (h₁ h₂) : (Int16.ofIntLE x h₁ h₂).toBitVec = BitVec.ofInt 16 x := (rfl)
|
||||
@[simp] theorem Int32.toBitVec_ofIntLE (x : Int) (h₁ h₂) : (Int32.ofIntLE x h₁ h₂).toBitVec = BitVec.ofInt 32 x := (rfl)
|
||||
@[simp] theorem Int64.toBitVec_ofIntLE (x : Int) (h₁ h₂) : (Int64.ofIntLE x h₁ h₂).toBitVec = BitVec.ofInt 64 x := (rfl)
|
||||
@[simp] theorem ISize.toBitVec_ofIntLE (x : Int) (h₁ h₂) : (ISize.ofIntLE x h₁ h₂).toBitVec = BitVec.ofInt System.Platform.numBits x := (rfl)
|
||||
@[simp] theorem Int8.toBitVec_ofIntLE (x : Int) (h₁ h₂) : (Int8.ofIntLE x h₁ h₂).toBitVec = BitVec.ofInt 8 x := rfl
|
||||
@[simp] theorem Int16.toBitVec_ofIntLE (x : Int) (h₁ h₂) : (Int16.ofIntLE x h₁ h₂).toBitVec = BitVec.ofInt 16 x := rfl
|
||||
@[simp] theorem Int32.toBitVec_ofIntLE (x : Int) (h₁ h₂) : (Int32.ofIntLE x h₁ h₂).toBitVec = BitVec.ofInt 32 x := rfl
|
||||
@[simp] theorem Int64.toBitVec_ofIntLE (x : Int) (h₁ h₂) : (Int64.ofIntLE x h₁ h₂).toBitVec = BitVec.ofInt 64 x := rfl
|
||||
@[simp] theorem ISize.toBitVec_ofIntLE (x : Int) (h₁ h₂) : (ISize.ofIntLE x h₁ h₂).toBitVec = BitVec.ofInt System.Platform.numBits x := rfl
|
||||
|
||||
@[simp] theorem Int8.toInt_bmod (x : Int8) : x.toInt.bmod 256 = x.toInt := Int.bmod_eq_of_le x.le_toInt x.toInt_lt
|
||||
@[simp] theorem Int16.toInt_bmod (x : Int16) : x.toInt.bmod 65536 = x.toInt := Int.bmod_eq_of_le x.le_toInt x.toInt_lt
|
||||
@@ -594,40 +594,40 @@ theorem ISize.toFin_toBitVec (x : ISize) : x.toBitVec.toFin = x.toUSize.toFin :=
|
||||
@[simp] theorem Int64.ofIntLE_toInt (x : Int64) : Int64.ofIntLE x.toInt x.minValue_le_toInt x.toInt_le = x := Int64.toBitVec.inj (by simp)
|
||||
@[simp] theorem ISize.ofIntLE_toInt (x : ISize) : ISize.ofIntLE x.toInt x.minValue_le_toInt x.toInt_le = x := ISize.toBitVec.inj (by simp)
|
||||
|
||||
theorem Int8.ofIntLE_int16ToInt (x : Int16) {h₁ h₂} : Int8.ofIntLE x.toInt h₁ h₂ = x.toInt8 := (rfl)
|
||||
theorem Int8.ofIntLE_int32ToInt (x : Int32) {h₁ h₂} : Int8.ofIntLE x.toInt h₁ h₂ = x.toInt8 := (rfl)
|
||||
theorem Int8.ofIntLE_int64ToInt (x : Int64) {h₁ h₂} : Int8.ofIntLE x.toInt h₁ h₂ = x.toInt8 := (rfl)
|
||||
theorem Int8.ofIntLE_iSizeToInt (x : ISize) {h₁ h₂} : Int8.ofIntLE x.toInt h₁ h₂ = x.toInt8 := (rfl)
|
||||
theorem Int8.ofIntLE_int16ToInt (x : Int16) {h₁ h₂} : Int8.ofIntLE x.toInt h₁ h₂ = x.toInt8 := rfl
|
||||
theorem Int8.ofIntLE_int32ToInt (x : Int32) {h₁ h₂} : Int8.ofIntLE x.toInt h₁ h₂ = x.toInt8 := rfl
|
||||
theorem Int8.ofIntLE_int64ToInt (x : Int64) {h₁ h₂} : Int8.ofIntLE x.toInt h₁ h₂ = x.toInt8 := rfl
|
||||
theorem Int8.ofIntLE_iSizeToInt (x : ISize) {h₁ h₂} : Int8.ofIntLE x.toInt h₁ h₂ = x.toInt8 := rfl
|
||||
|
||||
@[simp] theorem Int16.ofIntLE_int8ToInt (x : Int8) :
|
||||
Int16.ofIntLE x.toInt (Int.le_trans (by decide) x.minValue_le_toInt) (Int.le_trans x.toInt_le (by decide)) = x.toInt16 := (rfl)
|
||||
theorem Int16.ofIntLE_int32ToInt (x : Int32) {h₁ h₂} : Int16.ofIntLE x.toInt h₁ h₂ = x.toInt16 := (rfl)
|
||||
theorem Int16.ofIntLE_int64ToInt (x : Int64) {h₁ h₂} : Int16.ofIntLE x.toInt h₁ h₂ = x.toInt16 := (rfl)
|
||||
theorem Int16.ofIntLE_iSizeToInt (x : ISize) {h₁ h₂} : Int16.ofIntLE x.toInt h₁ h₂ = x.toInt16 := (rfl)
|
||||
Int16.ofIntLE x.toInt (Int.le_trans (by decide) x.minValue_le_toInt) (Int.le_trans x.toInt_le (by decide)) = x.toInt16 := rfl
|
||||
theorem Int16.ofIntLE_int32ToInt (x : Int32) {h₁ h₂} : Int16.ofIntLE x.toInt h₁ h₂ = x.toInt16 := rfl
|
||||
theorem Int16.ofIntLE_int64ToInt (x : Int64) {h₁ h₂} : Int16.ofIntLE x.toInt h₁ h₂ = x.toInt16 := rfl
|
||||
theorem Int16.ofIntLE_iSizeToInt (x : ISize) {h₁ h₂} : Int16.ofIntLE x.toInt h₁ h₂ = x.toInt16 := rfl
|
||||
|
||||
@[simp] theorem Int32.ofIntLE_int8ToInt (x : Int8) :
|
||||
Int32.ofIntLE x.toInt (Int.le_trans (by decide) x.minValue_le_toInt) (Int.le_trans x.toInt_le (by decide)) = x.toInt32 := (rfl)
|
||||
Int32.ofIntLE x.toInt (Int.le_trans (by decide) x.minValue_le_toInt) (Int.le_trans x.toInt_le (by decide)) = x.toInt32 := rfl
|
||||
@[simp] theorem Int32.ofIntLE_int16ToInt (x : Int16) :
|
||||
Int32.ofIntLE x.toInt (Int.le_trans (by decide) x.minValue_le_toInt) (Int.le_trans x.toInt_le (by decide)) = x.toInt32 := (rfl)
|
||||
theorem Int32.ofIntLE_int64ToInt (x : Int64) {h₁ h₂} : Int32.ofIntLE x.toInt h₁ h₂ = x.toInt32 := (rfl)
|
||||
theorem Int32.ofIntLE_iSizeToInt (x : ISize) {h₁ h₂} : Int32.ofIntLE x.toInt h₁ h₂ = x.toInt32 := (rfl)
|
||||
Int32.ofIntLE x.toInt (Int.le_trans (by decide) x.minValue_le_toInt) (Int.le_trans x.toInt_le (by decide)) = x.toInt32 := rfl
|
||||
theorem Int32.ofIntLE_int64ToInt (x : Int64) {h₁ h₂} : Int32.ofIntLE x.toInt h₁ h₂ = x.toInt32 := rfl
|
||||
theorem Int32.ofIntLE_iSizeToInt (x : ISize) {h₁ h₂} : Int32.ofIntLE x.toInt h₁ h₂ = x.toInt32 := rfl
|
||||
|
||||
@[simp] theorem Int64.ofIntLE_int8ToInt (x : Int8) :
|
||||
Int64.ofIntLE x.toInt (Int.le_trans (by decide) x.minValue_le_toInt) (Int.le_trans x.toInt_le (by decide)) = x.toInt64 := (rfl)
|
||||
Int64.ofIntLE x.toInt (Int.le_trans (by decide) x.minValue_le_toInt) (Int.le_trans x.toInt_le (by decide)) = x.toInt64 := rfl
|
||||
@[simp] theorem Int64.ofIntLE_int16ToInt (x : Int16) :
|
||||
Int64.ofIntLE x.toInt (Int.le_trans (by decide) x.minValue_le_toInt) (Int.le_trans x.toInt_le (by decide)) = x.toInt64 := (rfl)
|
||||
Int64.ofIntLE x.toInt (Int.le_trans (by decide) x.minValue_le_toInt) (Int.le_trans x.toInt_le (by decide)) = x.toInt64 := rfl
|
||||
@[simp] theorem Int64.ofIntLE_int32ToInt (x : Int32) :
|
||||
Int64.ofIntLE x.toInt (Int.le_trans (by decide) x.minValue_le_toInt) (Int.le_trans x.toInt_le (by decide)) = x.toInt64 := (rfl)
|
||||
Int64.ofIntLE x.toInt (Int.le_trans (by decide) x.minValue_le_toInt) (Int.le_trans x.toInt_le (by decide)) = x.toInt64 := rfl
|
||||
@[simp] theorem Int64.ofIntLE_iSizeToInt (x : ISize) :
|
||||
Int64.ofIntLE x.toInt x.int64MinValue_le_toInt x.toInt_le_int64MaxValue = x.toInt64 := (rfl)
|
||||
Int64.ofIntLE x.toInt x.int64MinValue_le_toInt x.toInt_le_int64MaxValue = x.toInt64 := rfl
|
||||
|
||||
@[simp] theorem ISize.ofIntLE_int8ToInt (x : Int8) :
|
||||
ISize.ofIntLE x.toInt x.iSizeMinValue_le_toInt x.toInt_le_iSizeMaxValue = x.toISize := (rfl)
|
||||
ISize.ofIntLE x.toInt x.iSizeMinValue_le_toInt x.toInt_le_iSizeMaxValue = x.toISize := rfl
|
||||
@[simp] theorem ISize.ofIntLE_int16ToInt (x : Int16) :
|
||||
ISize.ofIntLE x.toInt x.iSizeMinValue_le_toInt x.toInt_le_iSizeMaxValue = x.toISize := (rfl)
|
||||
ISize.ofIntLE x.toInt x.iSizeMinValue_le_toInt x.toInt_le_iSizeMaxValue = x.toISize := rfl
|
||||
@[simp] theorem ISize.ofIntLE_int32ToInt (x : Int32) :
|
||||
ISize.ofIntLE x.toInt x.iSizeMinValue_le_toInt x.toInt_le_iSizeMaxValue = x.toISize := (rfl)
|
||||
theorem ISize.ofIntLE_int64ToInt (x : Int64) {h₁ h₂} : ISize.ofIntLE x.toInt h₁ h₂ = x.toISize := (rfl)
|
||||
ISize.ofIntLE x.toInt x.iSizeMinValue_le_toInt x.toInt_le_iSizeMaxValue = x.toISize := rfl
|
||||
theorem ISize.ofIntLE_int64ToInt (x : Int64) {h₁ h₂} : ISize.ofIntLE x.toInt h₁ h₂ = x.toISize := rfl
|
||||
|
||||
@[simp] theorem Int8.ofInt_toInt (x : Int8) : Int8.ofInt x.toInt = x := Int8.toBitVec.inj (by simp)
|
||||
@[simp] theorem Int16.ofInt_toInt (x : Int16) : Int16.ofInt x.toInt = x := Int16.toBitVec.inj (by simp)
|
||||
@@ -635,30 +635,30 @@ theorem ISize.ofIntLE_int64ToInt (x : Int64) {h₁ h₂} : ISize.ofIntLE x.toInt
|
||||
@[simp] theorem Int64.ofInt_toInt (x : Int64) : Int64.ofInt x.toInt = x := Int64.toBitVec.inj (by simp)
|
||||
@[simp] theorem ISize.ofInt_toInt (x : ISize) : ISize.ofInt x.toInt = x := ISize.toBitVec.inj (by simp)
|
||||
|
||||
@[simp] theorem Int8.ofInt_int16ToInt (x : Int16) : Int8.ofInt x.toInt = x.toInt8 := (rfl)
|
||||
@[simp] theorem Int8.ofInt_int32ToInt (x : Int32) : Int8.ofInt x.toInt = x.toInt8 := (rfl)
|
||||
@[simp] theorem Int8.ofInt_int64ToInt (x : Int64) : Int8.ofInt x.toInt = x.toInt8 := (rfl)
|
||||
@[simp] theorem Int8.ofInt_iSizeToInt (x : ISize) : Int8.ofInt x.toInt = x.toInt8 := (rfl)
|
||||
@[simp] theorem Int8.ofInt_int16ToInt (x : Int16) : Int8.ofInt x.toInt = x.toInt8 := rfl
|
||||
@[simp] theorem Int8.ofInt_int32ToInt (x : Int32) : Int8.ofInt x.toInt = x.toInt8 := rfl
|
||||
@[simp] theorem Int8.ofInt_int64ToInt (x : Int64) : Int8.ofInt x.toInt = x.toInt8 := rfl
|
||||
@[simp] theorem Int8.ofInt_iSizeToInt (x : ISize) : Int8.ofInt x.toInt = x.toInt8 := rfl
|
||||
|
||||
@[simp] theorem Int16.ofInt_int8ToInt (x : Int8) : Int16.ofInt x.toInt = x.toInt16 := (rfl)
|
||||
@[simp] theorem Int16.ofInt_int32ToInt (x : Int32) : Int16.ofInt x.toInt = x.toInt16 := (rfl)
|
||||
@[simp] theorem Int16.ofInt_int64ToInt (x : Int64) : Int16.ofInt x.toInt = x.toInt16 := (rfl)
|
||||
@[simp] theorem Int16.ofInt_iSizeToInt (x : ISize) : Int16.ofInt x.toInt = x.toInt16 := (rfl)
|
||||
@[simp] theorem Int16.ofInt_int8ToInt (x : Int8) : Int16.ofInt x.toInt = x.toInt16 := rfl
|
||||
@[simp] theorem Int16.ofInt_int32ToInt (x : Int32) : Int16.ofInt x.toInt = x.toInt16 := rfl
|
||||
@[simp] theorem Int16.ofInt_int64ToInt (x : Int64) : Int16.ofInt x.toInt = x.toInt16 := rfl
|
||||
@[simp] theorem Int16.ofInt_iSizeToInt (x : ISize) : Int16.ofInt x.toInt = x.toInt16 := rfl
|
||||
|
||||
@[simp] theorem Int32.ofInt_int8ToInt (x : Int8) : Int32.ofInt x.toInt = x.toInt32 := (rfl)
|
||||
@[simp] theorem Int32.ofInt_int16ToInt (x : Int16) : Int32.ofInt x.toInt = x.toInt32 := (rfl)
|
||||
@[simp] theorem Int32.ofInt_int64ToInt (x : Int64) : Int32.ofInt x.toInt = x.toInt32 := (rfl)
|
||||
@[simp] theorem Int32.ofInt_iSizeToInt (x : ISize) : Int32.ofInt x.toInt = x.toInt32 := (rfl)
|
||||
@[simp] theorem Int32.ofInt_int8ToInt (x : Int8) : Int32.ofInt x.toInt = x.toInt32 := rfl
|
||||
@[simp] theorem Int32.ofInt_int16ToInt (x : Int16) : Int32.ofInt x.toInt = x.toInt32 := rfl
|
||||
@[simp] theorem Int32.ofInt_int64ToInt (x : Int64) : Int32.ofInt x.toInt = x.toInt32 := rfl
|
||||
@[simp] theorem Int32.ofInt_iSizeToInt (x : ISize) : Int32.ofInt x.toInt = x.toInt32 := rfl
|
||||
|
||||
@[simp] theorem Int64.ofInt_int8ToInt (x : Int8) : Int64.ofInt x.toInt = x.toInt64 := (rfl)
|
||||
@[simp] theorem Int64.ofInt_int16ToInt (x : Int16) : Int64.ofInt x.toInt = x.toInt64 := (rfl)
|
||||
@[simp] theorem Int64.ofInt_int32ToInt (x : Int32) : Int64.ofInt x.toInt = x.toInt64 := (rfl)
|
||||
@[simp] theorem Int64.ofInt_iSizeToInt (x : ISize) : Int64.ofInt x.toInt = x.toInt64 := (rfl)
|
||||
@[simp] theorem Int64.ofInt_int8ToInt (x : Int8) : Int64.ofInt x.toInt = x.toInt64 := rfl
|
||||
@[simp] theorem Int64.ofInt_int16ToInt (x : Int16) : Int64.ofInt x.toInt = x.toInt64 := rfl
|
||||
@[simp] theorem Int64.ofInt_int32ToInt (x : Int32) : Int64.ofInt x.toInt = x.toInt64 := rfl
|
||||
@[simp] theorem Int64.ofInt_iSizeToInt (x : ISize) : Int64.ofInt x.toInt = x.toInt64 := rfl
|
||||
|
||||
@[simp] theorem ISize.ofInt_int8ToInt (x : Int8) : ISize.ofInt x.toInt = x.toISize := (rfl)
|
||||
@[simp] theorem ISize.ofInt_int16ToInt (x : Int16) : ISize.ofInt x.toInt = x.toISize := (rfl)
|
||||
@[simp] theorem ISize.ofInt_int32ToInt (x : Int32) : ISize.ofInt x.toInt = x.toISize := (rfl)
|
||||
@[simp] theorem ISize.ofInt_int64ToInt (x : Int64) : ISize.ofInt x.toInt = x.toISize := (rfl)
|
||||
@[simp] theorem ISize.ofInt_int8ToInt (x : Int8) : ISize.ofInt x.toInt = x.toISize := rfl
|
||||
@[simp] theorem ISize.ofInt_int16ToInt (x : Int16) : ISize.ofInt x.toInt = x.toISize := rfl
|
||||
@[simp] theorem ISize.ofInt_int32ToInt (x : Int32) : ISize.ofInt x.toInt = x.toISize := rfl
|
||||
@[simp] theorem ISize.ofInt_int64ToInt (x : Int64) : ISize.ofInt x.toInt = x.toISize := rfl
|
||||
|
||||
@[simp] theorem Int8.toInt_ofIntLE {x : Int} {h₁ h₂} : (ofIntLE x h₁ h₂).toInt = x := by
|
||||
rw [ofIntLE, toInt_ofInt_of_le h₁ (Int.lt_of_le_sub_one h₂)]
|
||||
@@ -685,11 +685,11 @@ theorem Int64.ofIntLE_eq_ofIntTruncate {x : Int} {h₁ h₂} : (ofIntLE x h₁ h
|
||||
theorem ISize.ofIntLE_eq_ofIntTruncate {x : Int} {h₁ h₂} : (ofIntLE x h₁ h₂) = ofIntTruncate x := by
|
||||
rw [ofIntTruncate, dif_pos h₁, dif_pos h₂]
|
||||
|
||||
theorem Int8.ofIntLE_eq_ofInt {n : Int} (h₁ h₂) : Int8.ofIntLE n h₁ h₂ = Int8.ofInt n := (rfl)
|
||||
theorem Int16.ofIntLE_eq_ofInt {n : Int} (h₁ h₂) : Int16.ofIntLE n h₁ h₂ = Int16.ofInt n := (rfl)
|
||||
theorem Int32.ofIntLE_eq_ofInt {n : Int} (h₁ h₂) : Int32.ofIntLE n h₁ h₂ = Int32.ofInt n := (rfl)
|
||||
theorem Int64.ofIntLE_eq_ofInt {n : Int} (h₁ h₂) : Int64.ofIntLE n h₁ h₂ = Int64.ofInt n := (rfl)
|
||||
theorem ISize.ofIntLE_eq_ofInt {n : Int} (h₁ h₂) : ISize.ofIntLE n h₁ h₂ = ISize.ofInt n := (rfl)
|
||||
theorem Int8.ofIntLE_eq_ofInt {n : Int} (h₁ h₂) : Int8.ofIntLE n h₁ h₂ = Int8.ofInt n := rfl
|
||||
theorem Int16.ofIntLE_eq_ofInt {n : Int} (h₁ h₂) : Int16.ofIntLE n h₁ h₂ = Int16.ofInt n := rfl
|
||||
theorem Int32.ofIntLE_eq_ofInt {n : Int} (h₁ h₂) : Int32.ofIntLE n h₁ h₂ = Int32.ofInt n := rfl
|
||||
theorem Int64.ofIntLE_eq_ofInt {n : Int} (h₁ h₂) : Int64.ofIntLE n h₁ h₂ = Int64.ofInt n := rfl
|
||||
theorem ISize.ofIntLE_eq_ofInt {n : Int} (h₁ h₂) : ISize.ofIntLE n h₁ h₂ = ISize.ofInt n := rfl
|
||||
|
||||
theorem Int8.toInt_ofIntTruncate {x : Int} (h₁ : Int8.minValue.toInt ≤ x)
|
||||
(h₂ : x ≤ Int8.maxValue.toInt) : (Int8.ofIntTruncate x).toInt = x := by
|
||||
@@ -970,29 +970,29 @@ theorem UInt64.toInt64_ofNatLT {n : Nat} (hn) : (UInt64.ofNatLT n hn).toInt64 =
|
||||
theorem USize.toISize_ofNatLT {n : Nat} (hn) : (USize.ofNatLT n hn).toISize = ISize.ofNat n :=
|
||||
ISize.toBitVec.inj (by simp [BitVec.ofNatLT_eq_ofNat])
|
||||
|
||||
@[simp] theorem UInt8.toInt8_ofNat' {n : Nat} : (UInt8.ofNat n).toInt8 = Int8.ofNat n := (rfl)
|
||||
@[simp] theorem UInt16.toInt16_ofNat' {n : Nat} : (UInt16.ofNat n).toInt16 = Int16.ofNat n := (rfl)
|
||||
@[simp] theorem UInt32.toInt32_ofNat' {n : Nat} : (UInt32.ofNat n).toInt32 = Int32.ofNat n := (rfl)
|
||||
@[simp] theorem UInt64.toInt64_ofNat' {n : Nat} : (UInt64.ofNat n).toInt64 = Int64.ofNat n := (rfl)
|
||||
@[simp] theorem USize.toISize_ofNat' {n : Nat} : (USize.ofNat n).toISize = ISize.ofNat n := (rfl)
|
||||
@[simp] theorem UInt8.toInt8_ofNat' {n : Nat} : (UInt8.ofNat n).toInt8 = Int8.ofNat n := rfl
|
||||
@[simp] theorem UInt16.toInt16_ofNat' {n : Nat} : (UInt16.ofNat n).toInt16 = Int16.ofNat n := rfl
|
||||
@[simp] theorem UInt32.toInt32_ofNat' {n : Nat} : (UInt32.ofNat n).toInt32 = Int32.ofNat n := rfl
|
||||
@[simp] theorem UInt64.toInt64_ofNat' {n : Nat} : (UInt64.ofNat n).toInt64 = Int64.ofNat n := rfl
|
||||
@[simp] theorem USize.toISize_ofNat' {n : Nat} : (USize.ofNat n).toISize = ISize.ofNat n := rfl
|
||||
|
||||
@[simp] theorem UInt8.toInt8_ofNat {n : Nat} : toInt8 (no_index (OfNat.ofNat n)) = OfNat.ofNat n := (rfl)
|
||||
@[simp] theorem UInt16.toInt16_ofNat {n : Nat} : toInt16 (no_index (OfNat.ofNat n)) = OfNat.ofNat n := (rfl)
|
||||
@[simp] theorem UInt32.toInt32_ofNat {n : Nat} : toInt32 (no_index (OfNat.ofNat n)) = OfNat.ofNat n := (rfl)
|
||||
@[simp] theorem UInt64.toInt64_ofNat {n : Nat} : toInt64 (no_index (OfNat.ofNat n)) = OfNat.ofNat n := (rfl)
|
||||
@[simp] theorem USize.toISize_ofNat {n : Nat} : toISize (no_index (OfNat.ofNat n)) = OfNat.ofNat n := (rfl)
|
||||
@[simp] theorem UInt8.toInt8_ofNat {n : Nat} : toInt8 (no_index (OfNat.ofNat n)) = OfNat.ofNat n := rfl
|
||||
@[simp] theorem UInt16.toInt16_ofNat {n : Nat} : toInt16 (no_index (OfNat.ofNat n)) = OfNat.ofNat n := rfl
|
||||
@[simp] theorem UInt32.toInt32_ofNat {n : Nat} : toInt32 (no_index (OfNat.ofNat n)) = OfNat.ofNat n := rfl
|
||||
@[simp] theorem UInt64.toInt64_ofNat {n : Nat} : toInt64 (no_index (OfNat.ofNat n)) = OfNat.ofNat n := rfl
|
||||
@[simp] theorem USize.toISize_ofNat {n : Nat} : toISize (no_index (OfNat.ofNat n)) = OfNat.ofNat n := rfl
|
||||
|
||||
@[simp] theorem UInt8.toInt8_ofBitVec (b) : (UInt8.ofBitVec b).toInt8 = Int8.ofBitVec b := (rfl)
|
||||
@[simp] theorem UInt16.toInt16_ofBitVec (b) : (UInt16.ofBitVec b).toInt16 = Int16.ofBitVec b := (rfl)
|
||||
@[simp] theorem UInt32.toInt32_ofBitVec (b) : (UInt32.ofBitVec b).toInt32 = Int32.ofBitVec b := (rfl)
|
||||
@[simp] theorem UInt64.toInt64_ofBitVec (b) : (UInt64.ofBitVec b).toInt64 = Int64.ofBitVec b := (rfl)
|
||||
@[simp] theorem USize.toISize_ofBitVec (b) : (USize.ofBitVec b).toISize = ISize.ofBitVec b := (rfl)
|
||||
@[simp] theorem UInt8.toInt8_ofBitVec (b) : (UInt8.ofBitVec b).toInt8 = Int8.ofBitVec b := rfl
|
||||
@[simp] theorem UInt16.toInt16_ofBitVec (b) : (UInt16.ofBitVec b).toInt16 = Int16.ofBitVec b := rfl
|
||||
@[simp] theorem UInt32.toInt32_ofBitVec (b) : (UInt32.ofBitVec b).toInt32 = Int32.ofBitVec b := rfl
|
||||
@[simp] theorem UInt64.toInt64_ofBitVec (b) : (UInt64.ofBitVec b).toInt64 = Int64.ofBitVec b := rfl
|
||||
@[simp] theorem USize.toISize_ofBitVec (b) : (USize.ofBitVec b).toISize = ISize.ofBitVec b := rfl
|
||||
|
||||
@[simp] theorem Int8.toBitVec_ofBitVec (b) : (Int8.ofBitVec b).toBitVec = b := (rfl)
|
||||
@[simp] theorem Int16.toBitVec_ofBitVec (b) : (Int16.ofBitVec b).toBitVec = b := (rfl)
|
||||
@[simp] theorem Int32.toBitVec_ofBitVec (b) : (Int32.ofBitVec b).toBitVec = b := (rfl)
|
||||
@[simp] theorem Int64.toBitVec_ofBitVec (b) : (Int64.ofBitVec b).toBitVec = b := (rfl)
|
||||
@[simp] theorem ISize.toBitVec_ofBitVec (b) : (ISize.ofBitVec b).toBitVec = b := (rfl)
|
||||
@[simp] theorem Int8.toBitVec_ofBitVec (b) : (Int8.ofBitVec b).toBitVec = b := rfl
|
||||
@[simp] theorem Int16.toBitVec_ofBitVec (b) : (Int16.ofBitVec b).toBitVec = b := rfl
|
||||
@[simp] theorem Int32.toBitVec_ofBitVec (b) : (Int32.ofBitVec b).toBitVec = b := rfl
|
||||
@[simp] theorem Int64.toBitVec_ofBitVec (b) : (Int64.ofBitVec b).toBitVec = b := rfl
|
||||
@[simp] theorem ISize.toBitVec_ofBitVec (b) : (ISize.ofBitVec b).toBitVec = b := rfl
|
||||
|
||||
theorem Int8.toBitVec_ofIntTruncate {n : Int} (h₁ : Int8.minValue.toInt ≤ n) (h₂ : n ≤ Int8.maxValue.toInt) :
|
||||
(Int8.ofIntTruncate n).toBitVec = BitVec.ofInt _ n := by
|
||||
@@ -1010,11 +1010,11 @@ theorem ISize.toBitVec_ofIntTruncate {n : Int} (h₁ : ISize.minValue.toInt ≤
|
||||
(ISize.ofIntTruncate n).toBitVec = BitVec.ofInt _ n := by
|
||||
rw [← ofIntLE_eq_ofIntTruncate (h₁ := h₁) (h₂ := h₂), toBitVec_ofIntLE]
|
||||
|
||||
@[simp] theorem Int8.toInt_ofBitVec (b) : (Int8.ofBitVec b).toInt = b.toInt := (rfl)
|
||||
@[simp] theorem Int16.toInt_ofBitVec (b) : (Int16.ofBitVec b).toInt = b.toInt := (rfl)
|
||||
@[simp] theorem Int32.toInt_ofBitVec (b) : (Int32.ofBitVec b).toInt = b.toInt := (rfl)
|
||||
@[simp] theorem Int64.toInt_ofBitVec (b) : (Int64.ofBitVec b).toInt = b.toInt := (rfl)
|
||||
@[simp] theorem ISize.toInt_ofBitVec (b) : (ISize.ofBitVec b).toInt = b.toInt := (rfl)
|
||||
@[simp] theorem Int8.toInt_ofBitVec (b) : (Int8.ofBitVec b).toInt = b.toInt := rfl
|
||||
@[simp] theorem Int16.toInt_ofBitVec (b) : (Int16.ofBitVec b).toInt = b.toInt := rfl
|
||||
@[simp] theorem Int32.toInt_ofBitVec (b) : (Int32.ofBitVec b).toInt = b.toInt := rfl
|
||||
@[simp] theorem Int64.toInt_ofBitVec (b) : (Int64.ofBitVec b).toInt = b.toInt := rfl
|
||||
@[simp] theorem ISize.toInt_ofBitVec (b) : (ISize.ofBitVec b).toInt = b.toInt := rfl
|
||||
|
||||
@[simp] theorem Int8.toNatClampNeg_ofIntLE {n : Int} (h₁ h₂) : (Int8.ofIntLE n h₁ h₂).toNatClampNeg = n.toNat := by
|
||||
rw [ofIntLE, toNatClampNeg, toInt_ofInt_of_le h₁ (Int.lt_of_le_sub_one h₂)]
|
||||
@@ -1030,11 +1030,11 @@ theorem ISize.toBitVec_ofIntTruncate {n : Int} (h₁ : ISize.minValue.toInt ≤
|
||||
· apply Int.lt_of_le_sub_one
|
||||
rwa [← ISize.toInt_maxValue]
|
||||
|
||||
@[simp] theorem Int8.toNatClampNeg_ofBitVec (b) : (Int8.ofBitVec b).toNatClampNeg = b.toInt.toNat := (rfl)
|
||||
@[simp] theorem Int16.toNatClampNeg_ofBitVec (b) : (Int16.ofBitVec b).toNatClampNeg = b.toInt.toNat := (rfl)
|
||||
@[simp] theorem Int32.toNatClampNeg_ofBitVec (b) : (Int32.ofBitVec b).toNatClampNeg = b.toInt.toNat := (rfl)
|
||||
@[simp] theorem Int64.toNatClampNeg_ofBitVec (b) : (Int64.ofBitVec b).toNatClampNeg = b.toInt.toNat := (rfl)
|
||||
@[simp] theorem ISize.toNatClampNeg_ofBitVec (b) : (ISize.ofBitVec b).toNatClampNeg = b.toInt.toNat := (rfl)
|
||||
@[simp] theorem Int8.toNatClampNeg_ofBitVec (b) : (Int8.ofBitVec b).toNatClampNeg = b.toInt.toNat := rfl
|
||||
@[simp] theorem Int16.toNatClampNeg_ofBitVec (b) : (Int16.ofBitVec b).toNatClampNeg = b.toInt.toNat := rfl
|
||||
@[simp] theorem Int32.toNatClampNeg_ofBitVec (b) : (Int32.ofBitVec b).toNatClampNeg = b.toInt.toNat := rfl
|
||||
@[simp] theorem Int64.toNatClampNeg_ofBitVec (b) : (Int64.ofBitVec b).toNatClampNeg = b.toInt.toNat := rfl
|
||||
@[simp] theorem ISize.toNatClampNeg_ofBitVec (b) : (ISize.ofBitVec b).toNatClampNeg = b.toInt.toNat := rfl
|
||||
|
||||
theorem Int8.toNatClampNeg_ofInt_of_le {n : Int} (h₁ : -2 ^ 7 ≤ n) (h₂ : n < 2 ^ 7) :
|
||||
(Int8.ofInt n).toNatClampNeg = n.toNat := by rw [toNatClampNeg, toInt_ofInt_of_le h₁ h₂]
|
||||
@@ -1101,33 +1101,33 @@ theorem ISize.toNatClampNeg_ofIntTruncate_of_lt {n : Int} (h₁ : n < 2 ^ 31) :
|
||||
apply ISize.toNatClampNeg_ofIntTruncate_of_lt_two_pow_numBits (Int.lt_of_lt_of_le h₁ _)
|
||||
cases System.Platform.numBits_eq <;> simp_all
|
||||
|
||||
@[simp] theorem Int8.toUInt8_ofBitVec (b) : (Int8.ofBitVec b).toUInt8 = UInt8.ofBitVec b := (rfl)
|
||||
@[simp] theorem Int16.toUInt16_ofBitVec (b) : (Int16.ofBitVec b).toUInt16 = UInt16.ofBitVec b := (rfl)
|
||||
@[simp] theorem Int32.toUInt32_ofBitVec (b) : (Int32.ofBitVec b).toUInt32 = UInt32.ofBitVec b := (rfl)
|
||||
@[simp] theorem Int64.toUInt64_ofBitVec (b) : (Int64.ofBitVec b).toUInt64 = UInt64.ofBitVec b := (rfl)
|
||||
@[simp] theorem ISize.toUSize_ofBitVec (b) : (ISize.ofBitVec b).toUSize = USize.ofBitVec b := (rfl)
|
||||
@[simp] theorem Int8.toUInt8_ofBitVec (b) : (Int8.ofBitVec b).toUInt8 = UInt8.ofBitVec b := rfl
|
||||
@[simp] theorem Int16.toUInt16_ofBitVec (b) : (Int16.ofBitVec b).toUInt16 = UInt16.ofBitVec b := rfl
|
||||
@[simp] theorem Int32.toUInt32_ofBitVec (b) : (Int32.ofBitVec b).toUInt32 = UInt32.ofBitVec b := rfl
|
||||
@[simp] theorem Int64.toUInt64_ofBitVec (b) : (Int64.ofBitVec b).toUInt64 = UInt64.ofBitVec b := rfl
|
||||
@[simp] theorem ISize.toUSize_ofBitVec (b) : (ISize.ofBitVec b).toUSize = USize.ofBitVec b := rfl
|
||||
|
||||
@[simp] theorem Int8.toUInt8_ofNat' {n} : (Int8.ofNat n).toUInt8 = UInt8.ofNat n := (rfl)
|
||||
@[simp] theorem Int16.toUInt16_ofNat' {n} : (Int16.ofNat n).toUInt16 = UInt16.ofNat n := (rfl)
|
||||
@[simp] theorem Int32.toUInt32_ofNat' {n} : (Int32.ofNat n).toUInt32 = UInt32.ofNat n := (rfl)
|
||||
@[simp] theorem Int64.toUInt64_ofNat' {n} : (Int64.ofNat n).toUInt64 = UInt64.ofNat n := (rfl)
|
||||
@[simp] theorem ISize.toUSize_ofNat' {n} : (ISize.ofNat n).toUSize = USize.ofNat n := (rfl)
|
||||
@[simp] theorem Int8.toUInt8_ofNat' {n} : (Int8.ofNat n).toUInt8 = UInt8.ofNat n := rfl
|
||||
@[simp] theorem Int16.toUInt16_ofNat' {n} : (Int16.ofNat n).toUInt16 = UInt16.ofNat n := rfl
|
||||
@[simp] theorem Int32.toUInt32_ofNat' {n} : (Int32.ofNat n).toUInt32 = UInt32.ofNat n := rfl
|
||||
@[simp] theorem Int64.toUInt64_ofNat' {n} : (Int64.ofNat n).toUInt64 = UInt64.ofNat n := rfl
|
||||
@[simp] theorem ISize.toUSize_ofNat' {n} : (ISize.ofNat n).toUSize = USize.ofNat n := rfl
|
||||
|
||||
@[simp] theorem Int8.toUInt8_ofNat {n} : toUInt8 (OfNat.ofNat n) = OfNat.ofNat n := (rfl)
|
||||
@[simp] theorem Int16.toUInt16_ofNat {n} : toUInt16 (OfNat.ofNat n) = OfNat.ofNat n := (rfl)
|
||||
@[simp] theorem Int32.toUInt32_ofNat {n} : toUInt32 (OfNat.ofNat n) = OfNat.ofNat n := (rfl)
|
||||
@[simp] theorem Int64.toUInt64_ofNat {n} : toUInt64 (OfNat.ofNat n) = OfNat.ofNat n := (rfl)
|
||||
@[simp] theorem ISize.toUSize_ofNat {n} : toUSize (OfNat.ofNat n) = OfNat.ofNat n := (rfl)
|
||||
@[simp] theorem Int8.toUInt8_ofNat {n} : toUInt8 (OfNat.ofNat n) = OfNat.ofNat n := rfl
|
||||
@[simp] theorem Int16.toUInt16_ofNat {n} : toUInt16 (OfNat.ofNat n) = OfNat.ofNat n := rfl
|
||||
@[simp] theorem Int32.toUInt32_ofNat {n} : toUInt32 (OfNat.ofNat n) = OfNat.ofNat n := rfl
|
||||
@[simp] theorem Int64.toUInt64_ofNat {n} : toUInt64 (OfNat.ofNat n) = OfNat.ofNat n := rfl
|
||||
@[simp] theorem ISize.toUSize_ofNat {n} : toUSize (OfNat.ofNat n) = OfNat.ofNat n := rfl
|
||||
|
||||
theorem Int16.toInt8_ofIntLE {n} (h₁ h₂) : (Int16.ofIntLE n h₁ h₂).toInt8 = Int8.ofInt n := Int8.toInt.inj (by simp)
|
||||
theorem Int32.toInt8_ofIntLE {n} (h₁ h₂) : (Int32.ofIntLE n h₁ h₂).toInt8 = Int8.ofInt n := Int8.toInt.inj (by simp)
|
||||
theorem Int64.toInt8_ofIntLE {n} (h₁ h₂) : (Int64.ofIntLE n h₁ h₂).toInt8 = Int8.ofInt n := Int8.toInt.inj (by simp)
|
||||
theorem ISize.toInt8_ofIntLE {n} (h₁ h₂) : (ISize.ofIntLE n h₁ h₂).toInt8 = Int8.ofInt n := Int8.toInt.inj (by simp)
|
||||
|
||||
@[simp] theorem Int16.toInt8_ofBitVec (b) : (Int16.ofBitVec b).toInt8 = Int8.ofBitVec (b.signExtend _) := (rfl)
|
||||
@[simp] theorem Int32.toInt8_ofBitVec (b) : (Int32.ofBitVec b).toInt8 = Int8.ofBitVec (b.signExtend _) := (rfl)
|
||||
@[simp] theorem Int64.toInt8_ofBitVec (b) : (Int64.ofBitVec b).toInt8 = Int8.ofBitVec (b.signExtend _) := (rfl)
|
||||
@[simp] theorem ISize.toInt8_ofBitVec (b) : (ISize.ofBitVec b).toInt8 = Int8.ofBitVec (b.signExtend _) := (rfl)
|
||||
@[simp] theorem Int16.toInt8_ofBitVec (b) : (Int16.ofBitVec b).toInt8 = Int8.ofBitVec (b.signExtend _) := rfl
|
||||
@[simp] theorem Int32.toInt8_ofBitVec (b) : (Int32.ofBitVec b).toInt8 = Int8.ofBitVec (b.signExtend _) := rfl
|
||||
@[simp] theorem Int64.toInt8_ofBitVec (b) : (Int64.ofBitVec b).toInt8 = Int8.ofBitVec (b.signExtend _) := rfl
|
||||
@[simp] theorem ISize.toInt8_ofBitVec (b) : (ISize.ofBitVec b).toInt8 = Int8.ofBitVec (b.signExtend _) := rfl
|
||||
|
||||
@[simp] theorem Int16.toInt8_ofNat' {n} : (Int16.ofNat n).toInt8 = Int8.ofNat n :=
|
||||
Int8.toBitVec.inj (by simp [BitVec.signExtend_eq_setWidth_of_le])
|
||||
@@ -1177,9 +1177,9 @@ theorem Int32.toInt16_ofIntLE {n} (h₁ h₂) : (Int32.ofIntLE n h₁ h₂).toIn
|
||||
theorem Int64.toInt16_ofIntLE {n} (h₁ h₂) : (Int64.ofIntLE n h₁ h₂).toInt16 = Int16.ofInt n := Int16.toInt.inj (by simp)
|
||||
theorem ISize.toInt16_ofIntLE {n} (h₁ h₂) : (ISize.ofIntLE n h₁ h₂).toInt16 = Int16.ofInt n := Int16.toInt.inj (by simp)
|
||||
|
||||
@[simp] theorem Int32.toInt16_ofBitVec (b) : (Int32.ofBitVec b).toInt16 = Int16.ofBitVec (b.signExtend _) := (rfl)
|
||||
@[simp] theorem Int64.toInt16_ofBitVec (b) : (Int64.ofBitVec b).toInt16 = Int16.ofBitVec (b.signExtend _) := (rfl)
|
||||
@[simp] theorem ISize.toInt16_ofBitVec (b) : (ISize.ofBitVec b).toInt16 = Int16.ofBitVec (b.signExtend _) := (rfl)
|
||||
@[simp] theorem Int32.toInt16_ofBitVec (b) : (Int32.ofBitVec b).toInt16 = Int16.ofBitVec (b.signExtend _) := rfl
|
||||
@[simp] theorem Int64.toInt16_ofBitVec (b) : (Int64.ofBitVec b).toInt16 = Int16.ofBitVec (b.signExtend _) := rfl
|
||||
@[simp] theorem ISize.toInt16_ofBitVec (b) : (ISize.ofBitVec b).toInt16 = Int16.ofBitVec (b.signExtend _) := rfl
|
||||
|
||||
@[simp] theorem Int32.toInt16_ofNat' {n} : (Int32.ofNat n).toInt16 = Int16.ofNat n :=
|
||||
Int16.toBitVec.inj (by simp [BitVec.signExtend_eq_setWidth_of_le])
|
||||
@@ -1220,8 +1220,8 @@ theorem ISize.toInt16_ofIntTruncate {n : Int} (h₁ : -2 ^ (System.Platform.numB
|
||||
theorem Int64.toInt32_ofIntLE {n} (h₁ h₂) : (Int64.ofIntLE n h₁ h₂).toInt32 = Int32.ofInt n := Int32.toInt.inj (by simp)
|
||||
theorem ISize.toInt32_ofIntLE {n} (h₁ h₂) : (ISize.ofIntLE n h₁ h₂).toInt32 = Int32.ofInt n := Int32.toInt.inj (by simp)
|
||||
|
||||
@[simp] theorem Int64.toInt32_ofBitVec (b) : (Int64.ofBitVec b).toInt32 = Int32.ofBitVec (b.signExtend _) := (rfl)
|
||||
@[simp] theorem ISize.toInt32_ofBitVec (b) : (ISize.ofBitVec b).toInt32 = Int32.ofBitVec (b.signExtend _) := (rfl)
|
||||
@[simp] theorem Int64.toInt32_ofBitVec (b) : (Int64.ofBitVec b).toInt32 = Int32.ofBitVec (b.signExtend _) := rfl
|
||||
@[simp] theorem ISize.toInt32_ofBitVec (b) : (ISize.ofBitVec b).toInt32 = Int32.ofBitVec (b.signExtend _) := rfl
|
||||
|
||||
@[simp] theorem Int64.toInt32_ofNat' {n} : (Int64.ofNat n).toInt32 = Int32.ofNat n :=
|
||||
Int32.toBitVec.inj (by simp [BitVec.signExtend_eq_setWidth_of_le])
|
||||
@@ -1254,7 +1254,7 @@ theorem ISize.toInt32_ofIntTruncate {n : Int} (h₁ : -2 ^ (System.Platform.numB
|
||||
theorem Int64.toISize_ofIntLE {n} (h₁ h₂) : (Int64.ofIntLE n h₁ h₂).toISize = ISize.ofInt n :=
|
||||
ISize.toInt.inj (by simp [ISize.toInt_ofInt])
|
||||
|
||||
@[simp] theorem Int64.toISize_ofBitVec (b) : (Int64.ofBitVec b).toISize = ISize.ofBitVec (b.signExtend _) := (rfl)
|
||||
@[simp] theorem Int64.toISize_ofBitVec (b) : (Int64.ofBitVec b).toISize = ISize.ofBitVec (b.signExtend _) := rfl
|
||||
|
||||
@[simp] theorem Int64.toISize_ofNat' {n} : (Int64.ofNat n).toISize = ISize.ofNat n :=
|
||||
ISize.toBitVec.inj (by simp [BitVec.signExtend_eq_setWidth_of_le])
|
||||
@@ -1268,10 +1268,10 @@ theorem Int64.toISize_ofIntTruncate {n : Int} (h₁ : -2 ^ 63 ≤ n) (h₂ : n <
|
||||
(Int64.ofIntTruncate n).toISize = ISize.ofInt n := by
|
||||
rw [← ofIntLE_eq_ofIntTruncate (h₁ := h₁) (h₂ := Int.le_of_lt_add_one h₂), toISize_ofIntLE]
|
||||
|
||||
@[simp] theorem Int8.toBitVec_minValue : minValue.toBitVec = BitVec.intMin _ := (rfl)
|
||||
@[simp] theorem Int16.toBitVec_minValue : minValue.toBitVec = BitVec.intMin _ := (rfl)
|
||||
@[simp] theorem Int32.toBitVec_minValue : minValue.toBitVec = BitVec.intMin _ := (rfl)
|
||||
@[simp] theorem Int64.toBitVec_minValue : minValue.toBitVec = BitVec.intMin _ := (rfl)
|
||||
@[simp] theorem Int8.toBitVec_minValue : minValue.toBitVec = BitVec.intMin _ := rfl
|
||||
@[simp] theorem Int16.toBitVec_minValue : minValue.toBitVec = BitVec.intMin _ := rfl
|
||||
@[simp] theorem Int32.toBitVec_minValue : minValue.toBitVec = BitVec.intMin _ := rfl
|
||||
@[simp] theorem Int64.toBitVec_minValue : minValue.toBitVec = BitVec.intMin _ := rfl
|
||||
@[simp] theorem ISize.toBitVec_minValue : minValue.toBitVec = BitVec.intMin _ :=
|
||||
BitVec.eq_of_toInt_eq (by rw [toInt_toBitVec, toInt_minValue,
|
||||
BitVec.toInt_intMin_of_pos (by cases System.Platform.numBits_eq <;> simp_all)])
|
||||
@@ -1335,10 +1335,10 @@ theorem Int8.toISize_ofIntLE {n : Int} (h₁ h₂) :
|
||||
(Int.le_trans h₂ maxValue.toInt_le_iSizeMaxValue) :=
|
||||
ISize.toInt.inj (by simp)
|
||||
|
||||
@[simp] theorem Int8.toInt16_ofBitVec (b) : (Int8.ofBitVec b).toInt16 = Int16.ofBitVec (b.signExtend _) := (rfl)
|
||||
@[simp] theorem Int8.toInt32_ofBitVec (b) : (Int8.ofBitVec b).toInt32 = Int32.ofBitVec (b.signExtend _) := (rfl)
|
||||
@[simp] theorem Int8.toInt64_ofBitVec (b) : (Int8.ofBitVec b).toInt64 = Int64.ofBitVec (b.signExtend _) := (rfl)
|
||||
@[simp] theorem Int8.toISize_ofBitVec (b) : (Int8.ofBitVec b).toISize = ISize.ofBitVec (b.signExtend _) := (rfl)
|
||||
@[simp] theorem Int8.toInt16_ofBitVec (b) : (Int8.ofBitVec b).toInt16 = Int16.ofBitVec (b.signExtend _) := rfl
|
||||
@[simp] theorem Int8.toInt32_ofBitVec (b) : (Int8.ofBitVec b).toInt32 = Int32.ofBitVec (b.signExtend _) := rfl
|
||||
@[simp] theorem Int8.toInt64_ofBitVec (b) : (Int8.ofBitVec b).toInt64 = Int64.ofBitVec (b.signExtend _) := rfl
|
||||
@[simp] theorem Int8.toISize_ofBitVec (b) : (Int8.ofBitVec b).toISize = ISize.ofBitVec (b.signExtend _) := rfl
|
||||
|
||||
@[simp] theorem Int8.toInt16_ofInt {n : Int} (h₁ : Int8.minValue.toInt ≤ n) (h₂ : n ≤ Int8.maxValue.toInt) :
|
||||
(Int8.ofInt n).toInt16 = Int16.ofInt n := by rw [← Int8.ofIntLE_eq_ofInt h₁ h₂, toInt16_ofIntLE, Int16.ofIntLE_eq_ofInt]
|
||||
@@ -1382,9 +1382,9 @@ theorem Int16.toISize_ofIntLE {n : Int} (h₁ h₂) :
|
||||
(Int.le_trans h₂ maxValue.toInt_le_iSizeMaxValue) :=
|
||||
ISize.toInt.inj (by simp)
|
||||
|
||||
@[simp] theorem Int16.toInt32_ofBitVec (b) : (Int16.ofBitVec b).toInt32 = Int32.ofBitVec (b.signExtend _) := (rfl)
|
||||
@[simp] theorem Int16.toInt64_ofBitVec (b) : (Int16.ofBitVec b).toInt64 = Int64.ofBitVec (b.signExtend _) := (rfl)
|
||||
@[simp] theorem Int16.toISize_ofBitVec (b) : (Int16.ofBitVec b).toISize = ISize.ofBitVec (b.signExtend _) := (rfl)
|
||||
@[simp] theorem Int16.toInt32_ofBitVec (b) : (Int16.ofBitVec b).toInt32 = Int32.ofBitVec (b.signExtend _) := rfl
|
||||
@[simp] theorem Int16.toInt64_ofBitVec (b) : (Int16.ofBitVec b).toInt64 = Int64.ofBitVec (b.signExtend _) := rfl
|
||||
@[simp] theorem Int16.toISize_ofBitVec (b) : (Int16.ofBitVec b).toISize = ISize.ofBitVec (b.signExtend _) := rfl
|
||||
|
||||
@[simp] theorem Int16.toInt32_ofInt {n : Int} (h₁ : Int16.minValue.toInt ≤ n) (h₂ : n ≤ Int16.maxValue.toInt) :
|
||||
(Int16.ofInt n).toInt32 = Int32.ofInt n := by rw [← Int16.ofIntLE_eq_ofInt h₁ h₂, toInt32_ofIntLE, Int32.ofIntLE_eq_ofInt]
|
||||
@@ -1418,8 +1418,8 @@ theorem Int32.toISize_ofIntLE {n : Int} (h₁ h₂) :
|
||||
(Int.le_trans h₂ maxValue.toInt_le_iSizeMaxValue) :=
|
||||
ISize.toInt.inj (by simp)
|
||||
|
||||
@[simp] theorem Int32.toInt64_ofBitVec (b) : (Int32.ofBitVec b).toInt64 = Int64.ofBitVec (b.signExtend _) := (rfl)
|
||||
@[simp] theorem Int32.toISize_ofBitVec (b) : (Int32.ofBitVec b).toISize = ISize.ofBitVec (b.signExtend _) := (rfl)
|
||||
@[simp] theorem Int32.toInt64_ofBitVec (b) : (Int32.ofBitVec b).toInt64 = Int64.ofBitVec (b.signExtend _) := rfl
|
||||
@[simp] theorem Int32.toISize_ofBitVec (b) : (Int32.ofBitVec b).toISize = ISize.ofBitVec (b.signExtend _) := rfl
|
||||
|
||||
@[simp] theorem Int32.toInt64_ofInt {n : Int} (h₁ : Int32.minValue.toInt ≤ n) (h₂ : n ≤ Int32.maxValue.toInt) :
|
||||
(Int32.ofInt n).toInt64 = Int64.ofInt n := by rw [← Int32.ofIntLE_eq_ofInt h₁ h₂, toInt64_ofIntLE, Int64.ofIntLE_eq_ofInt]
|
||||
@@ -1443,7 +1443,7 @@ theorem ISize.toInt64_ofIntLE {n : Int} (h₁ h₂) :
|
||||
(Int.le_trans h₂ maxValue.toInt_le_int64MaxValue) :=
|
||||
Int64.toInt.inj (by simp)
|
||||
|
||||
@[simp] theorem ISize.toInt64_ofBitVec (b) : (ISize.ofBitVec b).toInt64 = Int64.ofBitVec (b.signExtend _) := (rfl)
|
||||
@[simp] theorem ISize.toInt64_ofBitVec (b) : (ISize.ofBitVec b).toInt64 = Int64.ofBitVec (b.signExtend _) := rfl
|
||||
|
||||
@[simp] theorem ISize.toInt64_ofInt {n : Int} (h₁ : ISize.minValue.toInt ≤ n) (h₂ : n ≤ ISize.maxValue.toInt) :
|
||||
(ISize.ofInt n).toInt64 = Int64.ofInt n := by rw [← ISize.ofIntLE_eq_ofInt h₁ h₂, toInt64_ofIntLE, Int64.ofIntLE_eq_ofInt]
|
||||
@@ -1486,17 +1486,17 @@ theorem Int64.ofBitVec_ofNatLT (n : Nat) (hn) : Int64.ofBitVec (BitVec.ofNatLT n
|
||||
theorem ISize.ofBitVec_ofNatLT (n : Nat) (hn) : ISize.ofBitVec (BitVec.ofNatLT n hn) = ISize.ofNat n :=
|
||||
ISize.toBitVec.inj (by simp [BitVec.ofNatLT_eq_ofNat hn])
|
||||
|
||||
@[simp] theorem Int8.ofBitVec_ofNat (n : Nat) : Int8.ofBitVec (BitVec.ofNat 8 n) = Int8.ofNat n := (rfl)
|
||||
@[simp] theorem Int16.ofBitVec_ofNat (n : Nat) : Int16.ofBitVec (BitVec.ofNat 16 n) = Int16.ofNat n := (rfl)
|
||||
@[simp] theorem Int32.ofBitVec_ofNat (n : Nat) : Int32.ofBitVec (BitVec.ofNat 32 n) = Int32.ofNat n := (rfl)
|
||||
@[simp] theorem Int64.ofBitVec_ofNat (n : Nat) : Int64.ofBitVec (BitVec.ofNat 64 n) = Int64.ofNat n := (rfl)
|
||||
@[simp] theorem ISize.ofBitVec_ofNat (n : Nat) : ISize.ofBitVec (BitVec.ofNat System.Platform.numBits n) = ISize.ofNat n := (rfl)
|
||||
@[simp] theorem Int8.ofBitVec_ofNat (n : Nat) : Int8.ofBitVec (BitVec.ofNat 8 n) = Int8.ofNat n := rfl
|
||||
@[simp] theorem Int16.ofBitVec_ofNat (n : Nat) : Int16.ofBitVec (BitVec.ofNat 16 n) = Int16.ofNat n := rfl
|
||||
@[simp] theorem Int32.ofBitVec_ofNat (n : Nat) : Int32.ofBitVec (BitVec.ofNat 32 n) = Int32.ofNat n := rfl
|
||||
@[simp] theorem Int64.ofBitVec_ofNat (n : Nat) : Int64.ofBitVec (BitVec.ofNat 64 n) = Int64.ofNat n := rfl
|
||||
@[simp] theorem ISize.ofBitVec_ofNat (n : Nat) : ISize.ofBitVec (BitVec.ofNat System.Platform.numBits n) = ISize.ofNat n := rfl
|
||||
|
||||
@[simp] theorem Int8.ofBitVec_ofInt (n : Int) : Int8.ofBitVec (BitVec.ofInt 8 n) = Int8.ofInt n := (rfl)
|
||||
@[simp] theorem Int16.ofBitVec_ofInt (n : Int) : Int16.ofBitVec (BitVec.ofInt 16 n) = Int16.ofInt n := (rfl)
|
||||
@[simp] theorem Int32.ofBitVec_ofInt (n : Int) : Int32.ofBitVec (BitVec.ofInt 32 n) = Int32.ofInt n := (rfl)
|
||||
@[simp] theorem Int64.ofBitVec_ofInt (n : Int) : Int64.ofBitVec (BitVec.ofInt 64 n) = Int64.ofInt n := (rfl)
|
||||
@[simp] theorem ISize.ofBitVec_ofInt (n : Int) : ISize.ofBitVec (BitVec.ofInt System.Platform.numBits n) = ISize.ofInt n := (rfl)
|
||||
@[simp] theorem Int8.ofBitVec_ofInt (n : Int) : Int8.ofBitVec (BitVec.ofInt 8 n) = Int8.ofInt n := rfl
|
||||
@[simp] theorem Int16.ofBitVec_ofInt (n : Int) : Int16.ofBitVec (BitVec.ofInt 16 n) = Int16.ofInt n := rfl
|
||||
@[simp] theorem Int32.ofBitVec_ofInt (n : Int) : Int32.ofBitVec (BitVec.ofInt 32 n) = Int32.ofInt n := rfl
|
||||
@[simp] theorem Int64.ofBitVec_ofInt (n : Int) : Int64.ofBitVec (BitVec.ofInt 64 n) = Int64.ofInt n := rfl
|
||||
@[simp] theorem ISize.ofBitVec_ofInt (n : Int) : ISize.ofBitVec (BitVec.ofInt System.Platform.numBits n) = ISize.ofInt n := rfl
|
||||
|
||||
@[simp] theorem Int8.ofNat_bitVecToNat (n : BitVec 8) : Int8.ofNat n.toNat = Int8.ofBitVec n :=
|
||||
Int8.toBitVec.inj (by simp)
|
||||
@@ -1741,10 +1741,10 @@ theorem ISize.toInt64_div_of_ne_right (a b : ISize) (hb : b ≠ -1) : (a / b).to
|
||||
Int64.toInt_inj.1 (by rw [toInt_toInt64, toInt_div_of_ne_right _ _ hb,
|
||||
Int64.toInt_div_of_ne_right _ _ (b.toInt64_ne_neg_one hb), toInt_toInt64, toInt_toInt64])
|
||||
|
||||
@[simp] theorem Int8.minValue_div_neg_one : minValue / -1 = minValue := (rfl)
|
||||
@[simp] theorem Int16.minValue_div_neg_one : minValue / -1 = minValue := (rfl)
|
||||
@[simp] theorem Int32.minValue_div_neg_one : minValue / -1 = minValue := (rfl)
|
||||
@[simp] theorem Int64.minValue_div_neg_one : minValue / -1 = minValue := (rfl)
|
||||
@[simp] theorem Int8.minValue_div_neg_one : minValue / -1 = minValue := rfl
|
||||
@[simp] theorem Int16.minValue_div_neg_one : minValue / -1 = minValue := rfl
|
||||
@[simp] theorem Int32.minValue_div_neg_one : minValue / -1 = minValue := rfl
|
||||
@[simp] theorem Int64.minValue_div_neg_one : minValue / -1 = minValue := rfl
|
||||
@[simp] theorem ISize.minValue_div_neg_one : minValue / -1 = minValue :=
|
||||
ISize.toBitVec_inj.1 (by simpa [BitVec.intMin_eq_neg_two_pow] using BitVec.intMin_sdiv_neg_one)
|
||||
|
||||
@@ -1907,11 +1907,11 @@ protected theorem ISize.sub_eq_add_neg (a b : ISize) : a - b = a + -b := ISize.t
|
||||
@[simp] theorem ISize.toInt64_le {a b : ISize} : a.toInt64 ≤ b.toInt64 ↔ a ≤ b := by
|
||||
simp [le_iff_toInt_le, Int64.le_iff_toInt_le]
|
||||
|
||||
@[simp] theorem Int8.ofBitVec_neg (a : BitVec 8) : Int8.ofBitVec (-a) = -Int8.ofBitVec a := (rfl)
|
||||
@[simp] theorem Int16.ofBitVec_neg (a : BitVec 16) : Int16.ofBitVec (-a) = -Int16.ofBitVec a := (rfl)
|
||||
@[simp] theorem Int32.ofBitVec_neg (a : BitVec 32) : Int32.ofBitVec (-a) = -Int32.ofBitVec a := (rfl)
|
||||
@[simp] theorem Int64.ofBitVec_neg (a : BitVec 64) : Int64.ofBitVec (-a) = -Int64.ofBitVec a := (rfl)
|
||||
@[simp] theorem ISize.ofBitVec_neg (a : BitVec System.Platform.numBits) : ISize.ofBitVec (-a) = -ISize.ofBitVec a := (rfl)
|
||||
@[simp] theorem Int8.ofBitVec_neg (a : BitVec 8) : Int8.ofBitVec (-a) = -Int8.ofBitVec a := rfl
|
||||
@[simp] theorem Int16.ofBitVec_neg (a : BitVec 16) : Int16.ofBitVec (-a) = -Int16.ofBitVec a := rfl
|
||||
@[simp] theorem Int32.ofBitVec_neg (a : BitVec 32) : Int32.ofBitVec (-a) = -Int32.ofBitVec a := rfl
|
||||
@[simp] theorem Int64.ofBitVec_neg (a : BitVec 64) : Int64.ofBitVec (-a) = -Int64.ofBitVec a := rfl
|
||||
@[simp] theorem ISize.ofBitVec_neg (a : BitVec System.Platform.numBits) : ISize.ofBitVec (-a) = -ISize.ofBitVec a := rfl
|
||||
|
||||
@[simp] theorem Int8.ofInt_neg (a : Int) : Int8.ofInt (-a) = -Int8.ofInt a := Int8.toInt_inj.1 (by simp)
|
||||
@[simp] theorem Int16.ofInt_neg (a : Int) : Int16.ofInt (-a) = -Int16.ofInt a := Int16.toInt_inj.1 (by simp)
|
||||
@@ -1931,11 +1931,11 @@ theorem Int64.ofInt_eq_iff_bmod_eq_toInt (a : Int) (b : Int64) : Int64.ofInt a =
|
||||
theorem ISize.ofInt_eq_iff_bmod_eq_toInt (a : Int) (b : ISize) : ISize.ofInt a = b ↔ a.bmod (2 ^ System.Platform.numBits) = b.toInt := by
|
||||
simp [← ISize.toInt_inj, ISize.toInt_ofInt]
|
||||
|
||||
@[simp] theorem Int8.ofBitVec_add (a b : BitVec 8) : Int8.ofBitVec (a + b) = Int8.ofBitVec a + Int8.ofBitVec b := (rfl)
|
||||
@[simp] theorem Int16.ofBitVec_add (a b : BitVec 16) : Int16.ofBitVec (a + b) = Int16.ofBitVec a + Int16.ofBitVec b := (rfl)
|
||||
@[simp] theorem Int32.ofBitVec_add (a b : BitVec 32) : Int32.ofBitVec (a + b) = Int32.ofBitVec a + Int32.ofBitVec b := (rfl)
|
||||
@[simp] theorem Int64.ofBitVec_add (a b : BitVec 64) : Int64.ofBitVec (a + b) = Int64.ofBitVec a + Int64.ofBitVec b := (rfl)
|
||||
@[simp] theorem ISize.ofBitVec_add (a b : BitVec System.Platform.numBits) : ISize.ofBitVec (a + b) = ISize.ofBitVec a + ISize.ofBitVec b := (rfl)
|
||||
@[simp] theorem Int8.ofBitVec_add (a b : BitVec 8) : Int8.ofBitVec (a + b) = Int8.ofBitVec a + Int8.ofBitVec b := rfl
|
||||
@[simp] theorem Int16.ofBitVec_add (a b : BitVec 16) : Int16.ofBitVec (a + b) = Int16.ofBitVec a + Int16.ofBitVec b := rfl
|
||||
@[simp] theorem Int32.ofBitVec_add (a b : BitVec 32) : Int32.ofBitVec (a + b) = Int32.ofBitVec a + Int32.ofBitVec b := rfl
|
||||
@[simp] theorem Int64.ofBitVec_add (a b : BitVec 64) : Int64.ofBitVec (a + b) = Int64.ofBitVec a + Int64.ofBitVec b := rfl
|
||||
@[simp] theorem ISize.ofBitVec_add (a b : BitVec System.Platform.numBits) : ISize.ofBitVec (a + b) = ISize.ofBitVec a + ISize.ofBitVec b := rfl
|
||||
|
||||
@[simp] theorem Int8.ofInt_add (a b : Int) : Int8.ofInt (a + b) = Int8.ofInt a + Int8.ofInt b := by
|
||||
simp [Int8.ofInt_eq_iff_bmod_eq_toInt]
|
||||
@@ -1970,11 +1970,11 @@ theorem Int64.ofIntLE_add {a b : Int} {hab₁ hab₂} : Int64.ofIntLE (a + b) ha
|
||||
theorem ISize.ofIntLE_add {a b : Int} {hab₁ hab₂} : ISize.ofIntLE (a + b) hab₁ hab₂ = ISize.ofInt a + ISize.ofInt b := by
|
||||
simp [ISize.ofIntLE_eq_ofInt]
|
||||
|
||||
@[simp] theorem Int8.ofBitVec_sub (a b : BitVec 8) : Int8.ofBitVec (a - b) = Int8.ofBitVec a - Int8.ofBitVec b := (rfl)
|
||||
@[simp] theorem Int16.ofBitVec_sub (a b : BitVec 16) : Int16.ofBitVec (a - b) = Int16.ofBitVec a - Int16.ofBitVec b := (rfl)
|
||||
@[simp] theorem Int32.ofBitVec_sub (a b : BitVec 32) : Int32.ofBitVec (a - b) = Int32.ofBitVec a - Int32.ofBitVec b := (rfl)
|
||||
@[simp] theorem Int64.ofBitVec_sub (a b : BitVec 64) : Int64.ofBitVec (a - b) = Int64.ofBitVec a - Int64.ofBitVec b := (rfl)
|
||||
@[simp] theorem ISize.ofBitVec_sub (a b : BitVec System.Platform.numBits) : ISize.ofBitVec (a - b) = ISize.ofBitVec a - ISize.ofBitVec b := (rfl)
|
||||
@[simp] theorem Int8.ofBitVec_sub (a b : BitVec 8) : Int8.ofBitVec (a - b) = Int8.ofBitVec a - Int8.ofBitVec b := rfl
|
||||
@[simp] theorem Int16.ofBitVec_sub (a b : BitVec 16) : Int16.ofBitVec (a - b) = Int16.ofBitVec a - Int16.ofBitVec b := rfl
|
||||
@[simp] theorem Int32.ofBitVec_sub (a b : BitVec 32) : Int32.ofBitVec (a - b) = Int32.ofBitVec a - Int32.ofBitVec b := rfl
|
||||
@[simp] theorem Int64.ofBitVec_sub (a b : BitVec 64) : Int64.ofBitVec (a - b) = Int64.ofBitVec a - Int64.ofBitVec b := rfl
|
||||
@[simp] theorem ISize.ofBitVec_sub (a b : BitVec System.Platform.numBits) : ISize.ofBitVec (a - b) = ISize.ofBitVec a - ISize.ofBitVec b := rfl
|
||||
|
||||
@[simp] theorem Int8.ofInt_sub (a b : Int) : Int8.ofInt (a - b) = Int8.ofInt a - Int8.ofInt b := by
|
||||
simp [Int8.ofInt_eq_iff_bmod_eq_toInt]
|
||||
@@ -2009,11 +2009,11 @@ theorem Int64.ofIntLE_sub {a b : Int} {hab₁ hab₂} : Int64.ofIntLE (a - b) ha
|
||||
theorem ISize.ofIntLE_sub {a b : Int} {hab₁ hab₂} : ISize.ofIntLE (a - b) hab₁ hab₂ = ISize.ofInt a - ISize.ofInt b := by
|
||||
simp [ISize.ofIntLE_eq_ofInt]
|
||||
|
||||
@[simp] theorem Int8.ofBitVec_mul (a b : BitVec 8) : Int8.ofBitVec (a * b) = Int8.ofBitVec a * Int8.ofBitVec b := (rfl)
|
||||
@[simp] theorem Int16.ofBitVec_mul (a b : BitVec 16) : Int16.ofBitVec (a * b) = Int16.ofBitVec a * Int16.ofBitVec b := (rfl)
|
||||
@[simp] theorem Int32.ofBitVec_mul (a b : BitVec 32) : Int32.ofBitVec (a * b) = Int32.ofBitVec a * Int32.ofBitVec b := (rfl)
|
||||
@[simp] theorem Int64.ofBitVec_mul (a b : BitVec 64) : Int64.ofBitVec (a * b) = Int64.ofBitVec a * Int64.ofBitVec b := (rfl)
|
||||
@[simp] theorem ISize.ofBitVec_mul (a b : BitVec System.Platform.numBits) : ISize.ofBitVec (a * b) = ISize.ofBitVec a * ISize.ofBitVec b := (rfl)
|
||||
@[simp] theorem Int8.ofBitVec_mul (a b : BitVec 8) : Int8.ofBitVec (a * b) = Int8.ofBitVec a * Int8.ofBitVec b := rfl
|
||||
@[simp] theorem Int16.ofBitVec_mul (a b : BitVec 16) : Int16.ofBitVec (a * b) = Int16.ofBitVec a * Int16.ofBitVec b := rfl
|
||||
@[simp] theorem Int32.ofBitVec_mul (a b : BitVec 32) : Int32.ofBitVec (a * b) = Int32.ofBitVec a * Int32.ofBitVec b := rfl
|
||||
@[simp] theorem Int64.ofBitVec_mul (a b : BitVec 64) : Int64.ofBitVec (a * b) = Int64.ofBitVec a * Int64.ofBitVec b := rfl
|
||||
@[simp] theorem ISize.ofBitVec_mul (a b : BitVec System.Platform.numBits) : ISize.ofBitVec (a * b) = ISize.ofBitVec a * ISize.ofBitVec b := rfl
|
||||
|
||||
@[simp] theorem Int8.ofInt_mul (a b : Int) : Int8.ofInt (a * b) = Int8.ofInt a * Int8.ofInt b := by
|
||||
simp [Int8.ofInt_eq_iff_bmod_eq_toInt]
|
||||
@@ -2056,18 +2056,18 @@ theorem ISize.toInt_minValue_lt_zero : minValue.toInt < 0 := by
|
||||
rw [toInt_minValue, Int.neg_lt_zero_iff]
|
||||
exact Int.pow_pos (by decide)
|
||||
|
||||
theorem Int8.toInt_maxValue_add_one : maxValue.toInt + 1 = 2 ^ 7 := (rfl)
|
||||
theorem Int16.toInt_maxValue_add_one : maxValue.toInt + 1 = 2 ^ 15 := (rfl)
|
||||
theorem Int32.toInt_maxValue_add_one : maxValue.toInt + 1 = 2 ^ 31 := (rfl)
|
||||
theorem Int64.toInt_maxValue_add_one : maxValue.toInt + 1 = 2 ^ 63 := (rfl)
|
||||
theorem Int8.toInt_maxValue_add_one : maxValue.toInt + 1 = 2 ^ 7 := rfl
|
||||
theorem Int16.toInt_maxValue_add_one : maxValue.toInt + 1 = 2 ^ 15 := rfl
|
||||
theorem Int32.toInt_maxValue_add_one : maxValue.toInt + 1 = 2 ^ 31 := rfl
|
||||
theorem Int64.toInt_maxValue_add_one : maxValue.toInt + 1 = 2 ^ 63 := rfl
|
||||
theorem ISize.toInt_maxValue_add_one : maxValue.toInt + 1 = 2 ^ (System.Platform.numBits - 1) := by
|
||||
rw [toInt_maxValue, Int.sub_add_cancel]
|
||||
|
||||
@[simp] theorem Int8.ofBitVec_sdiv (a b : BitVec 8) : Int8.ofBitVec (a.sdiv b) = Int8.ofBitVec a / Int8.ofBitVec b := (rfl)
|
||||
@[simp] theorem Int16.ofBitVec_sdiv (a b : BitVec 16) : Int16.ofBitVec (a.sdiv b) = Int16.ofBitVec a / Int16.ofBitVec b := (rfl)
|
||||
@[simp] theorem Int32.ofBitVec_sdiv (a b : BitVec 32) : Int32.ofBitVec (a.sdiv b) = Int32.ofBitVec a / Int32.ofBitVec b := (rfl)
|
||||
@[simp] theorem Int64.ofBitVec_sdiv (a b : BitVec 64) : Int64.ofBitVec (a.sdiv b) = Int64.ofBitVec a / Int64.ofBitVec b := (rfl)
|
||||
@[simp] theorem ISize.ofBitVec_sdiv (a b : BitVec System.Platform.numBits) : ISize.ofBitVec (a.sdiv b) = ISize.ofBitVec a / ISize.ofBitVec b := (rfl)
|
||||
@[simp] theorem Int8.ofBitVec_sdiv (a b : BitVec 8) : Int8.ofBitVec (a.sdiv b) = Int8.ofBitVec a / Int8.ofBitVec b := rfl
|
||||
@[simp] theorem Int16.ofBitVec_sdiv (a b : BitVec 16) : Int16.ofBitVec (a.sdiv b) = Int16.ofBitVec a / Int16.ofBitVec b := rfl
|
||||
@[simp] theorem Int32.ofBitVec_sdiv (a b : BitVec 32) : Int32.ofBitVec (a.sdiv b) = Int32.ofBitVec a / Int32.ofBitVec b := rfl
|
||||
@[simp] theorem Int64.ofBitVec_sdiv (a b : BitVec 64) : Int64.ofBitVec (a.sdiv b) = Int64.ofBitVec a / Int64.ofBitVec b := rfl
|
||||
@[simp] theorem ISize.ofBitVec_sdiv (a b : BitVec System.Platform.numBits) : ISize.ofBitVec (a.sdiv b) = ISize.ofBitVec a / ISize.ofBitVec b := rfl
|
||||
|
||||
theorem Int8.ofInt_tdiv {a b : Int} (ha₁ : minValue.toInt ≤ a) (ha₂ : a ≤ maxValue.toInt)
|
||||
(hb₁ : minValue.toInt ≤ b) (hb₂ : b ≤ maxValue.toInt) : Int8.ofInt (a.tdiv b) = Int8.ofInt a / Int8.ofInt b := by
|
||||
@@ -2162,11 +2162,11 @@ theorem ISize.ofNat_div {a b : Nat} (ha : a < 2 ^ (System.Platform.numBits - 1))
|
||||
· apply Int.le_of_lt_add_one
|
||||
simpa only [toInt_maxValue_add_one, ← Int.ofNat_lt, Int.natCast_pow] using hb
|
||||
|
||||
@[simp] theorem Int8.ofBitVec_srem (a b : BitVec 8) : Int8.ofBitVec (a.srem b) = Int8.ofBitVec a % Int8.ofBitVec b := (rfl)
|
||||
@[simp] theorem Int16.ofBitVec_srem (a b : BitVec 16) : Int16.ofBitVec (a.srem b) = Int16.ofBitVec a % Int16.ofBitVec b := (rfl)
|
||||
@[simp] theorem Int32.ofBitVec_srem (a b : BitVec 32) : Int32.ofBitVec (a.srem b) = Int32.ofBitVec a % Int32.ofBitVec b := (rfl)
|
||||
@[simp] theorem Int64.ofBitVec_srem (a b : BitVec 64) : Int64.ofBitVec (a.srem b) = Int64.ofBitVec a % Int64.ofBitVec b := (rfl)
|
||||
@[simp] theorem ISize.ofBitVec_srem (a b : BitVec System.Platform.numBits) : ISize.ofBitVec (a.srem b) = ISize.ofBitVec a % ISize.ofBitVec b := (rfl)
|
||||
@[simp] theorem Int8.ofBitVec_srem (a b : BitVec 8) : Int8.ofBitVec (a.srem b) = Int8.ofBitVec a % Int8.ofBitVec b := rfl
|
||||
@[simp] theorem Int16.ofBitVec_srem (a b : BitVec 16) : Int16.ofBitVec (a.srem b) = Int16.ofBitVec a % Int16.ofBitVec b := rfl
|
||||
@[simp] theorem Int32.ofBitVec_srem (a b : BitVec 32) : Int32.ofBitVec (a.srem b) = Int32.ofBitVec a % Int32.ofBitVec b := rfl
|
||||
@[simp] theorem Int64.ofBitVec_srem (a b : BitVec 64) : Int64.ofBitVec (a.srem b) = Int64.ofBitVec a % Int64.ofBitVec b := rfl
|
||||
@[simp] theorem ISize.ofBitVec_srem (a b : BitVec System.Platform.numBits) : ISize.ofBitVec (a.srem b) = ISize.ofBitVec a % ISize.ofBitVec b := rfl
|
||||
|
||||
@[simp] theorem Int8.toInt_bmod_size (a : Int8) : a.toInt.bmod size = a.toInt := BitVec.toInt_bmod_cancel _
|
||||
@[simp] theorem Int16.toInt_bmod_size (a : Int16) : a.toInt.bmod size = a.toInt := BitVec.toInt_bmod_cancel _
|
||||
@@ -2300,16 +2300,16 @@ theorem Int32.ofBitVec_lt_iff_slt (a b : BitVec 32) : Int32.ofBitVec a < Int32.o
|
||||
theorem Int64.ofBitVec_lt_iff_slt (a b : BitVec 64) : Int64.ofBitVec a < Int64.ofBitVec b ↔ a.slt b := Iff.rfl
|
||||
theorem ISize.ofBitVec_lt_iff_slt (a b : BitVec System.Platform.numBits) : ISize.ofBitVec a < ISize.ofBitVec b ↔ a.slt b := Iff.rfl
|
||||
|
||||
theorem Int8.toNatClampNeg_one : (1 : Int8).toNatClampNeg = 1 := (rfl)
|
||||
theorem Int16.toNatClampNeg_one : (1 : Int16).toNatClampNeg = 1 := (rfl)
|
||||
theorem Int32.toNatClampNeg_one : (1 : Int32).toNatClampNeg = 1 := (rfl)
|
||||
theorem Int64.toNatClampNeg_one : (1 : Int64).toNatClampNeg = 1 := (rfl)
|
||||
theorem Int8.toNatClampNeg_one : (1 : Int8).toNatClampNeg = 1 := rfl
|
||||
theorem Int16.toNatClampNeg_one : (1 : Int16).toNatClampNeg = 1 := rfl
|
||||
theorem Int32.toNatClampNeg_one : (1 : Int32).toNatClampNeg = 1 := rfl
|
||||
theorem Int64.toNatClampNeg_one : (1 : Int64).toNatClampNeg = 1 := rfl
|
||||
theorem ISize.toNatClampNeg_one : (1 : ISize).toNatClampNeg = 1 := by simp
|
||||
|
||||
theorem Int8.toInt_one : (1 : Int8).toInt = 1 := (rfl)
|
||||
theorem Int16.toInt_one : (1 : Int16).toInt = 1 := (rfl)
|
||||
theorem Int32.toInt_one : (1 : Int32).toInt = 1 := (rfl)
|
||||
theorem Int64.toInt_one : (1 : Int64).toInt = 1 := (rfl)
|
||||
theorem Int8.toInt_one : (1 : Int8).toInt = 1 := rfl
|
||||
theorem Int16.toInt_one : (1 : Int16).toInt = 1 := rfl
|
||||
theorem Int32.toInt_one : (1 : Int32).toInt = 1 := rfl
|
||||
theorem Int64.toInt_one : (1 : Int64).toInt = 1 := rfl
|
||||
theorem ISize.toInt_one : (1 : ISize).toInt = 1 := by simp
|
||||
|
||||
theorem Int8.zero_lt_one : (0 : Int8) < 1 := by simp
|
||||
@@ -2631,16 +2631,16 @@ instance : Std.LawfulCommIdentity (α := ISize) (· * ·) 1 where
|
||||
@[simp] theorem Int64.zero_mul {a : Int64} : 0 * a = 0 := Int64.toBitVec_inj.1 BitVec.zero_mul
|
||||
@[simp] theorem ISize.zero_mul {a : ISize} : 0 * a = 0 := ISize.toBitVec_inj.1 BitVec.zero_mul
|
||||
|
||||
@[simp] protected theorem Int8.pow_zero (x : Int8) : x ^ 0 = 1 := (rfl)
|
||||
protected theorem Int8.pow_succ (x : Int8) (n : Nat) : x ^ (n + 1) = x ^ n * x := (rfl)
|
||||
@[simp] protected theorem Int16.pow_zero (x : Int16) : x ^ 0 = 1 := (rfl)
|
||||
protected theorem Int16.pow_succ (x : Int16) (n : Nat) : x ^ (n + 1) = x ^ n * x := (rfl)
|
||||
@[simp] protected theorem Int32.pow_zero (x : Int32) : x ^ 0 = 1 := (rfl)
|
||||
protected theorem Int32.pow_succ (x : Int32) (n : Nat) : x ^ (n + 1) = x ^ n * x := (rfl)
|
||||
@[simp] protected theorem Int64.pow_zero (x : Int64) : x ^ 0 = 1 := (rfl)
|
||||
protected theorem Int64.pow_succ (x : Int64) (n : Nat) : x ^ (n + 1) = x ^ n * x := (rfl)
|
||||
@[simp] protected theorem ISize.pow_zero (x : ISize) : x ^ 0 = 1 := (rfl)
|
||||
protected theorem ISize.pow_succ (x : ISize) (n : Nat) : x ^ (n + 1) = x ^ n * x := (rfl)
|
||||
@[simp] protected theorem Int8.pow_zero (x : Int8) : x ^ 0 = 1 := rfl
|
||||
protected theorem Int8.pow_succ (x : Int8) (n : Nat) : x ^ (n + 1) = x ^ n * x := rfl
|
||||
@[simp] protected theorem Int16.pow_zero (x : Int16) : x ^ 0 = 1 := rfl
|
||||
protected theorem Int16.pow_succ (x : Int16) (n : Nat) : x ^ (n + 1) = x ^ n * x := rfl
|
||||
@[simp] protected theorem Int32.pow_zero (x : Int32) : x ^ 0 = 1 := rfl
|
||||
protected theorem Int32.pow_succ (x : Int32) (n : Nat) : x ^ (n + 1) = x ^ n * x := rfl
|
||||
@[simp] protected theorem Int64.pow_zero (x : Int64) : x ^ 0 = 1 := rfl
|
||||
protected theorem Int64.pow_succ (x : Int64) (n : Nat) : x ^ (n + 1) = x ^ n * x := rfl
|
||||
@[simp] protected theorem ISize.pow_zero (x : ISize) : x ^ 0 = 1 := rfl
|
||||
protected theorem ISize.pow_succ (x : ISize) (n : Nat) : x ^ (n + 1) = x ^ n * x := rfl
|
||||
|
||||
protected theorem Int8.mul_add {a b c : Int8} : a * (b + c) = a * b + a * c :=
|
||||
Int8.toBitVec_inj.1 BitVec.mul_add
|
||||
@@ -3092,53 +3092,53 @@ theorem Int64.toInt_eq_toNatClampNeg {a : Int64} (ha : 0 ≤ a) : a.toInt = a.to
|
||||
theorem ISize.toInt_eq_toNatClampNeg {a : ISize} (ha : 0 ≤ a) : a.toInt = a.toNatClampNeg := by
|
||||
simpa only [← toNat_toInt, Int.eq_natCast_toNat, le_iff_toInt_le, toInt_zero] using ha
|
||||
|
||||
@[simp] theorem UInt8.toInt8_add (a b : UInt8) : (a + b).toInt8 = a.toInt8 + b.toInt8 := (rfl)
|
||||
@[simp] theorem UInt16.toInt16_add (a b : UInt16) : (a + b).toInt16 = a.toInt16 + b.toInt16 := (rfl)
|
||||
@[simp] theorem UInt32.toInt32_add (a b : UInt32) : (a + b).toInt32 = a.toInt32 + b.toInt32 := (rfl)
|
||||
@[simp] theorem UInt64.toInt64_add (a b : UInt64) : (a + b).toInt64 = a.toInt64 + b.toInt64 := (rfl)
|
||||
@[simp] theorem USize.toISize_add (a b : USize) : (a + b).toISize = a.toISize + b.toISize := (rfl)
|
||||
@[simp] theorem UInt8.toInt8_add (a b : UInt8) : (a + b).toInt8 = a.toInt8 + b.toInt8 := rfl
|
||||
@[simp] theorem UInt16.toInt16_add (a b : UInt16) : (a + b).toInt16 = a.toInt16 + b.toInt16 := rfl
|
||||
@[simp] theorem UInt32.toInt32_add (a b : UInt32) : (a + b).toInt32 = a.toInt32 + b.toInt32 := rfl
|
||||
@[simp] theorem UInt64.toInt64_add (a b : UInt64) : (a + b).toInt64 = a.toInt64 + b.toInt64 := rfl
|
||||
@[simp] theorem USize.toISize_add (a b : USize) : (a + b).toISize = a.toISize + b.toISize := rfl
|
||||
|
||||
@[simp] theorem UInt8.toInt8_neg (a : UInt8) : (-a).toInt8 = -a.toInt8 := (rfl)
|
||||
@[simp] theorem UInt16.toInt16_neg (a : UInt16) : (-a).toInt16 = -a.toInt16 := (rfl)
|
||||
@[simp] theorem UInt32.toInt32_neg (a : UInt32) : (-a).toInt32 = -a.toInt32 := (rfl)
|
||||
@[simp] theorem UInt64.toInt64_neg (a : UInt64) : (-a).toInt64 = -a.toInt64 := (rfl)
|
||||
@[simp] theorem USize.toISize_neg (a : USize) : (-a).toISize = -a.toISize := (rfl)
|
||||
@[simp] theorem UInt8.toInt8_neg (a : UInt8) : (-a).toInt8 = -a.toInt8 := rfl
|
||||
@[simp] theorem UInt16.toInt16_neg (a : UInt16) : (-a).toInt16 = -a.toInt16 := rfl
|
||||
@[simp] theorem UInt32.toInt32_neg (a : UInt32) : (-a).toInt32 = -a.toInt32 := rfl
|
||||
@[simp] theorem UInt64.toInt64_neg (a : UInt64) : (-a).toInt64 = -a.toInt64 := rfl
|
||||
@[simp] theorem USize.toISize_neg (a : USize) : (-a).toISize = -a.toISize := rfl
|
||||
|
||||
@[simp] theorem UInt8.toInt8_sub (a b : UInt8) : (a - b).toInt8 = a.toInt8 - b.toInt8 := (rfl)
|
||||
@[simp] theorem UInt16.toInt16_sub (a b : UInt16) : (a - b).toInt16 = a.toInt16 - b.toInt16 := (rfl)
|
||||
@[simp] theorem UInt32.toInt32_sub (a b : UInt32) : (a - b).toInt32 = a.toInt32 - b.toInt32 := (rfl)
|
||||
@[simp] theorem UInt64.toInt64_sub (a b : UInt64) : (a - b).toInt64 = a.toInt64 - b.toInt64 := (rfl)
|
||||
@[simp] theorem USize.toISize_sub (a b : USize) : (a - b).toISize = a.toISize - b.toISize := (rfl)
|
||||
@[simp] theorem UInt8.toInt8_sub (a b : UInt8) : (a - b).toInt8 = a.toInt8 - b.toInt8 := rfl
|
||||
@[simp] theorem UInt16.toInt16_sub (a b : UInt16) : (a - b).toInt16 = a.toInt16 - b.toInt16 := rfl
|
||||
@[simp] theorem UInt32.toInt32_sub (a b : UInt32) : (a - b).toInt32 = a.toInt32 - b.toInt32 := rfl
|
||||
@[simp] theorem UInt64.toInt64_sub (a b : UInt64) : (a - b).toInt64 = a.toInt64 - b.toInt64 := rfl
|
||||
@[simp] theorem USize.toISize_sub (a b : USize) : (a - b).toISize = a.toISize - b.toISize := rfl
|
||||
|
||||
@[simp] theorem UInt8.toInt8_mul (a b : UInt8) : (a * b).toInt8 = a.toInt8 * b.toInt8 := (rfl)
|
||||
@[simp] theorem UInt16.toInt16_mul (a b : UInt16) : (a * b).toInt16 = a.toInt16 * b.toInt16 := (rfl)
|
||||
@[simp] theorem UInt32.toInt32_mul (a b : UInt32) : (a * b).toInt32 = a.toInt32 * b.toInt32 := (rfl)
|
||||
@[simp] theorem UInt64.toInt64_mul (a b : UInt64) : (a * b).toInt64 = a.toInt64 * b.toInt64 := (rfl)
|
||||
@[simp] theorem USize.toISize_mul (a b : USize) : (a * b).toISize = a.toISize * b.toISize := (rfl)
|
||||
@[simp] theorem UInt8.toInt8_mul (a b : UInt8) : (a * b).toInt8 = a.toInt8 * b.toInt8 := rfl
|
||||
@[simp] theorem UInt16.toInt16_mul (a b : UInt16) : (a * b).toInt16 = a.toInt16 * b.toInt16 := rfl
|
||||
@[simp] theorem UInt32.toInt32_mul (a b : UInt32) : (a * b).toInt32 = a.toInt32 * b.toInt32 := rfl
|
||||
@[simp] theorem UInt64.toInt64_mul (a b : UInt64) : (a * b).toInt64 = a.toInt64 * b.toInt64 := rfl
|
||||
@[simp] theorem USize.toISize_mul (a b : USize) : (a * b).toISize = a.toISize * b.toISize := rfl
|
||||
|
||||
@[simp] theorem Int8.toUInt8_add (a b : Int8) : (a + b).toUInt8 = a.toUInt8 + b.toUInt8 := (rfl)
|
||||
@[simp] theorem Int16.toUInt16_add (a b : Int16) : (a + b).toUInt16 = a.toUInt16 + b.toUInt16 := (rfl)
|
||||
@[simp] theorem Int32.toUInt32_add (a b : Int32) : (a + b).toUInt32 = a.toUInt32 + b.toUInt32 := (rfl)
|
||||
@[simp] theorem Int64.toUInt64_add (a b : Int64) : (a + b).toUInt64 = a.toUInt64 + b.toUInt64 := (rfl)
|
||||
@[simp] theorem ISize.toUSize_add (a b : ISize) : (a + b).toUSize = a.toUSize + b.toUSize := (rfl)
|
||||
@[simp] theorem Int8.toUInt8_add (a b : Int8) : (a + b).toUInt8 = a.toUInt8 + b.toUInt8 := rfl
|
||||
@[simp] theorem Int16.toUInt16_add (a b : Int16) : (a + b).toUInt16 = a.toUInt16 + b.toUInt16 := rfl
|
||||
@[simp] theorem Int32.toUInt32_add (a b : Int32) : (a + b).toUInt32 = a.toUInt32 + b.toUInt32 := rfl
|
||||
@[simp] theorem Int64.toUInt64_add (a b : Int64) : (a + b).toUInt64 = a.toUInt64 + b.toUInt64 := rfl
|
||||
@[simp] theorem ISize.toUSize_add (a b : ISize) : (a + b).toUSize = a.toUSize + b.toUSize := rfl
|
||||
|
||||
@[simp] theorem Int8.toUInt8_neg (a : Int8) : (-a).toUInt8 = -a.toUInt8 := (rfl)
|
||||
@[simp] theorem Int16.toUInt16_neg (a : Int16) : (-a).toUInt16 = -a.toUInt16 := (rfl)
|
||||
@[simp] theorem Int32.toUInt32_neg (a : Int32) : (-a).toUInt32 = -a.toUInt32 := (rfl)
|
||||
@[simp] theorem Int64.toUInt64_neg (a : Int64) : (-a).toUInt64 = -a.toUInt64 := (rfl)
|
||||
@[simp] theorem ISize.toUSize_neg (a : ISize) : (-a).toUSize = -a.toUSize := (rfl)
|
||||
@[simp] theorem Int8.toUInt8_neg (a : Int8) : (-a).toUInt8 = -a.toUInt8 := rfl
|
||||
@[simp] theorem Int16.toUInt16_neg (a : Int16) : (-a).toUInt16 = -a.toUInt16 := rfl
|
||||
@[simp] theorem Int32.toUInt32_neg (a : Int32) : (-a).toUInt32 = -a.toUInt32 := rfl
|
||||
@[simp] theorem Int64.toUInt64_neg (a : Int64) : (-a).toUInt64 = -a.toUInt64 := rfl
|
||||
@[simp] theorem ISize.toUSize_neg (a : ISize) : (-a).toUSize = -a.toUSize := rfl
|
||||
|
||||
@[simp] theorem Int8.toUInt8_sub (a b : Int8) : (a - b).toUInt8 = a.toUInt8 - b.toUInt8 := (rfl)
|
||||
@[simp] theorem Int16.toUInt16_sub (a b : Int16) : (a - b).toUInt16 = a.toUInt16 - b.toUInt16 := (rfl)
|
||||
@[simp] theorem Int32.toUInt32_sub (a b : Int32) : (a - b).toUInt32 = a.toUInt32 - b.toUInt32 := (rfl)
|
||||
@[simp] theorem Int64.toUInt64_sub (a b : Int64) : (a - b).toUInt64 = a.toUInt64 - b.toUInt64 := (rfl)
|
||||
@[simp] theorem ISize.toUSize_sub (a b : ISize) : (a - b).toUSize = a.toUSize - b.toUSize := (rfl)
|
||||
@[simp] theorem Int8.toUInt8_sub (a b : Int8) : (a - b).toUInt8 = a.toUInt8 - b.toUInt8 := rfl
|
||||
@[simp] theorem Int16.toUInt16_sub (a b : Int16) : (a - b).toUInt16 = a.toUInt16 - b.toUInt16 := rfl
|
||||
@[simp] theorem Int32.toUInt32_sub (a b : Int32) : (a - b).toUInt32 = a.toUInt32 - b.toUInt32 := rfl
|
||||
@[simp] theorem Int64.toUInt64_sub (a b : Int64) : (a - b).toUInt64 = a.toUInt64 - b.toUInt64 := rfl
|
||||
@[simp] theorem ISize.toUSize_sub (a b : ISize) : (a - b).toUSize = a.toUSize - b.toUSize := rfl
|
||||
|
||||
@[simp] theorem Int8.toUInt8_mul (a b : Int8) : (a * b).toUInt8 = a.toUInt8 * b.toUInt8 := (rfl)
|
||||
@[simp] theorem Int16.toUInt16_mul (a b : Int16) : (a * b).toUInt16 = a.toUInt16 * b.toUInt16 := (rfl)
|
||||
@[simp] theorem Int32.toUInt32_mul (a b : Int32) : (a * b).toUInt32 = a.toUInt32 * b.toUInt32 := (rfl)
|
||||
@[simp] theorem Int64.toUInt64_mul (a b : Int64) : (a * b).toUInt64 = a.toUInt64 * b.toUInt64 := (rfl)
|
||||
@[simp] theorem ISize.toUSize_mul (a b : ISize) : (a * b).toUSize = a.toUSize * b.toUSize := (rfl)
|
||||
@[simp] theorem Int8.toUInt8_mul (a b : Int8) : (a * b).toUInt8 = a.toUInt8 * b.toUInt8 := rfl
|
||||
@[simp] theorem Int16.toUInt16_mul (a b : Int16) : (a * b).toUInt16 = a.toUInt16 * b.toUInt16 := rfl
|
||||
@[simp] theorem Int32.toUInt32_mul (a b : Int32) : (a * b).toUInt32 = a.toUInt32 * b.toUInt32 := rfl
|
||||
@[simp] theorem Int64.toUInt64_mul (a b : Int64) : (a * b).toUInt64 = a.toUInt64 * b.toUInt64 := rfl
|
||||
@[simp] theorem ISize.toUSize_mul (a b : ISize) : (a * b).toUSize = a.toUSize * b.toUSize := rfl
|
||||
|
||||
theorem Int8.toNatClampNeg_le {a b : Int8} (hab : a ≤ b) : a.toNatClampNeg ≤ b.toNatClampNeg := by
|
||||
rw [← Int8.toNat_toInt, ← Int8.toNat_toInt]
|
||||
|
||||
@@ -57,7 +57,7 @@ Examples:
|
||||
* `"abc".length = 3`
|
||||
* `"L∃∀N".length = 4`
|
||||
-/
|
||||
@[extern "lean_string_length", expose]
|
||||
@[extern "lean_string_length"]
|
||||
def length : (@& String) → Nat
|
||||
| ⟨s⟩ => s.length
|
||||
|
||||
@@ -71,7 +71,7 @@ Examples:
|
||||
* `"abc".push 'd' = "abcd"`
|
||||
* `"".push 'a' = "a"`
|
||||
-/
|
||||
@[extern "lean_string_push", expose]
|
||||
@[extern "lean_string_push"]
|
||||
def push : String → Char → String
|
||||
| ⟨s⟩, c => ⟨s ++ [c]⟩
|
||||
|
||||
@@ -85,7 +85,7 @@ Examples:
|
||||
* `"abc" ++ "def" = "abcdef"`
|
||||
* `"" ++ "" = ""`
|
||||
-/
|
||||
@[extern "lean_string_append", expose]
|
||||
@[extern "lean_string_append"]
|
||||
def append : String → (@& String) → String
|
||||
| ⟨a⟩, ⟨b⟩ => ⟨a ++ b⟩
|
||||
|
||||
@@ -145,7 +145,7 @@ Examples:
|
||||
* `"abc".get ⟨3⟩ = (default : Char)` because byte `3` is at the end of the string.
|
||||
* `"L∃∀N".get ⟨2⟩ = (default : Char)` because byte `2` is in the middle of `'∃'`.
|
||||
-/
|
||||
@[extern "lean_string_utf8_get", expose]
|
||||
@[extern "lean_string_utf8_get"]
|
||||
def get (s : @& String) (p : @& Pos) : Char :=
|
||||
match s with
|
||||
| ⟨s⟩ => utf8GetAux s 0 p
|
||||
@@ -182,7 +182,7 @@ This function is overridden with an efficient implementation in runtime code. Se
|
||||
Examples
|
||||
* `"abc".get! ⟨1⟩ = 'b'`
|
||||
-/
|
||||
@[extern "lean_string_utf8_get_bang", expose]
|
||||
@[extern "lean_string_utf8_get_bang"]
|
||||
def get! (s : @& String) (p : @& Pos) : Char :=
|
||||
match s with
|
||||
| ⟨s⟩ => utf8GetAux s 0 p
|
||||
@@ -239,7 +239,7 @@ Examples:
|
||||
* `"abc".get ("abc".next 0) = 'b'`
|
||||
* `"L∃∀N".get (0 |> "L∃∀N".next |> "L∃∀N".next) = '∀'`
|
||||
-/
|
||||
@[extern "lean_string_utf8_next", expose]
|
||||
@[extern "lean_string_utf8_next"]
|
||||
def next (s : @& String) (p : @& Pos) : Pos :=
|
||||
let c := get s p
|
||||
p + c
|
||||
@@ -261,7 +261,7 @@ Examples:
|
||||
* `"abc".get ("abc".endPos |> "abc".prev) = 'c'`
|
||||
* `"L∃∀N".get ("L∃∀N".endPos |> "L∃∀N".prev |> "L∃∀N".prev |> "L∃∀N".prev) = '∃'`
|
||||
-/
|
||||
@[extern "lean_string_utf8_prev", expose]
|
||||
@[extern "lean_string_utf8_prev"]
|
||||
def prev : (@& String) → (@& Pos) → Pos
|
||||
| ⟨s⟩, p => if p = 0 then 0 else utf8PrevAux s 0 p
|
||||
|
||||
@@ -322,7 +322,7 @@ Examples:
|
||||
* `"abc".get' 0 (by decide) = 'a'`
|
||||
* `let lean := "L∃∀N"; lean.get' (0 |> lean.next |> lean.next) (by decide) = '∀'`
|
||||
-/
|
||||
@[extern "lean_string_utf8_get_fast", expose]
|
||||
@[extern "lean_string_utf8_get_fast"]
|
||||
def get' (s : @& String) (p : @& Pos) (h : ¬ s.atEnd p) : Char :=
|
||||
match s with
|
||||
| ⟨s⟩ => utf8GetAux s 0 p
|
||||
@@ -344,7 +344,7 @@ def next? (s: String) (p : String.Pos) : Option Char :=
|
||||
Example:
|
||||
* `let abc := "abc"; abc.get (abc.next' 0 (by decide)) = 'b'`
|
||||
-/
|
||||
@[extern "lean_string_utf8_next_fast", expose]
|
||||
@[extern "lean_string_utf8_next_fast"]
|
||||
def next' (s : @& String) (p : @& Pos) (h : ¬ s.atEnd p) : Pos :=
|
||||
let c := get s p
|
||||
p + c
|
||||
@@ -669,7 +669,7 @@ Examples:
|
||||
* `String.singleton '"' = "\""`
|
||||
* `String.singleton '𝒫' = "𝒫"`
|
||||
-/
|
||||
@[inline,expose] def singleton (c : Char) : String :=
|
||||
@[inline] def singleton (c : Char) : String :=
|
||||
"".push c
|
||||
|
||||
/--
|
||||
@@ -1954,7 +1954,7 @@ Examples:
|
||||
* `'L'.toString = "L"`
|
||||
* `'"'.toString = "\""`
|
||||
-/
|
||||
@[inline, expose] protected def toString (c : Char) : String :=
|
||||
@[inline] protected def toString (c : Char) : String :=
|
||||
String.singleton c
|
||||
|
||||
@[simp] theorem length_toString (c : Char) : c.toString.length = 1 := rfl
|
||||
|
||||
@@ -49,30 +49,30 @@ deriving instance BEq for Sum
|
||||
section get
|
||||
|
||||
/-- Checks whether a sum is the left injection `inl`. -/
|
||||
@[expose] def isLeft : α ⊕ β → Bool
|
||||
def isLeft : α ⊕ β → Bool
|
||||
| inl _ => true
|
||||
| inr _ => false
|
||||
|
||||
/-- Checks whether a sum is the right injection `inr`. -/
|
||||
@[expose] def isRight : α ⊕ β → Bool
|
||||
def isRight : α ⊕ β → Bool
|
||||
| inl _ => false
|
||||
| inr _ => true
|
||||
|
||||
/-- Retrieves the contents from a sum known to be `inl`.-/
|
||||
@[expose] def getLeft : (ab : α ⊕ β) → ab.isLeft → α
|
||||
def getLeft : (ab : α ⊕ β) → ab.isLeft → α
|
||||
| inl a, _ => a
|
||||
|
||||
/-- Retrieves the contents from a sum known to be `inr`.-/
|
||||
@[expose] def getRight : (ab : α ⊕ β) → ab.isRight → β
|
||||
def getRight : (ab : α ⊕ β) → ab.isRight → β
|
||||
| inr b, _ => b
|
||||
|
||||
/-- Checks whether a sum is the left injection `inl` and, if so, retrieves its contents. -/
|
||||
@[expose] def getLeft? : α ⊕ β → Option α
|
||||
def getLeft? : α ⊕ β → Option α
|
||||
| inl a => some a
|
||||
| inr _ => none
|
||||
|
||||
/-- Checks whether a sum is the right injection `inr` and, if so, retrieves its contents. -/
|
||||
@[expose] def getRight? : α ⊕ β → Option β
|
||||
def getRight? : α ⊕ β → Option β
|
||||
| inr b => some b
|
||||
| inl _ => none
|
||||
|
||||
@@ -95,7 +95,7 @@ end get
|
||||
Case analysis for sums that applies the appropriate function `f` or `g` after checking which
|
||||
constructor is present.
|
||||
-/
|
||||
@[expose] protected def elim {α β γ} (f : α → γ) (g : β → γ) : α ⊕ β → γ :=
|
||||
protected def elim {α β γ} (f : α → γ) (g : β → γ) : α ⊕ β → γ :=
|
||||
fun x => Sum.casesOn x f g
|
||||
|
||||
@[simp] theorem elim_inl (f : α → γ) (g : β → γ) (x : α) :
|
||||
@@ -109,7 +109,7 @@ Transforms a sum according to functions on each type.
|
||||
|
||||
This function maps `α ⊕ β` to `α' ⊕ β'`, sending `α` to `α'` and `β` to `β'`.
|
||||
-/
|
||||
@[expose] protected def map (f : α → α') (g : β → β') : α ⊕ β → α' ⊕ β' :=
|
||||
protected def map (f : α → α') (g : β → β') : α ⊕ β → α' ⊕ β' :=
|
||||
Sum.elim (inl ∘ f) (inr ∘ g)
|
||||
|
||||
@[simp] theorem map_inl (f : α → α') (g : β → β') (x : α) : (inl x).map f g = inl (f x) := rfl
|
||||
@@ -121,7 +121,7 @@ Swaps the factors of a sum type.
|
||||
|
||||
The constructor `Sum.inl` is replaced with `Sum.inr`, and vice versa.
|
||||
-/
|
||||
@[expose] def swap : α ⊕ β → β ⊕ α := Sum.elim inr inl
|
||||
def swap : α ⊕ β → β ⊕ α := Sum.elim inr inl
|
||||
|
||||
@[simp] theorem swap_inl : swap (inl x : α ⊕ β) = inr x := rfl
|
||||
|
||||
|
||||
@@ -220,7 +220,7 @@ instance UInt32.instOfNat : OfNat UInt32 n := ⟨UInt32.ofNat n⟩
|
||||
|
||||
theorem UInt32.ofNatLT_lt_of_lt {n m : Nat} (h1 : n < UInt32.size) (h2 : m < UInt32.size) :
|
||||
n < m → UInt32.ofNatLT n h1 < UInt32.ofNat m := by
|
||||
simp only [(· < ·), BitVec.toNat, ofNatLT, BitVec.ofNatLT, ofNat, BitVec.ofNat, Fin.ofNat,
|
||||
simp only [(· < ·), BitVec.toNat, ofNatLT, BitVec.ofNatLT, ofNat, BitVec.ofNat, Fin.ofNat',
|
||||
Nat.mod_eq_of_lt h2, imp_self]
|
||||
|
||||
@[deprecated UInt32.ofNatLT_lt_of_lt (since := "2025-02-13")]
|
||||
@@ -229,7 +229,7 @@ theorem UInt32.ofNat'_lt_of_lt {n m : Nat} (h1 : n < UInt32.size) (h2 : m < UInt
|
||||
|
||||
theorem UInt32.lt_ofNatLT_of_lt {n m : Nat} (h1 : n < UInt32.size) (h2 : m < UInt32.size) :
|
||||
m < n → UInt32.ofNat m < UInt32.ofNatLT n h1 := by
|
||||
simp only [(· < ·), BitVec.toNat, ofNatLT, BitVec.ofNatLT, ofNat, BitVec.ofNat, Fin.ofNat,
|
||||
simp only [(· < ·), BitVec.toNat, ofNatLT, BitVec.ofNatLT, ofNat, BitVec.ofNat, Fin.ofNat',
|
||||
Nat.mod_eq_of_lt h2, imp_self]
|
||||
|
||||
@[deprecated UInt32.lt_ofNatLT_of_lt (since := "2025-02-13")]
|
||||
@@ -336,6 +336,9 @@ theorem usize_size_eq : USize.size = 4294967296 ∨ USize.size = 184467440737095
|
||||
theorem usize_size_pos : 0 < USize.size :=
|
||||
USize.size_pos
|
||||
|
||||
@[deprecated USize.size_pos (since := "2024-11-24")] theorem usize_size_gt_zero : USize.size > 0 :=
|
||||
USize.size_pos
|
||||
|
||||
/-- Converts a `USize` into the corresponding `Fin USize.size`. -/
|
||||
def USize.toFin (x : USize) : Fin USize.size := x.toBitVec.toFin
|
||||
@[deprecated USize.toFin (since := "2025-02-12"), inherit_doc USize.toFin]
|
||||
|
||||
@@ -16,12 +16,12 @@ macro "declare_bitwise_uint_theorems" typeName:ident bits:term:arg : command =>
|
||||
`(
|
||||
namespace $typeName
|
||||
|
||||
@[simp, int_toBitVec] protected theorem toBitVec_not {a : $typeName} : (~~~a).toBitVec = ~~~a.toBitVec := (rfl)
|
||||
@[simp, int_toBitVec] protected theorem toBitVec_and (a b : $typeName) : (a &&& b).toBitVec = a.toBitVec &&& b.toBitVec := (rfl)
|
||||
@[simp, int_toBitVec] protected theorem toBitVec_or (a b : $typeName) : (a ||| b).toBitVec = a.toBitVec ||| b.toBitVec := (rfl)
|
||||
@[simp, int_toBitVec] protected theorem toBitVec_xor (a b : $typeName) : (a ^^^ b).toBitVec = a.toBitVec ^^^ b.toBitVec := (rfl)
|
||||
@[simp, int_toBitVec] protected theorem toBitVec_shiftLeft (a b : $typeName) : (a <<< b).toBitVec = a.toBitVec <<< (b.toBitVec % $bits) := (rfl)
|
||||
@[simp, int_toBitVec] protected theorem toBitVec_shiftRight (a b : $typeName) : (a >>> b).toBitVec = a.toBitVec >>> (b.toBitVec % $bits) := (rfl)
|
||||
@[simp, int_toBitVec] protected theorem toBitVec_not {a : $typeName} : (~~~a).toBitVec = ~~~a.toBitVec := rfl
|
||||
@[simp, int_toBitVec] protected theorem toBitVec_and (a b : $typeName) : (a &&& b).toBitVec = a.toBitVec &&& b.toBitVec := rfl
|
||||
@[simp, int_toBitVec] protected theorem toBitVec_or (a b : $typeName) : (a ||| b).toBitVec = a.toBitVec ||| b.toBitVec := rfl
|
||||
@[simp, int_toBitVec] protected theorem toBitVec_xor (a b : $typeName) : (a ^^^ b).toBitVec = a.toBitVec ^^^ b.toBitVec := rfl
|
||||
@[simp, int_toBitVec] protected theorem toBitVec_shiftLeft (a b : $typeName) : (a <<< b).toBitVec = a.toBitVec <<< (b.toBitVec % $bits) := rfl
|
||||
@[simp, int_toBitVec] protected theorem toBitVec_shiftRight (a b : $typeName) : (a >>> b).toBitVec = a.toBitVec >>> (b.toBitVec % $bits) := rfl
|
||||
|
||||
@[simp] protected theorem toNat_and (a b : $typeName) : (a &&& b).toNat = a.toNat &&& b.toNat := by simp [toNat, -toNat_toBitVec]
|
||||
@[simp] protected theorem toNat_or (a b : $typeName) : (a ||| b).toNat = a.toNat ||| b.toNat := by simp [toNat, -toNat_toBitVec]
|
||||
@@ -29,6 +29,10 @@ namespace $typeName
|
||||
@[simp] protected theorem toNat_shiftLeft (a b : $typeName) : (a <<< b).toNat = a.toNat <<< (b.toNat % $bits) % 2 ^ $bits := by simp [toNat, -toNat_toBitVec]
|
||||
@[simp] protected theorem toNat_shiftRight (a b : $typeName) : (a >>> b).toNat = a.toNat >>> (b.toNat % $bits) := by simp [toNat, -toNat_toBitVec]
|
||||
|
||||
open $typeName (toNat_and) in
|
||||
@[deprecated toNat_and (since := "2024-11-28")]
|
||||
protected theorem and_toNat (a b : $typeName) : (a &&& b).toNat = a.toNat &&& b.toNat := BitVec.toNat_and ..
|
||||
|
||||
end $typeName
|
||||
)
|
||||
declare_bitwise_uint_theorems UInt8 8
|
||||
@@ -71,25 +75,25 @@ theorem Bool.toBitVec_toUSize {b : Bool} :
|
||||
@[simp] theorem UInt64.toFin_and (a b : UInt64) : (a &&& b).toFin = a.toFin &&& b.toFin := Fin.val_inj.1 (by simp)
|
||||
@[simp] theorem USize.toFin_and (a b : USize) : (a &&& b).toFin = a.toFin &&& b.toFin := Fin.val_inj.1 (by simp)
|
||||
|
||||
@[simp] theorem UInt8.toUInt16_and (a b : UInt8) : (a &&& b).toUInt16 = a.toUInt16 &&& b.toUInt16 := (rfl)
|
||||
@[simp] theorem UInt8.toUInt32_and (a b : UInt8) : (a &&& b).toUInt32 = a.toUInt32 &&& b.toUInt32 := (rfl)
|
||||
@[simp] theorem UInt8.toUInt64_and (a b : UInt8) : (a &&& b).toUInt64 = a.toUInt64 &&& b.toUInt64 := (rfl)
|
||||
@[simp] theorem UInt8.toUSize_and (a b : UInt8) : (a &&& b).toUSize = a.toUSize &&& b.toUSize := (rfl)
|
||||
@[simp] theorem UInt8.toUInt16_and (a b : UInt8) : (a &&& b).toUInt16 = a.toUInt16 &&& b.toUInt16 := rfl
|
||||
@[simp] theorem UInt8.toUInt32_and (a b : UInt8) : (a &&& b).toUInt32 = a.toUInt32 &&& b.toUInt32 := rfl
|
||||
@[simp] theorem UInt8.toUInt64_and (a b : UInt8) : (a &&& b).toUInt64 = a.toUInt64 &&& b.toUInt64 := rfl
|
||||
@[simp] theorem UInt8.toUSize_and (a b : UInt8) : (a &&& b).toUSize = a.toUSize &&& b.toUSize := rfl
|
||||
|
||||
@[simp] theorem UInt16.toUInt8_and (a b : UInt16) : (a &&& b).toUInt8 = a.toUInt8 &&& b.toUInt8 := UInt8.toBitVec_inj.1 (by simp)
|
||||
@[simp] theorem UInt16.toUInt32_and (a b : UInt16) : (a &&& b).toUInt32 = a.toUInt32 &&& b.toUInt32 := (rfl)
|
||||
@[simp] theorem UInt16.toUInt64_and (a b : UInt16) : (a &&& b).toUInt64 = a.toUInt64 &&& b.toUInt64 := (rfl)
|
||||
@[simp] theorem UInt16.toUSize_and (a b : UInt16) : (a &&& b).toUSize = a.toUSize &&& b.toUSize := (rfl)
|
||||
@[simp] theorem UInt16.toUInt32_and (a b : UInt16) : (a &&& b).toUInt32 = a.toUInt32 &&& b.toUInt32 := rfl
|
||||
@[simp] theorem UInt16.toUInt64_and (a b : UInt16) : (a &&& b).toUInt64 = a.toUInt64 &&& b.toUInt64 := rfl
|
||||
@[simp] theorem UInt16.toUSize_and (a b : UInt16) : (a &&& b).toUSize = a.toUSize &&& b.toUSize := rfl
|
||||
|
||||
@[simp] theorem UInt32.toUInt8_and (a b : UInt32) : (a &&& b).toUInt8 = a.toUInt8 &&& b.toUInt8 := UInt8.toBitVec_inj.1 (by simp)
|
||||
@[simp] theorem UInt32.toUInt16_and (a b : UInt32) : (a &&& b).toUInt16 = a.toUInt16 &&& b.toUInt16 := UInt16.toBitVec_inj.1 (by simp)
|
||||
@[simp] theorem UInt32.toUInt64_and (a b : UInt32) : (a &&& b).toUInt64 = a.toUInt64 &&& b.toUInt64 := (rfl)
|
||||
@[simp] theorem UInt32.toUSize_and (a b : UInt32) : (a &&& b).toUSize = a.toUSize &&& b.toUSize := (rfl)
|
||||
@[simp] theorem UInt32.toUInt64_and (a b : UInt32) : (a &&& b).toUInt64 = a.toUInt64 &&& b.toUInt64 := rfl
|
||||
@[simp] theorem UInt32.toUSize_and (a b : UInt32) : (a &&& b).toUSize = a.toUSize &&& b.toUSize := rfl
|
||||
|
||||
@[simp] theorem USize.toUInt8_and (a b : USize) : (a &&& b).toUInt8 = a.toUInt8 &&& b.toUInt8 := UInt8.toBitVec_inj.1 (by simp)
|
||||
@[simp] theorem USize.toUInt16_and (a b : USize) : (a &&& b).toUInt16 = a.toUInt16 &&& b.toUInt16 := UInt16.toBitVec_inj.1 (by simp)
|
||||
@[simp] theorem USize.toUInt32_and (a b : USize) : (a &&& b).toUInt32 = a.toUInt32 &&& b.toUInt32 := UInt32.toBitVec_inj.1 (by simp)
|
||||
@[simp] theorem USize.toUInt64_and (a b : USize) : (a &&& b).toUInt64 = a.toUInt64 &&& b.toUInt64 := (rfl)
|
||||
@[simp] theorem USize.toUInt64_and (a b : USize) : (a &&& b).toUInt64 = a.toUInt64 &&& b.toUInt64 := rfl
|
||||
|
||||
@[simp] theorem UInt64.toUInt8_and (a b : UInt64) : (a &&& b).toUInt8 = a.toUInt8 &&& b.toUInt8 := UInt8.toBitVec_inj.1 (by simp)
|
||||
@[simp] theorem UInt64.toUInt16_and (a b : UInt64) : (a &&& b).toUInt16 = a.toUInt16 &&& b.toUInt16 := UInt16.toBitVec_inj.1 (by simp)
|
||||
@@ -102,25 +106,25 @@ theorem Bool.toBitVec_toUSize {b : Bool} :
|
||||
@[simp] theorem UInt64.toFin_or (a b : UInt64) : (a ||| b).toFin = a.toFin ||| b.toFin := Fin.val_inj.1 (by simp)
|
||||
@[simp] theorem USize.toFin_or (a b : USize) : (a ||| b).toFin = a.toFin ||| b.toFin := Fin.val_inj.1 (by simp)
|
||||
|
||||
@[simp] theorem UInt8.toUInt16_or (a b : UInt8) : (a ||| b).toUInt16 = a.toUInt16 ||| b.toUInt16 := (rfl)
|
||||
@[simp] theorem UInt8.toUInt32_or (a b : UInt8) : (a ||| b).toUInt32 = a.toUInt32 ||| b.toUInt32 := (rfl)
|
||||
@[simp] theorem UInt8.toUInt64_or (a b : UInt8) : (a ||| b).toUInt64 = a.toUInt64 ||| b.toUInt64 := (rfl)
|
||||
@[simp] theorem UInt8.toUSize_or (a b : UInt8) : (a ||| b).toUSize = a.toUSize ||| b.toUSize := (rfl)
|
||||
@[simp] theorem UInt8.toUInt16_or (a b : UInt8) : (a ||| b).toUInt16 = a.toUInt16 ||| b.toUInt16 := rfl
|
||||
@[simp] theorem UInt8.toUInt32_or (a b : UInt8) : (a ||| b).toUInt32 = a.toUInt32 ||| b.toUInt32 := rfl
|
||||
@[simp] theorem UInt8.toUInt64_or (a b : UInt8) : (a ||| b).toUInt64 = a.toUInt64 ||| b.toUInt64 := rfl
|
||||
@[simp] theorem UInt8.toUSize_or (a b : UInt8) : (a ||| b).toUSize = a.toUSize ||| b.toUSize := rfl
|
||||
|
||||
@[simp] theorem UInt16.toUInt8_or (a b : UInt16) : (a ||| b).toUInt8 = a.toUInt8 ||| b.toUInt8 := UInt8.toBitVec_inj.1 (by simp)
|
||||
@[simp] theorem UInt16.toUInt32_or (a b : UInt16) : (a ||| b).toUInt32 = a.toUInt32 ||| b.toUInt32 := (rfl)
|
||||
@[simp] theorem UInt16.toUInt64_or (a b : UInt16) : (a ||| b).toUInt64 = a.toUInt64 ||| b.toUInt64 := (rfl)
|
||||
@[simp] theorem UInt16.toUSize_or (a b : UInt16) : (a ||| b).toUSize = a.toUSize ||| b.toUSize := (rfl)
|
||||
@[simp] theorem UInt16.toUInt32_or (a b : UInt16) : (a ||| b).toUInt32 = a.toUInt32 ||| b.toUInt32 := rfl
|
||||
@[simp] theorem UInt16.toUInt64_or (a b : UInt16) : (a ||| b).toUInt64 = a.toUInt64 ||| b.toUInt64 := rfl
|
||||
@[simp] theorem UInt16.toUSize_or (a b : UInt16) : (a ||| b).toUSize = a.toUSize ||| b.toUSize := rfl
|
||||
|
||||
@[simp] theorem UInt32.toUInt8_or (a b : UInt32) : (a ||| b).toUInt8 = a.toUInt8 ||| b.toUInt8 := UInt8.toBitVec_inj.1 (by simp)
|
||||
@[simp] theorem UInt32.toUInt16_or (a b : UInt32) : (a ||| b).toUInt16 = a.toUInt16 ||| b.toUInt16 := UInt16.toBitVec_inj.1 (by simp)
|
||||
@[simp] theorem UInt32.toUInt64_or (a b : UInt32) : (a ||| b).toUInt64 = a.toUInt64 ||| b.toUInt64 := (rfl)
|
||||
@[simp] theorem UInt32.toUSize_or (a b : UInt32) : (a ||| b).toUSize = a.toUSize ||| b.toUSize := (rfl)
|
||||
@[simp] theorem UInt32.toUInt64_or (a b : UInt32) : (a ||| b).toUInt64 = a.toUInt64 ||| b.toUInt64 := rfl
|
||||
@[simp] theorem UInt32.toUSize_or (a b : UInt32) : (a ||| b).toUSize = a.toUSize ||| b.toUSize := rfl
|
||||
|
||||
@[simp] theorem USize.toUInt8_or (a b : USize) : (a ||| b).toUInt8 = a.toUInt8 ||| b.toUInt8 := UInt8.toBitVec_inj.1 (by simp)
|
||||
@[simp] theorem USize.toUInt16_or (a b : USize) : (a ||| b).toUInt16 = a.toUInt16 ||| b.toUInt16 := UInt16.toBitVec_inj.1 (by simp)
|
||||
@[simp] theorem USize.toUInt32_or (a b : USize) : (a ||| b).toUInt32 = a.toUInt32 ||| b.toUInt32 := UInt32.toBitVec_inj.1 (by simp)
|
||||
@[simp] theorem USize.toUInt64_or (a b : USize) : (a ||| b).toUInt64 = a.toUInt64 ||| b.toUInt64 := (rfl)
|
||||
@[simp] theorem USize.toUInt64_or (a b : USize) : (a ||| b).toUInt64 = a.toUInt64 ||| b.toUInt64 := rfl
|
||||
|
||||
@[simp] theorem UInt64.toUInt8_or (a b : UInt64) : (a ||| b).toUInt8 = a.toUInt8 ||| b.toUInt8 := UInt8.toBitVec_inj.1 (by simp)
|
||||
@[simp] theorem UInt64.toUInt16_or (a b : UInt64) : (a ||| b).toUInt16 = a.toUInt16 ||| b.toUInt16 := UInt16.toBitVec_inj.1 (by simp)
|
||||
@@ -133,25 +137,25 @@ theorem Bool.toBitVec_toUSize {b : Bool} :
|
||||
@[simp] theorem UInt64.toFin_xor (a b : UInt64) : (a ^^^ b).toFin = a.toFin ^^^ b.toFin := Fin.val_inj.1 (by simp)
|
||||
@[simp] theorem USize.toFin_xor (a b : USize) : (a ^^^ b).toFin = a.toFin ^^^ b.toFin := Fin.val_inj.1 (by simp)
|
||||
|
||||
@[simp] theorem UInt8.toUInt16_xor (a b : UInt8) : (a ^^^ b).toUInt16 = a.toUInt16 ^^^ b.toUInt16 := (rfl)
|
||||
@[simp] theorem UInt8.toUInt32_xor (a b : UInt8) : (a ^^^ b).toUInt32 = a.toUInt32 ^^^ b.toUInt32 := (rfl)
|
||||
@[simp] theorem UInt8.toUInt64_xor (a b : UInt8) : (a ^^^ b).toUInt64 = a.toUInt64 ^^^ b.toUInt64 := (rfl)
|
||||
@[simp] theorem UInt8.toUSize_xor (a b : UInt8) : (a ^^^ b).toUSize = a.toUSize ^^^ b.toUSize := (rfl)
|
||||
@[simp] theorem UInt8.toUInt16_xor (a b : UInt8) : (a ^^^ b).toUInt16 = a.toUInt16 ^^^ b.toUInt16 := rfl
|
||||
@[simp] theorem UInt8.toUInt32_xor (a b : UInt8) : (a ^^^ b).toUInt32 = a.toUInt32 ^^^ b.toUInt32 := rfl
|
||||
@[simp] theorem UInt8.toUInt64_xor (a b : UInt8) : (a ^^^ b).toUInt64 = a.toUInt64 ^^^ b.toUInt64 := rfl
|
||||
@[simp] theorem UInt8.toUSize_xor (a b : UInt8) : (a ^^^ b).toUSize = a.toUSize ^^^ b.toUSize := rfl
|
||||
|
||||
@[simp] theorem UInt16.toUInt8_xor (a b : UInt16) : (a ^^^ b).toUInt8 = a.toUInt8 ^^^ b.toUInt8 := UInt8.toBitVec_inj.1 (by simp)
|
||||
@[simp] theorem UInt16.toUInt32_xor (a b : UInt16) : (a ^^^ b).toUInt32 = a.toUInt32 ^^^ b.toUInt32 := (rfl)
|
||||
@[simp] theorem UInt16.toUInt64_xor (a b : UInt16) : (a ^^^ b).toUInt64 = a.toUInt64 ^^^ b.toUInt64 := (rfl)
|
||||
@[simp] theorem UInt16.toUSize_xor (a b : UInt16) : (a ^^^ b).toUSize = a.toUSize ^^^ b.toUSize := (rfl)
|
||||
@[simp] theorem UInt16.toUInt32_xor (a b : UInt16) : (a ^^^ b).toUInt32 = a.toUInt32 ^^^ b.toUInt32 := rfl
|
||||
@[simp] theorem UInt16.toUInt64_xor (a b : UInt16) : (a ^^^ b).toUInt64 = a.toUInt64 ^^^ b.toUInt64 := rfl
|
||||
@[simp] theorem UInt16.toUSize_xor (a b : UInt16) : (a ^^^ b).toUSize = a.toUSize ^^^ b.toUSize := rfl
|
||||
|
||||
@[simp] theorem UInt32.toUInt8_xor (a b : UInt32) : (a ^^^ b).toUInt8 = a.toUInt8 ^^^ b.toUInt8 := UInt8.toBitVec_inj.1 (by simp)
|
||||
@[simp] theorem UInt32.toUInt16_xor (a b : UInt32) : (a ^^^ b).toUInt16 = a.toUInt16 ^^^ b.toUInt16 := UInt16.toBitVec_inj.1 (by simp)
|
||||
@[simp] theorem UInt32.toUInt64_xor (a b : UInt32) : (a ^^^ b).toUInt64 = a.toUInt64 ^^^ b.toUInt64 := (rfl)
|
||||
@[simp] theorem UInt32.toUSize_xor (a b : UInt32) : (a ^^^ b).toUSize = a.toUSize ^^^ b.toUSize := (rfl)
|
||||
@[simp] theorem UInt32.toUInt64_xor (a b : UInt32) : (a ^^^ b).toUInt64 = a.toUInt64 ^^^ b.toUInt64 := rfl
|
||||
@[simp] theorem UInt32.toUSize_xor (a b : UInt32) : (a ^^^ b).toUSize = a.toUSize ^^^ b.toUSize := rfl
|
||||
|
||||
@[simp] theorem USize.toUInt8_xor (a b : USize) : (a ^^^ b).toUInt8 = a.toUInt8 ^^^ b.toUInt8 := UInt8.toBitVec_inj.1 (by simp)
|
||||
@[simp] theorem USize.toUInt16_xor (a b : USize) : (a ^^^ b).toUInt16 = a.toUInt16 ^^^ b.toUInt16 := UInt16.toBitVec_inj.1 (by simp)
|
||||
@[simp] theorem USize.toUInt32_xor (a b : USize) : (a ^^^ b).toUInt32 = a.toUInt32 ^^^ b.toUInt32 := UInt32.toBitVec_inj.1 (by simp)
|
||||
@[simp] theorem USize.toUInt64_xor (a b : USize) : (a ^^^ b).toUInt64 = a.toUInt64 ^^^ b.toUInt64 := (rfl)
|
||||
@[simp] theorem USize.toUInt64_xor (a b : USize) : (a ^^^ b).toUInt64 = a.toUInt64 ^^^ b.toUInt64 := rfl
|
||||
|
||||
@[simp] theorem UInt64.toUInt8_xor (a b : UInt64) : (a ^^^ b).toUInt8 = a.toUInt8 ^^^ b.toUInt8 := UInt8.toBitVec_inj.1 (by simp)
|
||||
@[simp] theorem UInt64.toUInt16_xor (a b : UInt64) : (a ^^^ b).toUInt16 = a.toUInt16 ^^^ b.toUInt16 := UInt16.toBitVec_inj.1 (by simp)
|
||||
@@ -429,11 +433,11 @@ expression `(a >>> b).toUInt8` is not a function of `a.toUInt8` and `b.toUInt8`.
|
||||
@[simp] theorem UInt64.ofFin_and (a b : Fin UInt64.size) : UInt64.ofFin (a &&& b) = UInt64.ofFin a &&& UInt64.ofFin b := UInt64.toFin_inj.1 (by simp)
|
||||
@[simp] theorem USize.ofFin_and (a b : Fin USize.size) : USize.ofFin (a &&& b) = USize.ofFin a &&& USize.ofFin b := USize.toFin_inj.1 (by simp)
|
||||
|
||||
@[simp] theorem UInt8.ofBitVec_and (a b : BitVec 8) : UInt8.ofBitVec (a &&& b) = UInt8.ofBitVec a &&& UInt8.ofBitVec b := (rfl)
|
||||
@[simp] theorem UInt16.ofBitVec_and (a b : BitVec 16) : UInt16.ofBitVec (a &&& b) = UInt16.ofBitVec a &&& UInt16.ofBitVec b := (rfl)
|
||||
@[simp] theorem UInt32.ofBitVec_and (a b : BitVec 32) : UInt32.ofBitVec (a &&& b) = UInt32.ofBitVec a &&& UInt32.ofBitVec b := (rfl)
|
||||
@[simp] theorem UInt64.ofBitVec_and (a b : BitVec 64) : UInt64.ofBitVec (a &&& b) = UInt64.ofBitVec a &&& UInt64.ofBitVec b := (rfl)
|
||||
@[simp] theorem USize.ofBitVec_and (a b : BitVec System.Platform.numBits) : USize.ofBitVec (a &&& b) = USize.ofBitVec a &&& USize.ofBitVec b := (rfl)
|
||||
@[simp] theorem UInt8.ofBitVec_and (a b : BitVec 8) : UInt8.ofBitVec (a &&& b) = UInt8.ofBitVec a &&& UInt8.ofBitVec b := rfl
|
||||
@[simp] theorem UInt16.ofBitVec_and (a b : BitVec 16) : UInt16.ofBitVec (a &&& b) = UInt16.ofBitVec a &&& UInt16.ofBitVec b := rfl
|
||||
@[simp] theorem UInt32.ofBitVec_and (a b : BitVec 32) : UInt32.ofBitVec (a &&& b) = UInt32.ofBitVec a &&& UInt32.ofBitVec b := rfl
|
||||
@[simp] theorem UInt64.ofBitVec_and (a b : BitVec 64) : UInt64.ofBitVec (a &&& b) = UInt64.ofBitVec a &&& UInt64.ofBitVec b := rfl
|
||||
@[simp] theorem USize.ofBitVec_and (a b : BitVec System.Platform.numBits) : USize.ofBitVec (a &&& b) = USize.ofBitVec a &&& USize.ofBitVec b := rfl
|
||||
|
||||
@[simp] theorem UInt8.ofNat_and (a b : Nat) : UInt8.ofNat (a &&& b) = UInt8.ofNat a &&& UInt8.ofNat b :=
|
||||
UInt8.toBitVec_inj.1 (by simp [UInt8.toBitVec_ofNat'])
|
||||
@@ -465,11 +469,11 @@ expression `(a >>> b).toUInt8` is not a function of `a.toUInt8` and `b.toUInt8`.
|
||||
@[simp] theorem UInt64.ofFin_or (a b : Fin UInt64.size) : UInt64.ofFin (a ||| b) = UInt64.ofFin a ||| UInt64.ofFin b := UInt64.toFin_inj.1 (by simp)
|
||||
@[simp] theorem USize.ofFin_or (a b : Fin USize.size) : USize.ofFin (a ||| b) = USize.ofFin a ||| USize.ofFin b := USize.toFin_inj.1 (by simp)
|
||||
|
||||
@[simp] theorem UInt8.ofBitVec_or (a b : BitVec 8) : UInt8.ofBitVec (a ||| b) = UInt8.ofBitVec a ||| UInt8.ofBitVec b := (rfl)
|
||||
@[simp] theorem UInt16.ofBitVec_or (a b : BitVec 16) : UInt16.ofBitVec (a ||| b) = UInt16.ofBitVec a ||| UInt16.ofBitVec b := (rfl)
|
||||
@[simp] theorem UInt32.ofBitVec_or (a b : BitVec 32) : UInt32.ofBitVec (a ||| b) = UInt32.ofBitVec a ||| UInt32.ofBitVec b := (rfl)
|
||||
@[simp] theorem UInt64.ofBitVec_or (a b : BitVec 64) : UInt64.ofBitVec (a ||| b) = UInt64.ofBitVec a ||| UInt64.ofBitVec b := (rfl)
|
||||
@[simp] theorem USize.ofBitVec_or (a b : BitVec System.Platform.numBits) : USize.ofBitVec (a ||| b) = USize.ofBitVec a ||| USize.ofBitVec b := (rfl)
|
||||
@[simp] theorem UInt8.ofBitVec_or (a b : BitVec 8) : UInt8.ofBitVec (a ||| b) = UInt8.ofBitVec a ||| UInt8.ofBitVec b := rfl
|
||||
@[simp] theorem UInt16.ofBitVec_or (a b : BitVec 16) : UInt16.ofBitVec (a ||| b) = UInt16.ofBitVec a ||| UInt16.ofBitVec b := rfl
|
||||
@[simp] theorem UInt32.ofBitVec_or (a b : BitVec 32) : UInt32.ofBitVec (a ||| b) = UInt32.ofBitVec a ||| UInt32.ofBitVec b := rfl
|
||||
@[simp] theorem UInt64.ofBitVec_or (a b : BitVec 64) : UInt64.ofBitVec (a ||| b) = UInt64.ofBitVec a ||| UInt64.ofBitVec b := rfl
|
||||
@[simp] theorem USize.ofBitVec_or (a b : BitVec System.Platform.numBits) : USize.ofBitVec (a ||| b) = USize.ofBitVec a ||| USize.ofBitVec b := rfl
|
||||
|
||||
@[simp] theorem UInt8.ofNat_or (a b : Nat) : UInt8.ofNat (a ||| b) = UInt8.ofNat a ||| UInt8.ofNat b :=
|
||||
UInt8.toBitVec_inj.1 (by simp [UInt8.toBitVec_ofNat'])
|
||||
@@ -501,11 +505,11 @@ expression `(a >>> b).toUInt8` is not a function of `a.toUInt8` and `b.toUInt8`.
|
||||
@[simp] theorem UInt64.ofFin_xor (a b : Fin UInt64.size) : UInt64.ofFin (a ^^^ b) = UInt64.ofFin a ^^^ UInt64.ofFin b := UInt64.toFin_inj.1 (by simp)
|
||||
@[simp] theorem USize.ofFin_xor (a b : Fin USize.size) : USize.ofFin (a ^^^ b) = USize.ofFin a ^^^ USize.ofFin b := USize.toFin_inj.1 (by simp)
|
||||
|
||||
@[simp] theorem UInt8.ofBitVec_xor (a b : BitVec 8) : UInt8.ofBitVec (a ^^^ b) = UInt8.ofBitVec a ^^^ UInt8.ofBitVec b := (rfl)
|
||||
@[simp] theorem UInt16.ofBitVec_xor (a b : BitVec 16) : UInt16.ofBitVec (a ^^^ b) = UInt16.ofBitVec a ^^^ UInt16.ofBitVec b := (rfl)
|
||||
@[simp] theorem UInt32.ofBitVec_xor (a b : BitVec 32) : UInt32.ofBitVec (a ^^^ b) = UInt32.ofBitVec a ^^^ UInt32.ofBitVec b := (rfl)
|
||||
@[simp] theorem UInt64.ofBitVec_xor (a b : BitVec 64) : UInt64.ofBitVec (a ^^^ b) = UInt64.ofBitVec a ^^^ UInt64.ofBitVec b := (rfl)
|
||||
@[simp] theorem USize.ofBitVec_xor (a b : BitVec System.Platform.numBits) : USize.ofBitVec (a ^^^ b) = USize.ofBitVec a ^^^ USize.ofBitVec b := (rfl)
|
||||
@[simp] theorem UInt8.ofBitVec_xor (a b : BitVec 8) : UInt8.ofBitVec (a ^^^ b) = UInt8.ofBitVec a ^^^ UInt8.ofBitVec b := rfl
|
||||
@[simp] theorem UInt16.ofBitVec_xor (a b : BitVec 16) : UInt16.ofBitVec (a ^^^ b) = UInt16.ofBitVec a ^^^ UInt16.ofBitVec b := rfl
|
||||
@[simp] theorem UInt32.ofBitVec_xor (a b : BitVec 32) : UInt32.ofBitVec (a ^^^ b) = UInt32.ofBitVec a ^^^ UInt32.ofBitVec b := rfl
|
||||
@[simp] theorem UInt64.ofBitVec_xor (a b : BitVec 64) : UInt64.ofBitVec (a ^^^ b) = UInt64.ofBitVec a ^^^ UInt64.ofBitVec b := rfl
|
||||
@[simp] theorem USize.ofBitVec_xor (a b : BitVec System.Platform.numBits) : USize.ofBitVec (a ^^^ b) = USize.ofBitVec a ^^^ USize.ofBitVec b := rfl
|
||||
|
||||
@[simp] theorem UInt8.ofNat_xor (a b : Nat) : UInt8.ofNat (a ^^^ b) = UInt8.ofNat a ^^^ UInt8.ofNat b :=
|
||||
UInt8.toBitVec_inj.1 (by simp [UInt8.toBitVec_ofNat'])
|
||||
@@ -531,11 +535,11 @@ expression `(a >>> b).toUInt8` is not a function of `a.toUInt8` and `b.toUInt8`.
|
||||
UInt64.ofNatLT (a ^^^ b) (Nat.xor_lt_two_pow ha hb) = UInt64.ofNatLT a ha ^^^ UInt64.ofNatLT b hb := by
|
||||
simp [UInt64.ofNatLT_eq_ofNat]
|
||||
|
||||
@[simp] theorem UInt8.ofBitVec_not (a : BitVec 8) : UInt8.ofBitVec (~~~a) = ~~~UInt8.ofBitVec a := (rfl)
|
||||
@[simp] theorem UInt16.ofBitVec_not (a : BitVec 16) : UInt16.ofBitVec (~~~a) = ~~~UInt16.ofBitVec a := (rfl)
|
||||
@[simp] theorem UInt32.ofBitVec_not (a : BitVec 32) : UInt32.ofBitVec (~~~a) = ~~~UInt32.ofBitVec a := (rfl)
|
||||
@[simp] theorem UInt64.ofBitVec_not (a : BitVec 64) : UInt64.ofBitVec (~~~a) = ~~~UInt64.ofBitVec a := (rfl)
|
||||
@[simp] theorem USize.ofBitVec_not (a : BitVec System.Platform.numBits) : USize.ofBitVec (~~~a) = ~~~USize.ofBitVec a := (rfl)
|
||||
@[simp] theorem UInt8.ofBitVec_not (a : BitVec 8) : UInt8.ofBitVec (~~~a) = ~~~UInt8.ofBitVec a := rfl
|
||||
@[simp] theorem UInt16.ofBitVec_not (a : BitVec 16) : UInt16.ofBitVec (~~~a) = ~~~UInt16.ofBitVec a := rfl
|
||||
@[simp] theorem UInt32.ofBitVec_not (a : BitVec 32) : UInt32.ofBitVec (~~~a) = ~~~UInt32.ofBitVec a := rfl
|
||||
@[simp] theorem UInt64.ofBitVec_not (a : BitVec 64) : UInt64.ofBitVec (~~~a) = ~~~UInt64.ofBitVec a := rfl
|
||||
@[simp] theorem USize.ofBitVec_not (a : BitVec System.Platform.numBits) : USize.ofBitVec (~~~a) = ~~~USize.ofBitVec a := rfl
|
||||
|
||||
@[simp] theorem UInt8.ofFin_rev (a : Fin UInt8.size) : UInt8.ofFin a.rev = ~~~UInt8.ofFin a := UInt8.toFin_inj.1 (by simp)
|
||||
@[simp] theorem UInt16.ofFin_rev (a : Fin UInt16.size) : UInt16.ofFin a.rev = ~~~UInt16.ofFin a := UInt16.toFin_inj.1 (by simp)
|
||||
@@ -596,7 +600,7 @@ expression `(a >>> b).toUInt8` is not a function of `a.toUInt8` and `b.toUInt8`.
|
||||
USize.ofFin (a <<< (b % ⟨System.Platform.numBits, by cases System.Platform.numBits_eq <;> simp_all [USize.size]⟩)) = USize.ofFin a <<< USize.ofFin b := by
|
||||
apply USize.toFin_inj.1
|
||||
rw [toFin_ofFin, USize.shiftLeft_eq_shiftLeft_mod, USize.toFin_shiftLeft, toFin_ofFin, USize.toFin_mod,
|
||||
toFin_ofFin, toFin.ofNat, ← Fin.ofNat_val_eq_self ⟨System.Platform.numBits, _⟩]
|
||||
toFin_ofFin, toFin_ofNat', ← Fin.ofNat'_val_eq_self ⟨System.Platform.numBits, _⟩]
|
||||
rw [USize.toNat_mod, toNat_ofNat']
|
||||
cases System.Platform.numBits_eq <;> simpa [*] using Nat.mod_lt _ (by decide)
|
||||
|
||||
@@ -691,7 +695,7 @@ expression `(a >>> b).toUInt8` is not a function of `a.toUInt8` and `b.toUInt8`.
|
||||
USize.ofFin (a >>> (b % ⟨System.Platform.numBits, by cases System.Platform.numBits_eq <;> simp_all [USize.size]⟩)) = USize.ofFin a >>> USize.ofFin b := by
|
||||
apply USize.toFin_inj.1
|
||||
rw [toFin_ofFin, USize.shiftRight_eq_shiftRight_mod, USize.toFin_shiftRight, toFin_ofFin, USize.toFin_mod,
|
||||
toFin_ofFin, toFin.ofNat, ← Fin.ofNat_val_eq_self ⟨System.Platform.numBits, _⟩]
|
||||
toFin_ofFin, toFin_ofNat', ← Fin.ofNat'_val_eq_self ⟨System.Platform.numBits, _⟩]
|
||||
rw [USize.toNat_mod, toNat_ofNat']
|
||||
cases System.Platform.numBits_eq <;> simpa [*] using Nat.mod_lt _ (by decide)
|
||||
|
||||
@@ -999,16 +1003,16 @@ instance : Std.LawfulCommIdentity (α := USize) (· ^^^ ·) 0 where
|
||||
@[simp] theorem USize.xor_right_inj {a b : USize} (c : USize) : (c ^^^ a = c ^^^ b) ↔ a = b := by
|
||||
simp [← USize.toBitVec_inj]
|
||||
|
||||
@[simp] theorem UInt8.not_zero : ~~~(0 : UInt8) = -1 := (rfl)
|
||||
@[simp] theorem UInt16.not_zero : ~~~(0 : UInt16) = -1 := (rfl)
|
||||
@[simp] theorem UInt32.not_zero : ~~~(0 : UInt32) = -1 := (rfl)
|
||||
@[simp] theorem UInt64.not_zero : ~~~(0 : UInt64) = -1 := (rfl)
|
||||
@[simp] theorem UInt8.not_zero : ~~~(0 : UInt8) = -1 := rfl
|
||||
@[simp] theorem UInt16.not_zero : ~~~(0 : UInt16) = -1 := rfl
|
||||
@[simp] theorem UInt32.not_zero : ~~~(0 : UInt32) = -1 := rfl
|
||||
@[simp] theorem UInt64.not_zero : ~~~(0 : UInt64) = -1 := rfl
|
||||
@[simp] theorem USize.not_zero : ~~~(0 : USize) = -1 := by simp [USize.not_eq_neg_sub]
|
||||
|
||||
@[simp] theorem UInt8.not_neg_one : ~~~(-1 : UInt8) = 0 := (rfl)
|
||||
@[simp] theorem UInt16.not_neg_one : ~~~(-1 : UInt16) = 0 := (rfl)
|
||||
@[simp] theorem UInt32.not_neg_one : ~~~(-1 : UInt32) = 0 := (rfl)
|
||||
@[simp] theorem UInt64.not_neg_one : ~~~(-1 : UInt64) = 0 := (rfl)
|
||||
@[simp] theorem UInt8.not_neg_one : ~~~(-1 : UInt8) = 0 := rfl
|
||||
@[simp] theorem UInt16.not_neg_one : ~~~(-1 : UInt16) = 0 := rfl
|
||||
@[simp] theorem UInt32.not_neg_one : ~~~(-1 : UInt32) = 0 := rfl
|
||||
@[simp] theorem UInt64.not_neg_one : ~~~(-1 : UInt64) = 0 := rfl
|
||||
@[simp] theorem USize.not_neg_one : ~~~(-1 : USize) = 0 := by simp [USize.not_eq_neg_sub]
|
||||
|
||||
@[simp] theorem UInt8.not_not {a : UInt8} : ~~~(~~~a) = a := by simp [← UInt8.toBitVec_inj]
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -22,7 +22,6 @@ to apply `f`.
|
||||
|
||||
We replace this at runtime with a more efficient version via the `csimp` lemma `pmap_eq_pmapImpl`.
|
||||
-/
|
||||
@[expose]
|
||||
def pmap {P : α → Prop} (f : ∀ a, P a → β) (xs : Vector α n) (H : ∀ a ∈ xs, P a) : Vector β n :=
|
||||
Vector.mk (xs.toArray.pmap f (fun a m => H a (by simpa using m))) (by simp)
|
||||
|
||||
@@ -35,13 +34,13 @@ Unsafe implementation of `attachWith`, taking advantage of the fact that the rep
|
||||
|
||||
/-- `O(1)`. "Attach" a proof `P x` that holds for all the elements of `xs` to produce a new array
|
||||
with the same elements but in the type `{x // P x}`. -/
|
||||
@[implemented_by attachWithImpl, expose] def attachWith
|
||||
@[implemented_by attachWithImpl] def attachWith
|
||||
(xs : Vector α n) (P : α → Prop) (H : ∀ x ∈ xs, P x) : Vector {x // P x} n :=
|
||||
Vector.mk (xs.toArray.attachWith P fun x h => H x (by simpa using h)) (by simp)
|
||||
|
||||
/-- `O(1)`. "Attach" the proof that the elements of `xs` are in `xs` to produce a new vector
|
||||
with the same elements but in the type `{x // x ∈ xs}`. -/
|
||||
@[inline, expose] def attach (xs : Vector α n) : Vector {x // x ∈ xs} n := xs.attachWith _ fun _ => id
|
||||
@[inline] def attach (xs : Vector α n) : Vector {x // x ∈ xs} n := xs.attachWith _ fun _ => id
|
||||
|
||||
@[simp] theorem attachWith_mk {xs : Array α} {h : xs.size = n} {P : α → Prop} {H : ∀ x ∈ mk xs h, P x} :
|
||||
(mk xs h).attachWith P H = mk (xs.attachWith P (by simpa using H)) (by simpa using h) := by
|
||||
@@ -475,10 +474,7 @@ If not, usually the right approach is `simp [Vector.unattach, -Vector.map_subtyp
|
||||
-/
|
||||
def unattach {α : Type _} {p : α → Prop} (xs : Vector { x // p x } n) : Vector α n := xs.map (·.val)
|
||||
|
||||
theorem unattach_empty {p : α → Prop} : (#v[] : Vector { x // p x } 0).unattach = #v[] := by simp
|
||||
|
||||
@[deprecated unattach_empty (since := "2025-05-26")]
|
||||
abbrev unattach_nil := @unattach_empty
|
||||
@[simp] theorem unattach_nil {p : α → Prop} : (#v[] : Vector { x // p x } 0).unattach = #v[] := by simp
|
||||
|
||||
@[simp] theorem unattach_push {p : α → Prop} {a : { x // p x }} {xs : Vector { x // p x } n} :
|
||||
(xs.push a).unattach = xs.unattach.push a.1 := by
|
||||
|
||||
@@ -54,7 +54,6 @@ recommended_spelling "empty" for "#v[]" in [Vector.mk, «term#v[_,]»]
|
||||
recommended_spelling "singleton" for "#v[x]" in [Vector.mk, «term#v[_,]»]
|
||||
|
||||
/-- Convert a vector to a list. -/
|
||||
@[expose]
|
||||
def toList (xs : Vector α n) : List α := xs.toArray.toList
|
||||
|
||||
/-- Custom eliminator for `Vector α n` through `Array α` -/
|
||||
@@ -72,13 +71,13 @@ def elimAsList {motive : Vector α n → Sort u}
|
||||
| ⟨⟨xs⟩, ha⟩ => mk xs ha
|
||||
|
||||
/-- Make an empty vector with pre-allocated capacity. -/
|
||||
@[inline, expose] def emptyWithCapacity (capacity : Nat) : Vector α 0 := ⟨.emptyWithCapacity capacity, by simp⟩
|
||||
@[inline] def emptyWithCapacity (capacity : Nat) : Vector α 0 := ⟨.emptyWithCapacity capacity, by simp⟩
|
||||
|
||||
@[deprecated emptyWithCapacity (since := "2025-03-12"), inherit_doc emptyWithCapacity]
|
||||
abbrev mkEmpty := @emptyWithCapacity
|
||||
|
||||
/-- Makes a vector of size `n` with all cells containing `v`. -/
|
||||
@[inline, expose] def replicate (n) (v : α) : Vector α n := ⟨Array.replicate n v, by simp⟩
|
||||
@[inline] def replicate (n) (v : α) : Vector α n := ⟨Array.replicate n v, by simp⟩
|
||||
|
||||
@[deprecated replicate (since := "2025-03-18")]
|
||||
abbrev mkVector := @replicate
|
||||
@@ -87,24 +86,23 @@ instance : Nonempty (Vector α 0) := ⟨#v[]⟩
|
||||
instance [Nonempty α] : Nonempty (Vector α n) := ⟨replicate _ Classical.ofNonempty⟩
|
||||
|
||||
/-- Returns a vector of size `1` with element `v`. -/
|
||||
@[inline, expose] def singleton (v : α) : Vector α 1 := ⟨#[v], rfl⟩
|
||||
@[inline] def singleton (v : α) : Vector α 1 := ⟨#[v], rfl⟩
|
||||
|
||||
instance [Inhabited α] : Inhabited (Vector α n) where
|
||||
default := replicate n default
|
||||
|
||||
/-- Get an element of a vector using a `Fin` index. -/
|
||||
@[inline, expose] def get (xs : Vector α n) (i : Fin n) : α :=
|
||||
@[inline] def get (xs : Vector α n) (i : Fin n) : α :=
|
||||
xs.toArray[(i.cast xs.size_toArray.symm).1]
|
||||
|
||||
/-- Get an element of a vector using a `USize` index and a proof that the index is within bounds. -/
|
||||
@[inline, expose] def uget (xs : Vector α n) (i : USize) (h : i.toNat < n) : α :=
|
||||
@[inline] def uget (xs : Vector α n) (i : USize) (h : i.toNat < n) : α :=
|
||||
xs.toArray.uget i (xs.size_toArray.symm ▸ h)
|
||||
|
||||
instance : GetElem (Vector α n) Nat α fun _ i => i < n where
|
||||
getElem xs i h := get xs ⟨i, h⟩
|
||||
|
||||
/-- Check if there is an element which satisfies `a == ·`. -/
|
||||
@[expose]
|
||||
def contains [BEq α] (xs : Vector α n) (a : α) : Bool := xs.toArray.contains a
|
||||
|
||||
/-- `a ∈ v` is a predicate which asserts that `a` is in the vector `v`. -/
|
||||
@@ -118,27 +116,27 @@ instance : Membership α (Vector α n) where
|
||||
Get an element of a vector using a `Nat` index. Returns the given default value if the index is out
|
||||
of bounds.
|
||||
-/
|
||||
@[inline, expose] def getD (xs : Vector α n) (i : Nat) (default : α) : α := xs.toArray.getD i default
|
||||
@[inline] def getD (xs : Vector α n) (i : Nat) (default : α) : α := xs.toArray.getD i default
|
||||
|
||||
/-- The last element of a vector. Panics if the vector is empty. -/
|
||||
@[inline, expose] def back! [Inhabited α] (xs : Vector α n) : α := xs.toArray.back!
|
||||
@[inline] def back! [Inhabited α] (xs : Vector α n) : α := xs.toArray.back!
|
||||
|
||||
/-- The last element of a vector, or `none` if the vector is empty. -/
|
||||
@[inline, expose] def back? (xs : Vector α n) : Option α := xs.toArray.back?
|
||||
@[inline] def back? (xs : Vector α n) : Option α := xs.toArray.back?
|
||||
|
||||
/-- The last element of a non-empty vector. -/
|
||||
@[inline, expose] def back [NeZero n] (xs : Vector α n) : α :=
|
||||
@[inline] def back [NeZero n] (xs : Vector α n) : α :=
|
||||
xs[n - 1]'(Nat.sub_one_lt (NeZero.ne n))
|
||||
|
||||
/-- The first element of a non-empty vector. -/
|
||||
@[inline, expose] def head [NeZero n] (xs : Vector α n) := xs[0]'(Nat.pos_of_neZero n)
|
||||
@[inline] def head [NeZero n] (xs : Vector α n) := xs[0]'(Nat.pos_of_neZero n)
|
||||
|
||||
/-- Push an element `x` to the end of a vector. -/
|
||||
@[inline, expose] def push (xs : Vector α n) (x : α) : Vector α (n + 1) :=
|
||||
@[inline] def push (xs : Vector α n) (x : α) : Vector α (n + 1) :=
|
||||
⟨xs.toArray.push x, by simp⟩
|
||||
|
||||
/-- Remove the last element of a vector. -/
|
||||
@[inline, expose] def pop (xs : Vector α n) : Vector α (n - 1) :=
|
||||
@[inline] def pop (xs : Vector α n) : Vector α (n - 1) :=
|
||||
⟨Array.pop xs.toArray, by simp⟩
|
||||
|
||||
/--
|
||||
@@ -147,7 +145,7 @@ bounds.
|
||||
|
||||
This will perform the update destructively provided that the vector has a reference count of 1.
|
||||
-/
|
||||
@[inline, expose] def set (xs : Vector α n) (i : Nat) (x : α) (h : i < n := by get_elem_tactic): Vector α n :=
|
||||
@[inline] def set (xs : Vector α n) (i : Nat) (x : α) (h : i < n := by get_elem_tactic): Vector α n :=
|
||||
⟨xs.toArray.set i x (by simp [*]), by simp⟩
|
||||
|
||||
/--
|
||||
@@ -156,7 +154,7 @@ bounds.
|
||||
|
||||
This will perform the update destructively provided that the vector has a reference count of 1.
|
||||
-/
|
||||
@[inline, expose] def setIfInBounds (xs : Vector α n) (i : Nat) (x : α) : Vector α n :=
|
||||
@[inline] def setIfInBounds (xs : Vector α n) (i : Nat) (x : α) : Vector α n :=
|
||||
⟨xs.toArray.setIfInBounds i x, by simp⟩
|
||||
|
||||
/--
|
||||
@@ -164,37 +162,37 @@ Set an element in a vector using a `Nat` index. Panics if the index is out of bo
|
||||
|
||||
This will perform the update destructively provided that the vector has a reference count of 1.
|
||||
-/
|
||||
@[inline, expose] def set! (xs : Vector α n) (i : Nat) (x : α) : Vector α n :=
|
||||
@[inline] def set! (xs : Vector α n) (i : Nat) (x : α) : Vector α n :=
|
||||
⟨xs.toArray.set! i x, by simp⟩
|
||||
|
||||
@[inline, expose] def foldlM [Monad m] (f : β → α → m β) (b : β) (xs : Vector α n) : m β :=
|
||||
@[inline] def foldlM [Monad m] (f : β → α → m β) (b : β) (xs : Vector α n) : m β :=
|
||||
xs.toArray.foldlM f b
|
||||
|
||||
@[inline, expose] def foldrM [Monad m] (f : α → β → m β) (b : β) (xs : Vector α n) : m β :=
|
||||
@[inline] def foldrM [Monad m] (f : α → β → m β) (b : β) (xs : Vector α n) : m β :=
|
||||
xs.toArray.foldrM f b
|
||||
|
||||
@[inline, expose] def foldl (f : β → α → β) (b : β) (xs : Vector α n) : β :=
|
||||
@[inline] def foldl (f : β → α → β) (b : β) (xs : Vector α n) : β :=
|
||||
xs.toArray.foldl f b
|
||||
|
||||
@[inline, expose] def foldr (f : α → β → β) (b : β) (xs : Vector α n) : β :=
|
||||
@[inline] def foldr (f : α → β → β) (b : β) (xs : Vector α n) : β :=
|
||||
xs.toArray.foldr f b
|
||||
|
||||
/-- Append two vectors. -/
|
||||
@[inline, expose] def append (xs : Vector α n) (ys : Vector α m) : Vector α (n + m) :=
|
||||
@[inline] def append (xs : Vector α n) (ys : Vector α m) : Vector α (n + m) :=
|
||||
⟨xs.toArray ++ ys.toArray, by simp⟩
|
||||
|
||||
instance : HAppend (Vector α n) (Vector α m) (Vector α (n + m)) where
|
||||
hAppend := append
|
||||
|
||||
/-- Creates a vector from another with a provably equal length. -/
|
||||
@[inline, expose] protected def cast (h : n = m) (xs : Vector α n) : Vector α m :=
|
||||
@[inline] protected def cast (h : n = m) (xs : Vector α n) : Vector α m :=
|
||||
⟨xs.toArray, by simp [*]⟩
|
||||
|
||||
/--
|
||||
Extracts the slice of a vector from indices `start` to `stop` (exclusive). If `start ≥ stop`, the
|
||||
result is empty. If `stop` is greater than the size of the vector, the size is used instead.
|
||||
-/
|
||||
@[inline, expose] def extract (xs : Vector α n) (start : Nat := 0) (stop : Nat := n) : Vector α (min stop n - start) :=
|
||||
@[inline] def extract (xs : Vector α n) (start : Nat := 0) (stop : Nat := n) : Vector α (min stop n - start) :=
|
||||
⟨xs.toArray.extract start stop, by simp⟩
|
||||
|
||||
/--
|
||||
@@ -203,7 +201,7 @@ vector then the vector is returned unchanged.
|
||||
|
||||
We immediately simplify this to the `extract` operation, so there is no verification API for this function.
|
||||
-/
|
||||
@[inline, expose] def take (xs : Vector α n) (i : Nat) : Vector α (min i n) :=
|
||||
@[inline] def take (xs : Vector α n) (i : Nat) : Vector α (min i n) :=
|
||||
⟨xs.toArray.take i, by simp⟩
|
||||
|
||||
@[simp] theorem take_eq_extract (xs : Vector α n) (i : Nat) : xs.take i = xs.extract 0 i := rfl
|
||||
@@ -214,7 +212,7 @@ vector then the empty vector is returned.
|
||||
|
||||
We immediately simplify this to the `extract` operation, so there is no verification API for this function.
|
||||
-/
|
||||
@[inline, expose] def drop (xs : Vector α n) (i : Nat) : Vector α (n - i) :=
|
||||
@[inline] def drop (xs : Vector α n) (i : Nat) : Vector α (n - i) :=
|
||||
⟨xs.toArray.drop i, by simp⟩
|
||||
|
||||
set_option linter.indexVariables false in
|
||||
@@ -227,23 +225,23 @@ Shrinks a vector to the first `m` elements, by repeatedly popping the last eleme
|
||||
|
||||
We immediately simplify this to the `extract` operation, so there is no verification API for this function.
|
||||
-/
|
||||
@[inline, expose] def shrink (xs : Vector α n) (i : Nat) : Vector α (min i n) :=
|
||||
@[inline] def shrink (xs : Vector α n) (i : Nat) : Vector α (min i n) :=
|
||||
⟨xs.toArray.shrink i, by simp⟩
|
||||
|
||||
@[simp] theorem shrink_eq_take (xs : Vector α n) (i : Nat) : xs.shrink i = xs.take i := by
|
||||
simp [shrink, take]
|
||||
|
||||
/-- Maps elements of a vector using the function `f`. -/
|
||||
@[inline, expose] def map (f : α → β) (xs : Vector α n) : Vector β n :=
|
||||
@[inline] def map (f : α → β) (xs : Vector α n) : Vector β n :=
|
||||
⟨xs.toArray.map f, by simp⟩
|
||||
|
||||
/-- Maps elements of a vector using the function `f`, which also receives the index of the element. -/
|
||||
@[inline, expose] def mapIdx (f : Nat → α → β) (xs : Vector α n) : Vector β n :=
|
||||
@[inline] def mapIdx (f : Nat → α → β) (xs : Vector α n) : Vector β n :=
|
||||
⟨xs.toArray.mapIdx f, by simp⟩
|
||||
|
||||
/-- Maps elements of a vector using the function `f`,
|
||||
which also receives the index of the element, and the fact that the index is less than the size of the vector. -/
|
||||
@[inline, expose] def mapFinIdx (xs : Vector α n) (f : (i : Nat) → α → (h : i < n) → β) : Vector β n :=
|
||||
@[inline] def mapFinIdx (xs : Vector α n) (f : (i : Nat) → α → (h : i < n) → β) : Vector β n :=
|
||||
⟨xs.toArray.mapFinIdx (fun i a h => f i a (by simpa [xs.size_toArray] using h)), by simp⟩
|
||||
|
||||
/-- Map a monadic function over a vector. -/
|
||||
@@ -256,7 +254,7 @@ where
|
||||
else
|
||||
return acc.cast (by omega)
|
||||
|
||||
@[inline, expose] protected def forM [Monad m] (xs : Vector α n) (f : α → m PUnit) : m PUnit :=
|
||||
@[inline] protected def forM [Monad m] (xs : Vector α n) (f : α → m PUnit) : m PUnit :=
|
||||
xs.toArray.forM f
|
||||
|
||||
@[inline] def flatMapM [Monad m] (xs : Vector α n) (f : α → m (Vector β k)) : m (Vector β (n * k)) := do
|
||||
@@ -269,7 +267,7 @@ where
|
||||
return acc.cast (by congr; omega)
|
||||
|
||||
/-- Variant of `mapIdxM` which receives the index `i` along with the bound `i < n. -/
|
||||
@[inline, expose]
|
||||
@[inline]
|
||||
def mapFinIdxM {α : Type u} {β : Type v} {m : Type v → Type w} [Monad m]
|
||||
(xs : Vector α n) (f : (i : Nat) → α → (h : i < n) → m β) : m (Vector β n) :=
|
||||
let rec @[specialize] map (i : Nat) (j : Nat) (inv : i + j = n) (ys : Vector β (n - i)) : m (Vector β n) := do
|
||||
@@ -283,38 +281,38 @@ def mapFinIdxM {α : Type u} {β : Type v} {m : Type v → Type w} [Monad m]
|
||||
map i (j+1) this ((ys.push (← f j xs[j] j_lt)).cast (by omega))
|
||||
map n 0 rfl (#v[].cast (by simp))
|
||||
|
||||
@[inline, expose]
|
||||
@[inline]
|
||||
def mapIdxM {α : Type u} {β : Type v} {m : Type v → Type w} [Monad m] (f : Nat → α → m β) (xs : Vector α n) : m (Vector β n) :=
|
||||
xs.mapFinIdxM fun i a _ => f i a
|
||||
|
||||
@[inline, expose] def firstM {α : Type u} {m : Type v → Type w} [Alternative m] (f : α → m β) (xs : Vector α n) : m β :=
|
||||
@[inline] def firstM {α : Type u} {m : Type v → Type w} [Alternative m] (f : α → m β) (xs : Vector α n) : m β :=
|
||||
xs.toArray.firstM f
|
||||
|
||||
@[inline, expose] def flatten (xs : Vector (Vector α n) m) : Vector α (m * n) :=
|
||||
@[inline] def flatten (xs : Vector (Vector α n) m) : Vector α (m * n) :=
|
||||
⟨(xs.toArray.map Vector.toArray).flatten,
|
||||
by rcases xs; simp_all [Function.comp_def, Array.map_const']⟩
|
||||
|
||||
@[inline, expose] def flatMap (xs : Vector α n) (f : α → Vector β m) : Vector β (n * m) :=
|
||||
@[inline] def flatMap (xs : Vector α n) (f : α → Vector β m) : Vector β (n * m) :=
|
||||
⟨xs.toArray.flatMap fun a => (f a).toArray, by simp [Array.map_const']⟩
|
||||
|
||||
@[inline, expose] def zipIdx (xs : Vector α n) (k : Nat := 0) : Vector (α × Nat) n :=
|
||||
@[inline] def zipIdx (xs : Vector α n) (k : Nat := 0) : Vector (α × Nat) n :=
|
||||
⟨xs.toArray.zipIdx k, by simp⟩
|
||||
|
||||
@[deprecated zipIdx (since := "2025-01-21")]
|
||||
abbrev zipWithIndex := @zipIdx
|
||||
|
||||
@[inline, expose] def zip (as : Vector α n) (bs : Vector β n) : Vector (α × β) n :=
|
||||
@[inline] def zip (as : Vector α n) (bs : Vector β n) : Vector (α × β) n :=
|
||||
⟨as.toArray.zip bs.toArray, by simp⟩
|
||||
|
||||
/-- Maps corresponding elements of two vectors of equal size using the function `f`. -/
|
||||
@[inline, expose] def zipWith (f : α → β → φ) (as : Vector α n) (bs : Vector β n) : Vector φ n :=
|
||||
@[inline] def zipWith (f : α → β → φ) (as : Vector α n) (bs : Vector β n) : Vector φ n :=
|
||||
⟨as.toArray.zipWith f bs.toArray, by simp⟩
|
||||
|
||||
@[inline, expose] def unzip (xs : Vector (α × β) n) : Vector α n × Vector β n :=
|
||||
@[inline] def unzip (xs : Vector (α × β) n) : Vector α n × Vector β n :=
|
||||
⟨⟨xs.toArray.unzip.1, by simp⟩, ⟨xs.toArray.unzip.2, by simp⟩⟩
|
||||
|
||||
/-- The vector of length `n` whose `i`-th element is `f i`. -/
|
||||
@[inline, expose] def ofFn (f : Fin n → α) : Vector α n :=
|
||||
@[inline] def ofFn (f : Fin n → α) : Vector α n :=
|
||||
⟨Array.ofFn f, by simp⟩
|
||||
|
||||
/-! See also `Vector.ofFnM` defined in `Init.Data.Vector.OfFn`. -/
|
||||
@@ -324,7 +322,7 @@ Swap two elements of a vector using `Fin` indices.
|
||||
|
||||
This will perform the update destructively provided that the vector has a reference count of 1.
|
||||
-/
|
||||
@[inline, expose] def swap (xs : Vector α n) (i j : Nat)
|
||||
@[inline] def swap (xs : Vector α n) (i j : Nat)
|
||||
(hi : i < n := by get_elem_tactic) (hj : j < n := by get_elem_tactic) : Vector α n :=
|
||||
⟨xs.toArray.swap i j (by simpa using hi) (by simpa using hj), by simp⟩
|
||||
|
||||
@@ -333,7 +331,7 @@ Swap two elements of a vector using `Nat` indices. Panics if either index is out
|
||||
|
||||
This will perform the update destructively provided that the vector has a reference count of 1.
|
||||
-/
|
||||
@[inline, expose] def swapIfInBounds (xs : Vector α n) (i j : Nat) : Vector α n :=
|
||||
@[inline] def swapIfInBounds (xs : Vector α n) (i j : Nat) : Vector α n :=
|
||||
⟨xs.toArray.swapIfInBounds i j, by simp⟩
|
||||
|
||||
/--
|
||||
@@ -342,7 +340,7 @@ along with the updated vector.
|
||||
|
||||
This will perform the update destructively provided that the vector has a reference count of 1.
|
||||
-/
|
||||
@[inline, expose] def swapAt (xs : Vector α n) (i : Nat) (x : α) (hi : i < n := by get_elem_tactic) :
|
||||
@[inline] def swapAt (xs : Vector α n) (i : Nat) (x : α) (hi : i < n := by get_elem_tactic) :
|
||||
α × Vector α n :=
|
||||
let a := xs.toArray.swapAt i x (by simpa using hi)
|
||||
⟨a.fst, a.snd, by simp [a]⟩
|
||||
@@ -353,38 +351,38 @@ bounds. The original value is returned along with the updated vector.
|
||||
|
||||
This will perform the update destructively provided that the vector has a reference count of 1.
|
||||
-/
|
||||
@[inline, expose] def swapAt! (xs : Vector α n) (i : Nat) (x : α) : α × Vector α n :=
|
||||
@[inline] def swapAt! (xs : Vector α n) (i : Nat) (x : α) : α × Vector α n :=
|
||||
let a := xs.toArray.swapAt! i x
|
||||
⟨a.fst, a.snd, by simp [a]⟩
|
||||
|
||||
/-- The vector `#v[0, 1, 2, ..., n-1]`. -/
|
||||
@[inline, expose] def range (n : Nat) : Vector Nat n := ⟨Array.range n, by simp⟩
|
||||
@[inline] def range (n : Nat) : Vector Nat n := ⟨Array.range n, by simp⟩
|
||||
|
||||
/-- The vector `#v[start, start + step, start + 2 * step, ..., start + (size - 1) * step]`. -/
|
||||
@[inline, expose] def range' (start size : Nat) (step : Nat := 1) : Vector Nat size :=
|
||||
@[inline] def range' (start size : Nat) (step : Nat := 1) : Vector Nat size :=
|
||||
⟨Array.range' start size step, by simp⟩
|
||||
|
||||
/--
|
||||
Compares two vectors of the same size using a given boolean relation `r`. `isEqv v w r` returns
|
||||
`true` if and only if `r v[i] w[i]` is true for all indices `i`.
|
||||
-/
|
||||
@[inline, expose] def isEqv (xs ys : Vector α n) (r : α → α → Bool) : Bool :=
|
||||
@[inline] def isEqv (xs ys : Vector α n) (r : α → α → Bool) : Bool :=
|
||||
Array.isEqvAux xs.toArray ys.toArray (by simp) r n (by simp)
|
||||
|
||||
instance [BEq α] : BEq (Vector α n) where
|
||||
beq xs ys := isEqv xs ys (· == ·)
|
||||
|
||||
/-- Reverse the elements of a vector. -/
|
||||
@[inline, expose] def reverse (xs : Vector α n) : Vector α n :=
|
||||
@[inline] def reverse (xs : Vector α n) : Vector α n :=
|
||||
⟨xs.toArray.reverse, by simp⟩
|
||||
|
||||
/-- Delete an element of a vector using a `Nat` index and a tactic provided proof. -/
|
||||
@[inline, expose] def eraseIdx (xs : Vector α n) (i : Nat) (h : i < n := by get_elem_tactic) :
|
||||
@[inline] def eraseIdx (xs : Vector α n) (i : Nat) (h : i < n := by get_elem_tactic) :
|
||||
Vector α (n-1) :=
|
||||
⟨xs.toArray.eraseIdx i (xs.size_toArray.symm ▸ h), by simp [Array.size_eraseIdx]⟩
|
||||
|
||||
/-- Delete an element of a vector using a `Nat` index. Panics if the index is out of bounds. -/
|
||||
@[inline, expose] def eraseIdx! (xs : Vector α n) (i : Nat) : Vector α (n-1) :=
|
||||
@[inline] def eraseIdx! (xs : Vector α n) (i : Nat) : Vector α (n-1) :=
|
||||
if _ : i < n then
|
||||
xs.eraseIdx i
|
||||
else
|
||||
@@ -392,12 +390,12 @@ instance [BEq α] : BEq (Vector α n) where
|
||||
panic! "index out of bounds"
|
||||
|
||||
/-- Insert an element into a vector using a `Nat` index and a tactic provided proof. -/
|
||||
@[inline, expose] def insertIdx (xs : Vector α n) (i : Nat) (x : α) (h : i ≤ n := by get_elem_tactic) :
|
||||
@[inline] def insertIdx (xs : Vector α n) (i : Nat) (x : α) (h : i ≤ n := by get_elem_tactic) :
|
||||
Vector α (n+1) :=
|
||||
⟨xs.toArray.insertIdx i x (xs.size_toArray.symm ▸ h), by simp [Array.size_insertIdx]⟩
|
||||
|
||||
/-- Insert an element into a vector using a `Nat` index. Panics if the index is out of bounds. -/
|
||||
@[inline, expose] def insertIdx! (xs : Vector α n) (i : Nat) (x : α) : Vector α (n+1) :=
|
||||
@[inline] def insertIdx! (xs : Vector α n) (i : Nat) (x : α) : Vector α (n+1) :=
|
||||
if _ : i ≤ n then
|
||||
xs.insertIdx i x
|
||||
else
|
||||
@@ -409,7 +407,7 @@ Delete the first element of a vector. Returns the empty vector if the input vect
|
||||
|
||||
We immediately simplify this to the `extract` operation, so there is no verification API for this function.
|
||||
-/
|
||||
@[inline, expose]
|
||||
@[inline]
|
||||
def tail (xs : Vector α n) : Vector α (n-1) :=
|
||||
(xs.extract 1).cast (by omega)
|
||||
|
||||
@@ -420,7 +418,7 @@ def tail (xs : Vector α n) : Vector α (n-1) :=
|
||||
Finds the first index of a given value in a vector using `==` for comparison. Returns `none` if the
|
||||
no element of the index matches the given value.
|
||||
-/
|
||||
@[inline, expose] def finIdxOf? [BEq α] (xs : Vector α n) (x : α) : Option (Fin n) :=
|
||||
@[inline] def finIdxOf? [BEq α] (xs : Vector α n) (x : α) : Option (Fin n) :=
|
||||
(xs.toArray.finIdxOf? x).map (Fin.cast xs.size_toArray)
|
||||
|
||||
@[deprecated finIdxOf? (since := "2025-01-29")]
|
||||
@@ -428,70 +426,70 @@ abbrev indexOf? := @finIdxOf?
|
||||
|
||||
/-- Finds the first index of a given value in a vector using a predicate. Returns `none` if the
|
||||
no element of the index matches the given value. -/
|
||||
@[inline, expose] def findFinIdx? (p : α → Bool) (xs : Vector α n) : Option (Fin n) :=
|
||||
@[inline] def findFinIdx? (p : α → Bool) (xs : Vector α n) : Option (Fin n) :=
|
||||
(xs.toArray.findFinIdx? p).map (Fin.cast xs.size_toArray)
|
||||
|
||||
/--
|
||||
Note that the universe level is constrained to `Type` here,
|
||||
to avoid having to have the predicate live in `p : α → m (ULift Bool)`.
|
||||
-/
|
||||
@[inline, expose] def findM? {α : Type} {m : Type → Type} [Monad m] (f : α → m Bool) (as : Vector α n) : m (Option α) :=
|
||||
@[inline] def findM? {α : Type} {m : Type → Type} [Monad m] (f : α → m Bool) (as : Vector α n) : m (Option α) :=
|
||||
as.toArray.findM? f
|
||||
|
||||
@[inline, expose] def findSomeM? [Monad m] (f : α → m (Option β)) (as : Vector α n) : m (Option β) :=
|
||||
@[inline] def findSomeM? [Monad m] (f : α → m (Option β)) (as : Vector α n) : m (Option β) :=
|
||||
as.toArray.findSomeM? f
|
||||
|
||||
/--
|
||||
Note that the universe level is constrained to `Type` here,
|
||||
to avoid having to have the predicate live in `p : α → m (ULift Bool)`.
|
||||
-/
|
||||
@[inline, expose] def findRevM? {α : Type} {m : Type → Type} [Monad m] (f : α → m Bool) (as : Vector α n) : m (Option α) :=
|
||||
@[inline] def findRevM? {α : Type} {m : Type → Type} [Monad m] (f : α → m Bool) (as : Vector α n) : m (Option α) :=
|
||||
as.toArray.findRevM? f
|
||||
|
||||
@[inline, expose] def findSomeRevM? [Monad m] (f : α → m (Option β)) (as : Vector α n) : m (Option β) :=
|
||||
@[inline] def findSomeRevM? [Monad m] (f : α → m (Option β)) (as : Vector α n) : m (Option β) :=
|
||||
as.toArray.findSomeRevM? f
|
||||
|
||||
@[inline, expose] def find? {α : Type} (f : α → Bool) (as : Vector α n) : Option α :=
|
||||
@[inline] def find? {α : Type} (f : α → Bool) (as : Vector α n) : Option α :=
|
||||
as.toArray.find? f
|
||||
|
||||
@[inline, expose] def findRev? {α : Type} (f : α → Bool) (as : Vector α n) : Option α :=
|
||||
@[inline] def findRev? {α : Type} (f : α → Bool) (as : Vector α n) : Option α :=
|
||||
as.toArray.findRev? f
|
||||
|
||||
@[inline, expose] def findSome? (f : α → Option β) (as : Vector α n) : Option β :=
|
||||
@[inline] def findSome? (f : α → Option β) (as : Vector α n) : Option β :=
|
||||
as.toArray.findSome? f
|
||||
|
||||
@[inline, expose] def findSomeRev? (f : α → Option β) (as : Vector α n) : Option β :=
|
||||
@[inline] def findSomeRev? (f : α → Option β) (as : Vector α n) : Option β :=
|
||||
as.toArray.findSomeRev? f
|
||||
|
||||
/-- Returns `true` when `xs` is a prefix of the vector `ys`. -/
|
||||
@[inline, expose] def isPrefixOf [BEq α] (xs : Vector α m) (ys : Vector α n) : Bool :=
|
||||
@[inline] def isPrefixOf [BEq α] (xs : Vector α m) (ys : Vector α n) : Bool :=
|
||||
xs.toArray.isPrefixOf ys.toArray
|
||||
|
||||
/-- Returns `true` with the monad if `p` returns `true` for any element of the vector. -/
|
||||
@[inline, expose] def anyM [Monad m] (p : α → m Bool) (xs : Vector α n) : m Bool :=
|
||||
@[inline] def anyM [Monad m] (p : α → m Bool) (xs : Vector α n) : m Bool :=
|
||||
xs.toArray.anyM p
|
||||
|
||||
/-- Returns `true` with the monad if `p` returns `true` for all elements of the vector. -/
|
||||
@[inline, expose] def allM [Monad m] (p : α → m Bool) (xs : Vector α n) : m Bool :=
|
||||
@[inline] def allM [Monad m] (p : α → m Bool) (xs : Vector α n) : m Bool :=
|
||||
xs.toArray.allM p
|
||||
|
||||
/-- Returns `true` if `p` returns `true` for any element of the vector. -/
|
||||
@[inline, expose] def any (xs : Vector α n) (p : α → Bool) : Bool :=
|
||||
@[inline] def any (xs : Vector α n) (p : α → Bool) : Bool :=
|
||||
xs.toArray.any p
|
||||
|
||||
/-- Returns `true` if `p` returns `true` for all elements of the vector. -/
|
||||
@[inline, expose] def all (xs : Vector α n) (p : α → Bool) : Bool :=
|
||||
@[inline] def all (xs : Vector α n) (p : α → Bool) : Bool :=
|
||||
xs.toArray.all p
|
||||
|
||||
/-- Count the number of elements of a vector that satisfy the predicate `p`. -/
|
||||
@[inline, expose] def countP (p : α → Bool) (xs : Vector α n) : Nat :=
|
||||
@[inline] def countP (p : α → Bool) (xs : Vector α n) : Nat :=
|
||||
xs.toArray.countP p
|
||||
|
||||
/-- Count the number of elements of a vector that are equal to `a`. -/
|
||||
@[inline, expose] def count [BEq α] (a : α) (xs : Vector α n) : Nat :=
|
||||
@[inline] def count [BEq α] (a : α) (xs : Vector α n) : Nat :=
|
||||
xs.toArray.count a
|
||||
|
||||
@[inline, expose] def replace [BEq α] (xs : Vector α n) (a b : α) : Vector α n :=
|
||||
@[inline] def replace [BEq α] (xs : Vector α n) (a b : α) : Vector α n :=
|
||||
⟨xs.toArray.replace a b, by simp⟩
|
||||
|
||||
/--
|
||||
@@ -501,7 +499,7 @@ Examples:
|
||||
* `#v[a, b, c].sum = a + (b + (c + 0))`
|
||||
* `#v[1, 2, 5].sum = 8`
|
||||
-/
|
||||
@[inline, expose] def sum [Add α] [Zero α] (xs : Vector α n) : α :=
|
||||
@[inline] def sum [Add α] [Zero α] (xs : Vector α n) : α :=
|
||||
xs.toArray.sum
|
||||
|
||||
/--
|
||||
|
||||
@@ -40,12 +40,12 @@ theorem countP_push {a : α} {xs : Vector α n} : countP p (xs.push a) = countP
|
||||
rcases xs with ⟨xs, rfl⟩
|
||||
simp [Array.countP_push]
|
||||
|
||||
theorem countP_singleton {a : α} : countP p #v[a] = if p a then 1 else 0 := by
|
||||
simp
|
||||
@[simp] theorem countP_singleton {a : α} : countP p #v[a] = if p a then 1 else 0 := by
|
||||
simp [countP_push]
|
||||
|
||||
theorem size_eq_countP_add_countP {xs : Vector α n} : n = countP p xs + countP (fun a => ¬p a) xs := by
|
||||
rcases xs with ⟨xs, rfl⟩
|
||||
simp [Array.size_eq_countP_add_countP (p := p)]
|
||||
simp [List.length_eq_countP_add_countP (p := p)]
|
||||
|
||||
theorem countP_le_size {xs : Vector α n} : countP p xs ≤ n := by
|
||||
rcases xs with ⟨xs, rfl⟩
|
||||
|
||||
@@ -48,18 +48,15 @@ theorem beq_eq_decide [BEq α] (xs ys : Vector α n) :
|
||||
(xs == ys) = decide (∀ (i : Nat) (h' : i < n), xs[i] == ys[i]) := by
|
||||
simp [BEq.beq, isEqv_eq_decide]
|
||||
|
||||
@[deprecated mk_beq_mk (since := "2025-05-26")]
|
||||
theorem beq_mk [BEq α] (xs ys : Array α) (ha : xs.size = n) (hb : ys.size = n) :
|
||||
@[simp] theorem beq_mk [BEq α] (xs ys : Array α) (ha : xs.size = n) (hb : ys.size = n) :
|
||||
(mk xs ha == mk ys hb) = (xs == ys) := by
|
||||
simp
|
||||
simp [BEq.beq]
|
||||
|
||||
@[deprecated toArray_beq_toArray (since := "2025-05-26")]
|
||||
theorem beq_toArray [BEq α] (xs ys : Vector α n) : (xs.toArray == ys.toArray) = (xs == ys) := by
|
||||
simp
|
||||
@[simp, grind =] theorem beq_toArray [BEq α] (xs ys : Vector α n) : (xs.toArray == ys.toArray) = (xs == ys) := by
|
||||
simp [beq_eq_decide, Array.beq_eq_decide]
|
||||
|
||||
@[deprecated toList_beq_toList (since := "2025-05-26")]
|
||||
theorem beq_toList [BEq α] (xs ys : Vector α n) : (xs.toList == ys.toList) = (xs == ys) := by
|
||||
simp
|
||||
@[simp] theorem beq_toList [BEq α] (xs ys : Vector α n) : (xs.toList == ys.toList) = (xs == ys) := by
|
||||
simp [beq_eq_decide, List.beq_eq_decide]
|
||||
|
||||
instance [BEq α] [ReflBEq α] : ReflBEq (Vector α n) where
|
||||
rfl := by simp [BEq.beq, isEqv_self_beq]
|
||||
|
||||
@@ -144,7 +144,7 @@ abbrev findSome?_mkVector_of_isNone := @findSome?_replicate_of_isNone
|
||||
|
||||
@[simp] theorem find?_empty : find? p #v[] = none := rfl
|
||||
|
||||
theorem find?_singleton {a : α} {p : α → Bool} :
|
||||
@[simp] theorem find?_singleton {a : α} {p : α → Bool} :
|
||||
#v[a].find? p = if p a then some a else none := by
|
||||
simp
|
||||
|
||||
@@ -291,8 +291,7 @@ theorem find?_eq_some_iff_getElem {xs : Vector α n} {p : α → Bool} {b : α}
|
||||
|
||||
/-! ### findFinIdx? -/
|
||||
|
||||
theorem findFinIdx?_empty {p : α → Bool} : findFinIdx? p (#v[] : Vector α 0) = none := by simp
|
||||
|
||||
@[simp] theorem findFinIdx?_empty {p : α → Bool} : findFinIdx? p (#v[] : Vector α 0) = none := by simp
|
||||
theorem findFinIdx?_singleton {a : α} {p : α → Bool} :
|
||||
#[a].findFinIdx? p = if p a then some ⟨0, by simp⟩ else none := by
|
||||
simp
|
||||
|
||||
@@ -684,7 +684,8 @@ abbrev toList_eq_empty_iff {α n} (xs) := @toList_eq_nil_iff α n xs
|
||||
|
||||
/-! ### empty -/
|
||||
|
||||
theorem empty_eq {xs : Vector α 0} : #v[] = xs ↔ xs = #v[] := by
|
||||
@[simp] theorem empty_eq {xs : Vector α 0} : #v[] = xs ↔ xs = #v[] := by
|
||||
cases xs
|
||||
simp
|
||||
|
||||
/-- A vector of length `0` is the empty vector. -/
|
||||
@@ -698,7 +699,7 @@ protected theorem eq_empty {xs : Vector α 0} : xs = #v[] := by
|
||||
theorem eq_empty_of_size_eq_zero {xs : Vector α n} (h : n = 0) : xs = #v[].cast h.symm := by
|
||||
rcases xs with ⟨xs, rfl⟩
|
||||
apply toArray_inj.1
|
||||
simp only [Array.size_eq_zero_iff] at h
|
||||
simp only [List.length_eq_zero_iff, Array.toList_eq_nil_iff] at h
|
||||
simp [h]
|
||||
|
||||
theorem size_eq_one {xs : Vector α 1} : ∃ a, xs = #v[a] := by
|
||||
@@ -815,11 +816,14 @@ abbrev mkVector_eq_mk_mkArray := @replicate_eq_mk_replicate
|
||||
|
||||
/-! ## L[i] and L[i]? -/
|
||||
|
||||
theorem getElem?_eq_none_iff {xs : Vector α n} : xs[i]? = none ↔ n ≤ i := by
|
||||
simp
|
||||
@[simp] theorem getElem?_eq_none_iff {xs : Vector α n} : xs[i]? = none ↔ n ≤ i := by
|
||||
by_cases h : i < n
|
||||
· simp [getElem?_pos, h]
|
||||
· rw [getElem?_neg xs i h]
|
||||
simp_all
|
||||
|
||||
theorem none_eq_getElem?_iff {xs : Vector α n} {i : Nat} : none = xs[i]? ↔ n ≤ i := by
|
||||
simp
|
||||
@[simp] theorem none_eq_getElem?_iff {xs : Vector α n} {i : Nat} : none = xs[i]? ↔ n ≤ i := by
|
||||
simp [eq_comm (a := none)]
|
||||
|
||||
theorem getElem?_eq_none {xs : Vector α n} (h : n ≤ i) : xs[i]? = none := by
|
||||
simp [getElem?_eq_none_iff, h]
|
||||
@@ -831,23 +835,23 @@ grind_pattern Vector.getElem?_eq_none => n ≤ i, xs[i]?
|
||||
@[simp] theorem getElem?_eq_getElem {xs : Vector α n} {i : Nat} (h : i < n) : xs[i]? = some xs[i] :=
|
||||
getElem?_pos ..
|
||||
|
||||
theorem getElem?_eq_some_iff {xs : Vector α n} : xs[i]? = some b ↔ ∃ h : i < n, xs[i] = b :=
|
||||
_root_.getElem?_eq_some_iff
|
||||
theorem getElem?_eq_some_iff {xs : Vector α n} : xs[i]? = some b ↔ ∃ h : i < n, xs[i] = b := by
|
||||
simp [getElem?_def]
|
||||
|
||||
@[grind →]
|
||||
theorem getElem_of_getElem? {xs : Vector α n} : xs[i]? = some a → ∃ h : i < n, xs[i] = a :=
|
||||
getElem?_eq_some_iff.mp
|
||||
|
||||
theorem some_eq_getElem?_iff {xs : Vector α n} : some b = xs[i]? ↔ ∃ h : i < n, xs[i] = b :=
|
||||
_root_.some_eq_getElem?_iff
|
||||
theorem some_eq_getElem?_iff {xs : Vector α n} : some b = xs[i]? ↔ ∃ h : i < n, xs[i] = b := by
|
||||
rw [eq_comm, getElem?_eq_some_iff]
|
||||
|
||||
theorem some_getElem_eq_getElem?_iff {xs : Vector α n} {i : Nat} (h : i < n) :
|
||||
@[simp] theorem some_getElem_eq_getElem?_iff {xs : Vector α n} {i : Nat} (h : i < n) :
|
||||
(some xs[i] = xs[i]?) ↔ True := by
|
||||
simp
|
||||
simp [h]
|
||||
|
||||
theorem getElem?_eq_some_getElem_iff {xs : Vector α n} {i : Nat} (h : i < n) :
|
||||
@[simp] theorem getElem?_eq_some_getElem_iff {xs : Vector α n} {i : Nat} (h : i < n) :
|
||||
(xs[i]? = some xs[i]) ↔ True := by
|
||||
simp
|
||||
simp [h]
|
||||
|
||||
theorem getElem_eq_iff {xs : Vector α n} {i : Nat} {h : i < n} : xs[i] = x ↔ xs[i]? = some x := by
|
||||
simp only [getElem?_eq_some_iff]
|
||||
@@ -887,11 +891,12 @@ theorem getElem?_push {xs : Vector α n} {x : α} {i : Nat} : (xs.push x)[i]? =
|
||||
(repeat' split) <;> first | rfl | omega
|
||||
|
||||
set_option linter.indexVariables false in
|
||||
theorem getElem?_push_size {xs : Vector α n} {x : α} : (xs.push x)[n]? = some x := by
|
||||
simp
|
||||
@[simp] theorem getElem?_push_size {xs : Vector α n} {x : α} : (xs.push x)[n]? = some x := by
|
||||
simp [getElem?_push]
|
||||
|
||||
theorem getElem_singleton {a : α} (h : i < 1) : #v[a][i] = a := by
|
||||
simp
|
||||
@[simp] theorem getElem_singleton {a : α} (h : i < 1) : #v[a][i] = a :=
|
||||
match i, h with
|
||||
| 0, _ => rfl
|
||||
|
||||
@[grind]
|
||||
theorem getElem?_singleton {a : α} {i : Nat} : #v[a][i]? = if i = 0 then some a else none := by
|
||||
@@ -903,7 +908,7 @@ theorem getElem?_singleton {a : α} {i : Nat} : #v[a][i]? = if i = 0 then some a
|
||||
rcases xs with ⟨xs, rfl⟩
|
||||
simp
|
||||
|
||||
theorem not_mem_empty (a : α) : ¬ a ∈ #v[] := nofun
|
||||
@[simp] theorem not_mem_empty (a : α) : ¬ a ∈ #v[] := nofun
|
||||
|
||||
@[simp] theorem mem_push {xs : Vector α n} {x y : α} : x ∈ xs.push y ↔ x ∈ xs ∨ x = y := by
|
||||
rcases xs with ⟨xs, rfl⟩
|
||||
@@ -952,7 +957,8 @@ theorem size_zero_iff_forall_not_mem {xs : Vector α n} : n = 0 ↔ ∀ a, a ∉
|
||||
theorem eq_of_mem_singleton (h : a ∈ #v[b]) : a = b := by
|
||||
simpa using h
|
||||
|
||||
theorem mem_singleton {a b : α} : a ∈ #v[b] ↔ a = b := by simp
|
||||
@[simp] theorem mem_singleton {a b : α} : a ∈ #v[b] ↔ a = b :=
|
||||
⟨eq_of_mem_singleton, (by simp [·])⟩
|
||||
|
||||
theorem forall_mem_push {p : α → Prop} {xs : Vector α n} {a : α} :
|
||||
(∀ x, x ∈ xs.push a → p x) ↔ p a ∧ ∀ x, x ∈ xs → p x := by
|
||||
@@ -1438,9 +1444,10 @@ theorem back_eq_getElem [NeZero n] {xs : Vector α n} : xs.back = xs[n - 1]'(by
|
||||
simp
|
||||
|
||||
/-- The empty vector maps to the empty vector. -/
|
||||
@[grind]
|
||||
@[simp, grind]
|
||||
theorem map_empty {f : α → β} : map f #v[] = #v[] := by
|
||||
simp
|
||||
rw [map, mk.injEq]
|
||||
exact Array.map_empty
|
||||
|
||||
@[simp, grind] theorem map_push {f : α → β} {as : Vector α n} {x : α} :
|
||||
(as.push x).map f = (as.map f).push (f x) := by
|
||||
@@ -1517,8 +1524,9 @@ theorem map_eq_push_iff {f : α → β} {xs : Vector α (n + 1)} {ys : Vector β
|
||||
· rintro ⟨xs', a, h₁, h₂, rfl⟩
|
||||
refine ⟨xs'.toArray, a, by simp_all⟩
|
||||
|
||||
theorem map_eq_singleton_iff {f : α → β} {xs : Vector α 1} {b : β} :
|
||||
@[simp] theorem map_eq_singleton_iff {f : α → β} {xs : Vector α 1} {b : β} :
|
||||
map f xs = #v[b] ↔ ∃ a, xs = #v[a] ∧ f a = b := by
|
||||
cases xs
|
||||
simp
|
||||
|
||||
theorem map_eq_map_iff {f g : α → β} {xs : Vector α n} :
|
||||
@@ -2097,7 +2105,7 @@ abbrev forall_mem_mkVector := @forall_mem_replicate
|
||||
@[deprecated getElem_replicate (since := "2025-03-18")]
|
||||
abbrev getElem_mkVector := @getElem_replicate
|
||||
|
||||
@[grind] theorem getElem?_replicate {a : α} {n i : Nat} : (replicate n a)[i]? = if i < n then some a else none := by
|
||||
@[grind]theorem getElem?_replicate {a : α} {n i : Nat} : (replicate n a)[i]? = if i < n then some a else none := by
|
||||
simp [getElem?_def]
|
||||
|
||||
@[deprecated getElem?_replicate (since := "2025-03-18")]
|
||||
@@ -2353,13 +2361,13 @@ set_option linter.indexVariables false in
|
||||
rcases ys with ⟨ys, rfl⟩
|
||||
simp
|
||||
|
||||
theorem foldlM_empty [Monad m] {f : β → α → m β} {init : β} :
|
||||
@[simp] theorem foldlM_empty [Monad m] {f : β → α → m β} {init : β} :
|
||||
foldlM f init #v[] = return init := by
|
||||
simp
|
||||
simp [foldlM]
|
||||
|
||||
@[grind] theorem foldrM_empty [Monad m] {f : α → β → m β} {init : β} :
|
||||
@[simp, grind] theorem foldrM_empty [Monad m] {f : α → β → m β} {init : β} :
|
||||
foldrM f init #v[] = return init := by
|
||||
simp
|
||||
simp [foldrM]
|
||||
|
||||
@[simp, grind] theorem foldlM_push [Monad m] [LawfulMonad m] {xs : Vector α n} {a : α} {f : β → α → m β} {b} :
|
||||
(xs.push a).foldlM f b = xs.foldlM f b >>= fun b => f b a := by
|
||||
@@ -2377,23 +2385,19 @@ theorem foldrM_pure [Monad m] [LawfulMonad m] {f : α → β → β} {b} {xs : V
|
||||
Array.foldrM_pure
|
||||
|
||||
theorem foldl_eq_foldlM {f : β → α → β} {b} {xs : Vector α n} :
|
||||
xs.foldl f b = (xs.foldlM (m := Id) (pure <| f · ·) b).run := rfl
|
||||
xs.foldl f b = xs.foldlM (m := Id) f b := by
|
||||
rcases xs with ⟨xs, rfl⟩
|
||||
simp [Array.foldl_eq_foldlM]
|
||||
|
||||
theorem foldr_eq_foldrM {f : α → β → β} {b} {xs : Vector α n} :
|
||||
xs.foldr f b = (xs.foldrM (m := Id) (pure <| f · ·) b).run := rfl
|
||||
xs.foldr f b = xs.foldrM (m := Id) f b := by
|
||||
rcases xs with ⟨xs, rfl⟩
|
||||
simp [Array.foldr_eq_foldrM]
|
||||
|
||||
@[simp] theorem idRun_foldlM {f : β → α → Id β} {b} {xs : Vector α n} :
|
||||
Id.run (xs.foldlM f b) = xs.foldl (f · · |>.run) b := foldl_eq_foldlM.symm
|
||||
|
||||
@[deprecated idRun_foldlM (since := "2025-05-21")]
|
||||
theorem id_run_foldlM {f : β → α → Id β} {b} {xs : Vector α n} :
|
||||
@[simp] theorem id_run_foldlM {f : β → α → Id β} {b} {xs : Vector α n} :
|
||||
Id.run (xs.foldlM f b) = xs.foldl f b := foldl_eq_foldlM.symm
|
||||
|
||||
@[simp] theorem idRun_foldrM {f : α → β → Id β} {b} {xs : Vector α n} :
|
||||
Id.run (xs.foldrM f b) = xs.foldr (f · · |>.run) b := foldr_eq_foldrM.symm
|
||||
|
||||
@[deprecated idRun_foldrM (since := "2025-05-21")]
|
||||
theorem id_run_foldrM {f : α → β → Id β} {b} {xs : Vector α n} :
|
||||
@[simp] theorem id_run_foldrM {f : α → β → Id β} {b} {xs : Vector α n} :
|
||||
Id.run (xs.foldrM f b) = xs.foldr f b := foldr_eq_foldrM.symm
|
||||
|
||||
@[simp] theorem foldlM_reverse [Monad m] {xs : Vector α n} {f : β → α → m β} {b} :
|
||||
@@ -2481,10 +2485,10 @@ theorem foldr_map_hom {g : α → β} {f : α → α → α} {f' : β → β →
|
||||
simp
|
||||
|
||||
@[simp, grind _=_] theorem foldl_append {β : Type _} {f : β → α → β} {b} {xs : Vector α n} {ys : Vector α k} :
|
||||
(xs ++ ys).foldl f b = ys.foldl f (xs.foldl f b) := foldlM_append
|
||||
(xs ++ ys).foldl f b = ys.foldl f (xs.foldl f b) := by simp [foldl_eq_foldlM]
|
||||
|
||||
@[simp, grind _=_] theorem foldr_append {f : α → β → β} {b} {xs : Vector α n} {ys : Vector α k} :
|
||||
(xs ++ ys).foldr f b = xs.foldr f (ys.foldr f b) := foldrM_append
|
||||
(xs ++ ys).foldr f b = xs.foldr f (ys.foldr f b) := by simp [foldr_eq_foldrM]
|
||||
|
||||
@[simp, grind] theorem foldl_flatten {f : β → α → β} {b} {xss : Vector (Vector α m) n} :
|
||||
(flatten xss).foldl f b = xss.foldl (fun b xs => xs.foldl f b) b := by
|
||||
@@ -2497,8 +2501,7 @@ theorem foldr_map_hom {g : α → β} {f : α → α → α} {f' : β → β →
|
||||
simp [Array.foldr_flatten', Array.foldr_map']
|
||||
|
||||
@[simp, grind] theorem foldl_reverse {xs : Vector α n} {f : β → α → β} {b} :
|
||||
xs.reverse.foldl f b = xs.foldr (fun x y => f y x) b :=
|
||||
foldlM_reverse
|
||||
xs.reverse.foldl f b = xs.foldr (fun x y => f y x) b := by simp [foldl_eq_foldlM, foldr_eq_foldrM]
|
||||
|
||||
@[simp, grind] theorem foldr_reverse {xs : Vector α n} {f : α → β → β} {b} :
|
||||
xs.reverse.foldr f b = xs.foldl (fun x y => f y x) b :=
|
||||
@@ -2677,7 +2680,7 @@ theorem contains_iff_exists_mem_beq [BEq α] {xs : Vector α n} {a : α} :
|
||||
rcases xs with ⟨xs, rfl⟩
|
||||
simp [Array.contains_iff_exists_mem_beq]
|
||||
|
||||
@[grind _=_]
|
||||
@[grind]
|
||||
theorem contains_iff_mem [BEq α] [LawfulBEq α] {xs : Vector α n} {a : α} :
|
||||
xs.contains a ↔ a ∈ xs := by
|
||||
simp
|
||||
@@ -3050,7 +3053,8 @@ end replace
|
||||
/-! Content below this point has not yet been aligned with `List` and `Array`. -/
|
||||
|
||||
set_option linter.indexVariables false in
|
||||
theorem getElem_push_last {xs : Vector α n} {x : α} : (xs.push x)[n] = x := by
|
||||
@[simp] theorem getElem_push_last {xs : Vector α n} {x : α} : (xs.push x)[n] = x := by
|
||||
rcases xs with ⟨xs, rfl⟩
|
||||
simp
|
||||
|
||||
@[simp] theorem push_pop_back (xs : Vector α (n + 1)) : xs.pop.push xs.back = xs := by
|
||||
@@ -3082,7 +3086,8 @@ theorem getElem_push_last {xs : Vector α n} {x : α} : (xs.push x)[n] = x := by
|
||||
/-! ### take -/
|
||||
|
||||
set_option linter.indexVariables false in
|
||||
theorem take_size {as : Vector α n} : as.take n = as.cast (by simp) := by
|
||||
@[simp] theorem take_size {as : Vector α n} : as.take n = as.cast (by simp) := by
|
||||
rcases as with ⟨as, rfl⟩
|
||||
simp
|
||||
|
||||
/-! ### swap -/
|
||||
@@ -3131,8 +3136,9 @@ theorem swap_comm {xs : Vector α n} {i j : Nat} (hi hj) :
|
||||
|
||||
/-! ### drop -/
|
||||
|
||||
@[grind =] theorem getElem_drop {xs : Vector α n} {j : Nat} (hi : i < n - j) :
|
||||
@[simp, grind =] theorem getElem_drop {xs : Vector α n} {j : Nat} (hi : i < n - j) :
|
||||
(xs.drop j)[i] = xs[j + i] := by
|
||||
cases xs
|
||||
simp
|
||||
|
||||
/-! ### Decidable quantifiers. -/
|
||||
|
||||
@@ -58,8 +58,9 @@ protected theorem not_le_iff_gt [DecidableEq α] [LT α] [DecidableLT α] {xs ys
|
||||
cases xs
|
||||
simp_all
|
||||
|
||||
theorem singleton_lex_singleton [BEq α] {lt : α → α → Bool} : #v[a].lex #v[b] lt = lt a b := by
|
||||
simp
|
||||
@[simp] theorem singleton_lex_singleton [BEq α] {lt : α → α → Bool} : #v[a].lex #v[b] lt = lt a b := by
|
||||
simp only [lex, getElem_mk, List.getElem_toArray, List.getElem_singleton]
|
||||
cases lt a b <;> cases a != b <;> simp [Id.run]
|
||||
|
||||
protected theorem lt_irrefl [LT α] [Std.Irrefl (· < · : α → α → Prop)] (xs : Vector α n) : ¬ xs < xs :=
|
||||
Array.lt_irrefl xs.toArray
|
||||
|
||||
@@ -295,8 +295,9 @@ theorem mapIdx_eq_push_iff {xs : Vector α (n + 1)} {b : β} :
|
||||
· rintro ⟨a, zs, rfl, rfl, rfl⟩
|
||||
exact ⟨zs, a, rfl, by simp⟩
|
||||
|
||||
theorem mapIdx_eq_singleton_iff {xs : Vector α 1} {f : Nat → α → β} {b : β} :
|
||||
@[simp] theorem mapIdx_eq_singleton_iff {xs : Vector α 1} {f : Nat → α → β} {b : β} :
|
||||
mapIdx f xs = #v[b] ↔ ∃ (a : α), xs = #v[a] ∧ f 0 a = b := by
|
||||
rcases xs with ⟨xs⟩
|
||||
simp
|
||||
|
||||
theorem mapIdx_eq_append_iff {xs : Vector α (n + m)} {f : Nat → α → β} {ys : Vector β n} {zs : Vector β m} :
|
||||
|
||||
@@ -25,10 +25,10 @@ open Nat
|
||||
|
||||
/-! ## Monadic operations -/
|
||||
|
||||
theorem map_toArray_inj [Monad m] [LawfulMonad m]
|
||||
@[simp] theorem map_toArray_inj [Monad m] [LawfulMonad m]
|
||||
{xs : m (Vector α n)} {ys : m (Vector α n)} :
|
||||
toArray <$> xs = toArray <$> ys ↔ xs = ys := by
|
||||
simp
|
||||
toArray <$> xs = toArray <$> ys ↔ xs = ys :=
|
||||
_root_.map_inj_right (by simp)
|
||||
|
||||
/-! ### mapM -/
|
||||
|
||||
@@ -148,18 +148,12 @@ theorem forIn'_eq_foldlM [Monad m] [LawfulMonad m]
|
||||
rcases xs with ⟨xs, rfl⟩
|
||||
simp [Array.forIn'_pure_yield_eq_foldl, Array.foldl_map]
|
||||
|
||||
theorem idRun_forIn'_yield_eq_foldl
|
||||
{xs : Vector α n} (f : (a : α) → a ∈ xs → β → Id β) (init : β) :
|
||||
(forIn' xs init (fun a m b => .yield <$> f a m b)).run =
|
||||
xs.attach.foldl (fun b ⟨a, h⟩ => f a h b |>.run) init := by
|
||||
simp
|
||||
|
||||
@[deprecated forIn'_yield_eq_foldl (since := "2025-05-21")]
|
||||
theorem forIn'_yield_eq_foldl
|
||||
@[simp] theorem forIn'_yield_eq_foldl
|
||||
{xs : Vector α n} (f : (a : α) → a ∈ xs → β → β) (init : β) :
|
||||
forIn' (m := Id) xs init (fun a m b => .yield (f a m b)) =
|
||||
xs.attach.foldl (fun b ⟨a, h⟩ => f a h b) init :=
|
||||
forIn'_pure_yield_eq_foldl _ _
|
||||
xs.attach.foldl (fun b ⟨a, h⟩ => f a h b) init := by
|
||||
rcases xs with ⟨xs, rfl⟩
|
||||
simp [List.foldl_map]
|
||||
|
||||
@[simp] theorem forIn'_map [Monad m] [LawfulMonad m]
|
||||
{xs : Vector α n} (g : α → β) (f : (b : β) → b ∈ xs.map g → γ → m (ForInStep γ)) :
|
||||
@@ -196,18 +190,12 @@ theorem forIn_eq_foldlM [Monad m] [LawfulMonad m]
|
||||
rcases xs with ⟨xs, rfl⟩
|
||||
simp [Array.forIn_pure_yield_eq_foldl, Array.foldl_map]
|
||||
|
||||
theorem idRun_forIn_yield_eq_foldl
|
||||
{xs : Vector α n} (f : α → β → Id β) (init : β) :
|
||||
(forIn xs init (fun a b => .yield <$> f a b)).run =
|
||||
xs.foldl (fun b a => f a b |>.run) init := by
|
||||
simp
|
||||
|
||||
@[deprecated idRun_forIn_yield_eq_foldl (since := "2025-05-21")]
|
||||
theorem forIn_yield_eq_foldl
|
||||
@[simp] theorem forIn_yield_eq_foldl
|
||||
{xs : Vector α n} (f : α → β → β) (init : β) :
|
||||
forIn (m := Id) xs init (fun a b => .yield (f a b)) =
|
||||
xs.foldl (fun b a => f a b) init :=
|
||||
forIn_pure_yield_eq_foldl _ _
|
||||
xs.foldl (fun b a => f a b) init := by
|
||||
rcases xs with ⟨xs, rfl⟩
|
||||
simp
|
||||
|
||||
@[simp] theorem forIn_map [Monad m] [LawfulMonad m]
|
||||
{xs : Vector α n} (g : α → β) (f : β → γ → m (ForInStep γ)) :
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user