mirror of
https://github.com/leanprover/lean4.git
synced 2026-03-31 09:14:11 +00:00
Compare commits
89 Commits
grind_chor
...
grind_etaS
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9b9a031ff7 | ||
|
|
bf08a49608 | ||
|
|
19eee3bf3f | ||
|
|
bfc364cf67 | ||
|
|
076bace223 | ||
|
|
1d90eac631 | ||
|
|
92b59ae4f6 | ||
|
|
aa3e7848c2 | ||
|
|
e0a266780b | ||
|
|
2299c3c9ec | ||
|
|
2cf3ac9461 | ||
|
|
384c78ae13 | ||
|
|
a6a2833c68 | ||
|
|
b04ecaefd7 | ||
|
|
e575736cae | ||
|
|
8eec1e4cfb | ||
|
|
9659469998 | ||
|
|
efcf94298a | ||
|
|
f75e36dcdb | ||
|
|
aa647f3cd6 | ||
|
|
77302b6572 | ||
|
|
29cc75531a | ||
|
|
a08d182359 | ||
|
|
ef77434a49 | ||
|
|
aa54390c85 | ||
|
|
579d0ad15d | ||
|
|
e212890dfc | ||
|
|
1aa16f1e3c | ||
|
|
cc80f7943d | ||
|
|
c55bf5172d | ||
|
|
3f75f08e1d | ||
|
|
eda467e066 | ||
|
|
ab5b8ffed1 | ||
|
|
7f6f4c889d | ||
|
|
294360518a | ||
|
|
c7acb7e481 | ||
|
|
9105c01757 | ||
|
|
d0c4d19270 | ||
|
|
60ea92fdb0 | ||
|
|
2b4f372317 | ||
|
|
10bda559f9 | ||
|
|
33aaabaed7 | ||
|
|
dc1a70fa43 | ||
|
|
ca73223d4c | ||
|
|
1f85fd2db8 | ||
|
|
e681855428 | ||
|
|
9096eb168d | ||
|
|
575b4786f9 | ||
|
|
ddf5512c9a | ||
|
|
eabde77d84 | ||
|
|
5df7770977 | ||
|
|
0e49576fe4 | ||
|
|
33afaa061e | ||
|
|
1db53b39c4 | ||
|
|
836d7b703a | ||
|
|
732471fddf | ||
|
|
02cbe4969f | ||
|
|
e602bdc80c | ||
|
|
529fb5c67f | ||
|
|
edcad9a14b | ||
|
|
cd100b8832 | ||
|
|
c96dfa54a4 | ||
|
|
898eec78cd | ||
|
|
65b37b40ff | ||
|
|
af51e3e4b1 | ||
|
|
9c7cb147b9 | ||
|
|
9576e48e1a | ||
|
|
77b9e510fc | ||
|
|
cdb18f48cd | ||
|
|
208ff3e2b3 | ||
|
|
ef603cf37d | ||
|
|
8cc4505bb1 | ||
|
|
70917fac9f | ||
|
|
132c608ebc | ||
|
|
d005a306f9 | ||
|
|
80349ac77b | ||
|
|
6e2e1a4f89 | ||
|
|
afab374305 | ||
|
|
bc1d30de38 | ||
|
|
14d647f219 | ||
|
|
daf7a579ed | ||
|
|
9f48af3edd | ||
|
|
63cf1052f4 | ||
|
|
0fd516a1df | ||
|
|
34d944c4a9 | ||
|
|
7f4f6b3457 | ||
|
|
43e8288e3f | ||
|
|
d26d7973ad | ||
|
|
1143b4766c |
@@ -5,7 +5,7 @@ option(USE_MIMALLOC "use mimalloc" ON)
|
||||
# store all variables passed on the command line into CL_ARGS so we can pass them to the stage builds
|
||||
# https://stackoverflow.com/a/48555098/161659
|
||||
# MUST be done before call to 'project'
|
||||
# Use standard release build (discarding LEAN_CXX_EXTRA_FLAGS etc.) for stage0 by default since it is assumed to be "good", but still pass through CMake platform arguments (compiler, toolchain file, ..).
|
||||
# Use standard release build (discarding LEAN_EXTRA_CXX_FLAGS etc.) for stage0 by default since it is assumed to be "good", but still pass through CMake platform arguments (compiler, toolchain file, ..).
|
||||
# Use `STAGE0_` prefix to pass variables to stage0 explicitly.
|
||||
get_cmake_property(vars CACHE_VARIABLES)
|
||||
foreach(var ${vars})
|
||||
@@ -39,10 +39,14 @@ endif()
|
||||
|
||||
# Don't do anything with cadical on wasm
|
||||
if (NOT ${CMAKE_SYSTEM_NAME} MATCHES "Emscripten")
|
||||
# On CI Linux, we source cadical from Nix instead; see flake.nix
|
||||
find_program(CADICAL cadical)
|
||||
if(NOT CADICAL)
|
||||
set(CADICAL_CXX c++)
|
||||
if (CADICAL_USE_CUSTOM_CXX)
|
||||
set(CADICAL_CXX ${CMAKE_CXX_COMPILER})
|
||||
set(CADICAL_CXXFLAGS "${LEAN_EXTRA_CXX_FLAGS}")
|
||||
set(CADICAL_LDFLAGS "-Wl,-rpath=\\$$ORIGIN/../lib")
|
||||
endif()
|
||||
find_program(CCACHE ccache)
|
||||
if(CCACHE)
|
||||
set(CADICAL_CXX "${CCACHE} ${CADICAL_CXX}")
|
||||
@@ -57,8 +61,11 @@ if (NOT ${CMAKE_SYSTEM_NAME} MATCHES "Emscripten")
|
||||
GIT_REPOSITORY https://github.com/arminbiere/cadical
|
||||
GIT_TAG rel-2.1.2
|
||||
CONFIGURE_COMMAND ""
|
||||
# https://github.com/arminbiere/cadical/blob/master/BUILD.md#manual-build
|
||||
BUILD_COMMAND $(MAKE) -f ${CMAKE_SOURCE_DIR}/src/cadical.mk CMAKE_EXECUTABLE_SUFFIX=${CMAKE_EXECUTABLE_SUFFIX} CXX=${CADICAL_CXX} CXXFLAGS=${CADICAL_CXXFLAGS}
|
||||
BUILD_COMMAND $(MAKE) -f ${CMAKE_SOURCE_DIR}/src/cadical.mk
|
||||
CMAKE_EXECUTABLE_SUFFIX=${CMAKE_EXECUTABLE_SUFFIX}
|
||||
CXX=${CADICAL_CXX}
|
||||
CXXFLAGS=${CADICAL_CXXFLAGS}
|
||||
LDFLAGS=${CADICAL_LDFLAGS}
|
||||
BUILD_IN_SOURCE ON
|
||||
INSTALL_COMMAND "")
|
||||
set(CADICAL ${CMAKE_BINARY_DIR}/cadical/cadical${CMAKE_EXECUTABLE_SUFFIX} CACHE FILEPATH "path to cadical binary" FORCE)
|
||||
|
||||
@@ -7,8 +7,9 @@
|
||||
/.github/ @kim-em
|
||||
/RELEASES.md @kim-em
|
||||
/src/kernel/ @leodemoura
|
||||
/src/library/compiler/ @zwarich
|
||||
/src/lake/ @tydeu
|
||||
/src/Lean/Compiler/ @leodemoura
|
||||
/src/Lean/Compiler/ @leodemoura @zwarich
|
||||
/src/Lean/Data/Lsp/ @mhuisi
|
||||
/src/Lean/Elab/Deriving/ @kim-em
|
||||
/src/Lean/Elab/Tactic/ @kim-em
|
||||
|
||||
@@ -144,6 +144,10 @@ We'll use `v4.7.0-rc1` as the intended release version in this example.
|
||||
- Run `script/release_steps.py v4.7.0-rc1 <repo>` (e.g. replacing `<repo>` with `batteries`), which will walk you through the following steps:
|
||||
- Create a new branch off `master`/`main` (as specified in the `branch` field), called `bump_to_v4.7.0-rc1`.
|
||||
- Merge `origin/bump/v4.7.0` if relevant (i.e. `bump-branch: true` appears in `release_repos.yml`).
|
||||
- Otherwise, you *may* need to merge `origin/nightly-testing`.
|
||||
- Note that for `verso` and `reference-manual` development happens on `nightly-testing`, so
|
||||
we will merge that branch into `bump_to_v4.7.0-rc1`, but it is essential in the GitHub interface that we do a rebase merge,
|
||||
in order to preserve the history.
|
||||
- Update the contents of `lean-toolchain` to `leanprover/lean4:v4.7.0-rc1`.
|
||||
- In the `lakefile.toml` or `lakefile.lean`, if there are dependencies on `nightly-testing`, `bump/v4.7.0`, or specific version tags, update them to the new tag.
|
||||
If they depend on `main` or `master`, don't change this; you've just updated the dependency, so `lake update` will take care of modifying the manifest.
|
||||
@@ -151,7 +155,7 @@ We'll use `v4.7.0-rc1` as the intended release version in this example.
|
||||
- Run `lake build && if lake check-test; then lake test; fi` to check things are working.
|
||||
- Commit the changes as `chore: bump toolchain to v4.7.0-rc1` and push.
|
||||
- Create a PR with title "chore: bump toolchain to v4.7.0-rc1".
|
||||
- Merge the PR once CI completes.
|
||||
- Merge the PR once CI completes. (Recall: for `verso` and `reference-manual` you will need to do a rebase merge.)
|
||||
- Re-running `script/release_checklist.py` will then create the tag `v4.7.0-rc1` from `master`/`main` and push it (unless `toolchain-tag: false` in the `release_repos.yml` file)
|
||||
- We do this for the same list of repositories as for stable releases, see above for notes about special cases.
|
||||
As above, there are dependencies between these, and so the process above is iterative.
|
||||
|
||||
1146
doc/style.md
Normal file
1146
doc/style.md
Normal file
File diff suppressed because it is too large
Load Diff
@@ -47,10 +47,10 @@ def run_command(command, check=True, capture_output=True):
|
||||
|
||||
|
||||
def clone_repo(repo, temp_dir):
|
||||
"""Clone the repository to a temporary directory using shallow clone."""
|
||||
print(f"Shallow cloning {repo}...")
|
||||
# Keep the shallow clone for efficiency
|
||||
clone_result = run_command(f"gh repo clone {repo} {temp_dir} -- --depth=1", check=False)
|
||||
"""Clone the repository to a temporary directory."""
|
||||
print(f"Cloning {repo}...")
|
||||
# Remove shallow clone for better merge detection
|
||||
clone_result = run_command(f"gh repo clone {repo} {temp_dir}", check=False)
|
||||
if clone_result.returncode != 0:
|
||||
print(f"Failed to clone repository {repo}.")
|
||||
print(f"Error: {clone_result.stderr}")
|
||||
@@ -95,26 +95,16 @@ def check_and_merge(repo, branch, tag, temp_dir):
|
||||
if checkout_result.returncode != 0:
|
||||
return False
|
||||
|
||||
# Try merging the tag in a dry-run to check if it can be merged cleanly
|
||||
print(f"Checking if {tag} can be merged cleanly into {branch}...")
|
||||
merge_check = run_command(f"git merge --no-commit --no-ff {tag}", check=False)
|
||||
# Try merging the tag directly
|
||||
print(f"Merging {tag} into {branch}...")
|
||||
merge_result = run_command(f"git merge {tag} --no-edit", check=False)
|
||||
|
||||
if merge_check.returncode != 0:
|
||||
if merge_result.returncode != 0:
|
||||
print(f"Cannot merge {tag} cleanly into {branch}.")
|
||||
print("Merge conflicts would occur. Aborting merge.")
|
||||
run_command("git merge --abort")
|
||||
return False
|
||||
|
||||
# Abort the test merge
|
||||
run_command("git reset --hard HEAD")
|
||||
|
||||
# Now perform the actual merge and push to remote
|
||||
print(f"Merging {tag} into {branch}...")
|
||||
merge_result = run_command(f"git merge {tag} --no-edit")
|
||||
if merge_result.returncode != 0:
|
||||
print(f"Failed to merge {tag} into {branch}.")
|
||||
return False
|
||||
|
||||
print(f"Pushing changes to remote...")
|
||||
push_result = run_command(f"git push origin {branch}")
|
||||
if push_result.returncode != 0:
|
||||
|
||||
@@ -55,7 +55,8 @@ $CP $GLIBC/lib/libc_nonshared.a stage1/lib/glibc
|
||||
$CP $GLIBC/lib/libpthread_nonshared.a stage1/lib/glibc
|
||||
for f in $GLIBC/lib/{ld,lib{c,dl,m,rt,pthread}}-*; do b=$(basename $f); cp $f stage1/lib/glibc/${b%-*}.so; done
|
||||
OPTIONS=()
|
||||
echo -n " -DLEAN_STANDALONE=ON"
|
||||
# We build cadical using the custom toolchain on Linux to avoid glibc versioning issues
|
||||
echo -n " -DLEAN_STANDALONE=ON -DCADICAL_USE_CUSTOM_CXX=ON"
|
||||
echo -n " -DCMAKE_CXX_COMPILER=$PWD/llvm-host/bin/clang++ -DLEAN_CXX_STDLIB='-Wl,-Bstatic -lc++ -lc++abi -Wl,-Bdynamic'"
|
||||
echo -n " -DLEAN_EXTRA_CXX_FLAGS='--sysroot $PWD/llvm -idirafter $GLIBC_DEV/include ${EXTRA_FLAGS:-}'"
|
||||
# use target compiler directly when not cross-compiling
|
||||
@@ -67,8 +68,9 @@ fi
|
||||
# use `-nostdinc` to make sure headers are not visible by default (in particular, not to `#include_next` in the clang headers),
|
||||
# but do not change sysroot so users can still link against system libs
|
||||
echo -n " -DLEANC_INTERNAL_FLAGS='--sysroot ROOT -nostdinc -isystem ROOT/include/clang' -DLEANC_CC=ROOT/bin/clang"
|
||||
# ld.so is usually included by the libc.so linker script but we discard those
|
||||
echo -n " -DLEANC_INTERNAL_LINKER_FLAGS='--sysroot ROOT -L ROOT/lib -L ROOT/lib/glibc ROOT/lib/glibc/libc_nonshared.a ROOT/lib/glibc/libpthread_nonshared.a -Wl,--as-needed -Wl,-Bstatic -lgmp -lunwind -luv -Wl,-Bdynamic ROOT/lib/glibc/ld.so -Wl,--no-as-needed -fuse-ld=lld'"
|
||||
# ld.so is usually included by the libc.so linker script but we discard those. Make sure it is linked to only after `libc.so` like in the original
|
||||
# linker script so that no libc symbols are bound to it instead.
|
||||
echo -n " -DLEANC_INTERNAL_LINKER_FLAGS='--sysroot ROOT -L ROOT/lib -L ROOT/lib/glibc -lc -lc_nonshared -Wl,--as-needed -l:ld.so -Wl,--no-as-needed -lpthread_nonshared -Wl,--as-needed -Wl,-Bstatic -lgmp -lunwind -luv -Wl,-Bdynamic -Wl,--no-as-needed -fuse-ld=lld'"
|
||||
# when not using the above flags, link GMP dynamically/as usual
|
||||
echo -n " -DLEAN_EXTRA_LINKER_FLAGS='-Wl,--as-needed -lgmp -luv -lpthread -ldl -lrt -Wl,--no-as-needed'"
|
||||
# do not set `LEAN_CC` for tests
|
||||
|
||||
@@ -7,6 +7,7 @@ import base64
|
||||
import subprocess
|
||||
import sys
|
||||
import os
|
||||
import re # Import re module
|
||||
# Import run_command from merge_remote.py
|
||||
from merge_remote import run_command
|
||||
|
||||
@@ -58,13 +59,29 @@ def release_page_exists(repo_url, tag_name, github_token):
|
||||
response = requests.get(api_url, headers=headers)
|
||||
return response.status_code == 200
|
||||
|
||||
def get_release_notes(repo_url, tag_name, github_token):
|
||||
api_url = repo_url.replace("https://github.com/", "https://api.github.com/repos/") + f"/releases/tags/{tag_name}"
|
||||
headers = {'Authorization': f'token {github_token}'} if github_token else {}
|
||||
response = requests.get(api_url, headers=headers)
|
||||
if response.status_code == 200:
|
||||
return response.json().get("body", "").strip()
|
||||
return None
|
||||
def get_release_notes(tag_name):
|
||||
"""Fetch release notes page title from lean-lang.org."""
|
||||
# Strip -rcX suffix if present for the URL
|
||||
base_tag = tag_name.split('-')[0]
|
||||
reference_url = f"https://lean-lang.org/doc/reference/latest/releases/{base_tag}/"
|
||||
try:
|
||||
response = requests.get(reference_url)
|
||||
response.raise_for_status() # Raise HTTPError for bad responses (4xx or 5xx)
|
||||
|
||||
# Extract title using regex
|
||||
match = re.search(r"<title>(.*?)</title>", response.text, re.IGNORECASE | re.DOTALL)
|
||||
if match:
|
||||
return match.group(1).strip()
|
||||
else:
|
||||
print(f" ⚠️ Could not find <title> tag in {reference_url}")
|
||||
return None
|
||||
|
||||
except requests.exceptions.RequestException as e:
|
||||
print(f" ❌ Error fetching release notes from {reference_url}: {e}")
|
||||
return None
|
||||
except Exception as e:
|
||||
print(f" ❌ An unexpected error occurred while processing release notes: {e}")
|
||||
return None
|
||||
|
||||
def get_branch_content(repo_url, branch, file_path, github_token):
|
||||
api_url = repo_url.replace("https://github.com/", "https://api.github.com/repos/") + f"/contents/{file_path}?ref={branch}"
|
||||
@@ -255,6 +272,7 @@ def main():
|
||||
branch_name = f"releases/v{version_major}.{version_minor}.0"
|
||||
if not branch_exists(lean_repo_url, branch_name, github_token):
|
||||
print(f" ❌ Branch {branch_name} does not exist")
|
||||
print(f" 🟡 After creating the branch, we'll need to check CMake version settings.")
|
||||
lean4_success = False
|
||||
else:
|
||||
print(f" ✅ Branch {branch_name} exists")
|
||||
@@ -274,14 +292,22 @@ def main():
|
||||
lean4_success = False
|
||||
else:
|
||||
print(f" ✅ Release page for {toolchain} exists")
|
||||
release_notes = get_release_notes(lean_repo_url, toolchain, github_token)
|
||||
if not (release_notes and toolchain in release_notes.splitlines()[0].strip()):
|
||||
previous_minor_version = version_minor - 1
|
||||
previous_release = f"v{version_major}.{previous_minor_version}.0"
|
||||
print(f" ❌ Release notes not published. Please run `script/release_notes.py --since {previous_release}` on branch `{branch_name}`.")
|
||||
lean4_success = False
|
||||
else:
|
||||
print(f" ✅ Release notes look good.")
|
||||
|
||||
# Check the actual release notes page title
|
||||
actual_title = get_release_notes(toolchain)
|
||||
expected_title_prefix = f"Lean {toolchain.lstrip('v')}" # e.g., "Lean 4.19.0" or "Lean 4.19.0-rc1"
|
||||
|
||||
if actual_title is None:
|
||||
# Error already printed by get_release_notes
|
||||
lean4_success = False
|
||||
elif not actual_title.startswith(expected_title_prefix):
|
||||
# Construct URL for the error message (using the base tag)
|
||||
base_tag = toolchain.split('-')[0]
|
||||
check_url = f"https://lean-lang.org/doc/reference/latest/releases/{base_tag}/"
|
||||
print(f" ❌ Release notes page title mismatch. Expected prefix '{expected_title_prefix}', got '{actual_title}'. Check {check_url}")
|
||||
lean4_success = False
|
||||
else:
|
||||
print(f" ✅ Release notes page title looks good ('{actual_title}').")
|
||||
|
||||
repo_status["lean4"] = lean4_success
|
||||
|
||||
@@ -360,10 +386,24 @@ def main():
|
||||
if check_stable and not is_release_candidate(toolchain):
|
||||
if not is_merged_into_stable(url, toolchain, "stable", github_token, verbose):
|
||||
org_repo = extract_org_repo_from_url(url)
|
||||
print(f" ❌ Tag {toolchain} is not merged into stable")
|
||||
print(f" Run `script/merge_remote.py {org_repo} stable {toolchain}` to merge it")
|
||||
repo_status[name] = False
|
||||
continue
|
||||
if args.dry_run:
|
||||
print(f" ❌ Tag {toolchain} is not merged into stable")
|
||||
print(f" Run `script/merge_remote.py {org_repo} stable {toolchain}` to merge it")
|
||||
repo_status[name] = False
|
||||
continue
|
||||
else:
|
||||
print(f" … Tag {toolchain} is not merged into stable. Running `script/merge_remote.py {org_repo} stable {toolchain}`...")
|
||||
|
||||
# Run the script to merge the tag
|
||||
subprocess.run(["script/merge_remote.py", org_repo, "stable", toolchain])
|
||||
|
||||
# Check again if the tag is merged now
|
||||
if not is_merged_into_stable(url, toolchain, "stable", github_token, verbose):
|
||||
print(f" ❌ Manual intervention required.")
|
||||
repo_status[name] = False
|
||||
continue
|
||||
|
||||
# This will print in all successful cases - whether tag was merged initially or was merged successfully
|
||||
print(f" ✅ Tag {toolchain} is merged into stable")
|
||||
|
||||
if check_bump:
|
||||
|
||||
@@ -21,12 +21,19 @@ repositories:
|
||||
branch: master
|
||||
dependencies: []
|
||||
|
||||
- name: lean4-cli
|
||||
url: https://github.com/leanprover/lean4-cli
|
||||
toolchain-tag: true
|
||||
stable-branch: false
|
||||
branch: main
|
||||
dependencies: []
|
||||
|
||||
- name: doc-gen4
|
||||
url: https://github.com/leanprover/doc-gen4
|
||||
toolchain-tag: true
|
||||
stable-branch: false
|
||||
branch: main
|
||||
dependencies: []
|
||||
dependencies: [lean4-cli]
|
||||
|
||||
- name: verso
|
||||
url: https://github.com/leanprover/verso
|
||||
@@ -42,20 +49,13 @@ repositories:
|
||||
branch: main
|
||||
dependencies: [verso]
|
||||
|
||||
- name: lean4-cli
|
||||
url: https://github.com/leanprover/lean4-cli
|
||||
toolchain-tag: true
|
||||
stable-branch: false
|
||||
branch: main
|
||||
dependencies: []
|
||||
|
||||
- name: ProofWidgets4
|
||||
url: https://github.com/leanprover-community/ProofWidgets4
|
||||
toolchain-tag: false
|
||||
stable-branch: false
|
||||
branch: main
|
||||
dependencies:
|
||||
- Batteries
|
||||
- batteries
|
||||
|
||||
- name: aesop
|
||||
url: https://github.com/leanprover-community/aesop
|
||||
@@ -63,7 +63,7 @@ repositories:
|
||||
stable-branch: true
|
||||
branch: master
|
||||
dependencies:
|
||||
- Batteries
|
||||
- batteries
|
||||
|
||||
- name: import-graph
|
||||
url: https://github.com/leanprover-community/import-graph
|
||||
@@ -71,8 +71,8 @@ repositories:
|
||||
stable-branch: false
|
||||
branch: main
|
||||
dependencies:
|
||||
- Cli
|
||||
- Batteries
|
||||
- lean4-cli
|
||||
- batteries
|
||||
|
||||
- name: plausible
|
||||
url: https://github.com/leanprover-community/plausible
|
||||
@@ -88,10 +88,11 @@ repositories:
|
||||
branch: master
|
||||
bump-branch: true
|
||||
dependencies:
|
||||
- Aesop
|
||||
- aesop
|
||||
- ProofWidgets4
|
||||
- lean4checker
|
||||
- Batteries
|
||||
- batteries
|
||||
- lean4-cli
|
||||
- doc-gen4
|
||||
- import-graph
|
||||
- plausible
|
||||
@@ -102,4 +103,4 @@ repositories:
|
||||
stable-branch: true
|
||||
branch: master
|
||||
dependencies:
|
||||
- Mathlib
|
||||
- mathlib4
|
||||
|
||||
@@ -68,7 +68,7 @@ def generate_script(repo, version, config):
|
||||
]
|
||||
|
||||
# Special cases for specific repositories
|
||||
if repo_name == "REPL":
|
||||
if repo_name == "repl":
|
||||
script_lines.extend([
|
||||
"lake update",
|
||||
"cd test/Mathlib",
|
||||
@@ -79,7 +79,7 @@ def generate_script(repo, version, config):
|
||||
"./test.sh"
|
||||
])
|
||||
elif dependencies:
|
||||
script_lines.append('echo "Please update the dependencies in lakefile.{lean,toml}"')
|
||||
script_lines.append('perl -pi -e \'s/"v4\\.[0-9]+(\\.[0-9]+)?(-rc[0-9]+)?"/"' + version + '"/g\' lakefile.*')
|
||||
script_lines.append("lake update")
|
||||
|
||||
script_lines.append("")
|
||||
@@ -89,13 +89,20 @@ def generate_script(repo, version, config):
|
||||
""
|
||||
])
|
||||
|
||||
if re.search(r'rc\d+$', version) and repo_name in ["Batteries", "Mathlib"]:
|
||||
if re.search(r'rc\d+$', version) and repo_name in ["batteries", "mathlib4"]:
|
||||
script_lines.extend([
|
||||
"echo 'This repo has nightly-testing infrastructure'",
|
||||
f"git merge origin/bump/{version.split('-rc')[0]}",
|
||||
"echo 'Please resolve any conflicts.'",
|
||||
""
|
||||
])
|
||||
if re.search(r'rc\d+$', version) and repo_name in ["verso", "reference-manual"]:
|
||||
script_lines.extend([
|
||||
"echo 'This repo does development on nightly-testing: remember to rebase merge the PR.'",
|
||||
f"git merge origin/nightly-testing",
|
||||
"echo 'Please resolve any conflicts.'",
|
||||
""
|
||||
])
|
||||
if repo_name != "Mathlib":
|
||||
script_lines.extend([
|
||||
"lake build && if lake check-test; then lake test; fi",
|
||||
@@ -104,7 +111,7 @@ def generate_script(repo, version, config):
|
||||
|
||||
script_lines.extend([
|
||||
'gh pr create --title "chore: bump toolchain to ' + version + '" --body ""',
|
||||
"echo 'Please review the PR and merge it.'",
|
||||
"echo 'Please review the PR and merge or rebase it.'",
|
||||
""
|
||||
])
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ endif()
|
||||
include(ExternalProject)
|
||||
project(LEAN CXX C)
|
||||
set(LEAN_VERSION_MAJOR 4)
|
||||
set(LEAN_VERSION_MINOR 20)
|
||||
set(LEAN_VERSION_MINOR 21)
|
||||
set(LEAN_VERSION_PATCH 0)
|
||||
set(LEAN_VERSION_IS_RELEASE 0) # This number is 1 in the release revision, and 0 otherwise.
|
||||
set(LEAN_SPECIAL_VERSION_DESC "" CACHE STRING "Additional version description like 'nightly-2018-03-11'")
|
||||
@@ -511,7 +511,10 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "Windows")
|
||||
# import libraries created by the stdlib.make targets
|
||||
string(APPEND LEANC_SHARED_LINKER_FLAGS " -lInit_shared -lleanshared_1 -lleanshared")
|
||||
elseif("${CMAKE_SYSTEM_NAME}" MATCHES "Darwin")
|
||||
string(APPEND LEANC_SHARED_LINKER_FLAGS " -Wl,-undefined,dynamic_lookup")
|
||||
# The second flag is necessary to even *load* dylibs without resolved symbols, as can happen
|
||||
# if a Lake `extern_lib` depends on a symbols defined by the Lean library but is loaded even
|
||||
# before definition.
|
||||
string(APPEND LEANC_SHARED_LINKER_FLAGS " -Wl,-undefined,dynamic_lookup -Wl,-no_fixup_chains")
|
||||
endif()
|
||||
# Linux ignores undefined symbols in shared libraries by default
|
||||
|
||||
|
||||
@@ -42,24 +42,3 @@ theorem apply_ite (f : α → β) (P : Prop) [Decidable P] (x y : α) :
|
||||
/-- A `dite` whose results do not actually depend on the condition may be reduced to an `ite`. -/
|
||||
@[simp] theorem dite_eq_ite [Decidable P] :
|
||||
(dite P (fun _ => a) (fun _ => b)) = ite P a b := rfl
|
||||
|
||||
@[deprecated "Use `ite_eq_right_iff`" (since := "2024-09-18")]
|
||||
theorem ite_some_none_eq_none [Decidable P] :
|
||||
(if P then some x else none) = none ↔ ¬ P := by
|
||||
simp only [ite_eq_right_iff, reduceCtorEq]
|
||||
rfl
|
||||
|
||||
@[deprecated "Use `Option.ite_none_right_eq_some`" (since := "2024-09-18")]
|
||||
theorem ite_some_none_eq_some [Decidable P] :
|
||||
(if P then some x else none) = some y ↔ P ∧ x = y := by
|
||||
split <;> simp_all
|
||||
|
||||
@[deprecated "Use `dite_eq_right_iff" (since := "2024-09-18")]
|
||||
theorem dite_some_none_eq_none [Decidable P] {x : P → α} :
|
||||
(if h : P then some (x h) else none) = none ↔ ¬P := by
|
||||
simp
|
||||
|
||||
@[deprecated "Use `Option.dite_none_right_eq_some`" (since := "2024-09-18")]
|
||||
theorem dite_some_none_eq_some [Decidable P] {x : P → α} {y : α} :
|
||||
(if h : P then some (x h) else none) = some y ↔ ∃ h : P, x h = y := by
|
||||
by_cases h : P <;> simp [h]
|
||||
|
||||
@@ -51,6 +51,9 @@ theorem Function.comp_def {α β δ} (f : β → δ) (g : α → β) : f ∘ g =
|
||||
@[simp] theorem Function.false_comp {f : α → β} : ((fun _ => false) ∘ f) = fun _ => false := by
|
||||
rfl
|
||||
|
||||
@[simp] theorem Function.comp_id (f : α → β) : f ∘ id = f := rfl
|
||||
@[simp] theorem Function.id_comp (f : α → β) : id ∘ f = f := rfl
|
||||
|
||||
attribute [simp] namedPattern
|
||||
|
||||
/--
|
||||
@@ -2524,9 +2527,6 @@ class Antisymm (r : α → α → Prop) : Prop where
|
||||
/-- An antisymmetric relation `r` satisfies `r a b → r b a → a = b`. -/
|
||||
antisymm (a b : α) : r a b → r b a → a = b
|
||||
|
||||
@[deprecated Antisymm (since := "2024-10-16"), inherit_doc Antisymm]
|
||||
abbrev _root_.Antisymm (r : α → α → Prop) : Prop := Std.Antisymm r
|
||||
|
||||
/-- `Asymm X r` means that the binary relation `r` on `X` is asymmetric, that is,
|
||||
`r a b → ¬ r b a`. -/
|
||||
class Asymm (r : α → α → Prop) : Prop where
|
||||
|
||||
@@ -56,15 +56,15 @@ well-founded recursion mechanism to prove that the function terminates.
|
||||
-/
|
||||
@[inline] def attach (xs : Array α) : Array {x // x ∈ xs} := xs.attachWith _ fun _ => id
|
||||
|
||||
@[simp] theorem _root_.List.attachWith_toArray {l : List α} {P : α → Prop} {H : ∀ x ∈ l.toArray, P x} :
|
||||
@[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
|
||||
simp [attachWith]
|
||||
|
||||
@[simp] theorem _root_.List.attach_toArray {l : List α} :
|
||||
@[simp, grind =] theorem _root_.List.attach_toArray {l : List α} :
|
||||
l.toArray.attach = (l.attachWith (· ∈ l.toArray) (by simp)).toArray := by
|
||||
simp [attach]
|
||||
|
||||
@[simp] theorem _root_.List.pmap_toArray {l : List α} {P : α → Prop} {f : ∀ a, P a → β} {H : ∀ a ∈ l.toArray, P a} :
|
||||
@[simp, grind =] theorem _root_.List.pmap_toArray {l : List α} {P : α → Prop} {f : ∀ a, P a → β} {H : ∀ a ∈ l.toArray, P a} :
|
||||
l.toArray.pmap f H = (l.pmap f (by simpa using H)).toArray := by
|
||||
simp [pmap]
|
||||
|
||||
@@ -590,7 +590,7 @@ def unattach {α : Type _} {p : α → Prop} (xs : Array { x // p x }) : Array
|
||||
unfold unattach
|
||||
simp
|
||||
|
||||
@[simp] theorem _root_.List.unattach_toArray {p : α → Prop} {xs : List { x // p x }} :
|
||||
@[simp, grind =] theorem _root_.List.unattach_toArray {p : α → Prop} {xs : List { x // p x }} :
|
||||
xs.toArray.unattach = xs.unattach.toArray := by
|
||||
simp only [unattach, List.map_toArray, List.unattach]
|
||||
|
||||
|
||||
@@ -36,8 +36,6 @@ variable {α : Type u}
|
||||
|
||||
namespace Array
|
||||
|
||||
@[deprecated toList (since := "2024-09-10")] abbrev data := @toList
|
||||
|
||||
/-! ### Preliminary theorems -/
|
||||
|
||||
@[simp, grind] theorem size_set {xs : Array α} {i : Nat} {v : α} (h : i < xs.size) :
|
||||
@@ -88,11 +86,11 @@ theorem ext' {xs ys : Array α} (h : xs.toList = ys.toList) : xs = ys := by
|
||||
@[simp] theorem toArrayAux_eq {as : List α} {acc : Array α} : (as.toArrayAux acc).toList = acc.toList ++ as := by
|
||||
induction as generalizing acc <;> simp [*, List.toArrayAux, Array.push, List.append_assoc, List.concat_eq_append]
|
||||
|
||||
@[simp] theorem toArray_toList {xs : Array α} : xs.toList.toArray = xs := rfl
|
||||
@[simp, grind =] theorem toArray_toList {xs : Array α} : xs.toList.toArray = xs := rfl
|
||||
|
||||
@[simp] 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} (h : i < xs.size) : xs.toList[i] = xs[i] := rfl
|
||||
|
||||
@[simp] theorem getElem?_toList {xs : Array α} {i : Nat} : xs.toList[i]? = xs[i]? := by
|
||||
@[simp, grind =] theorem getElem?_toList {xs : Array α} {i : Nat} : xs.toList[i]? = xs[i]? := by
|
||||
simp [getElem?_def]
|
||||
|
||||
/-- `a ∈ as` is a predicate which asserts that `a` is in the array `as`. -/
|
||||
@@ -107,7 +105,7 @@ instance : Membership α (Array α) where
|
||||
theorem mem_def {a : α} {as : Array α} : a ∈ as ↔ a ∈ as.toList :=
|
||||
⟨fun | .mk h => h, Array.Mem.mk⟩
|
||||
|
||||
@[simp] theorem mem_toArray {a : α} {l : List α} : a ∈ l.toArray ↔ a ∈ l := by
|
||||
@[simp, grind =] theorem mem_toArray {a : α} {l : List α} : a ∈ l.toArray ↔ a ∈ l := by
|
||||
simp [mem_def]
|
||||
|
||||
@[simp, grind] theorem getElem_mem {xs : Array α} {i : Nat} (h : i < xs.size) : xs[i] ∈ xs := by
|
||||
@@ -127,18 +125,18 @@ theorem toList_toArray {as : List α} : as.toArray.toList = as := rfl
|
||||
@[deprecated toList_toArray (since := "2025-02-17")]
|
||||
abbrev _root_.Array.toList_toArray := @List.toList_toArray
|
||||
|
||||
@[simp] theorem size_toArray {as : List α} : as.toArray.size = as.length := by simp [Array.size]
|
||||
@[simp, grind] theorem size_toArray {as : List α} : as.toArray.size = as.length := by simp [Array.size]
|
||||
|
||||
@[deprecated size_toArray (since := "2025-02-17")]
|
||||
abbrev _root_.Array.size_toArray := @List.size_toArray
|
||||
|
||||
@[simp] theorem getElem_toArray {xs : List α} {i : Nat} (h : i < xs.toArray.size) :
|
||||
@[simp, grind =] theorem getElem_toArray {xs : List α} {i : Nat} (h : i < xs.toArray.size) :
|
||||
xs.toArray[i] = xs[i]'(by simpa using h) := rfl
|
||||
|
||||
@[simp] theorem getElem?_toArray {xs : List α} {i : Nat} : xs.toArray[i]? = xs[i]? := by
|
||||
@[simp, grind =] theorem getElem?_toArray {xs : List α} {i : Nat} : xs.toArray[i]? = xs[i]? := by
|
||||
simp [getElem?_def]
|
||||
|
||||
@[simp] theorem getElem!_toArray [Inhabited α] {xs : List α} {i : Nat} :
|
||||
@[simp, grind =] theorem getElem!_toArray [Inhabited α] {xs : List α} {i : Nat} :
|
||||
xs.toArray[i]! = xs[i]! := by
|
||||
simp [getElem!_def]
|
||||
|
||||
@@ -148,8 +146,6 @@ namespace Array
|
||||
|
||||
theorem size_eq_length_toList {xs : Array α} : xs.size = xs.toList.length := rfl
|
||||
|
||||
@[deprecated toList_toArray (since := "2024-09-09")] abbrev data_toArray := @List.toList_toArray
|
||||
|
||||
/-! ### Externs -/
|
||||
|
||||
/--
|
||||
@@ -1487,8 +1483,6 @@ The resulting arrays are appended.
|
||||
def flatMapM [Monad m] (f : α → m (Array β)) (as : Array α) : m (Array β) :=
|
||||
as.foldlM (init := empty) fun bs a => do return bs ++ (← f a)
|
||||
|
||||
@[deprecated flatMapM (since := "2024-10-16")] abbrev concatMapM := @flatMapM
|
||||
|
||||
/--
|
||||
Applies a function that returns an array to each element of an array. The resulting arrays are
|
||||
appended.
|
||||
@@ -1501,8 +1495,6 @@ Examples:
|
||||
def flatMap (f : α → Array β) (as : Array α) : Array β :=
|
||||
as.foldl (init := empty) fun bs a => bs ++ f a
|
||||
|
||||
@[deprecated flatMap (since := "2024-10-16")] abbrev concatMap := @flatMap
|
||||
|
||||
/--
|
||||
Appends the contents of array of arrays into a single array. The resulting array contains the same
|
||||
elements as the nested arrays in the same order.
|
||||
@@ -2158,13 +2150,15 @@ Examples:
|
||||
|
||||
/-! ### Repr and ToString -/
|
||||
|
||||
protected def Array.repr {α : Type u} [Repr α] (xs : Array α) : Std.Format :=
|
||||
let _ : Std.ToFormat α := ⟨repr⟩
|
||||
if xs.size == 0 then
|
||||
"#[]"
|
||||
else
|
||||
Std.Format.bracketFill "#[" (Std.Format.joinSep (toList xs) ("," ++ Std.Format.line)) "]"
|
||||
|
||||
instance {α : Type u} [Repr α] : Repr (Array α) where
|
||||
reprPrec xs _ :=
|
||||
let _ : Std.ToFormat α := ⟨repr⟩
|
||||
if xs.size == 0 then
|
||||
"#[]"
|
||||
else
|
||||
Std.Format.bracketFill "#[" (Std.Format.joinSep (toList xs) ("," ++ Std.Format.line)) "]"
|
||||
reprPrec xs _ := Array.repr xs
|
||||
|
||||
instance [ToString α] : ToString (Array α) where
|
||||
toString xs := "#" ++ toString xs.toList
|
||||
|
||||
@@ -55,12 +55,12 @@ theorem foldlM_toList.aux [Monad m]
|
||||
rfl
|
||||
· rw [List.drop_of_length_le (Nat.ge_of_not_lt ‹_›)]; rfl
|
||||
|
||||
@[simp] theorem foldlM_toList [Monad m]
|
||||
@[simp, grind =] theorem foldlM_toList [Monad m]
|
||||
{f : β → α → m β} {init : β} {xs : Array α} :
|
||||
xs.toList.foldlM f init = xs.foldlM f init := by
|
||||
simp [foldlM, foldlM_toList.aux]
|
||||
|
||||
@[simp] theorem foldl_toList (f : β → α → β) {init : β} {xs : Array α} :
|
||||
@[simp, grind =] theorem foldl_toList (f : β → α → β) {init : β} {xs : Array α} :
|
||||
xs.toList.foldl f init = xs.foldl f init :=
|
||||
List.foldl_eq_foldlM .. ▸ foldlM_toList ..
|
||||
|
||||
@@ -79,32 +79,32 @@ theorem foldrM_eq_reverse_foldlM_toList [Monad m] {f : α → β → m β} {init
|
||||
match xs, this with | _, .inl rfl => rfl | xs, .inr h => ?_
|
||||
simp [foldrM, h, ← foldrM_eq_reverse_foldlM_toList.aux, List.take_length]
|
||||
|
||||
@[simp] theorem foldrM_toList [Monad m]
|
||||
@[simp, grind =] theorem foldrM_toList [Monad m]
|
||||
{f : α → β → m β} {init : β} {xs : Array α} :
|
||||
xs.toList.foldrM f init = xs.foldrM f init := by
|
||||
rw [foldrM_eq_reverse_foldlM_toList, List.foldlM_reverse]
|
||||
|
||||
@[simp] theorem foldr_toList (f : α → β → β) {init : β} {xs : Array α} :
|
||||
@[simp, grind =] theorem foldr_toList (f : α → β → β) {init : β} {xs : Array α} :
|
||||
xs.toList.foldr f init = xs.foldr f init :=
|
||||
List.foldr_eq_foldrM .. ▸ foldrM_toList ..
|
||||
|
||||
@[simp] theorem push_toList {xs : Array α} {a : α} : (xs.push a).toList = xs.toList ++ [a] := by
|
||||
@[simp, grind =] theorem push_toList {xs : Array α} {a : α} : (xs.push a).toList = xs.toList ++ [a] := by
|
||||
simp [push, List.concat_eq_append]
|
||||
|
||||
@[simp] theorem toListAppend_eq {xs : Array α} {l : List α} : xs.toListAppend l = xs.toList ++ l := by
|
||||
@[simp, grind =] theorem toListAppend_eq {xs : Array α} {l : List α} : xs.toListAppend l = xs.toList ++ l := by
|
||||
simp [toListAppend, ← foldr_toList]
|
||||
|
||||
@[simp] theorem toListImpl_eq {xs : Array α} : xs.toListImpl = xs.toList := by
|
||||
@[simp, grind =] theorem toListImpl_eq {xs : Array α} : xs.toListImpl = xs.toList := by
|
||||
simp [toListImpl, ← foldr_toList]
|
||||
|
||||
@[simp] theorem toList_pop {xs : Array α} : xs.pop.toList = xs.toList.dropLast := rfl
|
||||
@[simp, grind =] theorem toList_pop {xs : Array α} : xs.pop.toList = xs.toList.dropLast := rfl
|
||||
|
||||
@[deprecated toList_pop (since := "2025-02-17")]
|
||||
abbrev pop_toList := @Array.toList_pop
|
||||
|
||||
@[simp] theorem append_eq_append {xs ys : Array α} : xs.append ys = xs ++ ys := rfl
|
||||
|
||||
@[simp] theorem toList_append {xs ys : Array α} :
|
||||
@[simp, grind =] theorem toList_append {xs ys : Array α} :
|
||||
(xs ++ ys).toList = xs.toList ++ ys.toList := by
|
||||
rw [← append_eq_append]; unfold Array.append
|
||||
rw [← foldl_toList]
|
||||
@@ -112,13 +112,13 @@ abbrev pop_toList := @Array.toList_pop
|
||||
|
||||
@[simp] theorem toList_empty : (#[] : Array α).toList = [] := rfl
|
||||
|
||||
@[simp, grind] theorem append_empty {xs : Array α} : xs ++ #[] = xs := by
|
||||
@[simp, grind =] theorem append_empty {xs : Array α} : xs ++ #[] = xs := by
|
||||
apply ext'; simp only [toList_append, toList_empty, List.append_nil]
|
||||
|
||||
@[deprecated append_empty (since := "2025-01-13")]
|
||||
abbrev append_nil := @append_empty
|
||||
|
||||
@[simp, grind] theorem empty_append {xs : Array α} : #[] ++ xs = xs := by
|
||||
@[simp, grind =] theorem empty_append {xs : Array α} : #[] ++ xs = xs := by
|
||||
apply ext'; simp only [toList_append, toList_empty, List.nil_append]
|
||||
|
||||
@[deprecated empty_append (since := "2025-01-13")]
|
||||
@@ -129,7 +129,7 @@ abbrev nil_append := @empty_append
|
||||
|
||||
@[simp] theorem appendList_eq_append {xs : Array α} {l : List α} : xs.appendList l = xs ++ l := rfl
|
||||
|
||||
@[simp] theorem toList_appendList {xs : Array α} {l : List α} :
|
||||
@[simp, grind =] theorem toList_appendList {xs : Array α} {l : List α} :
|
||||
(xs ++ l).toList = xs.toList ++ l := by
|
||||
rw [← appendList_eq_append]; unfold Array.appendList
|
||||
induction l generalizing xs <;> simp [*]
|
||||
@@ -159,34 +159,4 @@ theorem foldl_eq_foldl_toList {f : β → α → β} {init : β} {xs : Array α}
|
||||
xs.foldl f init = xs.toList.foldl f init:= by
|
||||
simp
|
||||
|
||||
@[deprecated foldlM_toList (since := "2024-09-09")]
|
||||
abbrev foldlM_eq_foldlM_data := @foldlM_toList
|
||||
|
||||
@[deprecated foldl_toList (since := "2024-09-09")]
|
||||
abbrev foldl_eq_foldl_data := @foldl_toList
|
||||
|
||||
@[deprecated foldrM_eq_reverse_foldlM_toList (since := "2024-09-09")]
|
||||
abbrev foldrM_eq_reverse_foldlM_data := @foldrM_eq_reverse_foldlM_toList
|
||||
|
||||
@[deprecated foldrM_toList (since := "2024-09-09")]
|
||||
abbrev foldrM_eq_foldrM_data := @foldrM_toList
|
||||
|
||||
@[deprecated foldr_toList (since := "2024-09-09")]
|
||||
abbrev foldr_eq_foldr_data := @foldr_toList
|
||||
|
||||
@[deprecated push_toList (since := "2024-09-09")]
|
||||
abbrev push_data := @push_toList
|
||||
|
||||
@[deprecated toListImpl_eq (since := "2024-09-09")]
|
||||
abbrev toList_eq := @toListImpl_eq
|
||||
|
||||
@[deprecated pop_toList (since := "2024-09-09")]
|
||||
abbrev pop_data := @toList_pop
|
||||
|
||||
@[deprecated toList_append (since := "2024-09-09")]
|
||||
abbrev append_data := @toList_append
|
||||
|
||||
@[deprecated toList_appendList (since := "2024-09-09")]
|
||||
abbrev appendList_data := @toList_appendList
|
||||
|
||||
end Array
|
||||
|
||||
@@ -25,7 +25,7 @@ section countP
|
||||
|
||||
variable {p q : α → Bool}
|
||||
|
||||
@[simp] theorem _root_.List.countP_toArray {l : List α} : countP p l.toArray = l.countP p := by
|
||||
@[simp, grind =] theorem _root_.List.countP_toArray {l : List α} : countP p l.toArray = l.countP p := by
|
||||
simp [countP]
|
||||
induction l with
|
||||
| nil => rfl
|
||||
@@ -33,7 +33,7 @@ variable {p q : α → Bool}
|
||||
simp only [List.foldr_cons, ih, List.countP_cons]
|
||||
split <;> simp_all
|
||||
|
||||
@[simp] theorem countP_toList {xs : Array α} : xs.toList.countP p = countP p xs := by
|
||||
@[simp, grind =] theorem countP_toList {xs : Array α} : xs.toList.countP p = countP p xs := by
|
||||
cases xs
|
||||
simp
|
||||
|
||||
@@ -164,10 +164,10 @@ section count
|
||||
|
||||
variable [BEq α]
|
||||
|
||||
@[simp] theorem _root_.List.count_toArray {l : List α} {a : α} : count a l.toArray = l.count a := by
|
||||
@[simp, grind =] theorem _root_.List.count_toArray {l : List α} {a : α} : count a l.toArray = l.count a := by
|
||||
simp [count, List.count_eq_countP]
|
||||
|
||||
@[simp] theorem count_toList {xs : Array α} {a : α} : xs.toList.count a = xs.count a := by
|
||||
@[simp, grind =] theorem count_toList {xs : Array α} {a : α} : xs.toList.count a = xs.count a := by
|
||||
cases xs
|
||||
simp
|
||||
|
||||
|
||||
@@ -68,7 +68,7 @@ theorem isEqv_eq_decide (xs ys : Array α) (r) :
|
||||
Bool.not_eq_true]
|
||||
simpa [isEqv_iff_rel] using h'
|
||||
|
||||
@[simp] theorem isEqv_toList [BEq α] (xs ys : Array α) : (xs.toList.isEqv ys.toList r) = (xs.isEqv ys r) := by
|
||||
@[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]
|
||||
|
||||
theorem eq_of_isEqv [DecidableEq α] (xs ys : Array α) (h : Array.isEqv xs ys (fun x y => x = y)) : xs = ys := by
|
||||
@@ -99,17 +99,17 @@ theorem beq_eq_decide [BEq α] (xs ys : Array α) :
|
||||
decide (∀ (i : Nat) (h' : i < xs.size), xs[i] == ys[i]'(h ▸ h')) else false := by
|
||||
simp [BEq.beq, isEqv_eq_decide]
|
||||
|
||||
@[simp] theorem beq_toList [BEq α] (xs ys : Array α) : (xs.toList == ys.toList) = (xs == ys) := by
|
||||
@[simp, grind =] theorem beq_toList [BEq α] (xs ys : Array α) : (xs.toList == ys.toList) = (xs == ys) := by
|
||||
simp [beq_eq_decide, List.beq_eq_decide]
|
||||
|
||||
end Array
|
||||
|
||||
namespace List
|
||||
|
||||
@[simp] theorem isEqv_toArray [BEq α] (as bs : List α) : (as.toArray.isEqv bs.toArray r) = (as.isEqv bs r) := by
|
||||
@[simp, grind =] theorem isEqv_toArray [BEq α] (as bs : List α) : (as.toArray.isEqv bs.toArray r) = (as.isEqv bs r) := by
|
||||
simp [isEqv_eq_decide, Array.isEqv_eq_decide]
|
||||
|
||||
@[simp] theorem beq_toArray [BEq α] (as bs : List α) : (as.toArray == bs.toArray) = (as == bs) := by
|
||||
@[simp, grind =] theorem beq_toArray [BEq α] (as bs : List α) : (as.toArray == bs.toArray) = (as == bs) := by
|
||||
simp [beq_eq_decide, Array.beq_eq_decide]
|
||||
|
||||
end List
|
||||
|
||||
@@ -39,10 +39,10 @@ namespace Array
|
||||
@[simp] theorem toList_eq_nil_iff {xs : Array α} : xs.toList = [] ↔ xs = #[] := by
|
||||
cases xs <;> simp
|
||||
|
||||
@[simp] theorem mem_toList_iff {a : α} {xs : Array α} : a ∈ xs.toList ↔ a ∈ xs := by
|
||||
@[simp, grind =] theorem mem_toList_iff {a : α} {xs : Array α} : a ∈ xs.toList ↔ a ∈ xs := by
|
||||
cases xs <;> simp
|
||||
|
||||
@[simp] theorem length_toList {xs : Array α} : xs.toList.length = xs.size := rfl
|
||||
@[simp, grind =] theorem length_toList {xs : Array α} : xs.toList.length = xs.size := rfl
|
||||
|
||||
theorem eq_toArray : xs = List.toArray as ↔ xs.toList = as := by
|
||||
cases xs
|
||||
@@ -78,6 +78,7 @@ theorem ne_empty_of_size_pos (h : 0 < xs.size) : xs ≠ #[] := by
|
||||
cases xs
|
||||
simpa using List.ne_nil_of_length_pos h
|
||||
|
||||
@[grind]
|
||||
theorem size_eq_zero_iff : xs.size = 0 ↔ xs = #[] :=
|
||||
⟨eq_empty_of_size_eq_zero, fun h => h ▸ rfl⟩
|
||||
|
||||
@@ -527,7 +528,7 @@ theorem forall_getElem {xs : Array α} {p : α → Prop} :
|
||||
rcases xs with ⟨xs⟩
|
||||
simp
|
||||
|
||||
@[simp] theorem isEmpty_toList {xs : Array α} : xs.toList.isEmpty = xs.isEmpty := by
|
||||
@[simp, grind =] theorem isEmpty_toList {xs : Array α} : xs.toList.isEmpty = xs.isEmpty := by
|
||||
rcases xs with ⟨_ | _⟩ <;> simp
|
||||
|
||||
theorem isEmpty_eq_false_iff_exists_mem {xs : Array α} :
|
||||
@@ -592,7 +593,7 @@ theorem anyM_loop_cons [Monad m] {p : α → m Bool} {a : α} {as : List α} {st
|
||||
· rw [dif_neg]
|
||||
omega
|
||||
|
||||
@[simp] theorem anyM_toList [Monad m] {p : α → m Bool} {as : Array α} :
|
||||
@[simp, grind =] theorem anyM_toList [Monad m] {p : α → m Bool} {as : Array α} :
|
||||
as.toList.anyM p = as.anyM p :=
|
||||
match as with
|
||||
| ⟨[]⟩ => by simp [anyM, anyM.loop]
|
||||
@@ -651,7 +652,7 @@ theorem any_iff_exists {p : α → Bool} {as : Array α} {start stop} :
|
||||
rw [Bool.eq_false_iff, Ne, any_eq_true]
|
||||
simp
|
||||
|
||||
@[simp] theorem any_toList {p : α → Bool} {as : Array α} : as.toList.any p = as.any p := by
|
||||
@[simp, grind =] theorem any_toList {p : α → Bool} {as : Array α} : as.toList.any p = as.any p := by
|
||||
rw [Bool.eq_iff_iff, any_eq_true, List.any_eq_true]
|
||||
simp only [List.mem_iff_getElem, getElem_toList]
|
||||
exact ⟨fun ⟨_, ⟨i, w, rfl⟩, h⟩ => ⟨i, w, h⟩, fun ⟨i, w, h⟩ => ⟨_, ⟨i, w, rfl⟩, h⟩⟩
|
||||
@@ -661,7 +662,7 @@ theorem allM_eq_not_anyM_not [Monad m] [LawfulMonad m] {p : α → m Bool} {as :
|
||||
dsimp [allM, anyM]
|
||||
simp
|
||||
|
||||
@[simp] theorem allM_toList [Monad m] [LawfulMonad m] {p : α → m Bool} {as : Array α} :
|
||||
@[simp, grind =] theorem allM_toList [Monad m] [LawfulMonad m] {p : α → m Bool} {as : Array α} :
|
||||
as.toList.allM p = as.allM p := by
|
||||
rw [allM_eq_not_anyM_not]
|
||||
rw [← anyM_toList]
|
||||
@@ -690,7 +691,7 @@ theorem all_iff_forall {p : α → Bool} {as : Array α} {start stop} :
|
||||
rw [Bool.eq_false_iff, Ne, all_eq_true]
|
||||
simp
|
||||
|
||||
@[simp] theorem all_toList {p : α → Bool} {as : Array α} : as.toList.all p = as.all p := by
|
||||
@[simp, grind =] theorem all_toList {p : α → Bool} {as : Array α} : as.toList.all p = as.all p := by
|
||||
rw [Bool.eq_iff_iff, all_eq_true, List.all_eq_true]
|
||||
simp only [List.mem_iff_getElem, getElem_toList]
|
||||
constructor
|
||||
@@ -730,18 +731,18 @@ theorem all_eq_true_iff_forall_mem {xs : Array α} : xs.all p ↔ ∀ x, x ∈ x
|
||||
subst h
|
||||
rw [all_toList]
|
||||
|
||||
theorem _root_.List.anyM_toArray [Monad m] [LawfulMonad m] {p : α → m Bool} {l : List α} :
|
||||
@[grind] theorem _root_.List.anyM_toArray [Monad m] [LawfulMonad m] {p : α → m Bool} {l : List α} :
|
||||
l.toArray.anyM p = l.anyM p := by
|
||||
rw [← anyM_toList]
|
||||
|
||||
theorem _root_.List.any_toArray {p : α → Bool} {l : List α} : l.toArray.any p = l.any p := by
|
||||
@[grind] theorem _root_.List.any_toArray {p : α → Bool} {l : List α} : l.toArray.any p = l.any p := by
|
||||
rw [any_toList]
|
||||
|
||||
theorem _root_.List.allM_toArray [Monad m] [LawfulMonad m] {p : α → m Bool} {l : List α} :
|
||||
@[grind] theorem _root_.List.allM_toArray [Monad m] [LawfulMonad m] {p : α → m Bool} {l : List α} :
|
||||
l.toArray.allM p = l.allM p := by
|
||||
rw [← allM_toList]
|
||||
|
||||
theorem _root_.List.all_toArray {p : α → Bool} {l : List α} : l.toArray.all p = l.all p := by
|
||||
@[grind] theorem _root_.List.all_toArray {p : α → Bool} {l : List α} : l.toArray.all p = l.all p := by
|
||||
rw [all_toList]
|
||||
|
||||
/-- Variant of `any_eq_true` in terms of membership rather than an array index. -/
|
||||
@@ -807,7 +808,7 @@ theorem decide_forall_mem {xs : Array α} {p : α → Prop} [DecidablePred p] :
|
||||
decide (∀ x, x ∈ xs → p x) = xs.all p := by
|
||||
simp [all_eq']
|
||||
|
||||
@[simp] theorem _root_.List.contains_toArray [BEq α] {l : List α} {a : α} :
|
||||
@[simp, grind =] theorem _root_.List.contains_toArray [BEq α] {l : List α} {a : α} :
|
||||
l.toArray.contains a = l.contains a := by
|
||||
simp [Array.contains, List.any_beq]
|
||||
|
||||
@@ -1205,7 +1206,7 @@ where
|
||||
induction l generalizing xs <;> simp [*]
|
||||
simp [H]
|
||||
|
||||
@[simp] theorem _root_.List.map_toArray {f : α → β} {l : List α} :
|
||||
@[simp, grind =] theorem _root_.List.map_toArray {f : α → β} {l : List α} :
|
||||
l.toArray.map f = (l.map f).toArray := by
|
||||
apply ext'
|
||||
simp
|
||||
@@ -1428,7 +1429,7 @@ theorem filter_congr {xs ys : Array α} (h : xs = ys)
|
||||
induction xs with simp
|
||||
| cons => split <;> simp [*]
|
||||
|
||||
theorem toList_filter {p : α → Bool} {xs : Array α} :
|
||||
@[grind] theorem toList_filter {p : α → Bool} {xs : Array α} :
|
||||
(xs.filter p).toList = xs.toList.filter p := by
|
||||
simp
|
||||
|
||||
@@ -1437,7 +1438,7 @@ theorem toList_filter {p : α → Bool} {xs : Array α} :
|
||||
apply ext'
|
||||
simp [h]
|
||||
|
||||
theorem _root_.List.filter_toArray {p : α → Bool} {l : List α} :
|
||||
@[grind] theorem _root_.List.filter_toArray {p : α → Bool} {l : List α} :
|
||||
l.toArray.filter p = (l.filter p).toArray := by
|
||||
simp
|
||||
|
||||
@@ -1602,7 +1603,7 @@ theorem filterMap_congr {as bs : Array α} (h : as = bs)
|
||||
· simp_all [Id.run, List.filterMap_cons]
|
||||
split <;> simp_all
|
||||
|
||||
theorem toList_filterMap {f : α → Option β} {xs : Array α} :
|
||||
@[grind] theorem toList_filterMap {f : α → Option β} {xs : Array α} :
|
||||
(xs.filterMap f).toList = xs.toList.filterMap f := by
|
||||
simp [toList_filterMap']
|
||||
|
||||
@@ -1612,7 +1613,7 @@ theorem toList_filterMap {f : α → Option β} {xs : Array α} :
|
||||
apply ext'
|
||||
simp [h]
|
||||
|
||||
theorem _root_.List.filterMap_toArray {f : α → Option β} {l : List α} :
|
||||
@[grind] theorem _root_.List.filterMap_toArray {f : α → Option β} {l : List α} :
|
||||
l.toArray.filterMap f = (l.filterMap f).toArray := by
|
||||
simp
|
||||
|
||||
@@ -2097,7 +2098,7 @@ theorem append_eq_map_iff {f : α → β} :
|
||||
|
||||
@[simp, grind] theorem flatten_empty : (#[] : Array (Array α)).flatten = #[] := by simp [flatten]; rfl
|
||||
|
||||
@[simp] theorem toList_flatten {xss : Array (Array α)} :
|
||||
@[simp, grind] theorem toList_flatten {xss : Array (Array α)} :
|
||||
xss.flatten.toList = (xss.toList.map toList).flatten := by
|
||||
dsimp [flatten]
|
||||
simp only [← foldl_toList]
|
||||
@@ -2124,7 +2125,7 @@ theorem append_eq_map_iff {f : α → β} :
|
||||
apply ext'
|
||||
simp
|
||||
|
||||
@[simp] theorem size_flatten {xss : Array (Array α)} : xss.flatten.size = (xss.map size).sum := by
|
||||
@[simp, grind] theorem size_flatten {xss : Array (Array α)} : xss.flatten.size = (xss.map size).sum := by
|
||||
cases xss using array₂_induction
|
||||
simp [Function.comp_def]
|
||||
|
||||
@@ -2307,7 +2308,7 @@ theorem flatMap_toList {xs : Array α} {f : α → List β} :
|
||||
rcases xs with ⟨l⟩
|
||||
simp
|
||||
|
||||
@[simp] theorem toList_flatMap {xs : Array α} {f : α → Array β} :
|
||||
@[simp, grind =] theorem toList_flatMap {xs : Array α} {f : α → Array β} :
|
||||
(xs.flatMap f).toList = xs.toList.flatMap fun a => (f a).toList := by
|
||||
rcases xs with ⟨l⟩
|
||||
simp
|
||||
@@ -2322,7 +2323,7 @@ theorem flatMap_toArray_cons {β} {f : α → Array β} {a : α} {as : List α}
|
||||
intro cs
|
||||
induction as generalizing cs <;> simp_all
|
||||
|
||||
@[simp] 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
|
||||
induction as with
|
||||
| nil => simp
|
||||
@@ -2652,6 +2653,7 @@ abbrev sum_mkArray_nat := @sum_replicate_nat
|
||||
|
||||
/-! ### Preliminaries about `swap` needed for `reverse`. -/
|
||||
|
||||
@[grind]
|
||||
theorem getElem?_swap {xs : Array α} {i j : Nat} (hi hj) {k : Nat} : (xs.swap i j hi hj)[k]? =
|
||||
if j = k then some xs[i] else if i = k then some xs[j] else xs[k]? := by
|
||||
simp [swap_def, getElem?_set]
|
||||
@@ -2710,15 +2712,15 @@ theorem getElem?_swap {xs : Array α} {i j : Nat} (hi hj) {k : Nat} : (xs.swap i
|
||||
true_and, Nat.not_lt] at h
|
||||
rw [List.getElem?_eq_none_iff.2 ‹_›, List.getElem?_eq_none_iff.2 (xs.toList.length_reverse ▸ ‹_›)]
|
||||
|
||||
@[simp] theorem _root_.List.reverse_toArray {l : List α} : l.toArray.reverse = l.reverse.toArray := by
|
||||
@[simp, grind =] theorem _root_.List.reverse_toArray {l : List α} : l.toArray.reverse = l.reverse.toArray := by
|
||||
apply ext'
|
||||
simp only [toList_reverse]
|
||||
|
||||
@[simp, grind] theorem reverse_push {xs : Array α} {a : α} : (xs.push a).reverse = #[a] ++ xs.reverse := by
|
||||
@[simp, grind =] theorem reverse_push {xs : Array α} {a : α} : (xs.push a).reverse = #[a] ++ xs.reverse := by
|
||||
cases xs
|
||||
simp
|
||||
|
||||
@[simp, grind] theorem mem_reverse {x : α} {xs : Array α} : x ∈ xs.reverse ↔ x ∈ xs := by
|
||||
@[simp, grind =] theorem mem_reverse {x : α} {xs : Array α} : x ∈ xs.reverse ↔ x ∈ xs := by
|
||||
cases xs
|
||||
simp
|
||||
|
||||
@@ -2882,7 +2884,7 @@ theorem size_extract_loop {xs ys : Array α} {size start : Nat} :
|
||||
have h := Nat.le_of_not_gt h
|
||||
rw [extract_loop_of_ge (h:=h), Nat.sub_eq_zero_of_le h, Nat.min_zero, Nat.add_zero]
|
||||
|
||||
@[simp, grind] theorem size_extract {xs : Array α} {start stop : Nat} :
|
||||
@[simp, grind =] theorem size_extract {xs : Array α} {start stop : Nat} :
|
||||
(xs.extract start stop).size = min stop xs.size - start := by
|
||||
simp only [extract, Nat.sub_eq, emptyWithCapacity_eq]
|
||||
rw [size_extract_loop, size_empty, Nat.zero_add, Nat.sub_min_sub_right, Nat.min_assoc,
|
||||
@@ -2948,7 +2950,7 @@ theorem getElem_extract_aux {xs : Array α} {start stop : Nat} (h : i < (xs.extr
|
||||
rw [size_extract] at h; apply Nat.add_lt_of_lt_sub'; apply Nat.lt_of_lt_of_le h
|
||||
apply Nat.sub_le_sub_right; apply Nat.min_le_right
|
||||
|
||||
@[simp] theorem getElem_extract {xs : Array α} {start stop : Nat}
|
||||
@[simp, grind =] theorem getElem_extract {xs : Array α} {start stop : Nat}
|
||||
(h : i < (xs.extract start stop).size) :
|
||||
(xs.extract start stop)[i] = xs[start + i]'(getElem_extract_aux h) :=
|
||||
show (extract.loop xs (min stop xs.size - start) start #[])[i]
|
||||
@@ -3003,7 +3005,7 @@ theorem extract_empty_of_size_le_start {xs : Array α} {start stop : Nat} (h : x
|
||||
· simp
|
||||
· simp at h₁
|
||||
|
||||
@[simp] theorem _root_.List.extract_toArray {l : List α} {start stop : Nat} :
|
||||
@[simp, grind =] theorem _root_.List.extract_toArray {l : List α} {start stop : Nat} :
|
||||
l.toArray.extract start stop = (l.extract start stop).toArray := by
|
||||
apply ext'
|
||||
simp
|
||||
@@ -3742,25 +3744,25 @@ theorem contains_iff_mem [BEq α] [LawfulBEq α] {xs : Array α} {a : α} :
|
||||
xs.contains a ↔ a ∈ xs := by
|
||||
simp
|
||||
|
||||
@[simp, grind]
|
||||
@[simp, grind =]
|
||||
theorem contains_toList [BEq α] {xs : Array α} {x : α} :
|
||||
xs.toList.contains x = xs.contains x := by
|
||||
rcases xs with ⟨xs⟩
|
||||
simp
|
||||
|
||||
@[simp, grind]
|
||||
@[simp, grind =]
|
||||
theorem contains_map [BEq β] {xs : Array α} {x : β} {f : α → β} :
|
||||
(xs.map f).contains x = xs.any (fun a => x == f a) := by
|
||||
rcases xs with ⟨xs⟩
|
||||
simp
|
||||
|
||||
@[simp, grind]
|
||||
@[simp, grind =]
|
||||
theorem contains_filter [BEq α] {xs : Array α} {x : α} {p : α → Bool} :
|
||||
(xs.filter p).contains x = xs.any (fun a => x == a && p a) := by
|
||||
rcases xs with ⟨xs⟩
|
||||
simp
|
||||
|
||||
@[simp, grind]
|
||||
@[simp, grind =]
|
||||
theorem contains_filterMap [BEq β] {xs : Array α} {x : β} {f : α → Option β} :
|
||||
(xs.filterMap f).contains x = xs.any (fun a => (f a).any fun b => x == b) := by
|
||||
rcases xs with ⟨xs⟩
|
||||
@@ -3773,19 +3775,19 @@ theorem contains_append [BEq α] {xs ys : Array α} {x : α} :
|
||||
rcases ys with ⟨ys⟩
|
||||
simp
|
||||
|
||||
@[simp, grind]
|
||||
@[simp, grind =]
|
||||
theorem contains_flatten [BEq α] {xs : Array (Array α)} {x : α} :
|
||||
(xs.flatten).contains x = xs.any fun xs => xs.contains x := by
|
||||
rcases xs with ⟨xs⟩
|
||||
simp [Function.comp_def]
|
||||
|
||||
@[simp, grind]
|
||||
@[simp, grind =]
|
||||
theorem contains_reverse [BEq α] {xs : Array α} {x : α} :
|
||||
(xs.reverse).contains x = xs.contains x := by
|
||||
rcases xs with ⟨xs⟩
|
||||
simp
|
||||
|
||||
@[simp, grind]
|
||||
@[simp, grind =]
|
||||
theorem contains_flatMap [BEq β] {xs : Array α} {f : α → Array β} {x : β} :
|
||||
(xs.flatMap f).contains x = xs.any fun a => (f a).contains x := by
|
||||
rcases xs with ⟨xs⟩
|
||||
@@ -3798,7 +3800,7 @@ theorem pop_append {xs ys : Array α} :
|
||||
(xs ++ ys).pop = if ys.isEmpty then xs.pop else xs ++ ys.pop := by
|
||||
split <;> simp_all
|
||||
|
||||
@[simp] theorem pop_replicate {n : Nat} {a : α} : (replicate n a).pop = replicate (n - 1) a := by
|
||||
@[simp, grind =] theorem pop_replicate {n : Nat} {a : α} : (replicate n a).pop = replicate (n - 1) a := by
|
||||
ext <;> simp
|
||||
|
||||
@[deprecated pop_replicate (since := "2025-03-18")]
|
||||
@@ -4096,6 +4098,7 @@ theorem getElem_swap' {xs : Array α} {i j : Nat} {hi hj} {k : Nat} (hk : k < xs
|
||||
· simp_all only [getElem_swap_left]
|
||||
· split <;> simp_all
|
||||
|
||||
@[grind]
|
||||
theorem getElem_swap {xs : Array α} {i j : Nat} (hi hj) {k : Nat} (hk : k < (xs.swap i j hi hj).size) :
|
||||
(xs.swap i j hi hj)[k] = if k = i then xs[j] else if k = j then xs[i] else xs[k]'(by simp_all) := by
|
||||
apply getElem_swap'
|
||||
@@ -4361,7 +4364,10 @@ theorem foldl_toList_eq_map {l : List α} {acc : Array β} {G : α → β} :
|
||||
|
||||
/-! # uset -/
|
||||
|
||||
attribute [simp] uset
|
||||
-- For verification purposes, we use `simp` to replace `uset` with `set`.
|
||||
@[simp, grind =] theorem uset_eq_set {xs : Array α} {v : α} {i : USize} (h : i.toNat < xs.size) :
|
||||
uset xs i v h = set xs i.toNat v h := by
|
||||
simp [uset]
|
||||
|
||||
theorem size_uset {xs : Array α} {v : α} {i : USize} (h : i.toNat < xs.size) :
|
||||
(uset xs i v h).size = xs.size := by
|
||||
@@ -4378,7 +4384,7 @@ theorem getElem!_eq_getD [Inhabited α] {xs : Array α} {i} : xs[i]! = xs.getD i
|
||||
|
||||
/-! # mem -/
|
||||
|
||||
@[simp] 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
|
||||
@@ -4421,12 +4427,12 @@ theorem getElem?_push_eq {xs : Array α} {x : α} : (xs.push x)[xs.size]? = some
|
||||
|
||||
/-! ### forIn -/
|
||||
|
||||
@[simp] theorem forIn_toList [Monad m] {xs : Array α} {b : β} {f : α → β → m (ForInStep β)} :
|
||||
@[simp, grind =] theorem forIn_toList [Monad m] {xs : Array α} {b : β} {f : α → β → m (ForInStep β)} :
|
||||
forIn xs.toList b f = forIn xs b f := by
|
||||
cases xs
|
||||
simp
|
||||
|
||||
@[simp] theorem forIn'_toList [Monad m] {xs : Array α} {b : β} {f : (a : α) → a ∈ xs.toList → β → m (ForInStep β)} :
|
||||
@[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.mpr m) b) := by
|
||||
cases xs
|
||||
simp
|
||||
@@ -4439,7 +4445,7 @@ abbrev contains_def [DecidableEq α] {a : α} {xs : Array α} : xs.contains a
|
||||
|
||||
/-! ### isPrefixOf -/
|
||||
|
||||
@[simp] theorem isPrefixOf_toList [BEq α] {xs ys : Array α} :
|
||||
@[simp, grind =] theorem isPrefixOf_toList [BEq α] {xs ys : Array α} :
|
||||
xs.toList.isPrefixOf ys.toList = xs.isPrefixOf ys := by
|
||||
cases xs
|
||||
cases ys
|
||||
@@ -4480,32 +4486,32 @@ abbrev contains_def [DecidableEq α] {a : α} {xs : Array α} : xs.contains a
|
||||
|
||||
/-! ### findSomeM?, findM?, findSome?, find? -/
|
||||
|
||||
@[simp] theorem findSomeM?_toList [Monad m] [LawfulMonad m] {p : α → m (Option β)} {xs : Array α} :
|
||||
@[simp, grind =] theorem findSomeM?_toList [Monad m] [LawfulMonad m] {p : α → m (Option β)} {xs : Array α} :
|
||||
xs.toList.findSomeM? p = xs.findSomeM? p := by
|
||||
cases xs
|
||||
simp
|
||||
|
||||
@[simp] theorem findM?_toList [Monad m] [LawfulMonad m] {p : α → m Bool} {xs : Array α} :
|
||||
@[simp, grind =] theorem findM?_toList [Monad m] [LawfulMonad m] {p : α → m Bool} {xs : Array α} :
|
||||
xs.toList.findM? p = xs.findM? p := by
|
||||
cases xs
|
||||
simp
|
||||
|
||||
@[simp] theorem findSome?_toList {p : α → Option β} {xs : Array α} :
|
||||
@[simp, grind =] theorem findSome?_toList {p : α → Option β} {xs : Array α} :
|
||||
xs.toList.findSome? p = xs.findSome? p := by
|
||||
cases xs
|
||||
simp
|
||||
|
||||
@[simp] theorem find?_toList {p : α → Bool} {xs : Array α} :
|
||||
@[simp, grind =] theorem find?_toList {p : α → Bool} {xs : Array α} :
|
||||
xs.toList.find? p = xs.find? p := by
|
||||
cases xs
|
||||
simp
|
||||
|
||||
@[simp] theorem finIdxOf?_toList [BEq α] {a : α} {xs : Array α} :
|
||||
@[simp, grind =] theorem finIdxOf?_toList [BEq α] {a : α} {xs : Array α} :
|
||||
xs.toList.finIdxOf? a = (xs.finIdxOf? a).map (Fin.cast (by simp)) := by
|
||||
cases xs
|
||||
simp
|
||||
|
||||
@[simp] theorem findFinIdx?_toList {p : α → Bool} {xs : Array α} :
|
||||
@[simp, grind =] theorem findFinIdx?_toList {p : α → Bool} {xs : Array α} :
|
||||
xs.toList.findFinIdx? p = (xs.findFinIdx? p).map (Fin.cast (by simp)) := by
|
||||
cases xs
|
||||
simp
|
||||
@@ -4524,10 +4530,10 @@ 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
|
||||
|
||||
@[simp] theorem take_toArray {l : List α} {i : Nat} : l.toArray.take i = (l.take i).toArray := by
|
||||
@[simp, grind =] theorem take_toArray {l : List α} {i : Nat} : l.toArray.take i = (l.take i).toArray := by
|
||||
apply Array.ext <;> simp
|
||||
|
||||
@[simp] theorem mapM_toArray [Monad m] [LawfulMonad m] {f : α → m β} {l : List α} :
|
||||
@[simp, grind =] theorem mapM_toArray [Monad m] [LawfulMonad m] {f : α → m β} {l : List α} :
|
||||
l.toArray.mapM f = List.toArray <$> l.mapM f := by
|
||||
simp only [← mapM'_eq_mapM, mapM_eq_foldlM]
|
||||
suffices ∀ xs : Array β,
|
||||
@@ -4544,12 +4550,12 @@ theorem toListRev_toArray {l : List α} : l.toArray.toListRev = l.reverse := by
|
||||
theorem uset_toArray {l : List α} {i : USize} {a : α} {h : i.toNat < l.toArray.size} :
|
||||
l.toArray.uset i a h = (l.set i.toNat a).toArray := by simp
|
||||
|
||||
@[simp] theorem modify_toArray {f : α → α} {l : List α} {i : Nat} :
|
||||
@[simp, grind =] theorem modify_toArray {f : α → α} {l : List α} {i : Nat} :
|
||||
l.toArray.modify i f = (l.modify i f).toArray := by
|
||||
apply ext'
|
||||
simp
|
||||
|
||||
@[simp] theorem flatten_toArray {L : List (List α)} :
|
||||
@[simp, grind =] theorem flatten_toArray {L : List (List α)} :
|
||||
(L.toArray.map List.toArray).flatten = L.flatten.toArray := by
|
||||
apply ext'
|
||||
simp [Function.comp_def]
|
||||
@@ -4624,11 +4630,11 @@ end Array
|
||||
|
||||
namespace List
|
||||
|
||||
@[simp] theorem unzip_toArray {as : List (α × β)} :
|
||||
@[simp, grind =] theorem unzip_toArray {as : List (α × β)} :
|
||||
as.toArray.unzip = Prod.map List.toArray List.toArray as.unzip := by
|
||||
ext1 <;> simp
|
||||
|
||||
@[simp] theorem firstM_toArray [Alternative m] {as : List α} {f : α → m β} :
|
||||
@[simp, grind =] theorem firstM_toArray [Alternative m] {as : List α} {f : α → m β} :
|
||||
as.toArray.firstM f = as.firstM f := by
|
||||
unfold Array.firstM
|
||||
suffices ∀ i, i ≤ as.length → firstM.go f as.toArray (as.length - i) = firstM f (as.drop (as.length - i)) by
|
||||
@@ -4698,11 +4704,6 @@ theorem get!_eq_getD_getElem? [Inhabited α] (xs : Array α) (i : Nat) :
|
||||
set_option linter.deprecated false in
|
||||
@[deprecated get!_eq_getD_getElem? (since := "2025-02-12")] abbrev get!_eq_getElem? := @get!_eq_getD_getElem?
|
||||
|
||||
|
||||
@[deprecated mem_of_back? (since := "2024-10-21")] abbrev mem_of_back?_eq_some := @mem_of_back?
|
||||
|
||||
@[deprecated getElem?_size_le (since := "2024-10-21")] abbrev get?_len_le := @getElem?_size_le
|
||||
|
||||
set_option linter.deprecated false in
|
||||
@[deprecated "`Array.get?` is deprecated, use `a[i]?` instead." (since := "2025-02-12")]
|
||||
theorem get?_eq_get?_toList (xs : Array α) (i : Nat) : xs.get? i = xs.toList.get? i := by
|
||||
@@ -4711,45 +4712,11 @@ theorem get?_eq_get?_toList (xs : Array α) (i : Nat) : xs.get? i = xs.toList.ge
|
||||
set_option linter.deprecated false in
|
||||
@[deprecated get!_eq_getD_getElem? (since := "2025-02-12")] abbrev get!_eq_get? := @get!_eq_getD_getElem?
|
||||
|
||||
@[deprecated getElem?_push_lt (since := "2024-10-21")] abbrev get?_push_lt := @getElem?_push_lt
|
||||
|
||||
@[deprecated getElem?_push_eq (since := "2024-10-21")] abbrev get?_push_eq := @getElem?_push_eq
|
||||
|
||||
@[deprecated getElem?_push (since := "2024-10-21")] abbrev get?_push := @getElem?_push
|
||||
|
||||
@[deprecated getElem?_size (since := "2024-10-21")] abbrev get?_size := @getElem?_size
|
||||
|
||||
@[deprecated getElem_set_self (since := "2025-01-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 foldl_toList_eq_flatMap (since := "2024-10-16")]
|
||||
abbrev foldl_toList_eq_bind := @foldl_toList_eq_flatMap
|
||||
|
||||
@[deprecated foldl_toList_eq_flatMap (since := "2024-10-16")]
|
||||
abbrev foldl_data_eq_bind := @foldl_toList_eq_flatMap
|
||||
|
||||
@[deprecated getElem_mem (since := "2024-10-17")]
|
||||
abbrev getElem?_mem := @getElem_mem
|
||||
|
||||
@[deprecated getElem_fin_eq_getElem_toList (since := "2024-10-17")]
|
||||
abbrev getElem_fin_eq_toList_get := @getElem_fin_eq_getElem_toList
|
||||
|
||||
@[deprecated "Use reverse direction of `getElem?_toList`" (since := "2024-10-17")]
|
||||
abbrev getElem?_eq_toList_getElem? := @getElem?_toList
|
||||
|
||||
@[deprecated getElem?_swap (since := "2024-10-17")] abbrev get?_swap := @getElem?_swap
|
||||
|
||||
@[deprecated getElem_push (since := "2024-10-21")] abbrev get_push := @getElem_push
|
||||
@[deprecated getElem_push_lt (since := "2024-10-21")] abbrev get_push_lt := @getElem_push_lt
|
||||
@[deprecated getElem_push_eq (since := "2024-10-21")] abbrev get_push_eq := @getElem_push_eq
|
||||
|
||||
@[deprecated back!_eq_back? (since := "2024-10-31")] abbrev back_eq_back? := @back!_eq_back?
|
||||
@[deprecated back!_push (since := "2024-10-31")] abbrev back_push := @back!_push
|
||||
@[deprecated eq_push_pop_back!_of_size_ne_zero (since := "2024-10-31")]
|
||||
abbrev eq_push_pop_back_of_size_ne_zero := @eq_push_pop_back!_of_size_ne_zero
|
||||
|
||||
@[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
|
||||
|
||||
@@ -16,11 +16,11 @@ namespace Array
|
||||
|
||||
/-! ### Lexicographic ordering -/
|
||||
|
||||
@[simp] theorem _root_.List.lt_toArray [LT α] {l₁ l₂ : List α} : l₁.toArray < l₂.toArray ↔ l₁ < l₂ := Iff.rfl
|
||||
@[simp] theorem _root_.List.le_toArray [LT α] {l₁ l₂ : List α} : l₁.toArray ≤ l₂.toArray ↔ l₁ ≤ l₂ := Iff.rfl
|
||||
@[simp, grind =] theorem _root_.List.lt_toArray [LT α] {l₁ l₂ : List α} : l₁.toArray < l₂.toArray ↔ l₁ < l₂ := Iff.rfl
|
||||
@[simp, grind =] theorem _root_.List.le_toArray [LT α] {l₁ l₂ : List α} : l₁.toArray ≤ l₂.toArray ↔ l₁ ≤ l₂ := Iff.rfl
|
||||
|
||||
@[simp] theorem lt_toList [LT α] {xs ys : Array α} : xs.toList < ys.toList ↔ xs < ys := Iff.rfl
|
||||
@[simp] theorem le_toList [LT α] {xs ys : Array α} : xs.toList ≤ ys.toList ↔ xs ≤ ys := Iff.rfl
|
||||
@[simp, grind =] theorem lt_toList [LT α] {xs ys : Array α} : xs.toList < ys.toList ↔ xs < ys := Iff.rfl
|
||||
@[simp, grind =] theorem le_toList [LT α] {xs ys : Array α} : xs.toList ≤ ys.toList ↔ xs ≤ ys := Iff.rfl
|
||||
|
||||
protected theorem not_lt_iff_ge [LT α] {l₁ l₂ : List α} : ¬ l₁ < l₂ ↔ l₂ ≤ l₁ := Iff.rfl
|
||||
protected theorem not_le_iff_gt [DecidableEq α] [LT α] [DecidableLT α] {l₁ l₂ : List α} :
|
||||
@@ -47,7 +47,7 @@ private theorem cons_lex_cons [BEq α] {lt : α → α → Bool} {a b : α} {xs
|
||||
cases a == b <;> simp
|
||||
· simp
|
||||
|
||||
@[simp] theorem _root_.List.lex_toArray [BEq α] {lt : α → α → Bool} {l₁ l₂ : List α} :
|
||||
@[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, Id.run]
|
||||
@@ -57,7 +57,7 @@ private theorem cons_lex_cons [BEq α] {lt : α → α → Bool} {a b : α} {xs
|
||||
| cons y l₂ =>
|
||||
rw [List.toArray_cons, List.toArray_cons y, cons_lex_cons, List.lex, ih]
|
||||
|
||||
@[simp] theorem lex_toList [BEq α] {lt : α → α → Bool} {xs ys : Array α} :
|
||||
@[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
|
||||
|
||||
|
||||
@@ -111,11 +111,11 @@ end Array
|
||||
|
||||
namespace List
|
||||
|
||||
@[simp] theorem mapFinIdx_toArray {l : List α} {f : (i : Nat) → α → (h : i < l.length) → β} :
|
||||
@[simp, grind =] theorem mapFinIdx_toArray {l : List α} {f : (i : Nat) → α → (h : i < l.length) → β} :
|
||||
l.toArray.mapFinIdx f = (l.mapFinIdx f).toArray := by
|
||||
ext <;> simp
|
||||
|
||||
@[simp] theorem mapIdx_toArray {f : Nat → α → β} {l : List α} :
|
||||
@[simp, grind =] theorem mapIdx_toArray {f : Nat → α → β} {l : List α} :
|
||||
l.toArray.mapIdx f = (l.mapIdx f).toArray := by
|
||||
ext <;> simp
|
||||
|
||||
@@ -132,7 +132,7 @@ namespace Array
|
||||
@[deprecated getElem_zipIdx (since := "2025-01-21")]
|
||||
abbrev getElem_zipWithIndex := @getElem_zipIdx
|
||||
|
||||
@[simp] theorem zipIdx_toArray {l : List α} {k : Nat} :
|
||||
@[simp, grind =] theorem zipIdx_toArray {l : List α} {k : Nat} :
|
||||
l.toArray.zipIdx k = (l.zipIdx k).toArray := by
|
||||
ext i hi₁ hi₂ <;> simp [Nat.add_comm]
|
||||
|
||||
@@ -454,7 +454,7 @@ end Array
|
||||
|
||||
namespace List
|
||||
|
||||
theorem mapFinIdxM_toArray [Monad m] [LawfulMonad m] {l : List α}
|
||||
@[grind] theorem mapFinIdxM_toArray [Monad m] [LawfulMonad m] {l : List α}
|
||||
{f : (i : Nat) → α → (h : i < l.length) → m β} :
|
||||
l.toArray.mapFinIdxM f = toArray <$> l.mapFinIdxM f := by
|
||||
let rec go (i : Nat) (acc : Array β) (inv : i + acc.size = l.length) :
|
||||
@@ -475,7 +475,7 @@ theorem mapFinIdxM_toArray [Monad m] [LawfulMonad m] {l : List α}
|
||||
simp only [Array.mapFinIdxM, mapFinIdxM]
|
||||
exact go _ #[] _
|
||||
|
||||
theorem mapIdxM_toArray [Monad m] [LawfulMonad m] {l : List α}
|
||||
@[grind] theorem mapIdxM_toArray [Monad m] [LawfulMonad m] {l : List α}
|
||||
{f : Nat → α → m β} :
|
||||
l.toArray.mapIdxM f = toArray <$> l.mapIdxM f := by
|
||||
let rec go (bs : List α) (acc : Array β) (inv : bs.length + acc.size = l.length) :
|
||||
|
||||
@@ -264,7 +264,7 @@ end Array
|
||||
|
||||
namespace List
|
||||
|
||||
theorem filterM_toArray [Monad m] [LawfulMonad m] {l : List α} {p : α → m Bool} :
|
||||
@[grind =] theorem filterM_toArray [Monad m] [LawfulMonad m] {l : List α} {p : α → m Bool} :
|
||||
l.toArray.filterM p = toArray <$> l.filterM p := by
|
||||
simp only [Array.filterM, filterM, foldlM_toArray, bind_pure_comp, Functor.map_map]
|
||||
conv => lhs; rw [← reverse_nil]
|
||||
@@ -284,7 +284,7 @@ theorem filterM_toArray [Monad m] [LawfulMonad m] {l : List α} {p : α → m Bo
|
||||
subst w
|
||||
rw [filterM_toArray]
|
||||
|
||||
theorem filterRevM_toArray [Monad m] [LawfulMonad m] {l : List α} {p : α → m Bool} :
|
||||
@[grind =] theorem filterRevM_toArray [Monad m] [LawfulMonad m] {l : List α} {p : α → m Bool} :
|
||||
l.toArray.filterRevM p = toArray <$> l.filterRevM p := by
|
||||
simp [Array.filterRevM, filterRevM]
|
||||
rw [← foldlM_reverse, ← foldlM_toArray, ← Array.filterM, filterM_toArray]
|
||||
@@ -296,7 +296,7 @@ theorem filterRevM_toArray [Monad m] [LawfulMonad m] {l : List α} {p : α → m
|
||||
subst w
|
||||
rw [filterRevM_toArray]
|
||||
|
||||
theorem filterMapM_toArray [Monad m] [LawfulMonad m] {l : List α} {f : α → m (Option β)} :
|
||||
@[grind =] theorem filterMapM_toArray [Monad m] [LawfulMonad m] {l : List α} {f : α → m (Option β)} :
|
||||
l.toArray.filterMapM f = toArray <$> l.filterMapM f := by
|
||||
simp [Array.filterMapM, filterMapM]
|
||||
conv => lhs; rw [← reverse_nil]
|
||||
@@ -314,7 +314,7 @@ theorem filterMapM_toArray [Monad m] [LawfulMonad m] {l : List α} {f : α → m
|
||||
subst w
|
||||
rw [filterMapM_toArray]
|
||||
|
||||
@[simp] theorem flatMapM_toArray [Monad m] [LawfulMonad m] {l : List α} {f : α → m (Array β)} :
|
||||
@[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
|
||||
simp only [Array.flatMapM, bind_pure_comp, foldlM_toArray, flatMapM]
|
||||
conv => lhs; arg 2; change [].reverse.flatten.toArray
|
||||
|
||||
@@ -464,8 +464,12 @@ instance : Append (Subarray α) where
|
||||
let a := x.toArray ++ y.toArray
|
||||
a.toSubarray 0 a.size
|
||||
|
||||
/-- `Subarray` representation. -/
|
||||
protected def Subarray.repr [Repr α] (s : Subarray α) : Std.Format :=
|
||||
repr s.toArray ++ ".toSubarray"
|
||||
|
||||
instance [Repr α] : Repr (Subarray α) where
|
||||
reprPrec s _ := repr s.toArray ++ ".toSubarray"
|
||||
reprPrec s _ := Subarray.repr s
|
||||
|
||||
instance [ToString α] : ToString (Subarray α) where
|
||||
toString s := toString s.toArray
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -150,7 +150,7 @@ with `BitVec.toInt` results in the value `i.bmod (2^n)`.
|
||||
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
|
||||
exact Int.ofNat_pos.mpr (Nat.two_pow_pos _)
|
||||
exact Int.natCast_pos.mpr (Nat.two_pow_pos _)
|
||||
· apply Int.emod_nonneg
|
||||
intro eq
|
||||
apply Nat.ne_of_gt (Nat.two_pow_pos n)
|
||||
@@ -199,7 +199,13 @@ protected def toHex {n : Nat} (x : BitVec n) : String :=
|
||||
let t := (List.replicate ((n+3) / 4 - s.length) '0').asString
|
||||
t ++ s
|
||||
|
||||
instance : Repr (BitVec n) where reprPrec a _ := "0x" ++ (a.toHex : Std.Format) ++ "#" ++ repr n
|
||||
/-- `BitVec` representation. -/
|
||||
protected def BitVec.repr (a : BitVec n) : Std.Format :=
|
||||
"0x" ++ (a.toHex : Std.Format) ++ "#" ++ repr n
|
||||
|
||||
instance : Repr (BitVec n) where
|
||||
reprPrec a _ := BitVec.repr a
|
||||
|
||||
instance : ToString (BitVec n) where toString a := toString (repr a)
|
||||
|
||||
end repr_toString
|
||||
@@ -430,8 +436,6 @@ def setWidth' {n w : Nat} (le : n ≤ w) (x : BitVec n) : BitVec w :=
|
||||
apply Nat.lt_of_lt_of_le x.isLt
|
||||
exact Nat.pow_le_pow_right (by trivial) le)
|
||||
|
||||
@[deprecated setWidth' (since := "2024-09-18"), inherit_doc setWidth'] abbrev zeroExtend' := @setWidth'
|
||||
|
||||
/--
|
||||
Returns `zeroExtend (w+n) x <<< n` without needing to compute `x % 2^(2+n)`.
|
||||
-/
|
||||
|
||||
@@ -516,7 +516,7 @@ theorem msb_neg {w : Nat} {x : BitVec w} :
|
||||
rw [(show w = w - 1 + 1 by omega), Int.pow_succ] at this
|
||||
omega
|
||||
|
||||
@[simp] theorem BitVec.setWidth_neg_of_le {x : BitVec v} (h : w ≤ v) : BitVec.setWidth w (-x) = -BitVec.setWidth w x := by
|
||||
@[simp] theorem setWidth_neg_of_le {x : BitVec v} (h : w ≤ v) : BitVec.setWidth w (-x) = -BitVec.setWidth w x := by
|
||||
simp [← BitVec.signExtend_eq_setWidth_of_le _ h, BitVec.signExtend_neg_of_le h]
|
||||
|
||||
/-! ### abs -/
|
||||
@@ -668,11 +668,6 @@ theorem setWidth_setWidth_succ_eq_setWidth_setWidth_add_twoPow (x : BitVec w) (i
|
||||
getLsbD_zero, and_eq_false_imp, and_eq_true, decide_eq_true_eq, and_imp]
|
||||
by_cases hi : x.getLsbD i <;> simp [hi] <;> omega
|
||||
|
||||
@[deprecated setWidth_setWidth_succ_eq_setWidth_setWidth_add_twoPow (since := "2024-09-18"),
|
||||
inherit_doc setWidth_setWidth_succ_eq_setWidth_setWidth_add_twoPow]
|
||||
abbrev zeroExtend_truncate_succ_eq_zeroExtend_truncate_add_twoPow :=
|
||||
@setWidth_setWidth_succ_eq_setWidth_setWidth_add_twoPow
|
||||
|
||||
/--
|
||||
Recurrence lemma: multiplying `x` with the first `s` bits of `y` is the
|
||||
same as truncating `y` to `s` bits, then zero extending to the original length,
|
||||
@@ -699,10 +694,6 @@ theorem mulRec_eq_mul_signExtend_setWidth (x y : BitVec w) (s : Nat) :
|
||||
by_cases hy : y.getLsbD (s' + 1) <;> simp [hy]
|
||||
rw [heq, ← BitVec.mul_add, ← setWidth_setWidth_succ_eq_setWidth_setWidth_add_twoPow]
|
||||
|
||||
@[deprecated mulRec_eq_mul_signExtend_setWidth (since := "2024-09-18"),
|
||||
inherit_doc mulRec_eq_mul_signExtend_setWidth]
|
||||
abbrev mulRec_eq_mul_signExtend_truncate := @mulRec_eq_mul_signExtend_setWidth
|
||||
|
||||
theorem getLsbD_mul (x y : BitVec w) (i : Nat) :
|
||||
(x * y).getLsbD i = (mulRec x y w).getLsbD i := by
|
||||
simp only [mulRec_eq_mul_signExtend_setWidth]
|
||||
@@ -1501,7 +1492,6 @@ theorem sdiv_intMin {x : BitVec w} :
|
||||
by_cases h : x = intMin w
|
||||
· subst h
|
||||
simp
|
||||
omega
|
||||
· simp only [sdiv_eq, msb_intMin, show 0 < w by omega, h]
|
||||
have := Nat.two_pow_pos (w-1)
|
||||
by_cases hx : x.msb
|
||||
|
||||
@@ -315,6 +315,12 @@ 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] theorem ofFin_neg {x : Fin (2 ^ w)} : ofFin (-x) = -(ofFin x) := by
|
||||
rfl
|
||||
|
||||
@[simp, norm_cast] theorem ofFin_natCast (n : Nat) : ofFin (n : Fin (2^w)) = (n : BitVec w) := by
|
||||
rfl
|
||||
|
||||
theorem eq_of_toFin_eq : ∀ {x y : BitVec w}, x.toFin = y.toFin → x = y
|
||||
| ⟨_, _⟩, ⟨_, _⟩, rfl => rfl
|
||||
|
||||
@@ -330,6 +336,9 @@ theorem toFin_zero : toFin (0 : BitVec w) = 0 := rfl
|
||||
theorem toFin_one : toFin (1 : BitVec w) = 1 := by
|
||||
rw [toFin_inj]; simp only [ofNat_eq_ofNat, ofFin_ofNat]
|
||||
|
||||
@[simp, norm_cast] theorem toFin_natCast (n : Nat) : toFin (n : BitVec w) = (n : Fin (2^w)) := by
|
||||
rfl
|
||||
|
||||
@[simp] theorem toNat_ofBool (b : Bool) : (ofBool b).toNat = b.toNat := by
|
||||
cases b <;> rfl
|
||||
|
||||
@@ -518,6 +527,10 @@ theorem getElem_ofBool {b : Bool} {h : i < 1}: (ofBool b)[i] = b := by
|
||||
· rintro rfl
|
||||
simp
|
||||
|
||||
/-- `0#w = 1#w` iff the width is zero. -/
|
||||
@[simp] theorem zero_eq_one_iff (w : Nat) : (0#w = 1#w) ↔ (w = 0) := by
|
||||
rw [← one_eq_zero_iff, eq_comm]
|
||||
|
||||
/-! ### msb -/
|
||||
|
||||
@[simp] theorem msb_zero : (0#w).msb = false := by simp [BitVec.msb, getMsbD]
|
||||
@@ -668,6 +681,10 @@ theorem toInt_ne {x y : BitVec n} : x.toInt ≠ y.toInt ↔ x ≠ y := by
|
||||
theorem toInt_ofNat {n : Nat} (x : Nat) : (BitVec.ofNat n x).toInt = (x : Int).bmod (2^n) := by
|
||||
simp [toInt_eq_toNat_bmod, -Int.natCast_pow]
|
||||
|
||||
@[simp] theorem toInt_ofFin {w : Nat} (x : Fin (2^w)) :
|
||||
(BitVec.ofFin x).toInt = Int.bmod x (2^w) := by
|
||||
simp [toInt_eq_toNat_bmod]
|
||||
|
||||
@[simp] theorem toInt_ofInt {n : Nat} (i : Int) :
|
||||
(BitVec.ofInt n i).toInt = i.bmod (2^n) := by
|
||||
have _ := Nat.two_pow_pos n
|
||||
@@ -773,7 +790,6 @@ theorem le_two_mul_toInt {w : Nat} {x : BitVec w} : -2 ^ w ≤ 2 * x.toInt := by
|
||||
simp only [Nat.zero_lt_succ, Nat.mul_lt_mul_left, Int.natCast_mul, Int.cast_ofNat_Int]
|
||||
norm_cast; omega
|
||||
|
||||
|
||||
theorem le_toInt {w : Nat} (x : BitVec w) : -2 ^ (w - 1) ≤ x.toInt := by
|
||||
by_cases h : w = 0
|
||||
· subst h
|
||||
@@ -789,6 +805,17 @@ theorem le_toInt {w : Nat} (x : BitVec w) : -2 ^ (w - 1) ≤ x.toInt := by
|
||||
· simpa [Int.mul_comm _ 2] using le_two_mul_toInt
|
||||
· simpa [Int.mul_comm _ 2] using two_mul_toInt_lt
|
||||
|
||||
@[simp] theorem toNat_intCast {w : Nat} (x : Int) : (x : BitVec w).toNat = (x % 2^w).toNat := by
|
||||
change (BitVec.ofInt w x).toNat = _
|
||||
simp
|
||||
|
||||
@[simp] theorem toInt_intCast {w : Nat} (x : Int) : (x : BitVec w).toInt = Int.bmod x (2^w) := by
|
||||
rw [toInt_eq_toNat_bmod, toNat_intCast, Int.natCast_toNat_eq_self.mpr]
|
||||
· have h : (2 ^ w : Int) = (2 ^ w : Nat) := by simp
|
||||
rw [h, Int.emod_bmod]
|
||||
· apply Int.emod_nonneg
|
||||
exact Int.pow_ne_zero (by decide)
|
||||
|
||||
/-! ### sle/slt -/
|
||||
|
||||
/--
|
||||
@@ -3082,10 +3109,6 @@ theorem setWidth_succ (x : BitVec w) :
|
||||
· simp_all
|
||||
· omega
|
||||
|
||||
@[deprecated "Use the reverse direction of `cons_msb_setWidth`" (since := "2024-09-23")]
|
||||
theorem eq_msb_cons_setWidth (x : BitVec (w+1)) : x = (cons x.msb (x.setWidth w)) := by
|
||||
simp
|
||||
|
||||
@[simp] theorem not_cons (x : BitVec w) (b : Bool) : ~~~(cons b x) = cons (!b) (~~~x) := by
|
||||
simp [cons]
|
||||
|
||||
@@ -5312,6 +5335,14 @@ theorem msb_eq_toNat {x : BitVec w}:
|
||||
x.msb = decide (x.toNat ≥ 2 ^ (w - 1)) := by
|
||||
simp only [msb_eq_decide, ge_iff_le]
|
||||
|
||||
/-- Negating a bitvector created from a natural number equals
|
||||
creating a bitvector from the the negative of that number.
|
||||
-/
|
||||
theorem neg_ofNat_eq_ofInt_neg {w : Nat} {x : Nat} :
|
||||
- BitVec.ofNat w x = BitVec.ofInt w (- x) := by
|
||||
apply BitVec.eq_of_toInt_eq
|
||||
simp [BitVec.toInt_neg, BitVec.toInt_ofNat]
|
||||
|
||||
/-! ### abs -/
|
||||
|
||||
theorem abs_eq (x : BitVec w) : x.abs = if x.msb then -x else x := by rfl
|
||||
@@ -5547,150 +5578,6 @@ abbrev toFin_uShiftRight := @toFin_ushiftRight
|
||||
@[deprecated signExtend_eq_setWidth_of_msb_false (since := "2024-12-08")]
|
||||
abbrev signExtend_eq_not_setWidth_not_of_msb_false := @signExtend_eq_setWidth_of_msb_false
|
||||
|
||||
@[deprecated truncate_eq_setWidth (since := "2024-09-18")]
|
||||
abbrev truncate_eq_zeroExtend := @truncate_eq_setWidth
|
||||
|
||||
@[deprecated toNat_setWidth' (since := "2024-09-18")]
|
||||
abbrev toNat_zeroExtend' := @toNat_setWidth'
|
||||
|
||||
@[deprecated toNat_setWidth (since := "2024-09-18")]
|
||||
abbrev toNat_zeroExtend := @toNat_setWidth
|
||||
|
||||
@[deprecated toNat_setWidth (since := "2024-09-18")]
|
||||
abbrev toNat_truncate := @toNat_setWidth
|
||||
|
||||
@[deprecated setWidth_eq (since := "2024-09-18")]
|
||||
abbrev zeroExtend_eq := @setWidth_eq
|
||||
|
||||
@[deprecated setWidth_eq (since := "2024-09-18")]
|
||||
abbrev truncate_eq := @setWidth_eq
|
||||
|
||||
@[deprecated setWidth_zero (since := "2024-09-18")]
|
||||
abbrev zeroExtend_zero := @setWidth_zero
|
||||
|
||||
@[deprecated getElem_setWidth (since := "2024-09-18")]
|
||||
abbrev getElem_zeroExtend := @getElem_setWidth
|
||||
|
||||
@[deprecated getElem_setWidth' (since := "2024-09-18")]
|
||||
abbrev getElem_zeroExtend' := @getElem_setWidth'
|
||||
|
||||
@[deprecated getElem?_setWidth (since := "2024-09-18")]
|
||||
abbrev getElem?_zeroExtend := @getElem?_setWidth
|
||||
|
||||
@[deprecated getElem?_setWidth' (since := "2024-09-18")]
|
||||
abbrev getElem?_zeroExtend' := @getElem?_setWidth'
|
||||
|
||||
@[deprecated getLsbD_setWidth (since := "2024-09-18")]
|
||||
abbrev getLsbD_zeroExtend := @getLsbD_setWidth
|
||||
|
||||
@[deprecated getLsbD_setWidth' (since := "2024-09-18")]
|
||||
abbrev getLsbD_zeroExtend' := @getLsbD_setWidth'
|
||||
|
||||
@[deprecated getMsbD_setWidth_add (since := "2024-09-18")]
|
||||
abbrev getMsbD_zeroExtend_add := @getMsbD_setWidth_add
|
||||
|
||||
@[deprecated getMsbD_setWidth' (since := "2024-09-18")]
|
||||
abbrev getMsbD_zeroExtend' := @getMsbD_setWidth'
|
||||
|
||||
@[deprecated getElem_setWidth (since := "2024-09-18")]
|
||||
abbrev getElem_truncate := @getElem_setWidth
|
||||
|
||||
@[deprecated getElem?_setWidth (since := "2024-09-18")]
|
||||
abbrev getElem?_truncate := @getElem?_setWidth
|
||||
|
||||
@[deprecated getLsbD_setWidth (since := "2024-09-18")]
|
||||
abbrev getLsbD_truncate := @getLsbD_setWidth
|
||||
|
||||
@[deprecated msb_setWidth (since := "2024-09-18")]
|
||||
abbrev msb_truncate := @msb_setWidth
|
||||
|
||||
@[deprecated cast_setWidth (since := "2024-09-18")]
|
||||
abbrev cast_zeroExtend := @cast_setWidth
|
||||
|
||||
@[deprecated cast_setWidth (since := "2024-09-18")]
|
||||
abbrev cast_truncate := @cast_setWidth
|
||||
|
||||
@[deprecated setWidth_setWidth_of_le (since := "2024-09-18")]
|
||||
abbrev zeroExtend_zeroExtend_of_le := @setWidth_setWidth_of_le
|
||||
|
||||
@[deprecated setWidth_eq (since := "2024-09-18")]
|
||||
abbrev truncate_eq_self := @setWidth_eq
|
||||
|
||||
@[deprecated setWidth_cast (since := "2024-09-18")]
|
||||
abbrev truncate_cast := @setWidth_cast
|
||||
|
||||
@[deprecated msb_setWidth (since := "2024-09-18")]
|
||||
abbrev mbs_zeroExtend := @msb_setWidth
|
||||
|
||||
@[deprecated msb_setWidth' (since := "2024-09-18")]
|
||||
abbrev mbs_zeroExtend' := @msb_setWidth'
|
||||
|
||||
@[deprecated setWidth_one_eq_ofBool_getLsb_zero (since := "2024-09-18")]
|
||||
abbrev zeroExtend_one_eq_ofBool_getLsb_zero := @setWidth_one_eq_ofBool_getLsb_zero
|
||||
|
||||
@[deprecated setWidth_ofNat_one_eq_ofNat_one_of_lt (since := "2024-09-18")]
|
||||
abbrev zeroExtend_ofNat_one_eq_ofNat_one_of_lt := @setWidth_ofNat_one_eq_ofNat_one_of_lt
|
||||
|
||||
@[deprecated setWidth_one (since := "2024-09-18")]
|
||||
abbrev truncate_one := @setWidth_one
|
||||
|
||||
@[deprecated setWidth_ofNat_of_le (since := "2024-09-18")]
|
||||
abbrev truncate_ofNat_of_le := @setWidth_ofNat_of_le
|
||||
|
||||
@[deprecated setWidth_or (since := "2024-09-18")]
|
||||
abbrev truncate_or := @setWidth_or
|
||||
|
||||
@[deprecated setWidth_and (since := "2024-09-18")]
|
||||
abbrev truncate_and := @setWidth_and
|
||||
|
||||
@[deprecated setWidth_xor (since := "2024-09-18")]
|
||||
abbrev truncate_xor := @setWidth_xor
|
||||
|
||||
@[deprecated setWidth_not (since := "2024-09-18")]
|
||||
abbrev truncate_not := @setWidth_not
|
||||
|
||||
@[deprecated signExtend_eq_setWidth_of_msb_false (since := "2024-09-18")]
|
||||
abbrev signExtend_eq_not_zeroExtend_not_of_msb_false := @signExtend_eq_setWidth_of_msb_false
|
||||
|
||||
@[deprecated signExtend_eq_not_setWidth_not_of_msb_true (since := "2024-09-18")]
|
||||
abbrev signExtend_eq_not_zeroExtend_not_of_msb_true := @signExtend_eq_not_setWidth_not_of_msb_true
|
||||
|
||||
@[deprecated signExtend_eq_setWidth_of_lt (since := "2024-09-18")]
|
||||
abbrev signExtend_eq_truncate_of_lt := @signExtend_eq_setWidth_of_le
|
||||
|
||||
@[deprecated truncate_append (since := "2024-09-18")]
|
||||
abbrev truncate_append := @setWidth_append
|
||||
|
||||
@[deprecated truncate_append_of_eq (since := "2024-09-18")]
|
||||
abbrev truncate_append_of_eq := @setWidth_append_of_eq
|
||||
|
||||
@[deprecated truncate_cons (since := "2024-09-18")]
|
||||
abbrev truncate_cons := @setWidth_cons
|
||||
|
||||
@[deprecated truncate_succ (since := "2024-09-18")]
|
||||
abbrev truncate_succ := @setWidth_succ
|
||||
|
||||
@[deprecated truncate_add (since := "2024-09-18")]
|
||||
abbrev truncate_add := @setWidth_add
|
||||
|
||||
@[deprecated setWidth_setWidth_succ_eq_setWidth_setWidth_of_getLsbD_false (since := "2024-09-18")]
|
||||
abbrev zeroExtend_truncate_succ_eq_zeroExtend_truncate_of_getLsbD_false := @setWidth_setWidth_succ_eq_setWidth_setWidth_of_getLsbD_false
|
||||
|
||||
@[deprecated setWidth_setWidth_succ_eq_setWidth_setWidth_or_twoPow_of_getLsbD_true (since := "2024-09-18")]
|
||||
abbrev zeroExtend_truncate_succ_eq_zeroExtend_truncate_or_twoPow_of_getLsbD_true := @setWidth_setWidth_succ_eq_setWidth_setWidth_or_twoPow_of_getLsbD_true
|
||||
|
||||
@[deprecated and_one_eq_setWidth_ofBool_getLsbD (since := "2024-09-18")]
|
||||
abbrev and_one_eq_zeroExtend_ofBool_getLsbD := @and_one_eq_setWidth_ofBool_getLsbD
|
||||
|
||||
@[deprecated msb_sshiftRight (since := "2024-10-03")]
|
||||
abbrev sshiftRight_msb_eq_msb := @msb_sshiftRight
|
||||
|
||||
@[deprecated shiftLeft_zero (since := "2024-10-27")]
|
||||
abbrev shiftLeft_zero_eq := @shiftLeft_zero
|
||||
|
||||
@[deprecated ushiftRight_zero (since := "2024-10-27")]
|
||||
abbrev ushiftRight_zero_eq := @ushiftRight_zero
|
||||
|
||||
@[deprecated replicate_zero (since := "2025-01-08")]
|
||||
abbrev replicate_zero_eq := @replicate_zero
|
||||
|
||||
|
||||
@@ -230,6 +230,19 @@ instance : ShiftRight (Fin n) where
|
||||
instance instOfNat {n : Nat} [NeZero n] {i : Nat} : OfNat (Fin n) i where
|
||||
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 :=
|
||||
Nat.lt_of_le_of_lt (Nat.zero_le _) i.2
|
||||
|
||||
/-- Negation on `Fin n` -/
|
||||
instance neg (n : Nat) : Neg (Fin n) :=
|
||||
⟨fun a => ⟨(n - a) % n, Nat.mod_lt _ a.pos⟩⟩
|
||||
|
||||
theorem neg_def (a : Fin n) : -a = ⟨(n - a) % n, Nat.mod_lt _ a.pos⟩ := rfl
|
||||
|
||||
protected theorem coe_neg (a : Fin n) : ((-a : Fin n) : Nat) = (n - a) % n :=
|
||||
rfl
|
||||
|
||||
instance instInhabited {n : Nat} [NeZero n] : Inhabited (Fin n) where
|
||||
default := 0
|
||||
|
||||
@@ -247,10 +260,6 @@ theorem modn_lt : ∀ {m : Nat} (i : Fin n), m > 0 → (modn i m).val < m
|
||||
theorem val_lt_of_le (i : Fin b) (h : b ≤ n) : i.val < n :=
|
||||
Nat.lt_of_lt_of_le i.isLt h
|
||||
|
||||
/-- If you actually have an element of `Fin n`, then the `n` is always positive -/
|
||||
protected theorem pos (i : Fin n) : 0 < n :=
|
||||
Nat.lt_of_le_of_lt (Nat.zero_le _) i.2
|
||||
|
||||
/--
|
||||
The greatest value of `Fin (n+1)`, namely `n`.
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ module
|
||||
prelude
|
||||
import Init.Data.Fin.Basic
|
||||
import Init.Data.Nat.Lemmas
|
||||
import Init.Data.Int.DivMod.Lemmas
|
||||
import Init.Ext
|
||||
import Init.ByCases
|
||||
import Init.Conv
|
||||
@@ -99,6 +100,21 @@ theorem dite_val {n : Nat} {c : Prop} [Decidable c] {x y : Fin n} :
|
||||
(if c then x else y).val = if c then x.val else y.val := by
|
||||
by_cases c <;> simp [*]
|
||||
|
||||
instance (n : Nat) [NeZero n] : NatCast (Fin n) where
|
||||
natCast a := Fin.ofNat' n a
|
||||
|
||||
def intCast [NeZero n] (a : Int) : Fin n :=
|
||||
if 0 ≤ a then
|
||||
Fin.ofNat' n a.natAbs
|
||||
else
|
||||
- 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
|
||||
|
||||
/-! ### order -/
|
||||
|
||||
theorem le_def {a b : Fin n} : a ≤ b ↔ a.1 ≤ b.1 := .rfl
|
||||
@@ -156,7 +172,7 @@ protected theorem eq_or_lt_of_le {a b : Fin n} : a ≤ b → a = b ∨ a < b :=
|
||||
protected theorem lt_or_eq_of_le {a b : Fin n} : a ≤ b → a < b ∨ a = b := by
|
||||
rw [Fin.ext_iff]; exact Nat.lt_or_eq_of_le
|
||||
|
||||
theorem is_le (i : Fin (n + 1)) : i ≤ n := Nat.le_of_lt_succ i.is_lt
|
||||
theorem is_le (i : Fin (n + 1)) : i.1 ≤ n := Nat.le_of_lt_succ i.is_lt
|
||||
|
||||
@[simp] theorem is_le' {a : Fin n} : a ≤ n := Nat.le_of_lt a.is_lt
|
||||
|
||||
@@ -174,13 +190,13 @@ theorem mk_le_of_le_val {b : Fin n} {a : Nat} (h : a ≤ b) :
|
||||
|
||||
@[simp] theorem mk_zero : (⟨0, Nat.succ_pos n⟩ : Fin (n + 1)) = 0 := rfl
|
||||
|
||||
@[simp] theorem zero_le (a : Fin (n + 1)) : 0 ≤ a := Nat.zero_le a.val
|
||||
@[simp] theorem zero_le [NeZero n] (a : Fin n) : 0 ≤ a := Nat.zero_le a.val
|
||||
|
||||
theorem zero_lt_one : (0 : Fin (n + 2)) < 1 := Nat.zero_lt_one
|
||||
|
||||
@[simp] theorem not_lt_zero (a : Fin (n + 1)) : ¬a < 0 := nofun
|
||||
@[simp] theorem not_lt_zero [NeZero n] (a : Fin n) : ¬a < 0 := nofun
|
||||
|
||||
theorem pos_iff_ne_zero {a : Fin (n + 1)} : 0 < a ↔ a ≠ 0 := by
|
||||
theorem pos_iff_ne_zero [NeZero n] {a : Fin n} : 0 < a ↔ a ≠ 0 := by
|
||||
rw [lt_def, val_zero, Nat.pos_iff_ne_zero, ← val_ne_iff]; rfl
|
||||
|
||||
theorem eq_zero_or_eq_succ {n : Nat} : ∀ i : Fin (n + 1), i = 0 ∨ ∃ j : Fin n, i = j.succ
|
||||
@@ -219,7 +235,7 @@ theorem rev_eq {n a : Nat} (i : Fin (n + 1)) (h : n = a + i) :
|
||||
|
||||
/-! ### last -/
|
||||
|
||||
@[simp] theorem val_last (n : Nat) : last n = n := rfl
|
||||
@[simp] theorem val_last (n : Nat) : (last n).1 = n := rfl
|
||||
|
||||
@[simp] theorem last_zero : (Fin.last 0 : Fin 1) = 0 := by
|
||||
ext
|
||||
@@ -260,7 +276,7 @@ theorem subsingleton_iff_le_one : Subsingleton (Fin n) ↔ n ≤ 1 := by
|
||||
(match n with | 0 | 1 | n+2 => ?_) <;> try simp
|
||||
· exact ⟨nofun⟩
|
||||
· exact ⟨fun ⟨0, _⟩ ⟨0, _⟩ => rfl⟩
|
||||
· exact iff_of_false (fun h => Fin.ne_of_lt zero_lt_one (h.elim ..)) (of_decide_eq_false rfl)
|
||||
· exact fun h => by have := zero_lt_one (n := n); simp_all [h.elim 0 1]
|
||||
|
||||
instance subsingleton_zero : Subsingleton (Fin 0) := subsingleton_iff_le_one.2 (by decide)
|
||||
|
||||
@@ -506,17 +522,17 @@ theorem castSucc_inj {a b : Fin n} : a.castSucc = b.castSucc ↔ a = b := by sim
|
||||
|
||||
theorem castSucc_lt_last (a : Fin n) : a.castSucc < last n := a.is_lt
|
||||
|
||||
@[simp] theorem castSucc_zero : castSucc (0 : Fin (n + 1)) = 0 := rfl
|
||||
@[simp] theorem castSucc_zero [NeZero n] : castSucc (0 : Fin n) = 0 := rfl
|
||||
|
||||
@[simp] theorem castSucc_one {n : Nat} : castSucc (1 : Fin (n + 2)) = 1 := rfl
|
||||
|
||||
/-- `castSucc i` is positive when `i` is positive -/
|
||||
theorem castSucc_pos {i : Fin (n + 1)} (h : 0 < i) : 0 < i.castSucc := by
|
||||
theorem castSucc_pos [NeZero n] {i : Fin n} (h : 0 < i) : 0 < i.castSucc := by
|
||||
simpa [lt_def] using h
|
||||
|
||||
@[simp] theorem castSucc_eq_zero_iff {a : Fin (n + 1)} : a.castSucc = 0 ↔ a = 0 := by simp [Fin.ext_iff]
|
||||
@[simp] theorem castSucc_eq_zero_iff [NeZero n] {a : Fin n} : a.castSucc = 0 ↔ a = 0 := by simp [Fin.ext_iff]
|
||||
|
||||
theorem castSucc_ne_zero_iff {a : Fin (n + 1)} : a.castSucc ≠ 0 ↔ a ≠ 0 :=
|
||||
theorem castSucc_ne_zero_iff [NeZero n] {a : Fin n} : a.castSucc ≠ 0 ↔ a ≠ 0 :=
|
||||
not_congr <| castSucc_eq_zero_iff
|
||||
|
||||
theorem castSucc_fin_succ (n : Nat) (j : Fin n) :
|
||||
@@ -925,6 +941,15 @@ theorem addCases_right {m n : Nat} {motive : Fin (m + n) → Sort _} {left right
|
||||
have : ¬(natAdd m i : Nat) < m := Nat.not_lt.2 (le_coe_natAdd ..)
|
||||
rw [addCases, dif_neg this]; exact eq_of_heq <| (eqRec_heq _ _).trans (by congr 1; simp)
|
||||
|
||||
/-! ### zero -/
|
||||
|
||||
@[simp, norm_cast]
|
||||
theorem val_eq_zero_iff [NeZero n] {a : Fin n} : a.val = 0 ↔ a = 0 := by
|
||||
rw [Fin.ext_iff, val_zero]
|
||||
|
||||
theorem val_ne_zero_iff [NeZero n] {a : Fin n} : a.val ≠ 0 ↔ a ≠ 0 :=
|
||||
not_congr val_eq_zero_iff
|
||||
|
||||
/-! ### add -/
|
||||
|
||||
theorem ofNat'_add [NeZero n] (x : Nat) (y : Fin n) :
|
||||
@@ -984,6 +1009,17 @@ theorem coe_sub_iff_lt {a b : Fin n} : (↑(a - b) : Nat) = n + a - b ↔ a < b
|
||||
rw [Nat.mod_eq_of_lt]
|
||||
all_goals omega
|
||||
|
||||
/-! ### neg -/
|
||||
|
||||
theorem val_neg {n : Nat} [NeZero n] (x : Fin n) :
|
||||
(-x).val = if x = 0 then 0 else n - x.val := by
|
||||
change (n - ↑x) % n = _
|
||||
split <;> rename_i h
|
||||
· simp_all
|
||||
· rw [Nat.mod_eq_of_lt]
|
||||
have := Fin.val_ne_zero_iff.mpr h
|
||||
omega
|
||||
|
||||
/-! ### mul -/
|
||||
|
||||
theorem ofNat'_mul [NeZero n] (x : Nat) (y : Fin n) :
|
||||
@@ -1002,10 +1038,12 @@ theorem val_mul {n : Nat} : ∀ a b : Fin n, (a * b).val = a.val * b.val % n
|
||||
theorem coe_mul {n : Nat} : ∀ a b : Fin n, ((a * b : Fin n) : Nat) = a * b % n
|
||||
| ⟨_, _⟩, ⟨_, _⟩ => rfl
|
||||
|
||||
protected theorem mul_one (k : Fin (n + 1)) : k * 1 = k := by
|
||||
match n with
|
||||
| 0 => exact Subsingleton.elim (α := Fin 1) ..
|
||||
| n+1 => simp [Fin.ext_iff, mul_def, Nat.mod_eq_of_lt (is_lt k)]
|
||||
protected theorem mul_one [i : NeZero n] (k : Fin n) : k * 1 = k := by
|
||||
match n, i with
|
||||
| n + 1, _ =>
|
||||
match n with
|
||||
| 0 => exact Subsingleton.elim (α := Fin 1) ..
|
||||
| n+1 => simp [Fin.ext_iff, mul_def, Nat.mod_eq_of_lt (is_lt k)]
|
||||
|
||||
protected theorem mul_comm (a b : Fin n) : a * b = b * a :=
|
||||
Fin.ext <| by rw [mul_def, mul_def, Nat.mul_comm]
|
||||
@@ -1018,15 +1056,17 @@ protected theorem mul_assoc (a b c : Fin n) : a * b * c = a * (b * c) := by
|
||||
simp only [← Nat.mul_mod, Nat.mul_assoc]
|
||||
instance : Std.Associative (α := Fin n) (· * ·) := ⟨Fin.mul_assoc⟩
|
||||
|
||||
protected theorem one_mul (k : Fin (n + 1)) : (1 : Fin (n + 1)) * k = k := by
|
||||
protected theorem one_mul [NeZero n] (k : Fin n) : (1 : Fin n) * k = k := by
|
||||
rw [Fin.mul_comm, Fin.mul_one]
|
||||
instance : Std.LawfulIdentity (α := Fin (n + 1)) (· * ·) 1 where
|
||||
|
||||
instance [NeZero n] : Std.LawfulIdentity (α := Fin n) (· * ·) 1 where
|
||||
left_id := Fin.one_mul
|
||||
right_id := Fin.mul_one
|
||||
|
||||
protected theorem mul_zero (k : Fin (n + 1)) : k * 0 = 0 := by simp [Fin.ext_iff, mul_def]
|
||||
protected theorem mul_zero [NeZero n] (k : Fin n) : k * 0 = 0 := by
|
||||
simp [Fin.ext_iff, mul_def]
|
||||
|
||||
protected theorem zero_mul (k : Fin (n + 1)) : (0 : Fin (n + 1)) * k = 0 := by
|
||||
protected theorem zero_mul [NeZero n] (k : Fin n) : (0 : Fin n) * k = 0 := by
|
||||
simp [Fin.ext_iff, mul_def]
|
||||
|
||||
end Fin
|
||||
|
||||
@@ -291,8 +291,11 @@ implementation.
|
||||
instance : Inhabited Float where
|
||||
default := UInt64.toFloat 0
|
||||
|
||||
protected def Float.repr (n : Float) (prec : Nat) : Std.Format :=
|
||||
if n < UInt64.toFloat 0 then Repr.addAppParen (toString n) prec else toString n
|
||||
|
||||
instance : Repr Float where
|
||||
reprPrec n prec := if n < UInt64.toFloat 0 then Repr.addAppParen (toString n) prec else toString n
|
||||
reprPrec := Float.repr
|
||||
|
||||
instance : ReprAtom Float := ⟨⟩
|
||||
|
||||
|
||||
@@ -292,8 +292,11 @@ implementation.
|
||||
instance : Inhabited Float32 where
|
||||
default := UInt64.toFloat32 0
|
||||
|
||||
protected def Float32.repr (n : Float32) (prec : Nat) : Std.Format :=
|
||||
if n < UInt64.toFloat32 0 then Repr.addAppParen (toString n) prec else toString n
|
||||
|
||||
instance : Repr Float32 where
|
||||
reprPrec n prec := if n < UInt64.toFloat32 0 then Repr.addAppParen (toString n) prec else toString n
|
||||
reprPrec := Float32.repr
|
||||
|
||||
instance : ReprAtom Float32 := ⟨⟩
|
||||
|
||||
|
||||
@@ -7,7 +7,8 @@ module
|
||||
|
||||
prelude
|
||||
import Init.Data.UInt.Basic
|
||||
import Init.Data.String
|
||||
import Init.Data.String.Basic
|
||||
import Init.Data.ByteArray.Basic
|
||||
universe u
|
||||
|
||||
instance : Hashable Nat where
|
||||
|
||||
@@ -108,7 +108,7 @@ theorem resolve_left_lt_lcm (a c d p x : Int) (a_pos : 0 < a) (d_pos : 0 < d) (h
|
||||
resolve_left a c d p x < lcm a (a * d / gcd (a * d) c) := by
|
||||
simp only [h₁, resolve_left_eq, resolve_left', add_of_le, Int.ofNat_lt]
|
||||
exact Nat.mod_lt _ (Nat.pos_of_ne_zero (lcm_ne_zero (Int.ne_of_gt a_pos)
|
||||
(Int.ne_of_gt (Int.ediv_pos_of_pos_of_dvd (Int.mul_pos a_pos d_pos) (Int.ofNat_nonneg _)
|
||||
(Int.ne_of_gt (Int.ediv_pos_of_pos_of_dvd (Int.mul_pos a_pos d_pos) (Int.natCast_nonneg _)
|
||||
(gcd_dvd_left _ _)))))
|
||||
|
||||
theorem resolve_left_ineq (a c d p x : Int) (a_pos : 0 < a) (b_pos : 0 < b)
|
||||
|
||||
@@ -44,7 +44,7 @@ Integer division that uses the E-rounding convention. Usually accessed via the `
|
||||
Division by zero is defined to be zero, rather than an error.
|
||||
|
||||
In the E-rounding convention (Euclidean division), `Int.emod x y` satisfies `0 ≤ Int.emod x y < Int.natAbs y`
|
||||
for `y ≠ 0` and `Int.ediv` is the unique function satisfying `Int.emod x y + (Int.edivx y) * y = x`
|
||||
for `y ≠ 0` and `Int.ediv` is the unique function satisfying `Int.emod x y + (Int.ediv x y) * y = x`
|
||||
for `y ≠ 0`.
|
||||
|
||||
This means that `Int.ediv x y` is `⌊x / y⌋` when `y > 0` and `⌈x / y⌉` when `y < 0`.
|
||||
@@ -76,7 +76,7 @@ def ediv : (@& Int) → (@& Int) → Int
|
||||
Integer modulus that uses the E-rounding convention. Usually accessed via the `%` operator.
|
||||
|
||||
In the E-rounding convention (Euclidean division), `Int.emod x y` satisfies `0 ≤ Int.emod x y < Int.natAbs y`
|
||||
for `y ≠ 0` and `Int.ediv` is the unique function satisfying `Int.emod x y + (Int.edivx y) * y = x`
|
||||
for `y ≠ 0` and `Int.ediv` is the unique function satisfying `Int.emod x y + (Int.ediv x y) * y = x`
|
||||
for `y ≠ 0`.
|
||||
|
||||
This function is overridden by the compiler with an efficient implementation. This definition is
|
||||
|
||||
@@ -23,6 +23,8 @@ open Nat (succ)
|
||||
|
||||
namespace Int
|
||||
|
||||
@[simp high] theorem natCast_eq_zero {n : Nat} : (n : Int) = 0 ↔ n = 0 := by omega
|
||||
|
||||
protected theorem exists_add_of_le {a b : Int} (h : a ≤ b) : ∃ (c : Nat), b = a + c :=
|
||||
⟨(b - a).toNat, by omega⟩
|
||||
|
||||
@@ -143,6 +145,20 @@ theorem dvd_of_mul_dvd_mul_left {a m n : Int} (ha : a ≠ 0) (h : a * m ∣ a *
|
||||
theorem dvd_of_mul_dvd_mul_right {a m n : Int} (ha : a ≠ 0) (h : m * a ∣ n * a) : m ∣ n :=
|
||||
dvd_of_mul_dvd_mul_left ha (by simpa [Int.mul_comm] using h)
|
||||
|
||||
@[norm_cast] theorem natCast_dvd_natCast {m n : Nat} : (↑m : Int) ∣ ↑n ↔ m ∣ n where
|
||||
mp := by
|
||||
rintro ⟨a, h⟩
|
||||
obtain rfl | hm := m.eq_zero_or_pos
|
||||
· simpa using h
|
||||
have ha : 0 ≤ a := Int.not_lt.1 fun ha ↦ by
|
||||
simpa [← h, Int.not_lt.2 (Int.natCast_nonneg _)]
|
||||
using Int.mul_neg_of_pos_of_neg (natCast_pos.2 hm) ha
|
||||
match a, ha with
|
||||
| (a : Nat), _ =>
|
||||
norm_cast at h
|
||||
exact ⟨a, h⟩
|
||||
mpr := by rintro ⟨a, rfl⟩; simp [Int.dvd_mul_right]
|
||||
|
||||
/-! ### *div zero -/
|
||||
|
||||
@[simp] protected theorem zero_tdiv : ∀ b : Int, tdiv 0 b = 0
|
||||
@@ -1031,6 +1047,27 @@ theorem ediv_dvd_of_dvd {m n : Int} (hmn : m ∣ n) : n / m ∣ n := by
|
||||
· obtain ⟨a, ha⟩ := hmn
|
||||
simp [ha, Int.mul_ediv_cancel_left _ hm, Int.dvd_mul_left]
|
||||
|
||||
theorem emod_natAbs_of_nonneg {x : Int} (h : 0 ≤ x) {n : Nat} :
|
||||
x.natAbs % n = (x % n).toNat := by
|
||||
match x, h with
|
||||
| (x : Nat), _ => rw [Int.natAbs_natCast, Int.ofNat_mod_ofNat, Int.toNat_natCast]
|
||||
|
||||
theorem emod_natAbs_of_neg {x : Int} (h : x < 0) {n : Nat} (w : n ≠ 0) :
|
||||
x.natAbs % n = if (n : Int) ∣ x then 0 else n - (x % n).toNat := by
|
||||
match x, h with
|
||||
| -(x + 1 : Nat), _ =>
|
||||
rw [Int.natAbs_neg]
|
||||
rw [Int.natAbs_cast]
|
||||
rw [Int.neg_emod]
|
||||
simp only [Int.dvd_neg]
|
||||
simp only [Int.natCast_dvd_natCast]
|
||||
split <;> rename_i h
|
||||
· rw [Nat.mod_eq_zero_of_dvd h]
|
||||
· rw [← Int.natCast_emod]
|
||||
simp only [Int.natAbs_natCast]
|
||||
have : (x + 1) % n < n := Nat.mod_lt (x + 1) (by omega)
|
||||
omega
|
||||
|
||||
/-! ### `/` and ordering -/
|
||||
|
||||
protected theorem ediv_mul_le (a : Int) {b : Int} (H : b ≠ 0) : a / b * b ≤ a :=
|
||||
@@ -1308,7 +1345,7 @@ theorem sign_tdiv (a b : Int) : sign (a.tdiv b) = if natAbs a < natAbs b then 0
|
||||
theorem ofNat_tmod (m n : Nat) : (↑(m % n) : Int) = tmod m n := rfl
|
||||
|
||||
theorem tmod_nonneg : ∀ {a : Int} (b : Int), 0 ≤ a → 0 ≤ tmod a b
|
||||
| ofNat _, -[_+1], _ | ofNat _, ofNat _, _ => ofNat_nonneg _
|
||||
| ofNat _, -[_+1], _ | ofNat _, ofNat _, _ => natCast_nonneg _
|
||||
|
||||
@[simp] theorem tmod_neg (a b : Int) : tmod a (-b) = tmod a b := by
|
||||
rw [tmod_def, tmod_def, Int.tdiv_neg, Int.neg_mul_neg]
|
||||
@@ -1321,7 +1358,7 @@ theorem tmod_lt_of_pos (a : Int) {b : Int} (H : 0 < b) : tmod a b < b :=
|
||||
match a, b, eq_succ_of_zero_lt H with
|
||||
| ofNat _, _, ⟨n, rfl⟩ => ofNat_lt.2 <| Nat.mod_lt _ n.succ_pos
|
||||
| -[_+1], _, ⟨n, rfl⟩ => Int.lt_of_le_of_lt
|
||||
(Int.neg_nonpos_of_nonneg <| Int.ofNat_nonneg _) (ofNat_pos.2 n.succ_pos)
|
||||
(Int.neg_nonpos_of_nonneg <| natCast_nonneg _) (natCast_pos.2 n.succ_pos)
|
||||
|
||||
theorem lt_tmod_of_pos (a : Int) {b : Int} (H : 0 < b) : -b < tmod a b :=
|
||||
match a, b, eq_succ_of_zero_lt H with
|
||||
@@ -1724,7 +1761,7 @@ protected theorem tdiv_mul_le (a : Int) {b : Int} (hb : b ≠ 0) : a.tdiv b * b
|
||||
· simp_all [tmod_nonneg]
|
||||
· match b, hb with
|
||||
| .ofNat (b + 1), _ =>
|
||||
have := lt_tmod_of_pos a (Int.ofNat_pos.2 (b.succ_pos))
|
||||
have := lt_tmod_of_pos a (natCast_pos.2 (b.succ_pos))
|
||||
simp_all
|
||||
omega
|
||||
| .negSucc b, _ =>
|
||||
@@ -2679,8 +2716,8 @@ theorem le_bmod {x : Int} {m : Nat} (h : 0 < m) : - (m/2) ≤ Int.bmod x m := by
|
||||
have v : (m : Int) % 2 = 0 ∨ (m : Int) % 2 = 1 := emod_two_eq _
|
||||
split <;> rename_i w
|
||||
· refine Int.le_trans ?_ (Int.emod_nonneg _ ?_)
|
||||
· exact Int.neg_nonpos_of_nonneg (Int.ediv_nonneg (Int.ofNat_nonneg _) (by decide))
|
||||
· exact Int.ne_of_gt (ofNat_pos.mpr h)
|
||||
· exact Int.neg_nonpos_of_nonneg (Int.ediv_nonneg (natCast_nonneg _) (by decide))
|
||||
· exact Int.ne_of_gt (natCast_pos.mpr h)
|
||||
· simp [Int.not_lt] at w
|
||||
refine Int.le_trans ?_ (Int.sub_le_sub_right w _)
|
||||
rw [← ediv_add_emod m 2]
|
||||
@@ -2713,7 +2750,7 @@ theorem bmod_lt {x : Int} {m : Nat} (h : 0 < m) : bmod x m < (m + 1) / 2 := by
|
||||
· assumption
|
||||
· apply Int.lt_of_lt_of_le
|
||||
· show _ < 0
|
||||
have : x % m < m := emod_lt_of_pos x (ofNat_pos.mpr h)
|
||||
have : x % m < m := emod_lt_of_pos x (natCast_pos.mpr h)
|
||||
exact Int.sub_neg_of_lt this
|
||||
· exact Int.le.intro_sub _ rfl
|
||||
|
||||
|
||||
@@ -594,4 +594,6 @@ protected theorem natCast_zero : ((0 : Nat) : Int) = (0 : Int) := rfl
|
||||
|
||||
protected theorem natCast_one : ((1 : Nat) : Int) = (1 : Int) := rfl
|
||||
|
||||
@[simp, norm_cast] theorem natAbs_cast (n : Nat) : natAbs ↑n = n := rfl
|
||||
|
||||
end Int
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace Int
|
||||
@[simp] protected theorem neg_nonpos_iff (i : Int) : -i ≤ 0 ↔ 0 ≤ i := by omega
|
||||
|
||||
@[simp] theorem zero_le_ofNat (n : Nat) : 0 ≤ ((no_index (OfNat.ofNat n)) : Int) :=
|
||||
ofNat_nonneg _
|
||||
natCast_nonneg _
|
||||
|
||||
@[simp] theorem neg_natCast_le_natCast (n m : Nat) : -(n : Int) ≤ (m : Int) :=
|
||||
Int.le_trans (by simp) (ofNat_zero_le m)
|
||||
@@ -52,25 +52,17 @@ protected theorem ofNat_add_one_out (n : Nat) : ↑n + (1 : Int) = ↑(Nat.succ
|
||||
|
||||
@[norm_cast] theorem natCast_inj {m n : Nat} : (m : Int) = (n : Int) ↔ m = n := ofNat_inj
|
||||
|
||||
@[simp, norm_cast] theorem natAbs_cast (n : Nat) : natAbs ↑n = n := rfl
|
||||
|
||||
@[norm_cast]
|
||||
protected theorem natCast_sub {n m : Nat} : n ≤ m → (↑(m - n) : Int) = ↑m - ↑n := ofNat_sub
|
||||
|
||||
@[simp high] theorem natCast_eq_zero {n : Nat} : (n : Int) = 0 ↔ n = 0 := by omega
|
||||
|
||||
theorem natCast_ne_zero {n : Nat} : (n : Int) ≠ 0 ↔ n ≠ 0 := by omega
|
||||
|
||||
theorem natCast_ne_zero_iff_pos {n : Nat} : (n : Int) ≠ 0 ↔ 0 < n := by omega
|
||||
|
||||
@[simp high] theorem natCast_pos {n : Nat} : (0 : Int) < n ↔ 0 < n := by omega
|
||||
|
||||
theorem natCast_succ_pos (n : Nat) : 0 < (n.succ : Int) := natCast_pos.2 n.succ_pos
|
||||
|
||||
@[simp high] theorem natCast_nonpos_iff {n : Nat} : (n : Int) ≤ 0 ↔ n = 0 := by omega
|
||||
|
||||
theorem natCast_nonneg (n : Nat) : 0 ≤ (n : Int) := ofNat_le.2 (Nat.zero_le _)
|
||||
|
||||
@[simp] theorem sign_natCast_add_one (n : Nat) : sign (n + 1) = 1 := rfl
|
||||
|
||||
@[simp, norm_cast] theorem cast_id {n : Int} : Int.cast n = n := rfl
|
||||
|
||||
@@ -282,7 +282,6 @@ attribute [local simp] Poly.denote_addConst
|
||||
theorem Poly.denote_insert (ctx : Context) (k : Int) (v : Var) (p : Poly) :
|
||||
(p.insert k v).denote ctx = p.denote ctx + k * v.denote ctx := by
|
||||
fun_induction p.insert k v <;>
|
||||
simp only [insert, cond_true, cond_false, ↓reduceIte, *] <;>
|
||||
simp_all [← Int.add_mul]
|
||||
|
||||
attribute [local simp] Poly.denote_insert
|
||||
@@ -299,7 +298,6 @@ attribute [local simp] Poly.denote_append
|
||||
|
||||
theorem Poly.denote_combine' (ctx : Context) (fuel : Nat) (p₁ p₂ : Poly) : (p₁.combine' fuel p₂).denote ctx = p₁.denote ctx + p₂.denote ctx := by
|
||||
fun_induction p₁.combine' fuel p₂ <;>
|
||||
simp +zetaDelta only [combine', cond_true, cond_false, *] <;>
|
||||
simp_all +zetaDelta [denote, ← Int.add_mul]
|
||||
|
||||
theorem Poly.denote_combine (ctx : Context) (p₁ p₂ : Poly) : (p₁.combine p₂).denote ctx = p₁.denote ctx + p₂.denote ctx := by
|
||||
|
||||
@@ -77,8 +77,14 @@ theorem lt.dest {a b : Int} (h : a < b) : ∃ n : Nat, a + Nat.succ n = b :=
|
||||
@[simp, norm_cast] theorem ofNat_lt {n m : Nat} : (↑n : Int) < ↑m ↔ n < m := by
|
||||
rw [lt_iff_add_one_le, ← natCast_succ, ofNat_le]; rfl
|
||||
|
||||
@[simp, norm_cast] theorem ofNat_pos {n : Nat} : 0 < (↑n : Int) ↔ 0 < n := ofNat_lt
|
||||
@[simp, norm_cast] theorem natCast_pos {n : Nat} : (0 : Int) < n ↔ 0 < n := ofNat_lt
|
||||
|
||||
@[deprecated natCast_pos (since := "2025-05-13"), simp high]
|
||||
theorem ofNat_pos {n : Nat} : 0 < (↑n : Int) ↔ 0 < n := ofNat_lt
|
||||
|
||||
theorem natCast_nonneg (n : Nat) : 0 ≤ (n : Int) := ⟨_⟩
|
||||
|
||||
@[deprecated natCast_nonneg (since := "2025-05-13")]
|
||||
theorem ofNat_nonneg (n : Nat) : 0 ≤ (n : Int) := ⟨_⟩
|
||||
|
||||
theorem ofNat_succ_pos (n : Nat) : 0 < (succ n : Int) := ofNat_lt.2 <| Nat.succ_pos _
|
||||
@@ -475,7 +481,7 @@ instance : Std.IdempotentOp (α := Int) max := ⟨Int.max_self⟩
|
||||
protected theorem mul_nonneg {a b : Int} (ha : 0 ≤ a) (hb : 0 ≤ b) : 0 ≤ a * b := by
|
||||
let ⟨n, hn⟩ := eq_ofNat_of_zero_le ha
|
||||
let ⟨m, hm⟩ := eq_ofNat_of_zero_le hb
|
||||
rw [hn, hm, ← natCast_mul]; apply ofNat_nonneg
|
||||
rw [hn, hm, ← natCast_mul]; apply natCast_nonneg
|
||||
|
||||
protected theorem mul_pos {a b : Int} (ha : 0 < a) (hb : 0 < b) : 0 < a * b := by
|
||||
let ⟨n, hn⟩ := eq_succ_of_zero_lt ha
|
||||
@@ -1253,7 +1259,7 @@ theorem neg_of_sign_eq_neg_one : ∀ {a : Int}, sign a = -1 → a < 0
|
||||
| 0 => rfl
|
||||
| .ofNat (_ + 1) =>
|
||||
simp +decide only [sign, true_iff]
|
||||
exact Int.le_add_one (ofNat_nonneg _)
|
||||
exact Int.le_add_one (natCast_nonneg _)
|
||||
| .negSucc _ => simp +decide [sign]
|
||||
|
||||
@[deprecated sign_nonneg_iff (since := "2025-03-11")] abbrev sign_nonneg := @sign_nonneg_iff
|
||||
|
||||
@@ -29,6 +29,11 @@ protected theorem pow_nonneg {n : Int} {m : Nat} : 0 ≤ n → 0 ≤ n ^ m := by
|
||||
| zero => simp
|
||||
| succ m ih => exact fun h => Int.mul_nonneg (ih h) h
|
||||
|
||||
protected theorem pow_ne_zero {n : Int} {m : Nat} : n ≠ 0 → n ^ m ≠ 0 := by
|
||||
induction m with
|
||||
| zero => simp
|
||||
| succ m ih => exact fun h => Int.mul_ne_zero (ih h) h
|
||||
|
||||
@[deprecated Nat.pow_le_pow_left (since := "2025-02-17")]
|
||||
abbrev pow_le_pow_of_le_left := @Nat.pow_le_pow_left
|
||||
|
||||
|
||||
@@ -90,8 +90,6 @@ theorem pmap_congr_left {p q : α → Prop} {f : ∀ a, p a → β} {g : ∀ a,
|
||||
| cons x l ih =>
|
||||
rw [pmap, pmap, h _ mem_cons_self, ih fun a ha => h a (mem_cons_of_mem _ ha)]
|
||||
|
||||
@[deprecated pmap_congr_left (since := "2024-09-06")] abbrev pmap_congr := @pmap_congr_left
|
||||
|
||||
theorem map_pmap {p : α → Prop} {g : β → γ} {f : ∀ a, p a → β} {l : List α} (H) :
|
||||
map g (pmap f l H) = pmap (fun a h => g (f a h)) l H := by
|
||||
induction l
|
||||
@@ -237,11 +235,6 @@ theorem attachWith_ne_nil_iff {l : List α} {P : α → Prop} {H : ∀ a ∈ l,
|
||||
l.attachWith P H ≠ [] ↔ l ≠ [] :=
|
||||
pmap_ne_nil_iff _ _
|
||||
|
||||
@[deprecated pmap_eq_nil_iff (since := "2024-09-06")] abbrev pmap_eq_nil := @pmap_eq_nil_iff
|
||||
@[deprecated pmap_ne_nil_iff (since := "2024-09-06")] abbrev pmap_ne_nil := @pmap_ne_nil_iff
|
||||
@[deprecated attach_eq_nil_iff (since := "2024-09-06")] abbrev attach_eq_nil := @attach_eq_nil_iff
|
||||
@[deprecated attach_ne_nil_iff (since := "2024-09-06")] abbrev attach_ne_nil := @attach_ne_nil_iff
|
||||
|
||||
@[simp]
|
||||
theorem getElem?_pmap {p : α → Prop} {f : ∀ a, p a → β} {l : List α} (h : ∀ a ∈ l, p a) (i : Nat) :
|
||||
(pmap f l h)[i]? = Option.pmap f l[i]? fun x H => h x (mem_of_getElem? H) := by
|
||||
@@ -776,8 +769,6 @@ and simplifies these to the function directly taking the value.
|
||||
| nil => simp
|
||||
| cons a l ih => simp [ih, hf]
|
||||
|
||||
@[deprecated flatMap_subtype (since := "2024-10-16")] abbrev bind_subtype := @flatMap_subtype
|
||||
|
||||
@[simp] theorem findSome?_subtype {p : α → Prop} {l : List { x // p x }}
|
||||
{f : { x // p x } → Option β} {g : α → Option β} (hf : ∀ x h, f ⟨x, h⟩ = g x) :
|
||||
l.findSome? f = l.unattach.findSome? g := by
|
||||
@@ -830,8 +821,6 @@ and simplifies these to the function directly taking the value.
|
||||
unfold unattach
|
||||
induction l <;> simp_all
|
||||
|
||||
@[deprecated unattach_flatten (since := "2024-10-14")] abbrev unattach_join := @unattach_flatten
|
||||
|
||||
@[simp] theorem unattach_replicate {p : α → Prop} {n : Nat} {x : { x // p x }} :
|
||||
(List.replicate n x).unattach = List.replicate n x.1 := by
|
||||
simp [unattach, -map_subtype]
|
||||
|
||||
@@ -703,8 +703,6 @@ def flatten : List (List α) → List α
|
||||
@[simp, grind] theorem flatten_nil : List.flatten ([] : List (List α)) = [] := rfl
|
||||
@[simp, grind] theorem flatten_cons : (l :: L).flatten = l ++ L.flatten := rfl
|
||||
|
||||
@[deprecated flatten (since := "2024-10-14"), inherit_doc flatten] abbrev join := @flatten
|
||||
|
||||
/-! ### singleton -/
|
||||
|
||||
/--
|
||||
@@ -717,9 +715,6 @@ Examples:
|
||||
-/
|
||||
@[inline] protected def singleton {α : Type u} (a : α) : List α := [a]
|
||||
|
||||
set_option linter.missingDocs false in
|
||||
@[deprecated singleton (since := "2024-10-16")] protected abbrev pure := @singleton
|
||||
|
||||
/-! ### flatMap -/
|
||||
|
||||
/--
|
||||
@@ -736,13 +731,6 @@ Examples:
|
||||
@[simp, grind] theorem flatMap_cons {x : α} {xs : List α} {f : α → List β} :
|
||||
List.flatMap f (x :: xs) = f x ++ List.flatMap f xs := by simp [flatten, List.flatMap]
|
||||
|
||||
set_option linter.missingDocs false in
|
||||
@[deprecated flatMap (since := "2024-10-16")] abbrev bind := @flatMap
|
||||
set_option linter.missingDocs false in
|
||||
@[deprecated flatMap_nil (since := "2024-10-16")] abbrev nil_flatMap := @flatMap_nil
|
||||
set_option linter.missingDocs false in
|
||||
@[deprecated flatMap_cons (since := "2024-10-16")] abbrev cons_flatMap := @flatMap_cons
|
||||
|
||||
/-! ### replicate -/
|
||||
|
||||
/--
|
||||
@@ -2087,18 +2075,6 @@ def sum {α} [Add α] [Zero α] : List α → α :=
|
||||
@[simp, grind] theorem sum_nil [Add α] [Zero α] : ([] : List α).sum = 0 := rfl
|
||||
@[simp, grind] theorem sum_cons [Add α] [Zero α] {a : α} {l : List α} : (a::l).sum = a + l.sum := rfl
|
||||
|
||||
/-- Sum of a list of natural numbers. -/
|
||||
@[deprecated List.sum (since := "2024-10-17")]
|
||||
protected def _root_.Nat.sum (l : List Nat) : Nat := l.foldr (·+·) 0
|
||||
|
||||
set_option linter.deprecated false in
|
||||
@[deprecated sum_nil (since := "2024-10-17")]
|
||||
theorem _root_.Nat.sum_nil : Nat.sum ([] : List Nat) = 0 := rfl
|
||||
set_option linter.deprecated false in
|
||||
@[deprecated sum_cons (since := "2024-10-17")]
|
||||
theorem _root_.Nat.sum_cons (a : Nat) (l : List Nat) :
|
||||
Nat.sum (a::l) = a + Nat.sum l := rfl
|
||||
|
||||
/-! ### range -/
|
||||
|
||||
/--
|
||||
@@ -2220,8 +2196,6 @@ def min? [Min α] : List α → Option α
|
||||
| [] => none
|
||||
| a::as => some <| as.foldl min a
|
||||
|
||||
@[inherit_doc min?, deprecated min? (since := "2024-09-29")] abbrev minimum? := @min?
|
||||
|
||||
/-! ### max? -/
|
||||
|
||||
/--
|
||||
@@ -2236,8 +2210,6 @@ def max? [Max α] : List α → Option α
|
||||
| [] => none
|
||||
| a::as => some <| as.foldl max a
|
||||
|
||||
@[inherit_doc max?, deprecated max? (since := "2024-09-29")] abbrev maximum? := @max?
|
||||
|
||||
/-! ## Other list operations
|
||||
|
||||
The functions are currently mostly used in meta code,
|
||||
@@ -2410,8 +2382,6 @@ where
|
||||
| false => loop as a [] ((b::r).reverse::acc)
|
||||
| [], ag, r, acc => ((ag::r).reverse::acc).reverse
|
||||
|
||||
@[deprecated splitBy (since := "2024-10-30"), inherit_doc splitBy] abbrev groupBy := @splitBy
|
||||
|
||||
/-! ### removeAll -/
|
||||
|
||||
/--
|
||||
|
||||
@@ -83,8 +83,6 @@ theorem countP_le_length : countP p l ≤ l.length := by
|
||||
@[simp] theorem countP_pos_iff {p} : 0 < countP p l ↔ ∃ a ∈ l, p a := by
|
||||
simp only [countP_eq_length_filter, length_pos_iff_exists_mem, mem_filter, exists_prop]
|
||||
|
||||
@[deprecated countP_pos_iff (since := "2024-09-09")] abbrev countP_pos := @countP_pos_iff
|
||||
|
||||
@[simp] theorem one_le_countP_iff {p} : 1 ≤ countP p l ↔ ∃ a ∈ l, p a :=
|
||||
countP_pos_iff
|
||||
|
||||
@@ -165,8 +163,6 @@ theorem countP_filterMap {p : β → Bool} {f : α → Option β} {l : List α}
|
||||
simp only [countP_eq_length_filter, filter_flatten]
|
||||
simp [countP_eq_length_filter']
|
||||
|
||||
@[deprecated countP_flatten (since := "2024-10-14")] abbrev countP_join := @countP_flatten
|
||||
|
||||
theorem countP_flatMap {p : β → Bool} {l : List α} {f : α → List β} :
|
||||
countP p (l.flatMap f) = sum (map (countP p ∘ f) l) := by
|
||||
rw [List.flatMap, countP_flatten, map_map]
|
||||
@@ -242,8 +238,6 @@ theorem count_singleton {a b : α} : count a [b] = if b == a then 1 else 0 := by
|
||||
theorem count_flatten {a : α} {l : List (List α)} : count a l.flatten = (l.map (count a)).sum := by
|
||||
simp only [count_eq_countP, countP_flatten, count_eq_countP']
|
||||
|
||||
@[deprecated count_flatten (since := "2024-10-14")] abbrev count_join := @count_flatten
|
||||
|
||||
@[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]
|
||||
|
||||
@@ -268,8 +262,6 @@ theorem count_concat_self {a : α} {l : List α} : count a (concat l a) = count
|
||||
theorem count_pos_iff {a : α} {l : List α} : 0 < count a l ↔ a ∈ l := by
|
||||
simp only [count, countP_pos_iff, beq_iff_eq, exists_eq_right]
|
||||
|
||||
@[deprecated count_pos_iff (since := "2024-09-09")] abbrev count_pos_iff_mem := @count_pos_iff
|
||||
|
||||
@[simp] theorem one_le_count_iff {a : α} {l : List α} : 1 ≤ count a l ↔ a ∈ l :=
|
||||
count_pos_iff
|
||||
|
||||
|
||||
@@ -47,8 +47,6 @@ theorem exists_of_findSome?_eq_some {l : List α} {f : α → Option β} (w : l.
|
||||
@[simp] theorem findSome?_eq_none_iff : findSome? p l = none ↔ ∀ x ∈ l, p x = none := by
|
||||
induction l <;> simp [findSome?_cons]; split <;> simp [*]
|
||||
|
||||
@[deprecated findSome?_eq_none_iff (since := "2024-09-05")] abbrev findSome?_eq_none := @findSome?_eq_none_iff
|
||||
|
||||
@[simp] theorem findSome?_isSome_iff {f : α → Option β} {l : List α} :
|
||||
(l.findSome? f).isSome ↔ ∃ x, x ∈ l ∧ (f x).isSome := by
|
||||
induction l with
|
||||
@@ -386,17 +384,10 @@ abbrev find?_flatten_eq_some := @find?_flatten_eq_some_iff
|
||||
(xs.flatMap f).find? p = xs.findSome? (fun x => (f x).find? p) := by
|
||||
simp [flatMap_def, findSome?_map]; rfl
|
||||
|
||||
@[deprecated find?_flatMap (since := "2024-10-16")] abbrev find?_bind := @find?_flatMap
|
||||
|
||||
theorem find?_flatMap_eq_none_iff {xs : List α} {f : α → List β} {p : β → Bool} :
|
||||
(xs.flatMap f).find? p = none ↔ ∀ x ∈ xs, ∀ y ∈ f x, !p y := by
|
||||
simp
|
||||
|
||||
@[deprecated find?_flatMap_eq_none_iff (since := "2024-10-16")]
|
||||
abbrev find?_flatMap_eq_none := @find?_flatMap_eq_none_iff
|
||||
|
||||
@[deprecated find?_flatMap_eq_none (since := "2024-10-16")] abbrev find?_bind_eq_none := @find?_flatMap_eq_none_iff
|
||||
|
||||
theorem find?_replicate : find? p (replicate n a) = if n = 0 then none else if p a then some a else none := by
|
||||
cases n
|
||||
· simp
|
||||
@@ -1270,13 +1261,4 @@ theorem IsInfix.lookup_eq_none {l₁ l₂ : List (α × β)} (h : l₁ <:+: l₂
|
||||
|
||||
end lookup
|
||||
|
||||
/-! ### Deprecations -/
|
||||
|
||||
@[deprecated head_flatten (since := "2024-10-14")] abbrev head_join := @head_flatten
|
||||
@[deprecated getLast_flatten (since := "2024-10-14")] abbrev getLast_join := @getLast_flatten
|
||||
@[deprecated find?_flatten (since := "2024-10-14")] abbrev find?_join := @find?_flatten
|
||||
@[deprecated find?_flatten_eq_none (since := "2024-10-14")] abbrev find?_join_eq_none := @find?_flatten_eq_none_iff
|
||||
@[deprecated find?_flatten_eq_some (since := "2024-10-14")] abbrev find?_join_eq_some := @find?_flatten_eq_some_iff
|
||||
@[deprecated findIdx?_flatten (since := "2024-10-14")] abbrev findIdx?_join := @findIdx?_flatten
|
||||
|
||||
end List
|
||||
|
||||
@@ -92,7 +92,9 @@ open Nat
|
||||
|
||||
/-! ### length -/
|
||||
|
||||
@[grind →] theorem eq_nil_of_length_eq_zero (_ : length l = 0) : l = [] := match l with | [] => rfl
|
||||
-- Note: this is not a good `grind` candidate,
|
||||
-- as in some circumstances it results in many case splits.
|
||||
theorem eq_nil_of_length_eq_zero (_ : length l = 0) : l = [] := match l with | [] => rfl
|
||||
|
||||
theorem ne_nil_of_length_eq_add_one (_ : length l = n + 1) : l ≠ [] := fun _ => nomatch l
|
||||
|
||||
@@ -239,15 +241,17 @@ theorem getElem!_eq_getElem?_getD [Inhabited α] {l : List α} {i : Nat} :
|
||||
|
||||
@[simp, grind =] theorem getElem?_nil {i : Nat} : ([] : List α)[i]? = none := rfl
|
||||
|
||||
@[grind =]
|
||||
theorem getElem_cons {l : List α} (w : i < (a :: l).length) :
|
||||
(a :: l)[i] =
|
||||
if h : i = 0 then a else l[i-1]'(match i, h with | i+1, _ => succ_lt_succ_iff.mp w) := by
|
||||
cases i <;> simp
|
||||
|
||||
@[grind =] theorem getElem?_cons_zero {l : List α} : (a::l)[0]? = some a := rfl
|
||||
theorem getElem?_cons_zero {l : List α} : (a::l)[0]? = some a := rfl
|
||||
|
||||
@[simp, grind =] theorem getElem?_cons_succ {l : List α} : (a::l)[i+1]? = l[i]? := rfl
|
||||
@[simp] theorem getElem?_cons_succ {l : List α} : (a::l)[i+1]? = l[i]? := rfl
|
||||
|
||||
@[grind =]
|
||||
theorem getElem?_cons : (a :: l)[i]? = if i = 0 then some a else l[i-1]? := by
|
||||
cases i <;> simp [getElem?_cons_zero]
|
||||
|
||||
@@ -313,7 +317,7 @@ theorem getElem_zero {l : List α} (h : 0 < l.length) : l[0] = l.head (length_po
|
||||
match l, h with
|
||||
| _ :: _, _ => rfl
|
||||
|
||||
@[ext, grind ext] theorem ext_getElem? {l₁ l₂ : List α} (h : ∀ i : Nat, l₁[i]? = l₂[i]?) : l₁ = l₂ :=
|
||||
@[ext] theorem ext_getElem? {l₁ l₂ : List α} (h : ∀ i : Nat, l₁[i]? = l₂[i]?) : l₁ = l₂ :=
|
||||
match l₁, l₂, h with
|
||||
| [], [], _ => rfl
|
||||
| _ :: _, [], h => by simpa using h 0
|
||||
@@ -595,7 +599,7 @@ theorem decide_forall_mem {l : List α} {p : α → Prop} [DecidablePred p] :
|
||||
@[simp] theorem all_eq_false {l : List α} : l.all p = false ↔ ∃ x, x ∈ l ∧ ¬p x := by
|
||||
simp [all_eq]
|
||||
|
||||
theorem any_beq [BEq α] {l : List α} {a : α} : (l.any fun x => a == x) = l.contains a := by
|
||||
@[grind] theorem any_beq [BEq α] {l : List α} {a : α} : (l.any fun x => a == x) = l.contains a := by
|
||||
induction l <;> simp_all [contains_cons]
|
||||
|
||||
/-- Variant of `any_beq` with `==` reversed. -/
|
||||
@@ -603,7 +607,7 @@ theorem any_beq' [BEq α] [PartialEquivBEq α] {l : List α} :
|
||||
(l.any fun x => x == a) = l.contains a := by
|
||||
simp only [BEq.comm, any_beq]
|
||||
|
||||
theorem all_bne [BEq α] {l : List α} : (l.all fun x => a != x) = !l.contains a := by
|
||||
@[grind] theorem all_bne [BEq α] {l : List α} : (l.all fun x => a != x) = !l.contains a := by
|
||||
induction l <;> simp_all [bne]
|
||||
|
||||
/-- Variant of `all_bne` with `!=` reversed. -/
|
||||
@@ -1139,8 +1143,6 @@ theorem forall_mem_map {f : α → β} {l : List α} {P : β → Prop} :
|
||||
@[simp] theorem map_eq_nil_iff {f : α → β} {l : List α} : map f l = [] ↔ l = [] := by
|
||||
constructor <;> exact fun _ => match l with | [] => rfl
|
||||
|
||||
@[deprecated map_eq_nil_iff (since := "2024-09-05")] abbrev map_eq_nil := @map_eq_nil_iff
|
||||
|
||||
@[grind →]
|
||||
theorem eq_nil_of_map_eq_nil {f : α → β} {l : List α} (h : map f l = []) : l = [] :=
|
||||
map_eq_nil_iff.mp h
|
||||
@@ -1182,14 +1184,10 @@ theorem map_eq_cons_iff {f : α → β} {l : List α} :
|
||||
· rintro ⟨a, l₁, ⟨rfl, rfl⟩, ⟨rfl, rfl⟩⟩
|
||||
constructor <;> rfl
|
||||
|
||||
@[deprecated map_eq_cons_iff (since := "2024-09-05")] abbrev map_eq_cons := @map_eq_cons_iff
|
||||
|
||||
theorem map_eq_cons_iff' {f : α → β} {l : List α} :
|
||||
map f l = b :: l₂ ↔ l.head?.map f = some b ∧ l.tail?.map (map f) = some l₂ := by
|
||||
induction l <;> simp_all
|
||||
|
||||
@[deprecated map_eq_cons' (since := "2024-09-05")] abbrev map_eq_cons' := @map_eq_cons_iff'
|
||||
|
||||
@[simp] theorem map_eq_singleton_iff {f : α → β} {l : List α} {b : β} :
|
||||
map f l = [b] ↔ ∃ a, l = [a] ∧ f a = b := by
|
||||
simp [map_eq_cons_iff]
|
||||
@@ -1214,11 +1212,6 @@ theorem map_eq_foldr {f : α → β} {l : List α} : map f l = foldr (fun a bs =
|
||||
| nil => simp
|
||||
| cons b l ih => cases i <;> simp_all
|
||||
|
||||
@[deprecated "Use the reverse direction of `map_set`." (since := "2024-09-20")]
|
||||
theorem set_map {f : α → β} {l : List α} {i : Nat} {a : α} :
|
||||
(map f l).set i (f a) = map f (l.set i a) := by
|
||||
simp
|
||||
|
||||
@[simp] theorem head_map {f : α → β} {l : List α} (w) :
|
||||
(map f l).head w = f (l.head (by simpa using w)) := by
|
||||
cases l
|
||||
@@ -1320,8 +1313,6 @@ abbrev filter_length_eq_length := @length_filter_eq_length_iff
|
||||
@[simp] theorem filter_eq_nil_iff {l} : filter p l = [] ↔ ∀ a, a ∈ l → ¬p a := by
|
||||
simp only [eq_nil_iff_forall_not_mem, mem_filter, not_and]
|
||||
|
||||
@[deprecated filter_eq_nil_iff (since := "2024-09-05")] abbrev filter_eq_nil := @filter_eq_nil_iff
|
||||
|
||||
theorem forall_mem_filter {l : List α} {p : α → Bool} {P : α → Prop} :
|
||||
(∀ (i) (_ : i ∈ l.filter p), P i) ↔ ∀ (j) (_ : j ∈ l), p j → P j := by
|
||||
simp
|
||||
@@ -1383,8 +1374,6 @@ theorem filter_eq_cons_iff {l} {a} {as} :
|
||||
· rintro ⟨l₁, l₂, rfl, h₁, h, h₂⟩
|
||||
simp [h₂, filter_cons, filter_eq_nil_iff.mpr h₁, h]
|
||||
|
||||
@[deprecated filter_eq_cons_iff (since := "2024-09-05")] abbrev filter_eq_cons := @filter_eq_cons_iff
|
||||
|
||||
theorem filter_congr {p q : α → Bool} :
|
||||
∀ {l : List α}, (∀ x ∈ l, p x = q x) → filter p l = filter q l
|
||||
| [], _ => rfl
|
||||
@@ -1544,8 +1533,6 @@ theorem forall_none_of_filterMap_eq_nil (h : filterMap f xs = []) : ∀ x ∈ xs
|
||||
simp_all
|
||||
· simp_all
|
||||
|
||||
@[deprecated filterMap_eq_nil_iff (since := "2024-09-05")] abbrev filterMap_eq_nil := @filterMap_eq_nil_iff
|
||||
|
||||
theorem filterMap_eq_cons_iff {l} {b} {bs} :
|
||||
filterMap f l = b :: bs ↔
|
||||
∃ l₁ a l₂, l = l₁ ++ a :: l₂ ∧ (∀ x, x ∈ l₁ → f x = none) ∧ f a = some b ∧
|
||||
@@ -1568,8 +1555,6 @@ theorem filterMap_eq_cons_iff {l} {b} {bs} :
|
||||
· rintro ⟨l₁, a, l₂, rfl, h₁, h₂, h₃⟩
|
||||
simp_all [filterMap_eq_nil_iff.mpr h₁, filterMap_cons_some h₂]
|
||||
|
||||
@[deprecated filterMap_eq_cons_iff (since := "2024-09-05")] abbrev filterMap_eq_cons := @filterMap_eq_cons_iff
|
||||
|
||||
/-! ### append -/
|
||||
|
||||
@[simp] theorem nil_append_fun : (([] : List α) ++ ·) = id := rfl
|
||||
@@ -1826,14 +1811,10 @@ theorem filterMap_eq_append_iff {f : α → Option β} :
|
||||
· rintro ⟨l₁, l₂, rfl, rfl, rfl⟩
|
||||
simp
|
||||
|
||||
@[deprecated filterMap_eq_append_iff (since := "2024-09-05")] abbrev filterMap_eq_append := @filterMap_eq_append_iff
|
||||
|
||||
theorem append_eq_filterMap_iff {f : α → Option β} :
|
||||
L₁ ++ L₂ = filterMap f l ↔ ∃ l₁ l₂, l = l₁ ++ l₂ ∧ filterMap f l₁ = L₁ ∧ filterMap f l₂ = L₂ := by
|
||||
rw [eq_comm, filterMap_eq_append_iff]
|
||||
|
||||
@[deprecated append_eq_filterMap (since := "2024-09-05")] abbrev append_eq_filterMap := @append_eq_filterMap_iff
|
||||
|
||||
theorem filter_eq_append_iff {p : α → Bool} :
|
||||
filter p l = L₁ ++ L₂ ↔ ∃ l₁ l₂, l = l₁ ++ l₂ ∧ filter p l₁ = L₁ ∧ filter p l₂ = L₂ := by
|
||||
rw [← filterMap_eq_filter, filterMap_eq_append_iff]
|
||||
@@ -1842,8 +1823,6 @@ theorem append_eq_filter_iff {p : α → Bool} :
|
||||
L₁ ++ L₂ = filter p l ↔ ∃ l₁ l₂, l = l₁ ++ l₂ ∧ filter p l₁ = L₁ ∧ filter p l₂ = L₂ := by
|
||||
rw [eq_comm, filter_eq_append_iff]
|
||||
|
||||
@[deprecated append_eq_filter_iff (since := "2024-09-05")] abbrev append_eq_filter := @append_eq_filter_iff
|
||||
|
||||
@[simp, grind] theorem map_append {f : α → β} : ∀ {l₁ l₂}, map f (l₁ ++ l₂) = map f l₁ ++ map f l₂ := by
|
||||
intro l₁; induction l₁ <;> intros <;> simp_all
|
||||
|
||||
@@ -1855,9 +1834,6 @@ theorem append_eq_map_iff {f : α → β} :
|
||||
L₁ ++ L₂ = map f l ↔ ∃ l₁ l₂, l = l₁ ++ l₂ ∧ map f l₁ = L₁ ∧ map f l₂ = L₂ := by
|
||||
rw [eq_comm, map_eq_append_iff]
|
||||
|
||||
@[deprecated map_eq_append_iff (since := "2024-09-05")] abbrev map_eq_append := @map_eq_append_iff
|
||||
@[deprecated append_eq_map_iff (since := "2024-09-05")] abbrev append_eq_map := @append_eq_map_iff
|
||||
|
||||
/-! ### concat
|
||||
|
||||
Note that `concat_eq_append` is a `@[simp]` lemma, so `concat` should usually not appear in goals.
|
||||
@@ -1889,8 +1865,6 @@ theorem concat_inj_left {l l' : List α} (a : α) : concat l a = concat l' a ↔
|
||||
theorem concat_inj_right {l : List α} {a a' : α} : concat l a = concat l a' ↔ a = a' :=
|
||||
⟨last_eq_of_concat_eq, by simp⟩
|
||||
|
||||
@[deprecated concat_inj (since := "2024-09-05")] abbrev concat_eq_concat := @concat_inj
|
||||
|
||||
theorem concat_append {a : α} {l₁ l₂ : List α} : concat l₁ a ++ l₂ = l₁ ++ a :: l₂ := by simp
|
||||
|
||||
theorem append_concat {a : α} {l₁ l₂ : List α} : l₁ ++ concat l₂ a = concat (l₁ ++ l₂) a := by simp
|
||||
@@ -2104,8 +2078,6 @@ theorem flatMap_eq_nil_iff {l : List α} {f : α → List β} : l.flatMap f = []
|
||||
flatten_eq_nil_iff.trans <| by
|
||||
simp only [mem_map, forall_exists_index, and_imp, forall_apply_eq_imp_iff₂]
|
||||
|
||||
@[deprecated flatMap_eq_nil_iff (since := "2024-09-05")] abbrev bind_eq_nil := @flatMap_eq_nil_iff
|
||||
|
||||
theorem forall_mem_flatMap {p : β → Prop} {l : List α} {f : α → List β} :
|
||||
(∀ (x) (_ : x ∈ l.flatMap f), p x) ↔ ∀ (a) (_ : a ∈ l) (b) (_ : b ∈ f a), p b := by
|
||||
simp only [mem_flatMap, forall_exists_index, and_imp]
|
||||
@@ -2184,12 +2156,6 @@ theorem contains_replicate [BEq α] {n : Nat} {a b : α} :
|
||||
simp only [replicate_succ, elem_cons]
|
||||
split <;> simp_all
|
||||
|
||||
@[deprecated mem_replicate (since := "2024-09-05")]
|
||||
theorem decide_mem_replicate [BEq α] [LawfulBEq α] {a b : α} :
|
||||
∀ {n}, decide (b ∈ replicate n a) = ((¬ n == 0) && b == a) := by
|
||||
have : DecidableEq α := instDecidableEqOfLawfulBEq
|
||||
simp [Bool.beq_eq_decide_eq]
|
||||
|
||||
@[grind →] theorem eq_of_mem_replicate {a b : α} {n} (h : b ∈ replicate n a) : b = a := (mem_replicate.1 h).2
|
||||
|
||||
theorem forall_mem_replicate {p : α → Prop} {a : α} {n} :
|
||||
@@ -2202,8 +2168,6 @@ theorem forall_mem_replicate {p : α → Prop} {a : α} {n} :
|
||||
@[simp] theorem replicate_eq_nil_iff {n : Nat} (a : α) : replicate n a = [] ↔ n = 0 := by
|
||||
cases n <;> simp
|
||||
|
||||
@[deprecated replicate_eq_nil_iff (since := "2024-09-05")] abbrev replicate_eq_nil := @replicate_eq_nil_iff
|
||||
|
||||
@[simp, grind] theorem getElem_replicate {a : α} {n : Nat} {i : Nat} (h : i < (replicate n a).length) :
|
||||
(replicate n a)[i] = a :=
|
||||
eq_of_mem_replicate (getElem_mem _)
|
||||
@@ -2255,8 +2219,6 @@ theorem eq_replicate_iff {a : α} {n} {l : List α} :
|
||||
⟨fun h => h ▸ ⟨length_replicate .., fun _ => eq_of_mem_replicate⟩,
|
||||
fun ⟨e, al⟩ => e ▸ eq_replicate_of_mem al⟩
|
||||
|
||||
@[deprecated eq_replicate_iff (since := "2024-09-05")] abbrev eq_replicate := @eq_replicate_iff
|
||||
|
||||
theorem map_eq_replicate_iff {l : List α} {f : α → β} {b : β} :
|
||||
l.map f = replicate l.length b ↔ ∀ x ∈ l, f x = b := by
|
||||
simp [eq_replicate_iff]
|
||||
@@ -2298,8 +2260,6 @@ theorem append_eq_replicate_iff {l₁ l₂ : List α} {a : α} :
|
||||
{ mp := fun h => ⟨fun b m => h b (Or.inl m), fun b m => h b (Or.inr m)⟩,
|
||||
mpr := fun h b x => Or.casesOn x (fun m => h.left b m) fun m => h.right b m }
|
||||
|
||||
@[deprecated append_eq_replicate_iff (since := "2024-09-05")] abbrev append_eq_replicate := @append_eq_replicate_iff
|
||||
|
||||
theorem replicate_eq_append_iff {l₁ l₂ : List α} {a : α} :
|
||||
replicate n a = l₁ ++ l₂ ↔
|
||||
l₁.length + l₂.length = n ∧ l₁ = replicate l₁.length a ∧ l₂ = replicate l₂.length a := by
|
||||
@@ -2479,8 +2439,6 @@ theorem reverse_eq_iff {as bs : List α} : as.reverse = bs ↔ as = bs.reverse :
|
||||
xs.reverse = a :: ys ↔ xs = ys.reverse ++ [a] := by
|
||||
rw [reverse_eq_iff, reverse_cons]
|
||||
|
||||
@[deprecated reverse_eq_cons_iff (since := "2024-09-05")] abbrev reverse_eq_cons := @reverse_eq_cons_iff
|
||||
|
||||
@[simp, grind] theorem getLast?_reverse {l : List α} : l.reverse.getLast? = l.head? := by
|
||||
cases l <;> simp [getLast?_concat]
|
||||
|
||||
@@ -2531,8 +2489,6 @@ theorem getLast_of_mem_getLast? {l : List α} (hx : x ∈ l.getLast?) :
|
||||
xs.reverse = ys ++ zs ↔ xs = zs.reverse ++ ys.reverse := by
|
||||
rw [reverse_eq_iff, reverse_append]
|
||||
|
||||
@[deprecated reverse_eq_append_iff (since := "2024-09-05")] abbrev reverse_eq_append := @reverse_eq_append_iff
|
||||
|
||||
@[grind _=_] theorem reverse_concat {l : List α} {a : α} : (l ++ [a]).reverse = a :: l.reverse := by
|
||||
rw [reverse_append]; rfl
|
||||
|
||||
@@ -2638,8 +2594,6 @@ theorem foldr_eq_foldrM {f : α → β → β} {b : β} {l : List α} :
|
||||
|
||||
theorem foldr_cons_nil {l : List α} : l.foldr cons [] = l := by simp
|
||||
|
||||
@[deprecated foldr_cons_nil (since := "2024-09-04")] abbrev foldr_self := @foldr_cons_nil
|
||||
|
||||
theorem foldl_map {f : β₁ → β₂} {g : α → β₂ → α} {l : List β₁} {init : α} :
|
||||
(l.map f).foldl g init = l.foldl (fun x y => g x (f y)) init := by
|
||||
induction l generalizing init <;> simp [*]
|
||||
@@ -2885,8 +2839,6 @@ theorem getLast?_eq_some_iff {xs : List α} {a : α} : xs.getLast? = some a ↔
|
||||
rw [getLast?_eq_head?_reverse, isSome_head?]
|
||||
simp
|
||||
|
||||
@[deprecated mem_of_getLast? (since := "2024-10-21")] abbrev mem_of_getLast?_eq_some := @mem_of_getLast?
|
||||
|
||||
@[simp, grind] theorem getLast_reverse {l : List α} (h : l.reverse ≠ []) :
|
||||
l.reverse.getLast h = l.head (by simp_all) := by
|
||||
simp [getLast_eq_head_reverse]
|
||||
@@ -3275,13 +3227,9 @@ theorem all_eq_not_any_not {l : List α} {p : α → Bool} : l.all p = !l.any (!
|
||||
@[simp, grind] theorem any_flatten {l : List (List α)} : l.flatten.any f = l.any (any · f) := by
|
||||
induction l <;> simp_all
|
||||
|
||||
@[deprecated any_flatten (since := "2024-10-14")] abbrev any_join := @any_flatten
|
||||
|
||||
@[simp, grind] theorem all_flatten {l : List (List α)} : l.flatten.all f = l.all (all · f) := by
|
||||
induction l <;> simp_all
|
||||
|
||||
@[deprecated all_flatten (since := "2024-10-14")] abbrev all_join := @all_flatten
|
||||
|
||||
@[simp, grind] theorem any_flatMap {l : List α} {f : α → List β} :
|
||||
(l.flatMap f).any p = l.any fun a => (f a).any p := by
|
||||
induction l <;> simp_all
|
||||
@@ -3741,74 +3689,6 @@ theorem mem_iff_get? {a} {l : List α} : a ∈ l ↔ ∃ n, l.get? n = some a :=
|
||||
|
||||
/-! ### Deprecations -/
|
||||
|
||||
@[deprecated getElem_eq_getElem?_get (since := "2024-09-04")] abbrev getElem_eq_getElem? :=
|
||||
@getElem_eq_getElem?_get
|
||||
@[deprecated flatten_eq_nil_iff (since := "2024-09-05")] abbrev join_eq_nil := @flatten_eq_nil_iff
|
||||
@[deprecated flatten_ne_nil_iff (since := "2024-09-05")] abbrev join_ne_nil := @flatten_ne_nil_iff
|
||||
@[deprecated flatten_eq_cons_iff (since := "2024-09-05")] abbrev join_eq_cons_iff := @flatten_eq_cons_iff
|
||||
@[deprecated flatten_eq_cons_iff (since := "2024-09-05")] abbrev join_eq_cons := @flatten_eq_cons_iff
|
||||
@[deprecated flatten_eq_append_iff (since := "2024-09-05")] abbrev join_eq_append := @flatten_eq_append_iff
|
||||
@[deprecated mem_of_getElem? (since := "2024-09-06")] abbrev getElem?_mem := @mem_of_getElem?
|
||||
@[deprecated getElem_set_self (since := "2024-09-04")] abbrev getElem_set_eq := @getElem_set_self
|
||||
@[deprecated getElem?_set_self (since := "2024-09-04")] abbrev getElem?_set_eq := @getElem?_set_self
|
||||
@[deprecated set_eq_nil_iff (since := "2024-09-05")] abbrev set_eq_nil := @set_eq_nil_iff
|
||||
|
||||
@[deprecated flatten_nil (since := "2024-10-14")] abbrev join_nil := @flatten_nil
|
||||
@[deprecated flatten_cons (since := "2024-10-14")] abbrev join_cons := @flatten_cons
|
||||
@[deprecated length_flatten (since := "2024-10-14")] abbrev length_join := @length_flatten
|
||||
@[deprecated flatten_singleton (since := "2024-10-14")] abbrev join_singleton := @flatten_singleton
|
||||
@[deprecated mem_flatten (since := "2024-10-14")] abbrev mem_join := @mem_flatten
|
||||
@[deprecated flatten_eq_nil_iff (since := "2024-10-14")] abbrev join_eq_nil_iff := @flatten_eq_nil_iff
|
||||
@[deprecated flatten_ne_nil_iff (since := "2024-10-14")] abbrev join_ne_nil_iff := @flatten_ne_nil_iff
|
||||
@[deprecated exists_of_mem_flatten (since := "2024-10-14")] abbrev exists_of_mem_join := @exists_of_mem_flatten
|
||||
@[deprecated mem_flatten_of_mem (since := "2024-10-14")] abbrev mem_join_of_mem := @mem_flatten_of_mem
|
||||
@[deprecated forall_mem_flatten (since := "2024-10-14")] abbrev forall_mem_join := @forall_mem_flatten
|
||||
@[deprecated flatten_eq_flatMap (since := "2024-10-14")] abbrev join_eq_bind := @flatten_eq_flatMap
|
||||
@[deprecated head?_flatten (since := "2024-10-14")] abbrev head?_join := @head?_flatten
|
||||
@[deprecated foldl_flatten (since := "2024-10-14")] abbrev foldl_join := @foldl_flatten
|
||||
@[deprecated foldr_flatten (since := "2024-10-14")] abbrev foldr_join := @foldr_flatten
|
||||
@[deprecated map_flatten (since := "2024-10-14")] abbrev map_join := @map_flatten
|
||||
@[deprecated filterMap_flatten (since := "2024-10-14")] abbrev filterMap_join := @filterMap_flatten
|
||||
@[deprecated filter_flatten (since := "2024-10-14")] abbrev filter_join := @filter_flatten
|
||||
@[deprecated flatten_filter_not_isEmpty (since := "2024-10-14")] abbrev join_filter_not_isEmpty := @flatten_filter_not_isEmpty
|
||||
@[deprecated flatten_filter_ne_nil (since := "2024-10-14")] abbrev join_filter_ne_nil := @flatten_filter_ne_nil
|
||||
@[deprecated flatten_append (since := "2024-10-14")] abbrev join_append := @flatten_append
|
||||
@[deprecated flatten_concat (since := "2024-10-14")] abbrev join_concat := @flatten_concat
|
||||
@[deprecated flatten_flatten (since := "2024-10-14")] abbrev join_join := @flatten_flatten
|
||||
@[deprecated flatten_eq_append_iff (since := "2024-10-14")] abbrev join_eq_append_iff := @flatten_eq_append_iff
|
||||
@[deprecated eq_iff_flatten_eq (since := "2024-10-14")] abbrev eq_iff_join_eq := @eq_iff_flatten_eq
|
||||
@[deprecated flatten_replicate_nil (since := "2024-10-14")] abbrev join_replicate_nil := @flatten_replicate_nil
|
||||
@[deprecated flatten_replicate_singleton (since := "2024-10-14")] abbrev join_replicate_singleton := @flatten_replicate_singleton
|
||||
@[deprecated flatten_replicate_replicate (since := "2024-10-14")] abbrev join_replicate_replicate := @flatten_replicate_replicate
|
||||
@[deprecated reverse_flatten (since := "2024-10-14")] abbrev reverse_join := @reverse_flatten
|
||||
@[deprecated flatten_reverse (since := "2024-10-14")] abbrev join_reverse := @flatten_reverse
|
||||
@[deprecated getLast?_flatten (since := "2024-10-14")] abbrev getLast?_join := @getLast?_flatten
|
||||
@[deprecated flatten_eq_flatMap (since := "2024-10-16")] abbrev flatten_eq_bind := @flatten_eq_flatMap
|
||||
@[deprecated flatMap_def (since := "2024-10-16")] abbrev bind_def := @flatMap_def
|
||||
@[deprecated flatMap_id (since := "2024-10-16")] abbrev bind_id := @flatMap_id
|
||||
@[deprecated mem_flatMap (since := "2024-10-16")] abbrev mem_bind := @mem_flatMap
|
||||
@[deprecated exists_of_mem_flatMap (since := "2024-10-16")] abbrev exists_of_mem_bind := @exists_of_mem_flatMap
|
||||
@[deprecated mem_flatMap_of_mem (since := "2024-10-16")] abbrev mem_bind_of_mem := @mem_flatMap_of_mem
|
||||
@[deprecated flatMap_eq_nil_iff (since := "2024-10-16")] abbrev bind_eq_nil_iff := @flatMap_eq_nil_iff
|
||||
@[deprecated forall_mem_flatMap (since := "2024-10-16")] abbrev forall_mem_bind := @forall_mem_flatMap
|
||||
@[deprecated flatMap_singleton (since := "2024-10-16")] abbrev bind_singleton := @flatMap_singleton
|
||||
@[deprecated flatMap_singleton' (since := "2024-10-16")] abbrev bind_singleton' := @flatMap_singleton'
|
||||
@[deprecated head?_flatMap (since := "2024-10-16")] abbrev head_bind := @head?_flatMap
|
||||
@[deprecated flatMap_append (since := "2024-10-16")] abbrev bind_append := @flatMap_append
|
||||
@[deprecated flatMap_assoc (since := "2024-10-16")] abbrev bind_assoc := @flatMap_assoc
|
||||
@[deprecated map_flatMap (since := "2024-10-16")] abbrev map_bind := @map_flatMap
|
||||
@[deprecated flatMap_map (since := "2024-10-16")] abbrev bind_map := @flatMap_map
|
||||
@[deprecated map_eq_flatMap (since := "2024-10-16")] abbrev map_eq_bind := @map_eq_flatMap
|
||||
@[deprecated filterMap_flatMap (since := "2024-10-16")] abbrev filterMap_bind := @filterMap_flatMap
|
||||
@[deprecated filter_flatMap (since := "2024-10-16")] abbrev filter_bind := @filter_flatMap
|
||||
@[deprecated flatMap_eq_foldl (since := "2024-10-16")] abbrev bind_eq_foldl := @flatMap_eq_foldl
|
||||
@[deprecated flatMap_replicate (since := "2024-10-16")] abbrev bind_replicate := @flatMap_replicate
|
||||
@[deprecated reverse_flatMap (since := "2024-10-16")] abbrev reverse_bind := @reverse_flatMap
|
||||
@[deprecated flatMap_reverse (since := "2024-10-16")] abbrev bind_reverse := @flatMap_reverse
|
||||
@[deprecated getLast?_flatMap (since := "2024-10-16")] abbrev getLast?_bind := @getLast?_flatMap
|
||||
@[deprecated any_flatMap (since := "2024-10-16")] abbrev any_bind := @any_flatMap
|
||||
@[deprecated all_flatMap (since := "2024-10-16")] abbrev all_bind := @all_flatMap
|
||||
|
||||
@[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
|
||||
|
||||
@@ -194,21 +194,4 @@ theorem foldl_max [Max α] [Std.IdempotentOp (max : α → α → α)] [Std.Asso
|
||||
{l : List α} {a : α} : l.foldl (init := a) max = max a (l.max?.getD a) := by
|
||||
cases l <;> simp [max?, foldl_assoc, Std.IdempotentOp.idempotent]
|
||||
|
||||
@[deprecated min?_nil (since := "2024-09-29")] abbrev minimum?_nil := @min?_nil
|
||||
@[deprecated min?_cons (since := "2024-09-29")] abbrev minimum?_cons := @min?_cons
|
||||
@[deprecated min?_eq_none_iff (since := "2024-09-29")] abbrev mininmum?_eq_none_iff := @min?_eq_none_iff
|
||||
@[deprecated min?_mem (since := "2024-09-29")] abbrev minimum?_mem := @min?_mem
|
||||
@[deprecated le_min?_iff (since := "2024-09-29")] abbrev le_minimum?_iff := @le_min?_iff
|
||||
@[deprecated min?_eq_some_iff (since := "2024-09-29")] abbrev minimum?_eq_some_iff := @min?_eq_some_iff
|
||||
@[deprecated min?_replicate (since := "2024-09-29")] abbrev minimum?_replicate := @min?_replicate
|
||||
@[deprecated min?_replicate_of_pos (since := "2024-09-29")] abbrev minimum?_replicate_of_pos := @min?_replicate_of_pos
|
||||
@[deprecated max?_nil (since := "2024-09-29")] abbrev maximum?_nil := @max?_nil
|
||||
@[deprecated max?_cons (since := "2024-09-29")] abbrev maximum?_cons := @max?_cons
|
||||
@[deprecated max?_eq_none_iff (since := "2024-09-29")] abbrev maximum?_eq_none_iff := @max?_eq_none_iff
|
||||
@[deprecated max?_mem (since := "2024-09-29")] abbrev maximum?_mem := @max?_mem
|
||||
@[deprecated max?_le_iff (since := "2024-09-29")] abbrev maximum?_le_iff := @max?_le_iff
|
||||
@[deprecated max?_eq_some_iff (since := "2024-09-29")] abbrev maximum?_eq_some_iff := @max?_eq_some_iff
|
||||
@[deprecated max?_replicate (since := "2024-09-29")] abbrev maximum?_replicate := @max?_replicate
|
||||
@[deprecated max?_replicate_of_pos (since := "2024-09-29")] abbrev maximum?_replicate_of_pos := @max?_replicate_of_pos
|
||||
|
||||
end List
|
||||
|
||||
@@ -109,6 +109,47 @@ theorem length_rightpad {n : Nat} {a : α} {l : List α} :
|
||||
simp [rightpad]
|
||||
omega
|
||||
|
||||
/-! ### intersperse -/
|
||||
section intersperse
|
||||
|
||||
variable {l : List α} {sep : α} {i : Nat}
|
||||
|
||||
@[simp] theorem length_intersperse : (l.intersperse sep).length = 2 * l.length - 1 := by
|
||||
fun_induction intersperse <;> simp only [intersperse, length_cons, length_nil] at *
|
||||
rename_i h _
|
||||
have := length_pos_iff.mpr h
|
||||
omega
|
||||
|
||||
@[simp] theorem getElem?_intersperse_two_mul : (l.intersperse sep)[2 * i]? = l[i]? := by
|
||||
induction l using intersperse.induct_unfolding sep generalizing i <;> cases i
|
||||
all_goals simp [mul_succ, *]
|
||||
|
||||
theorem getElem?_intersperse_two_mul_add_one (h : i + 1 < l.length) :
|
||||
(l.intersperse sep)[2 * i + 1]? = some sep := by
|
||||
fun_induction intersperse generalizing i
|
||||
· contradiction
|
||||
· contradiction
|
||||
· rename_i hn _
|
||||
have ⟨_, tl, _⟩ := ne_nil_iff_exists_cons.mp hn
|
||||
cases tl <;> cases i <;> simp_all +arith
|
||||
|
||||
@[simp] theorem getElem_intersperse_two_mul (h : 2 * i < (l.intersperse sep).length) :
|
||||
(l.intersperse sep)[2 * i] = l[i]'(by rw [length_intersperse] at h; omega) := by
|
||||
rw [← Option.some_inj, ← getElem?_eq_getElem h]
|
||||
simp
|
||||
|
||||
@[simp] theorem getElem_intersperse_two_mul_add_one (h : 2 * i + 1 < (l.intersperse sep).length) :
|
||||
(l.intersperse sep)[2 * i + 1] = sep := by
|
||||
rw [← Option.some_inj, ← getElem?_eq_getElem h, getElem?_intersperse_two_mul_add_one]
|
||||
rw [length_intersperse] at h
|
||||
omega
|
||||
|
||||
theorem getElem_eq_getElem_intersperse_two_mul (h : i < l.length) :
|
||||
l[i] = (l.intersperse sep)[2 * i]'(by rw [length_intersperse]; omega) := by
|
||||
simp
|
||||
|
||||
end intersperse
|
||||
|
||||
/-! ### eraseIdx -/
|
||||
|
||||
theorem mem_eraseIdx_iff_getElem {x : α} :
|
||||
@@ -186,11 +227,4 @@ theorem le_max?_getD_of_mem {l : List Nat} {a k : Nat} (h : a ∈ l) :
|
||||
a ≤ l.max?.getD k :=
|
||||
Option.get_eq_getD _ ▸ le_max?_get_of_mem h
|
||||
|
||||
@[deprecated min?_eq_some_iff' (since := "2024-09-29")] abbrev minimum?_eq_some_iff' := @min?_eq_some_iff'
|
||||
@[deprecated min?_cons' (since := "2024-09-29")] abbrev minimum?_cons' := @min?_cons'
|
||||
@[deprecated min?_getD_le_of_mem (since := "2024-09-29")] abbrev minimum?_getD_le_of_mem := @min?_getD_le_of_mem
|
||||
@[deprecated max?_eq_some_iff' (since := "2024-09-29")] abbrev maximum?_eq_some_iff' := @max?_eq_some_iff'
|
||||
@[deprecated max?_cons' (since := "2024-09-29")] abbrev maximum?_cons' := @max?_cons'
|
||||
@[deprecated le_max?_getD_of_mem (since := "2024-09-29")] abbrev le_maximum?_getD_of_mem := @le_max?_getD_of_mem
|
||||
|
||||
end List
|
||||
|
||||
@@ -27,7 +27,7 @@ open Nat
|
||||
|
||||
/-! ### take -/
|
||||
|
||||
@[simp] theorem length_take : ∀ {i : Nat} {l : List α}, (take i l).length = min i l.length
|
||||
@[simp, grind =] theorem length_take : ∀ {i : Nat} {l : List α}, (take i l).length = min i l.length
|
||||
| 0, l => by simp [Nat.zero_min]
|
||||
| succ n, [] => by simp [Nat.min_zero]
|
||||
| succ n, _ :: l => by simp [Nat.succ_min_succ, length_take]
|
||||
@@ -47,7 +47,7 @@ theorem getElem_take' {xs : List α} {i j : Nat} (hi : i < xs.length) (hj : i <
|
||||
|
||||
/-- The `i`-th element of a list coincides with the `i`-th element of any of its prefixes of
|
||||
length `> i`. Version designed to rewrite from the small list to the big list. -/
|
||||
@[simp] theorem getElem_take {xs : List α} {j i : Nat} {h : i < (xs.take j).length} :
|
||||
@[simp, grind =] theorem getElem_take {xs : List α} {j i : Nat} {h : i < (xs.take j).length} :
|
||||
(xs.take j)[i] =
|
||||
xs[i]'(Nat.lt_of_lt_of_le h (length_take_le' _ _)) := by
|
||||
rw [length_take, Nat.lt_min] at h; rw [getElem_take' (xs := xs) _ h.1]
|
||||
@@ -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
|
||||
|
||||
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
|
||||
@@ -184,8 +184,6 @@ theorem dropLast_take {i : Nat} {l : List α} (h : i < l.length) :
|
||||
(l.take i).dropLast = l.take (i - 1) := by
|
||||
simp only [dropLast_eq_take, length_take, Nat.le_of_lt h, Nat.min_eq_left, take_take, sub_le]
|
||||
|
||||
@[deprecated map_eq_append_iff (since := "2024-09-05")] abbrev map_eq_append_split := @map_eq_append_iff
|
||||
|
||||
theorem take_eq_dropLast {l : List α} {i : Nat} (h : i + 1 = l.length) :
|
||||
l.take i = l.dropLast := by
|
||||
induction l generalizing i with
|
||||
@@ -232,7 +230,7 @@ theorem getElem_drop' {xs : List α} {i j : Nat} (h : i + j < xs.length) :
|
||||
|
||||
/-- The `i + j`-th element of a list coincides with the `j`-th element of the list obtained by
|
||||
dropping the first `i` elements. Version designed to rewrite from the small list to the big list. -/
|
||||
@[simp] theorem getElem_drop {xs : List α} {i : Nat} {j : Nat} {h : j < (xs.drop i).length} :
|
||||
@[simp, grind =] theorem getElem_drop {xs : List α} {i : Nat} {j : Nat} {h : j < (xs.drop i).length} :
|
||||
(xs.drop i)[j] = xs[i + j]'(by
|
||||
rw [Nat.add_comm]
|
||||
exact Nat.add_lt_of_lt_sub (length_drop ▸ h)) := by
|
||||
@@ -365,8 +363,6 @@ theorem drop_take : ∀ {i j : Nat} {l : List α}, drop i (take j l) = take (j -
|
||||
| _, _, [] => by simp
|
||||
| i+1, j+1, h :: t => by
|
||||
simp [take_succ_cons, drop_succ_cons, drop_take]
|
||||
congr 1
|
||||
omega
|
||||
|
||||
@[simp] theorem drop_take_self : drop i (take i l) = [] := by
|
||||
rw [drop_take]
|
||||
|
||||
@@ -174,15 +174,11 @@ theorem pairwise_flatten {L : List (List α)} :
|
||||
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⟩
|
||||
|
||||
@[deprecated pairwise_flatten (since := "2024-10-14")] abbrev pairwise_join := @pairwise_flatten
|
||||
|
||||
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]
|
||||
|
||||
@[deprecated pairwise_flatMap (since := "2024-10-14")] abbrev pairwise_bind := @pairwise_flatMap
|
||||
|
||||
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]
|
||||
|
||||
@@ -497,8 +497,6 @@ theorem Perm.flatten {l₁ l₂ : List (List α)} (h : l₁ ~ l₂) : l₁.flatt
|
||||
| swap => simp only [flatten_cons, ← append_assoc, perm_append_right_iff]; exact perm_append_comm ..
|
||||
| trans _ _ ih₁ ih₂ => exact trans ih₁ ih₂
|
||||
|
||||
@[deprecated Perm.flatten (since := "2024-10-14")] abbrev Perm.join := @Perm.flatten
|
||||
|
||||
theorem cons_append_cons_perm {a b : α} {as bs : List α} :
|
||||
a :: as ++ b :: bs ~ b :: as ++ a :: bs := by
|
||||
suffices [[a], as, [b], bs].flatten ~ [[b], as, [a], bs].flatten by simpa
|
||||
@@ -511,8 +509,6 @@ theorem cons_append_cons_perm {a b : α} {as bs : List α} :
|
||||
theorem Perm.flatMap_right {l₁ l₂ : List α} (f : α → List β) (p : l₁ ~ l₂) : l₁.flatMap f ~ l₂.flatMap f :=
|
||||
(p.map _).flatten
|
||||
|
||||
@[deprecated Perm.flatMap_right (since := "2024-10-16")] abbrev Perm.bind_right := @Perm.flatMap_right
|
||||
|
||||
theorem Perm.eraseP (f : α → Bool) {l₁ l₂ : List α}
|
||||
(H : Pairwise (fun a b => f a → f b → False) l₁) (p : l₁ ~ l₂) : eraseP f l₁ ~ eraseP f l₂ := by
|
||||
induction p with
|
||||
|
||||
@@ -306,8 +306,6 @@ theorem sorted_mergeSort
|
||||
apply sorted_mergeSort trans total
|
||||
termination_by l => l.length
|
||||
|
||||
@[deprecated sorted_mergeSort (since := "2024-09-02")] abbrev mergeSort_sorted := @sorted_mergeSort
|
||||
|
||||
/--
|
||||
If the input list is already sorted, then `mergeSort` does not change the list.
|
||||
-/
|
||||
@@ -444,9 +442,6 @@ theorem sublist_mergeSort
|
||||
((fun w => Sublist.of_sublist_append_right w h') fun b m₁ m₃ =>
|
||||
(Bool.eq_not_self true).mp ((rel_of_pairwise_cons hc m₁).symm.trans (h₃ b m₃))))
|
||||
|
||||
@[deprecated sublist_mergeSort (since := "2024-09-02")]
|
||||
abbrev mergeSort_stable := @sublist_mergeSort
|
||||
|
||||
/--
|
||||
Another statement of stability of merge sort.
|
||||
If a pair `[a, b]` is a sublist of `l` and `le a b`,
|
||||
@@ -458,9 +453,6 @@ theorem pair_sublist_mergeSort
|
||||
(hab : le a b) (h : [a, b] <+ l) : [a, b] <+ mergeSort l le :=
|
||||
sublist_mergeSort trans total (pairwise_pair.mpr hab) h
|
||||
|
||||
@[deprecated pair_sublist_mergeSort(since := "2024-09-02")]
|
||||
abbrev mergeSort_stable_pair := @pair_sublist_mergeSort
|
||||
|
||||
theorem map_merge {f : α → β} {r : α → α → Bool} {s : β → β → Bool} {l l' : List α}
|
||||
(hl : ∀ a ∈ l, ∀ b ∈ l', r a b = s (f a) (f b)) :
|
||||
(l.merge l' r).map f = (l.map f).merge (l'.map f) s := by
|
||||
|
||||
@@ -1092,11 +1092,4 @@ theorem prefix_iff_eq_take : l₁ <+: l₂ ↔ l₁ = take (length l₁) l₂ :=
|
||||
|
||||
-- See `Init.Data.List.Nat.Sublist` for `suffix_iff_eq_append`, `prefix_take_iff`, and `suffix_iff_eq_drop`.
|
||||
|
||||
/-! ### Deprecations -/
|
||||
|
||||
@[deprecated sublist_flatten_of_mem (since := "2024-10-14")] abbrev sublist_join_of_mem := @sublist_flatten_of_mem
|
||||
@[deprecated sublist_flatten_iff (since := "2024-10-14")] abbrev sublist_join_iff := @sublist_flatten_iff
|
||||
@[deprecated flatten_sublist_iff (since := "2024-10-14")] abbrev flatten_join_iff := @flatten_sublist_iff
|
||||
@[deprecated infix_of_mem_flatten (since := "2024-10-14")] abbrev infix_of_mem_join := @infix_of_mem_flatten
|
||||
|
||||
end List
|
||||
|
||||
@@ -40,7 +40,7 @@ theorem drop_one : ∀ {l : List α}, l.drop 1 = l.tail
|
||||
| _ + 1, [] => rfl
|
||||
| _ + 1, x :: _ => congrArg (cons x) (take_append_drop ..)
|
||||
|
||||
@[simp] theorem length_drop : ∀ {i : Nat} {l : List α}, (drop i l).length = l.length - i
|
||||
@[simp, grind =] theorem length_drop : ∀ {i : Nat} {l : List α}, (drop i l).length = l.length - i
|
||||
| 0, _ => rfl
|
||||
| succ i, [] => Eq.symm (Nat.zero_sub (succ i))
|
||||
| succ i, x :: l => calc
|
||||
@@ -131,8 +131,6 @@ theorem drop_eq_nil_iff {l : List α} {i : Nat} : l.drop i = [] ↔ l.length ≤
|
||||
· simp only [drop] at h
|
||||
simpa [Nat.succ_le_succ_iff] using hi h
|
||||
|
||||
@[deprecated drop_eq_nil_iff (since := "2024-09-10")] abbrev drop_eq_nil_iff_le := @drop_eq_nil_iff
|
||||
|
||||
@[simp]
|
||||
theorem take_eq_nil_iff {l : List α} {k : Nat} : l.take k = [] ↔ k = 0 ∨ l = [] := by
|
||||
cases l <;> cases k <;> simp [Nat.succ_ne_zero]
|
||||
|
||||
@@ -66,7 +66,7 @@ theorem toArray_cons (a : α) (l : List α) : (a :: l).toArray = #[a] ++ l.toArr
|
||||
apply ext'
|
||||
simp
|
||||
|
||||
@[simp] theorem push_toArray (l : List α) (a : α) : l.toArray.push a = (l ++ [a]).toArray := by
|
||||
@[simp, grind =] theorem push_toArray (l : List α) (a : α) : l.toArray.push a = (l ++ [a]).toArray := by
|
||||
apply ext'
|
||||
simp
|
||||
|
||||
@@ -75,37 +75,37 @@ theorem toArray_cons (a : α) (l : List α) : (a :: l).toArray = #[a] ++ l.toArr
|
||||
funext a
|
||||
simp
|
||||
|
||||
@[simp] theorem isEmpty_toArray (l : List α) : l.toArray.isEmpty = l.isEmpty := by
|
||||
@[simp, grind =] theorem isEmpty_toArray (l : List α) : l.toArray.isEmpty = l.isEmpty := by
|
||||
cases l <;> simp [Array.isEmpty]
|
||||
|
||||
@[simp] theorem toArray_singleton (a : α) : (List.singleton a).toArray = Array.singleton a := rfl
|
||||
|
||||
@[simp] theorem back!_toArray [Inhabited α] (l : List α) : l.toArray.back! = l.getLast! := by
|
||||
@[simp, grind =] theorem back!_toArray [Inhabited α] (l : List α) : l.toArray.back! = l.getLast! := by
|
||||
simp only [back!, size_toArray, getElem!_toArray, getLast!_eq_getElem!]
|
||||
|
||||
@[simp] theorem back?_toArray (l : List α) : l.toArray.back? = l.getLast? := by
|
||||
@[simp, grind =] theorem back?_toArray (l : List α) : l.toArray.back? = l.getLast? := by
|
||||
simp [back?, List.getLast?_eq_getElem?]
|
||||
|
||||
@[simp] theorem back_toArray (l : List α) (h) :
|
||||
@[simp, grind =] theorem back_toArray (l : List α) (h) :
|
||||
l.toArray.back = l.getLast (by simp at h; exact ne_nil_of_length_pos h) := by
|
||||
simp [back, List.getLast_eq_getElem]
|
||||
|
||||
@[simp] theorem _root_.Array.getLast!_toList [Inhabited α] (xs : Array α) :
|
||||
@[simp, grind =] theorem _root_.Array.getLast!_toList [Inhabited α] (xs : Array α) :
|
||||
xs.toList.getLast! = xs.back! := by
|
||||
rcases xs with ⟨xs⟩
|
||||
simp
|
||||
|
||||
@[simp] theorem _root_.Array.getLast?_toList (xs : Array α) :
|
||||
@[simp, grind =] theorem _root_.Array.getLast?_toList (xs : Array α) :
|
||||
xs.toList.getLast? = xs.back? := by
|
||||
rcases xs with ⟨xs⟩
|
||||
simp
|
||||
|
||||
@[simp] theorem _root_.Array.getLast_toList (xs : Array α) (h) :
|
||||
@[simp, grind =] theorem _root_.Array.getLast_toList (xs : Array α) (h) :
|
||||
xs.toList.getLast h = xs.back (by simpa [ne_nil_iff_length_pos] using h) := by
|
||||
rcases xs with ⟨xs⟩
|
||||
simp
|
||||
|
||||
@[simp] theorem set_toArray (l : List α) (i : Nat) (a : α) (h : i < l.length) :
|
||||
@[simp, grind =] theorem set_toArray (l : List α) (i : Nat) (a : α) (h : i < l.length) :
|
||||
(l.toArray.set i a) = (l.set i a).toArray := rfl
|
||||
|
||||
@[simp] theorem forIn'_loop_toArray [Monad m] (l : List α) (f : (a : α) → a ∈ l.toArray → β → m (ForInStep β)) (i : Nat)
|
||||
@@ -126,30 +126,30 @@ theorem toArray_cons (a : α) (l : List α) : (a :: l).toArray = #[a] ++ l.toArr
|
||||
simp only [t]
|
||||
congr
|
||||
|
||||
@[simp] theorem forIn'_toArray [Monad m] (l : List α) (b : β) (f : (a : α) → a ∈ l.toArray → β → m (ForInStep β)) :
|
||||
@[simp, grind =] theorem forIn'_toArray [Monad m] (l : List α) (b : β) (f : (a : α) → a ∈ l.toArray → β → m (ForInStep β)) :
|
||||
forIn' l.toArray b f = forIn' l b (fun a m b => f a (mem_toArray.mpr m) b) := by
|
||||
change Array.forIn' _ _ _ = List.forIn' _ _ _
|
||||
rw [Array.forIn', forIn'_loop_toArray]
|
||||
simp
|
||||
|
||||
@[simp] theorem forIn_toArray [Monad m] (l : List α) (b : β) (f : α → β → m (ForInStep β)) :
|
||||
@[simp, grind =] theorem forIn_toArray [Monad m] (l : List α) (b : β) (f : α → β → m (ForInStep β)) :
|
||||
forIn l.toArray b f = forIn l b f := by
|
||||
simpa using forIn'_toArray l b fun a m b => f a b
|
||||
|
||||
theorem foldrM_toArray [Monad m] (f : α → β → m β) (init : β) (l : List α) :
|
||||
@[grind =] theorem foldrM_toArray [Monad m] (f : α → β → m β) (init : β) (l : List α) :
|
||||
l.toArray.foldrM f init = l.foldrM f init := by
|
||||
rw [foldrM_eq_reverse_foldlM_toList]
|
||||
simp
|
||||
|
||||
theorem foldlM_toArray [Monad m] (f : β → α → m β) (init : β) (l : List α) :
|
||||
@[grind =] theorem foldlM_toArray [Monad m] (f : β → α → m β) (init : β) (l : List α) :
|
||||
l.toArray.foldlM f init = l.foldlM f init := by
|
||||
rw [foldlM_toList]
|
||||
|
||||
theorem foldr_toArray (f : α → β → β) (init : β) (l : List α) :
|
||||
@[grind =] theorem foldr_toArray (f : α → β → β) (init : β) (l : List α) :
|
||||
l.toArray.foldr f init = l.foldr f init := by
|
||||
rw [foldr_toList]
|
||||
|
||||
theorem foldl_toArray (f : β → α → β) (init : β) (l : List α) :
|
||||
@[grind =] theorem foldl_toArray (f : β → α → β) (init : β) (l : List α) :
|
||||
l.toArray.foldl f init = l.foldl f init := by
|
||||
rw [foldl_toList]
|
||||
|
||||
@@ -176,7 +176,7 @@ theorem foldl_toArray (f : β → α → β) (init : β) (l : List α) :
|
||||
simp only [size_toArray, foldlM_toArray']
|
||||
induction l <;> simp_all
|
||||
|
||||
@[simp]
|
||||
@[simp, grind =]
|
||||
theorem forM_toArray [Monad m] (l : List α) (f : α → m PUnit) :
|
||||
(forM l.toArray f) = l.forM f :=
|
||||
forM_toArray' l f rfl
|
||||
@@ -195,15 +195,15 @@ theorem forM_toArray [Monad m] (l : List α) (f : α → m PUnit) :
|
||||
subst h
|
||||
rw [foldl_toList]
|
||||
|
||||
@[simp] theorem sum_toArray [Add α] [Zero α] (l : List α) : l.toArray.sum = l.sum := by
|
||||
@[simp, grind =] theorem sum_toArray [Add α] [Zero α] (l : List α) : l.toArray.sum = l.sum := by
|
||||
simp [Array.sum, List.sum]
|
||||
|
||||
@[simp] theorem append_toArray (l₁ l₂ : List α) :
|
||||
@[simp, grind =] theorem append_toArray (l₁ l₂ : List α) :
|
||||
l₁.toArray ++ l₂.toArray = (l₁ ++ l₂).toArray := by
|
||||
apply ext'
|
||||
simp
|
||||
|
||||
@[simp] theorem push_append_toArray {as : Array α} {a : α} {bs : List α} : as.push a ++ bs.toArray = as ++ (a ::bs).toArray := by
|
||||
@[simp] theorem push_append_toArray {as : Array α} {a : α} {bs : List α} : as.push a ++ bs.toArray = as ++ (a :: bs).toArray := by
|
||||
cases as
|
||||
simp
|
||||
|
||||
@@ -213,7 +213,7 @@ theorem forM_toArray [Monad m] (l : List α) (f : α → m PUnit) :
|
||||
@[simp] theorem foldr_push {l : List α} {as : Array α} : l.foldr (fun a bs => push bs a) as = as ++ l.reverse.toArray := by
|
||||
rw [foldr_eq_foldl_reverse, foldl_push]
|
||||
|
||||
@[simp] theorem findSomeM?_toArray [Monad m] [LawfulMonad m] (f : α → m (Option β)) (l : List α) :
|
||||
@[simp, grind =] theorem findSomeM?_toArray [Monad m] [LawfulMonad m] (f : α → m (Option β)) (l : List α) :
|
||||
l.toArray.findSomeM? f = l.findSomeM? f := by
|
||||
rw [Array.findSomeM?]
|
||||
simp only [bind_pure_comp, map_pure, forIn_toArray]
|
||||
@@ -246,7 +246,7 @@ theorem findRevM?_toArray [Monad m] [LawfulMonad m] (f : α → m Bool) (l : Lis
|
||||
l.toArray.findRevM? f = l.reverse.findM? f := by
|
||||
rw [Array.findRevM?, findSomeRevM?_toArray, findM?_eq_findSomeM?]
|
||||
|
||||
@[simp] theorem findM?_toArray [Monad m] [LawfulMonad m] (f : α → m Bool) (l : List α) :
|
||||
@[simp, grind =] theorem findM?_toArray [Monad m] [LawfulMonad m] (f : α → m Bool) (l : List α) :
|
||||
l.toArray.findM? f = l.findM? f := by
|
||||
rw [Array.findM?]
|
||||
simp only [bind_pure_comp, map_pure, forIn_toArray]
|
||||
@@ -257,11 +257,11 @@ theorem findRevM?_toArray [Monad m] [LawfulMonad m] (f : α → m Bool) (l : Lis
|
||||
congr
|
||||
ext1 (_|_) <;> simp [ih]
|
||||
|
||||
@[simp] theorem findSome?_toArray (f : α → Option β) (l : List α) :
|
||||
@[simp, grind =] theorem findSome?_toArray (f : α → Option β) (l : List α) :
|
||||
l.toArray.findSome? f = l.findSome? f := by
|
||||
rw [Array.findSome?, ← findSomeM?_id, findSomeM?_toArray, Id.run]
|
||||
|
||||
@[simp] theorem find?_toArray (f : α → Bool) (l : List α) :
|
||||
@[simp, grind =] theorem find?_toArray (f : α → Bool) (l : List α) :
|
||||
l.toArray.find? f = l.find? f := by
|
||||
rw [Array.find?]
|
||||
simp only [Id.run, Id, Id.pure_eq, Id.bind_eq, forIn_toArray]
|
||||
@@ -297,12 +297,12 @@ private theorem findFinIdx?_loop_toArray (w : l' = l.drop j) :
|
||||
simp
|
||||
termination_by l.length - j
|
||||
|
||||
@[simp] theorem findFinIdx?_toArray (p : α → Bool) (l : List α) :
|
||||
@[simp, grind =] theorem findFinIdx?_toArray (p : α → Bool) (l : List α) :
|
||||
l.toArray.findFinIdx? p = l.findFinIdx? p := by
|
||||
rw [Array.findFinIdx?, findFinIdx?, findFinIdx?_loop_toArray]
|
||||
simp
|
||||
|
||||
@[simp] theorem findIdx?_toArray (p : α → Bool) (l : List α) :
|
||||
@[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
|
||||
@@ -334,21 +334,21 @@ private theorem idxAuxOf_toArray [BEq α] (a : α) (l : List α) (j : Nat) (w :
|
||||
simp
|
||||
termination_by l.length - j
|
||||
|
||||
@[simp] theorem finIdxOf?_toArray [BEq α] (a : α) (l : List α) :
|
||||
@[simp, grind =] theorem finIdxOf?_toArray [BEq α] (a : α) (l : List α) :
|
||||
l.toArray.finIdxOf? a = l.finIdxOf? a := by
|
||||
rw [Array.finIdxOf?, finIdxOf?, findFinIdx?]
|
||||
simp [idxAuxOf_toArray]
|
||||
|
||||
@[simp] theorem idxOf?_toArray [BEq α] (a : α) (l : List α) :
|
||||
@[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]
|
||||
|
||||
@[simp] theorem findIdx_toArray {as : List α} {p : α → Bool} :
|
||||
@[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?]
|
||||
|
||||
@[simp] theorem idxOf_toArray [BEq α] {as : List α} {a : α} :
|
||||
@[simp, grind =] theorem idxOf_toArray [BEq α] {as : List α} {a : α} :
|
||||
as.toArray.idxOf a = as.idxOf a := by
|
||||
rw [Array.idxOf, findIdx_toArray, idxOf]
|
||||
|
||||
@@ -383,7 +383,7 @@ theorem isPrefixOfAux_toArray_zero [BEq α] (l₁ l₂ : List α) (hle : l₁.le
|
||||
| a::l₁, b::l₂ =>
|
||||
simp [isPrefixOf_cons₂, isPrefixOfAux_toArray_succ', isPrefixOfAux_toArray_zero]
|
||||
|
||||
@[simp] theorem isPrefixOf_toArray [BEq α] (l₁ l₂ : List α) :
|
||||
@[simp, grind =] theorem isPrefixOf_toArray [BEq α] (l₁ l₂ : List α) :
|
||||
l₁.toArray.isPrefixOf l₂.toArray = l₁.isPrefixOf l₂ := by
|
||||
rw [Array.isPrefixOf]
|
||||
split <;> rename_i h
|
||||
@@ -429,12 +429,12 @@ theorem zipWithAux_toArray_zero (f : α → β → γ) (as : List α) (bs : List
|
||||
| a :: as, b :: bs =>
|
||||
simp [zipWith_cons_cons, zipWithAux_toArray_succ', zipWithAux_toArray_zero, push_append_toArray]
|
||||
|
||||
@[simp] theorem zipWith_toArray (as : List α) (bs : List β) (f : α → β → γ) :
|
||||
@[simp, grind =] theorem zipWith_toArray (as : List α) (bs : List β) (f : α → β → γ) :
|
||||
Array.zipWith f as.toArray bs.toArray = (List.zipWith f as bs).toArray := by
|
||||
rw [Array.zipWith]
|
||||
simp [zipWithAux_toArray_zero]
|
||||
|
||||
@[simp] theorem zip_toArray (as : List α) (bs : List β) :
|
||||
@[simp, grind =] theorem zip_toArray (as : List α) (bs : List β) :
|
||||
Array.zip as.toArray bs.toArray = (List.zip as bs).toArray := by
|
||||
simp [Array.zip, zipWith_toArray, zip]
|
||||
|
||||
@@ -472,16 +472,16 @@ theorem zipWithAll_go_toArray (as : List α) (bs : List β) (f : Option α → O
|
||||
termination_by max as.length bs.length - i
|
||||
decreasing_by simp_wf; decreasing_trivial_pre_omega
|
||||
|
||||
@[simp] theorem zipWithAll_toArray (f : Option α → Option β → γ) (as : List α) (bs : List β) :
|
||||
@[simp, grind =] theorem zipWithAll_toArray (f : Option α → Option β → γ) (as : List α) (bs : List β) :
|
||||
Array.zipWithAll f as.toArray bs.toArray = (List.zipWithAll f as bs).toArray := by
|
||||
simp [Array.zipWithAll, zipWithAll_go_toArray]
|
||||
|
||||
@[simp] theorem toArray_appendList (l₁ l₂ : List α) :
|
||||
@[simp, grind =] theorem toArray_appendList (l₁ l₂ : List α) :
|
||||
l₁.toArray ++ l₂ = (l₁ ++ l₂).toArray := by
|
||||
apply ext'
|
||||
simp
|
||||
|
||||
@[simp] theorem pop_toArray (l : List α) : l.toArray.pop = l.dropLast.toArray := by
|
||||
@[simp, grind =] theorem pop_toArray (l : List α) : l.toArray.pop = l.dropLast.toArray := by
|
||||
apply ext'
|
||||
simp
|
||||
|
||||
@@ -513,7 +513,7 @@ theorem takeWhile_go_toArray (p : α → Bool) (l : List α) (i : Nat) :
|
||||
split <;> simp_all
|
||||
· simp_all [drop_eq_nil_of_le]
|
||||
|
||||
@[simp] theorem takeWhile_toArray (p : α → Bool) (l : List α) :
|
||||
@[simp, grind =] theorem takeWhile_toArray (p : α → Bool) (l : List α) :
|
||||
l.toArray.takeWhile p = (l.takeWhile p).toArray := by
|
||||
simp [Array.takeWhile, takeWhile_go_toArray]
|
||||
|
||||
@@ -528,11 +528,11 @@ private theorem popWhile_toArray_aux (p : α → Bool) (l : List α) :
|
||||
· rfl
|
||||
· simp
|
||||
|
||||
@[simp] theorem popWhile_toArray (p : α → Bool) (l : List α) :
|
||||
@[simp, grind =] theorem popWhile_toArray (p : α → Bool) (l : List α) :
|
||||
l.toArray.popWhile p = (l.reverse.dropWhile p).reverse.toArray := by
|
||||
simp [← popWhile_toArray_aux]
|
||||
|
||||
@[simp] theorem setIfInBounds_toArray (l : List α) (i : Nat) (a : α) :
|
||||
@[simp, grind =] theorem setIfInBounds_toArray (l : List α) (i : Nat) (a : α) :
|
||||
l.toArray.setIfInBounds i a = (l.set i a).toArray := by
|
||||
apply ext'
|
||||
simp only [setIfInBounds]
|
||||
@@ -540,7 +540,7 @@ private theorem popWhile_toArray_aux (p : α → Bool) (l : List α) :
|
||||
· simp
|
||||
· simp_all [List.set_eq_of_length_le]
|
||||
|
||||
@[simp] theorem toArray_replicate (n : Nat) (v : α) :
|
||||
@[simp, grind =] theorem toArray_replicate (n : Nat) (v : α) :
|
||||
(List.replicate n v).toArray = Array.replicate n v := rfl
|
||||
|
||||
theorem _root_.Array.replicate_eq_toArray_replicate :
|
||||
@@ -550,7 +550,7 @@ theorem _root_.Array.replicate_eq_toArray_replicate :
|
||||
@[deprecated _root_.Array.replicate_eq_toArray_replicate (since := "2025-03-18")]
|
||||
abbrev _root_.Array.mkArray_eq_toArray_replicate := @_root_.Array.replicate_eq_toArray_replicate
|
||||
|
||||
@[simp] theorem flatMap_empty {β} (f : α → Array β) : (#[] : Array α).flatMap f = #[] := rfl
|
||||
@[simp, grind =] theorem flatMap_empty {β} (f : α → Array β) : (#[] : Array α).flatMap f = #[] := rfl
|
||||
|
||||
theorem flatMap_toArray_cons {β} (f : α → Array β) (a : α) (as : List α) :
|
||||
(a :: as).toArray.flatMap f = f a ++ as.toArray.flatMap f := by
|
||||
@@ -562,7 +562,7 @@ theorem flatMap_toArray_cons {β} (f : α → Array β) (a : α) (as : List α)
|
||||
intro xs
|
||||
induction as generalizing xs <;> simp_all
|
||||
|
||||
@[simp] 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
|
||||
induction as with
|
||||
| nil => simp
|
||||
@@ -570,12 +570,12 @@ theorem flatMap_toArray_cons {β} (f : α → Array β) (a : α) (as : List α)
|
||||
apply ext'
|
||||
simp [ih, flatMap_toArray_cons]
|
||||
|
||||
@[simp] theorem swap_toArray (l : List α) (i j : Nat) {hi hj}:
|
||||
@[simp, grind =] theorem swap_toArray (l : List α) (i j : Nat) {hi hj}:
|
||||
l.toArray.swap i j hi hj = ((l.set i l[j]).set j l[i]).toArray := by
|
||||
apply ext'
|
||||
simp
|
||||
|
||||
@[simp] theorem eraseIdx_toArray (l : List α) (i : Nat) (h : i < l.toArray.size) :
|
||||
@[simp, grind =] theorem eraseIdx_toArray (l : List α) (i : Nat) (h : i < l.toArray.size) :
|
||||
l.toArray.eraseIdx i h = (l.eraseIdx i).toArray := by
|
||||
rw [Array.eraseIdx]
|
||||
split <;> rename_i h'
|
||||
@@ -593,19 +593,19 @@ decreasing_by
|
||||
simp
|
||||
omega
|
||||
|
||||
@[simp] theorem eraseIdxIfInBounds_toArray (l : List α) (i : Nat) :
|
||||
@[simp, grind =] theorem eraseIdxIfInBounds_toArray (l : List α) (i : Nat) :
|
||||
l.toArray.eraseIdxIfInBounds i = (l.eraseIdx i).toArray := by
|
||||
rw [Array.eraseIdxIfInBounds]
|
||||
split
|
||||
· simp
|
||||
· simp_all [eraseIdx_eq_self.2]
|
||||
|
||||
@[simp] theorem eraseP_toArray {as : List α} {p : α → Bool} :
|
||||
@[simp, grind =] theorem eraseP_toArray {as : List α} {p : α → Bool} :
|
||||
as.toArray.eraseP p = (as.eraseP p).toArray := by
|
||||
rw [Array.eraseP, List.eraseP_eq_eraseIdx, findFinIdx?_toArray]
|
||||
split <;> simp [*, findIdx?_eq_map_findFinIdx?_val]
|
||||
|
||||
@[simp] theorem erase_toArray [BEq α] {as : List α} {a : α} :
|
||||
@[simp, grind =] theorem erase_toArray [BEq α] {as : List α} {a : α} :
|
||||
as.toArray.erase a = (as.erase a).toArray := by
|
||||
rw [Array.erase, finIdxOf?_toArray, List.erase_eq_eraseIdx]
|
||||
rw [idxOf?_eq_map_finIdxOf?_val]
|
||||
@@ -635,7 +635,7 @@ private theorem insertIdx_loop_toArray (i : Nat) (l : List α) (j : Nat) (hj : j
|
||||
subst this
|
||||
simp
|
||||
|
||||
@[simp] theorem insertIdx_toArray (l : List α) (i : Nat) (a : α) (h : i ≤ l.toArray.size):
|
||||
@[simp, grind =] theorem insertIdx_toArray (l : List α) (i : Nat) (a : α) (h : i ≤ l.toArray.size):
|
||||
l.toArray.insertIdx i a = (l.insertIdx i a).toArray := by
|
||||
rw [Array.insertIdx]
|
||||
rw [insertIdx_loop_toArray (h := h)]
|
||||
@@ -658,7 +658,7 @@ private theorem insertIdx_loop_toArray (i : Nat) (l : List α) (j : Nat) (hj : j
|
||||
congr
|
||||
omega
|
||||
|
||||
@[simp] theorem insertIdxIfInBounds_toArray (l : List α) (i : Nat) (a : α) :
|
||||
@[simp, grind =] theorem insertIdxIfInBounds_toArray (l : List α) (i : Nat) (a : α) :
|
||||
l.toArray.insertIdxIfInBounds i a = (l.insertIdx i a).toArray := by
|
||||
rw [Array.insertIdxIfInBounds]
|
||||
split <;> rename_i h'
|
||||
@@ -666,7 +666,7 @@ private theorem insertIdx_loop_toArray (i : Nat) (l : List α) (j : Nat) (hj : j
|
||||
· simp only [size_toArray, Nat.not_le] at h'
|
||||
rw [List.insertIdx_of_length_lt (h := h')]
|
||||
|
||||
@[simp]
|
||||
@[simp, grind =]
|
||||
theorem replace_toArray [BEq α] [LawfulBEq α] (l : List α) (a b : α) :
|
||||
l.toArray.replace a b = (l.replace a b).toArray := by
|
||||
rw [Array.replace]
|
||||
@@ -700,11 +700,11 @@ theorem replace_toArray [BEq α] [LawfulBEq α] (l : List α) (a b : α) :
|
||||
exact ⟨i, by omega, h.1⟩
|
||||
· rfl
|
||||
|
||||
@[simp] theorem leftpad_toArray (n : Nat) (a : α) (l : List α) :
|
||||
@[simp, grind =] theorem leftpad_toArray (n : Nat) (a : α) (l : List α) :
|
||||
Array.leftpad n a l.toArray = (leftpad n a l).toArray := by
|
||||
simp [leftpad, Array.leftpad, ← toArray_replicate]
|
||||
|
||||
@[simp] theorem rightpad_toArray (n : Nat) (a : α) (l : List α) :
|
||||
@[simp, grind =] theorem rightpad_toArray (n : Nat) (a : α) (l : List α) :
|
||||
Array.rightpad n a l.toArray = (rightpad n a l).toArray := by
|
||||
simp [rightpad, Array.rightpad, ← toArray_replicate]
|
||||
|
||||
|
||||
@@ -524,8 +524,6 @@ theorem and_lt_two_pow (x : Nat) {y n : Nat} (right : y < 2^n) : (x &&& y) < 2^n
|
||||
|
||||
@[deprecated and_two_pow_sub_one_eq_mod (since := "2025-03-18")]
|
||||
abbrev and_pow_two_sub_one_eq_mod := @and_two_pow_sub_one_eq_mod
|
||||
@[deprecated and_two_pow_sub_one_eq_mod (since := "2024-09-11")]
|
||||
abbrev and_pow_two_is_mod := @and_two_pow_sub_one_eq_mod
|
||||
|
||||
theorem and_two_pow_sub_one_of_lt_two_pow {x : Nat} (lt : x < 2^n) : x &&& 2^n - 1 = x := by
|
||||
rw [and_two_pow_sub_one_eq_mod]
|
||||
@@ -533,8 +531,6 @@ theorem and_two_pow_sub_one_of_lt_two_pow {x : Nat} (lt : x < 2^n) : x &&& 2^n -
|
||||
|
||||
@[deprecated and_two_pow_sub_one_of_lt_two_pow (since := "2025-03-18")]
|
||||
abbrev and_pow_two_sub_one_of_lt_two_pow := @and_two_pow_sub_one_of_lt_two_pow
|
||||
@[deprecated and_two_pow_sub_one_of_lt_two_pow (since := "2024-09-11")]
|
||||
abbrev and_two_pow_identity := @and_two_pow_sub_one_of_lt_two_pow
|
||||
|
||||
@[simp] theorem and_mod_two_eq_one : (a &&& b) % 2 = 1 ↔ a % 2 = 1 ∧ b % 2 = 1 := by
|
||||
simp only [mod_two_eq_one_iff_testBit_zero]
|
||||
|
||||
@@ -14,3 +14,4 @@ import Init.Data.Option.Lemmas
|
||||
import Init.Data.Option.Attach
|
||||
import Init.Data.Option.List
|
||||
import Init.Data.Option.Monadic
|
||||
import Init.Data.Option.Array
|
||||
|
||||
26
src/Init/Data/Option/Array.lean
Normal file
26
src/Init/Data/Option/Array.lean
Normal file
@@ -0,0 +1,26 @@
|
||||
/-
|
||||
Copyright (c) 2025 Lean FRO, LLC. All rights reserved.
|
||||
Released under Apache 2.0 license as described in the file LICENSE.
|
||||
Authors: Markus Himmel
|
||||
-/
|
||||
module
|
||||
|
||||
prelude
|
||||
import Init.Data.Array.Lemmas
|
||||
import Init.Data.Option.List
|
||||
|
||||
namespace Option
|
||||
|
||||
@[simp]
|
||||
theorem toList_toArray {o : Option α} : o.toArray.toList = o.toList := by
|
||||
cases o <;> simp
|
||||
|
||||
@[simp]
|
||||
theorem toArray_toList {o : Option α} : o.toList.toArray = o.toArray := by
|
||||
cases o <;> simp
|
||||
|
||||
theorem toArray_filter {o : Option α} {p : α → Bool} :
|
||||
(o.filter p).toArray = o.toArray.filter p := by
|
||||
rw [← toArray_toList, toList_filter, ← List.filter_toArray, toArray_toList]
|
||||
|
||||
end Option
|
||||
@@ -138,7 +138,7 @@ theorem toList_attach (o : Option α) :
|
||||
o.attach.toList = o.toList.attach.map fun ⟨x, h⟩ => ⟨x, by simpa using h⟩ := by
|
||||
cases o <;> simp
|
||||
|
||||
@[simp] theorem attach_toList (o : Option α) :
|
||||
@[simp, grind =] theorem attach_toList (o : Option α) :
|
||||
o.toList.attach = (o.attach.map fun ⟨a, h⟩ => ⟨a, by simpa using h⟩).toList := by
|
||||
cases o <;> simp
|
||||
|
||||
@@ -195,7 +195,7 @@ theorem attach_filter {o : Option α} {p : α → Bool} :
|
||||
| some a =>
|
||||
simp only [filter_some, attach_some]
|
||||
ext
|
||||
simp only [attach_eq_some_iff, ite_none_right_eq_some, some.injEq, some_bind,
|
||||
simp only [attach_eq_some_iff, ite_none_right_eq_some, some.injEq, bind_some,
|
||||
dite_none_right_eq_some]
|
||||
constructor
|
||||
· rintro ⟨h, w⟩
|
||||
@@ -207,6 +207,10 @@ 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]
|
||||
|
||||
theorem toList_pbind {o : Option α} {f : (a : α) → o = some a → Option β} :
|
||||
(o.pbind f).toList = o.attach.toList.flatMap (fun ⟨x, h⟩ => (f x h).toList) := by
|
||||
cases o <;> simp
|
||||
|
||||
/-! ## unattach
|
||||
|
||||
`Option.unattach` is the (one-sided) inverse of `Option.attach`. It is a synonym for `Option.map Subtype.val`.
|
||||
|
||||
@@ -13,11 +13,20 @@ namespace Option
|
||||
deriving instance DecidableEq for Option
|
||||
deriving instance BEq for Option
|
||||
|
||||
@[simp, grind] theorem getD_none : getD none a = a := rfl
|
||||
@[simp, grind] theorem getD_some : getD (some a) b = a := rfl
|
||||
|
||||
@[simp, grind] theorem map_none (f : α → β) : none.map f = none := rfl
|
||||
@[simp, grind] theorem map_some (a) (f : α → β) : (some a).map f = some (f a) := rfl
|
||||
|
||||
/-- Lifts an optional value to any `Alternative`, sending `none` to `failure`. -/
|
||||
def getM [Alternative m] : Option α → m α
|
||||
| none => failure
|
||||
| some a => pure a
|
||||
|
||||
@[simp, grind] theorem getM_none [Alternative m] : getM none = (failure : m α) := rfl
|
||||
@[simp, grind] theorem getM_some [Alternative m] {a : α} : getM (some a) = (pure a : m α) := rfl
|
||||
|
||||
/-- Returns `true` on `some x` and `false` on `none`. -/
|
||||
@[inline] def isSome : Option α → Bool
|
||||
| some _ => true
|
||||
@@ -75,6 +84,14 @@ Examples:
|
||||
| none, _ => none
|
||||
| some a, f => f a
|
||||
|
||||
@[simp, grind] theorem bind_none (f : α → Option β) : none.bind f = none := rfl
|
||||
@[simp, grind] theorem bind_some (a) (f : α → Option β) : (some a).bind f = f a := rfl
|
||||
|
||||
@[deprecated bind_none (since := "2025-05-03")]
|
||||
abbrev none_bind := @bind_none
|
||||
@[deprecated bind_some (since := "2025-05-03")]
|
||||
abbrev some_bind := @bind_some
|
||||
|
||||
/--
|
||||
Runs the monadic action `f` on `o`'s value, if any, and returns the result, or `none` if there is
|
||||
no value.
|
||||
@@ -90,6 +107,9 @@ resulting collections are empty.
|
||||
return none
|
||||
|
||||
/--
|
||||
Applies a function in some applicative functor to an optional value, returning `none` with no
|
||||
effects if the value is missing.
|
||||
|
||||
Runs a monadic function `f` on an optional value, returning the result. If the optional value is
|
||||
`none`, the function is not called and the result is also `none`.
|
||||
|
||||
@@ -102,6 +122,9 @@ This function only requires `m` to be an applicative functor. An alias `Option.m
|
||||
| none => pure none
|
||||
| some x => some <$> f x
|
||||
|
||||
@[simp, grind] theorem mapM_none [Applicative m] (f : α → m β) : none.mapM f = pure none := rfl
|
||||
@[simp, grind] theorem mapM_some [Applicative m] (x) (f : α → m β) : (some x).mapM f = some <$> f x := rfl
|
||||
|
||||
/--
|
||||
Applies a function in some applicative functor to an optional value, returning `none` with no
|
||||
effects if the value is missing.
|
||||
@@ -111,9 +134,23 @@ This is an alias for `Option.mapM`, which already works for applicative functors
|
||||
@[inline] protected def mapA [Applicative m] (f : α → m β) : Option α → m (Option β) :=
|
||||
Option.mapM f
|
||||
|
||||
/-- For verification purposes, we replace `mapA` with `mapM`. -/
|
||||
@[simp, grind] theorem mapA_eq_mapM [Applicative m] {f : α → m β} : Option.mapA f o = Option.mapM f o := rfl
|
||||
|
||||
@[simp, grind]
|
||||
theorem map_id : (Option.map id : Option α → Option α) = id :=
|
||||
funext (fun o => match o with | none => rfl | some _ => rfl)
|
||||
|
||||
/--
|
||||
Keeps an optional value only if it satisfies a monadic Boolean predicate.
|
||||
|
||||
If `Option` is thought of as a collection that contains at most one element, then `Option.filterM`
|
||||
is analogous to `List.filterM`.
|
||||
-/
|
||||
@[inline] protected def filterM [Applicative m] (p : α → m Bool) : Option α → m (Option α)
|
||||
| none => pure none
|
||||
| some a => (fun b => if b then some a else none) <$> p a
|
||||
|
||||
/--
|
||||
Keeps an optional value only if it satisfies a Boolean predicate.
|
||||
|
||||
@@ -142,6 +179,9 @@ Examples:
|
||||
| some a => p a
|
||||
| none => true
|
||||
|
||||
@[simp, grind] theorem all_none : Option.all p none = true := rfl
|
||||
@[simp, grind] theorem all_some : Option.all p (some x) = p x := rfl
|
||||
|
||||
/--
|
||||
Checks whether an optional value is not `none` and satisfies a Boolean predicate.
|
||||
|
||||
@@ -154,6 +194,9 @@ Examples:
|
||||
| some a => p a
|
||||
| none => false
|
||||
|
||||
@[simp, grind] theorem any_none : Option.any p none = false := rfl
|
||||
@[simp, grind] theorem any_some : Option.any p (some x) = p x := rfl
|
||||
|
||||
/--
|
||||
Implementation of `OrElse`'s `<|>` syntax for `Option`. If the first argument is `some a`, returns
|
||||
`some a`, otherwise evaluates and returns the second argument.
|
||||
@@ -164,6 +207,9 @@ See also `or` for a version that is strict in the second argument.
|
||||
| some a, _ => some a
|
||||
| none, b => b ()
|
||||
|
||||
@[simp, grind] theorem orElse_some : (some a).orElse b = some a := rfl
|
||||
@[simp, grind] theorem orElse_none : none.orElse b = b () := rfl
|
||||
|
||||
instance : OrElse (Option α) where
|
||||
orElse := Option.orElse
|
||||
|
||||
@@ -230,15 +276,6 @@ def merge (fn : α → α → α) : Option α → Option α → Option α
|
||||
| none , some y => some y
|
||||
| some x, some y => some <| fn x y
|
||||
|
||||
@[simp, grind] theorem getD_none : getD none a = a := rfl
|
||||
@[simp, grind] theorem getD_some : getD (some a) b = a := rfl
|
||||
|
||||
@[simp, grind] theorem map_none (f : α → β) : none.map f = none := rfl
|
||||
@[simp, grind] theorem map_some (a) (f : α → β) : (some a).map f = some (f a) := rfl
|
||||
|
||||
@[simp, grind] theorem none_bind (f : α → Option β) : none.bind f = none := rfl
|
||||
@[simp, grind] theorem some_bind (a) (f : α → Option β) : (some a).bind f = f a := rfl
|
||||
|
||||
/--
|
||||
A case analysis function for `Option`.
|
||||
|
||||
@@ -262,9 +299,9 @@ Extracts the value from an option that can be proven to be `some`.
|
||||
@[inline] def get {α : Type u} : (o : Option α) → isSome o → α
|
||||
| some x, _ => x
|
||||
|
||||
@[simp] theorem some_get : ∀ {x : Option α} (h : isSome x), some (x.get h) = x
|
||||
@[simp, grind] theorem some_get : ∀ {x : Option α} (h : isSome x), some (x.get h) = x
|
||||
| some _, _ => rfl
|
||||
@[simp] theorem get_some (x : α) (h : isSome (some x)) : (some x).get h = x := rfl
|
||||
@[simp, grind] theorem get_some (x : α) (h : isSome (some x)) : (some x).get h = x := rfl
|
||||
|
||||
/--
|
||||
Returns `none` if a value doesn't satisfy a Boolean predicate, or the value itself otherwise.
|
||||
@@ -340,7 +377,10 @@ Examples:
|
||||
* `(some none).join = none`
|
||||
* `(some (some v)).join = some v`
|
||||
-/
|
||||
@[simp, inline] def join (x : Option (Option α)) : Option α := x.bind id
|
||||
@[inline] def join (x : Option (Option α)) : Option α := x.bind id
|
||||
|
||||
@[simp, grind] theorem join_none : (none : Option (Option α)).join = none := rfl
|
||||
@[simp, grind] theorem join_some : (some o).join = o := rfl
|
||||
|
||||
/--
|
||||
Converts an optional monadic computation into a monadic computation of an optional value.
|
||||
@@ -363,7 +403,10 @@ some "world"
|
||||
-/
|
||||
@[inline] def sequence [Applicative m] {α : Type u} : Option (m α) → m (Option α)
|
||||
| none => pure none
|
||||
| some fn => some <$> fn
|
||||
| some f => some <$> f
|
||||
|
||||
@[simp, grind] theorem sequence_none [Applicative m] : (none : Option (m α)).sequence = pure none := rfl
|
||||
@[simp, grind] theorem sequence_some [Applicative m] (f : m α) : (some f).sequence = some <$> f := rfl
|
||||
|
||||
/--
|
||||
A monadic case analysis function for `Option`.
|
||||
@@ -388,6 +431,9 @@ This is the monadic analogue of `Option.getD`.
|
||||
| some a => pure a
|
||||
| none => y
|
||||
|
||||
@[simp, grind] theorem getDM_none [Pure m] (y : m α) : (none : Option α).getDM y = y := rfl
|
||||
@[simp, grind] theorem getDM_some [Pure m] (a : α) (y : m α) : (some a).getDM y = pure a := rfl
|
||||
|
||||
instance (α) [BEq α] [ReflBEq α] : ReflBEq (Option α) where
|
||||
rfl {x} :=
|
||||
match x with
|
||||
@@ -400,12 +446,6 @@ instance (α) [BEq α] [LawfulBEq α] : LawfulBEq (Option α) where
|
||||
| some x, some y => rw [LawfulBEq.eq_of_beq (α := α) h]
|
||||
| none, none => rfl
|
||||
|
||||
@[simp, grind] theorem all_none : Option.all p none = true := rfl
|
||||
@[simp, grind] theorem all_some : Option.all p (some x) = p x := rfl
|
||||
|
||||
@[simp, grind] theorem any_none : Option.any p none = false := rfl
|
||||
@[simp, grind] theorem any_some : Option.any p (some x) = p x := rfl
|
||||
|
||||
/--
|
||||
The minimum of two optional values, with `none` treated as the least element. This function is
|
||||
usually accessed through the `Min (Option α)` instance, rather than directly.
|
||||
@@ -428,10 +468,18 @@ protected def min [Min α] : Option α → Option α → Option α
|
||||
|
||||
instance [Min α] : Min (Option α) where min := Option.min
|
||||
|
||||
@[simp] theorem min_some_some [Min α] {a b : α} : min (some a) (some b) = some (min a b) := rfl
|
||||
@[simp] theorem min_some_none [Min α] {a : α} : min (some a) none = none := rfl
|
||||
@[simp] theorem min_none_some [Min α] {b : α} : min none (some b) = none := rfl
|
||||
@[simp] theorem min_none_none [Min α] : min (none : Option α) none = none := rfl
|
||||
@[simp, grind] theorem min_some_some [Min α] {a b : α} : min (some a) (some b) = some (min a b) := rfl
|
||||
@[simp, grind] theorem min_none_left [Min α] {o : Option α} : min none o = none := by
|
||||
cases o <;> rfl
|
||||
@[simp, grind] theorem min_none_right [Min α] {o : Option α} : min o none = none := by
|
||||
cases o <;> rfl
|
||||
|
||||
@[deprecated min_none_right (since := "2025-05-12")]
|
||||
theorem min_some_none [Min α] {a : α} : min (some a) none = none := rfl
|
||||
@[deprecated min_none_left (since := "2025-05-12")]
|
||||
theorem min_none_some [Min α] {b : α} : min none (some b) = none := rfl
|
||||
@[deprecated min_none_left (since := "2025-05-12")]
|
||||
theorem min_none_none [Min α] : min (none : Option α) none = none := rfl
|
||||
|
||||
/--
|
||||
The maximum of two optional values.
|
||||
@@ -453,10 +501,18 @@ protected def max [Max α] : Option α → Option α → Option α
|
||||
|
||||
instance [Max α] : Max (Option α) where max := Option.max
|
||||
|
||||
@[simp] theorem max_some_some [Max α] {a b : α} : max (some a) (some b) = some (max a b) := rfl
|
||||
@[simp] theorem max_some_none [Max α] {a : α} : max (some a) none = some a := rfl
|
||||
@[simp] theorem max_none_some [Max α] {b : α} : max none (some b) = some b := rfl
|
||||
@[simp] theorem max_none_none [Max α] : max (none : Option α) none = none := rfl
|
||||
@[simp, grind] theorem max_some_some [Max α] {a b : α} : max (some a) (some b) = some (max a b) := rfl
|
||||
@[simp, grind] theorem max_none_left [Max α] {o : Option α} : max none o = o := by
|
||||
cases o <;> rfl
|
||||
@[simp, grind] theorem max_none_right [Max α] {o : Option α} : max o none = o := by
|
||||
cases o <;> rfl
|
||||
|
||||
@[deprecated max_none_right (since := "2025-05-12")]
|
||||
theorem max_some_none [Max α] {a : α} : max (some a) none = some a := rfl
|
||||
@[deprecated max_none_left (since := "2025-05-12")]
|
||||
theorem max_none_some [Max α] {b : α} : max none (some b) = some b := rfl
|
||||
@[deprecated max_none_left (since := "2025-05-12")]
|
||||
theorem max_none_none [Max α] : max (none : Option α) none = none := rfl
|
||||
|
||||
|
||||
end Option
|
||||
@@ -481,6 +537,7 @@ instance : Alternative Option where
|
||||
failure := Option.none
|
||||
orElse := Option.orElse
|
||||
|
||||
-- This is a duplicate of `Option.getM`; one may be deprecated in the future.
|
||||
def liftOption [Alternative m] : Option α → m α
|
||||
| some a => pure a
|
||||
| none => failure
|
||||
|
||||
@@ -12,7 +12,7 @@ universe u v
|
||||
|
||||
namespace Option
|
||||
|
||||
theorem eq_of_eq_some {α : Type u} : ∀ {x y : Option α}, (∀z, x = some z ↔ y = some z) → x = y
|
||||
theorem eq_of_eq_some {α : Type u} : ∀ {x y : Option α}, (∀ z, x = some z ↔ y = some z) → x = y
|
||||
| none, none, _ => rfl
|
||||
| none, some z, h => Option.noConfusion ((h z).2 rfl)
|
||||
| some z, none, h => Option.noConfusion ((h z).1 rfl)
|
||||
|
||||
@@ -91,8 +91,6 @@ theorem eq_some_unique {o : Option α} {a b : α} (ha : o = some a) (hb : o = so
|
||||
| some _, _, H => ((H _).1 rfl).symm
|
||||
| _, some _, H => (H _).2 rfl
|
||||
|
||||
set_option Elab.async false
|
||||
|
||||
theorem eq_none_iff_forall_ne_some : o = none ↔ ∀ a, o ≠ some a := by
|
||||
cases o <;> simp
|
||||
|
||||
@@ -174,15 +172,15 @@ theorem forall_ne_none {p : Option α → Prop} : (∀ x (_ : x ≠ none), p x)
|
||||
@[deprecated forall_ne_none (since := "2025-04-04")]
|
||||
abbrev ball_ne_none := @forall_ne_none
|
||||
|
||||
@[simp] theorem pure_def : pure = @some α := rfl
|
||||
@[simp, grind] theorem pure_def : pure = @some α := rfl
|
||||
|
||||
@[simp] theorem bind_eq_bind : bind = @Option.bind α β := rfl
|
||||
@[simp, grind] theorem bind_eq_bind : bind = @Option.bind α β := rfl
|
||||
|
||||
@[simp] theorem orElse_eq_orElse : HOrElse.hOrElse = @Option.orElse α := rfl
|
||||
@[simp, grind] theorem orElse_eq_orElse : HOrElse.hOrElse = @Option.orElse α := rfl
|
||||
|
||||
@[simp] theorem bind_some (x : Option α) : x.bind some = x := by cases x <;> rfl
|
||||
@[simp, grind] theorem bind_fun_some (x : Option α) : x.bind some = x := by cases x <;> rfl
|
||||
|
||||
@[simp] theorem bind_none (x : Option α) : x.bind (fun _ => none (α := β)) = none := by
|
||||
@[simp] theorem bind_fun_none (x : Option α) : x.bind (fun _ => none (α := β)) = none := by
|
||||
cases x <;> rfl
|
||||
|
||||
theorem bind_eq_some_iff : x.bind f = some b ↔ ∃ a, x = some a ∧ f a = some b := by
|
||||
@@ -201,7 +199,7 @@ theorem bind_eq_none' {o : Option α} {f : α → Option β} :
|
||||
o.bind f = none ↔ ∀ b a, o = some a → f a ≠ some b := by
|
||||
cases o <;> simp [eq_none_iff_forall_ne_some]
|
||||
|
||||
theorem mem_bind_iff {o : Option α} {f : α → Option β} :
|
||||
@[grind] theorem mem_bind_iff {o : Option α} {f : α → Option β} :
|
||||
b ∈ o.bind f ↔ ∃ a, a ∈ o ∧ b ∈ f a := by
|
||||
cases o <;> simp
|
||||
|
||||
@@ -209,6 +207,7 @@ theorem bind_comm {f : α → β → Option γ} (a : Option α) (b : Option β)
|
||||
(a.bind fun x => b.bind (f x)) = b.bind fun y => a.bind fun x => f x y := by
|
||||
cases a <;> cases b <;> rfl
|
||||
|
||||
@[grind]
|
||||
theorem bind_assoc (x : Option α) (f : α → Option β) (g : β → Option γ) :
|
||||
(x.bind f).bind g = x.bind fun y => (f y).bind g := by cases x <;> rfl
|
||||
|
||||
@@ -216,10 +215,16 @@ theorem bind_congr {α β} {o : Option α} {f g : α → Option β} :
|
||||
(h : ∀ a, o = some a → f a = g a) → o.bind f = o.bind g := by
|
||||
cases o <;> simp
|
||||
|
||||
@[grind]
|
||||
theorem isSome_bind {α β : Type _} (x : Option α) (f : α → Option β) :
|
||||
(x.bind f).isSome = x.any (fun x => (f x).isSome) := by
|
||||
cases x <;> rfl
|
||||
|
||||
@[grind]
|
||||
theorem isNone_bind {α β : Type _} (x : Option α) (f : α → Option β) :
|
||||
(x.bind f).isNone = x.all (fun x => (f x).isNone) := by
|
||||
cases x <;> rfl
|
||||
|
||||
theorem isSome_of_isSome_bind {α β : Type _} {x : Option α} {f : α → Option β}
|
||||
(h : (x.bind f).isSome) : x.isSome := by
|
||||
cases x <;> trivial
|
||||
@@ -228,13 +233,15 @@ theorem isSome_apply_of_isSome_bind {α β : Type _} {x : Option α} {f : α →
|
||||
(h : (x.bind f).isSome) : (f (x.get (isSome_of_isSome_bind h))).isSome := by
|
||||
cases x <;> trivial
|
||||
|
||||
@[simp] theorem get_bind {α β : Type _} {x : Option α} {f : α → Option β} (h : (x.bind f).isSome) :
|
||||
@[simp, grind] theorem get_bind {α β : Type _} {x : Option α} {f : α → Option β} (h : (x.bind f).isSome) :
|
||||
(x.bind f).get h = (f (x.get (isSome_of_isSome_bind h))).get
|
||||
(isSome_apply_of_isSome_bind h) := by
|
||||
cases x <;> trivial
|
||||
|
||||
theorem join_eq_bind_id {x : Option (Option α)} : x.join = x.bind id := rfl
|
||||
|
||||
theorem join_eq_some_iff : x.join = some a ↔ x = some (some a) := by
|
||||
simp [bind_eq_some_iff]
|
||||
simp [join_eq_bind_id, bind_eq_some_iff]
|
||||
|
||||
@[deprecated join_eq_some_iff (since := "2025-04-10")]
|
||||
abbrev join_eq_some := @join_eq_some_iff
|
||||
@@ -246,14 +253,14 @@ theorem join_ne_none' : ¬x.join = none ↔ ∃ z, x = some (some z) :=
|
||||
join_ne_none
|
||||
|
||||
theorem join_eq_none_iff : o.join = none ↔ o = none ∨ o = some none :=
|
||||
match o with | none | some none | some (some _) => by simp
|
||||
match o with | none | some none | some (some _) => by simp [join_eq_bind_id]
|
||||
|
||||
@[deprecated join_eq_none_iff (since := "2025-04-10")]
|
||||
abbrev join_eq_none := @join_eq_none_iff
|
||||
|
||||
theorem bind_id_eq_join {x : Option (Option α)} : x.bind id = x.join := rfl
|
||||
@[grind] theorem bind_id_eq_join {x : Option (Option α)} : x.bind id = x.join := rfl
|
||||
|
||||
@[simp] theorem map_eq_map : Functor.map f = Option.map f := rfl
|
||||
@[simp, grind] theorem map_eq_map : Functor.map f = Option.map f := rfl
|
||||
|
||||
@[deprecated map_none (since := "2025-04-10")]
|
||||
abbrev map_none' := @map_none
|
||||
@@ -295,28 +302,28 @@ theorem map_congr {x : Option α} (h : ∀ a, x = some a → f a = g a) :
|
||||
x.map f = x.map g := by
|
||||
cases x <;> simp only [map_none, map_some, h]
|
||||
|
||||
@[simp] theorem map_id_fun {α : Type u} : Option.map (id : α → α) = id := by
|
||||
@[simp, grind] theorem map_id_fun {α : Type u} : Option.map (id : α → α) = id := by
|
||||
funext; simp [map_id]
|
||||
|
||||
theorem map_id' {x : Option α} : (x.map fun a => a) = x := congrFun map_id x
|
||||
|
||||
@[simp] theorem map_id_fun' {α : Type u} : Option.map (fun (a : α) => a) = id := by
|
||||
@[simp, grind] theorem map_id_fun' {α : Type u} : Option.map (fun (a : α) => a) = id := by
|
||||
funext; simp [map_id']
|
||||
|
||||
theorem get_map {f : α → β} {o : Option α} {h : (o.map f).isSome} :
|
||||
@[simp, grind] theorem get_map {f : α → β} {o : Option α} {h : (o.map f).isSome} :
|
||||
(o.map f).get h = f (o.get (by simpa using h)) := by
|
||||
cases o with
|
||||
| none => simp at h
|
||||
| some a => simp
|
||||
|
||||
@[simp] theorem map_map (h : β → γ) (g : α → β) (x : Option α) :
|
||||
@[simp, grind _=_] theorem map_map (h : β → γ) (g : α → β) (x : Option α) :
|
||||
(x.map g).map h = x.map (h ∘ g) := by
|
||||
cases x <;> simp only [map_none, map_some, ·∘·]
|
||||
|
||||
theorem comp_map (h : β → γ) (g : α → β) (x : Option α) : x.map (h ∘ g) = (x.map g).map h :=
|
||||
(map_map ..).symm
|
||||
|
||||
@[simp] theorem map_comp_map (f : α → β) (g : β → γ) :
|
||||
@[simp, grind _=_] theorem map_comp_map (f : α → β) (g : β → γ) :
|
||||
Option.map g ∘ Option.map f = Option.map (g ∘ f) := by funext x; simp
|
||||
|
||||
theorem mem_map_of_mem (g : α → β) (h : a ∈ x) : g a ∈ Option.map g x := h.symm ▸ map_some ..
|
||||
@@ -342,6 +349,12 @@ theorem map_inj_right {f : α → β} {o o' : Option α} (w : ∀ x y, f x = f y
|
||||
|
||||
@[grind] theorem filter_some : Option.filter p (some a) = if p a then some a else none := rfl
|
||||
|
||||
theorem filter_some_pos (h : p a) : Option.filter p (some a) = some a := by
|
||||
rw [filter_some, if_pos h]
|
||||
|
||||
theorem filter_some_neg (h : p a = false) : Option.filter p (some a) = none := by
|
||||
rw [filter_some, if_neg] <;> simpa
|
||||
|
||||
theorem isSome_of_isSome_filter (p : α → Bool) (o : Option α) (h : (o.filter p).isSome) :
|
||||
o.isSome := by
|
||||
cases o <;> simp at h ⊢
|
||||
@@ -373,6 +386,11 @@ abbrev filter_eq_none := @filter_eq_none_iff
|
||||
@[deprecated filter_eq_some_iff (since := "2025-04-10")]
|
||||
abbrev filter_eq_some := @filter_eq_some_iff
|
||||
|
||||
theorem filter_some_eq_some : Option.filter p (some a) = some a ↔ p a := by simp
|
||||
|
||||
theorem filter_some_eq_none : Option.filter p (some a) = none ↔ ¬p a := by simp
|
||||
|
||||
@[grind]
|
||||
theorem mem_filter_iff {p : α → Bool} {a : α} {o : Option α} :
|
||||
a ∈ o.filter p ↔ a ∈ o ∧ p a := by
|
||||
simp
|
||||
@@ -381,12 +399,68 @@ theorem filter_eq_bind (x : Option α) (p : α → Bool) :
|
||||
x.filter p = x.bind (Option.guard p) := by
|
||||
cases x <;> rfl
|
||||
|
||||
@[simp] theorem all_guard (a : α) :
|
||||
@[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 =>
|
||||
match h : p a with
|
||||
| false => by simp [filter_some_neg h, h]
|
||||
| true => by simp [filter_some_pos h, h]
|
||||
|
||||
@[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 =>
|
||||
match h : p a with
|
||||
| false => by simp [filter_some_neg h, h]
|
||||
| true => by simp [filter_some_pos h, h]
|
||||
|
||||
@[simp] theorem isNone_filter :
|
||||
Option.isNone (Option.filter p o) = Option.all (fun a => !p a) o :=
|
||||
match o with
|
||||
| none => rfl
|
||||
| some a =>
|
||||
match h : p a with
|
||||
| false => by simp [filter_some_neg h, h]
|
||||
| true => by simp [filter_some_pos h, h]
|
||||
|
||||
@[simp, grind] theorem isSome_filter : Option.isSome (Option.filter p o) = Option.any p o :=
|
||||
match o with
|
||||
| none => rfl
|
||||
| some a =>
|
||||
match h : p a with
|
||||
| false => by simp [filter_some_neg h, h]
|
||||
| true => by simp [filter_some_pos h, h]
|
||||
|
||||
@[simp] theorem filter_filter :
|
||||
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)
|
||||
|
||||
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
|
||||
| some a =>
|
||||
simp only [bind_some, filter_some]
|
||||
cases h : f a with
|
||||
| none => simp
|
||||
| some b =>
|
||||
simp only [any_some, filter_some]
|
||||
split <;> simp [h]
|
||||
|
||||
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
|
||||
|
||||
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, 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
|
||||
|
||||
@@ -425,33 +499,45 @@ theorem any_eq_false_iff_get (p : α → Bool) (x : Option α) :
|
||||
theorem isSome_of_any {x : Option α} {p : α → Bool} (h : x.any p) : x.isSome := by
|
||||
cases x <;> trivial
|
||||
|
||||
@[grind]
|
||||
theorem any_map {α β : Type _} {x : Option α} {f : α → β} {p : β → Bool} :
|
||||
(x.map f).any p = x.any (fun a => p (f a)) := by
|
||||
cases x <;> rfl
|
||||
|
||||
@[grind]
|
||||
theorem all_map {α β : Type _} {x : Option α} {f : α → β} {p : β → Bool} :
|
||||
(x.map f).all p = x.all (fun a => p (f a)) := by
|
||||
cases x <;> rfl
|
||||
|
||||
theorem bind_map_comm {α β} {x : Option (Option α)} {f : α → β} :
|
||||
x.bind (Option.map f) = (x.map (Option.map f)).bind id := by cases x <;> simp
|
||||
|
||||
theorem bind_map {f : α → β} {g : β → Option γ} {x : Option α} :
|
||||
@[grind] theorem bind_map {f : α → β} {g : β → Option γ} {x : Option α} :
|
||||
(x.map f).bind g = x.bind (g ∘ f) := by cases x <;> simp
|
||||
|
||||
@[simp] theorem map_bind {f : α → Option β} {g : β → γ} {x : Option α} :
|
||||
@[simp, grind] theorem map_bind {f : α → Option β} {g : β → γ} {x : Option α} :
|
||||
(x.bind f).map g = x.bind (Option.map g ∘ f) := by cases x <;> simp
|
||||
|
||||
theorem join_map_eq_map_join {f : α → β} {x : Option (Option α)} :
|
||||
@[grind] theorem join_map_eq_map_join {f : α → β} {x : Option (Option α)} :
|
||||
(x.map (Option.map f)).join = x.join.map f := by cases x <;> simp
|
||||
|
||||
theorem join_join {x : Option (Option (Option α))} : x.join.join = (x.map join).join := by
|
||||
@[grind _=_] theorem join_join {x : Option (Option (Option α))} : x.join.join = (x.map join).join := by
|
||||
cases x <;> simp
|
||||
|
||||
theorem mem_of_mem_join {a : α} {x : Option (Option α)} (h : a ∈ x.join) : some a ∈ x :=
|
||||
h.symm ▸ join_eq_some_iff.1 h
|
||||
|
||||
@[simp, grind] theorem some_orElse (a : α) (f) : (some a).orElse f = some a := rfl
|
||||
@[deprecated orElse_some (since := "2025-05-03")]
|
||||
theorem some_orElse (a : α) (f) : (some a).orElse f = some a := rfl
|
||||
|
||||
@[simp, grind] theorem none_orElse (f : Unit → Option α) : none.orElse f = f () := rfl
|
||||
@[deprecated orElse_none (since := "2025-05-03")]
|
||||
theorem none_orElse (f : Unit → Option α) : none.orElse f = f () := rfl
|
||||
|
||||
@[simp] theorem orElse_none (x : Option α) : x.orElse (fun _ => none) = x := by cases x <;> rfl
|
||||
@[simp] theorem orElse_fun_none (x : Option α) : x.orElse (fun _ => none) = x := by cases x <;> rfl
|
||||
|
||||
@[simp] theorem orElse_fun_some (x : Option α) (a : α) :
|
||||
x.orElse (fun _ => some a) = some (x.getD a) := by
|
||||
cases x <;> simp
|
||||
|
||||
theorem orElse_eq_some_iff (o : Option α) (f) (x : α) :
|
||||
(o.orElse f) = some x ↔ o = some x ∨ o = none ∧ f () = some x := by
|
||||
@@ -460,7 +546,7 @@ theorem orElse_eq_some_iff (o : Option α) (f) (x : α) :
|
||||
theorem orElse_eq_none_iff (o : Option α) (f) : (o.orElse f) = none ↔ o = none ∧ f () = none := by
|
||||
cases o <;> simp
|
||||
|
||||
theorem map_orElse {x : Option α} {y} :
|
||||
@[grind] theorem map_orElse {x : Option α} {y} :
|
||||
(x.orElse y).map f = (x.map f).orElse (fun _ => (y ()).map f) := by
|
||||
cases x <;> simp
|
||||
|
||||
@@ -479,9 +565,6 @@ abbrev guard_isSome := @isSome_guard
|
||||
@[simp] theorem guard_eq_none_iff : Option.guard p a = none ↔ p a = false :=
|
||||
if h : p a then by simp [Option.guard, h] else by simp [Option.guard, h]
|
||||
|
||||
@[deprecated guard_eq_none_iff (since := "2025-04-10")]
|
||||
abbrev guard_eq_none := @guard_eq_none_iff
|
||||
|
||||
@[simp] theorem guard_pos (h : p a) : Option.guard p a = some a := by
|
||||
simp [Option.guard, h]
|
||||
|
||||
@@ -504,7 +587,7 @@ theorem guard_comp {p : α → Bool} {f : β → α} :
|
||||
ext1 b
|
||||
simp [guard]
|
||||
|
||||
theorem bind_guard (x : Option α) (p : α → Bool) :
|
||||
@[grind] theorem bind_guard (x : Option α) (p : α → Bool) :
|
||||
x.bind (Option.guard p) = x.filter p := by
|
||||
simp only [Option.filter_eq_bind, decide_eq_true_eq]
|
||||
|
||||
@@ -513,9 +596,41 @@ theorem guard_eq_map (p : α → Bool) :
|
||||
funext x
|
||||
simp [Option.guard]
|
||||
|
||||
@[grind]
|
||||
theorem guard_def (p : α → Bool) :
|
||||
Option.guard p = fun x => if p x then some x else none := rfl
|
||||
|
||||
theorem guard_eq_ite {p : α → Bool} {x : α} :
|
||||
Option.guard p x = if p x then some x else none := rfl
|
||||
|
||||
theorem guard_eq_filter {p : α → Bool} {x : α} :
|
||||
Option.guard p x = Option.filter p (some x) := rfl
|
||||
|
||||
@[simp] theorem filter_guard {p q : α → Bool} {x : α} :
|
||||
(Option.guard p x).filter q = Option.guard (fun y => p y && q y) x := by
|
||||
rw [guard_eq_ite]
|
||||
split <;> simp_all [filter_some, guard_eq_ite]
|
||||
|
||||
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
|
||||
simp only [join_some, filter_some]
|
||||
split <;> simp
|
||||
| some (some a) => by
|
||||
simp only [join_some, filter_some]
|
||||
split <;> simp
|
||||
|
||||
theorem filter_join {p : α → Bool} : {o : Option (Option α)} →
|
||||
o.join.filter p = (o.filter (Option.any p)).join
|
||||
| none => by simp
|
||||
| some none => by
|
||||
simp only [join_some, filter_some]
|
||||
split <;> simp
|
||||
| some (some a) => by
|
||||
simp only [join_some, filter_some, any_some]
|
||||
split <;> simp
|
||||
|
||||
theorem merge_eq_or_eq {f : α → α → α} (h : ∀ a b, f a b = a ∨ f a b = b) :
|
||||
∀ o₁ o₂, merge f o₁ o₂ = o₁ ∨ merge f o₁ o₂ = o₂
|
||||
| none, none => .inl rfl
|
||||
@@ -569,6 +684,15 @@ instance lawfulIdentity_merge (f : α → α → α) : Std.LawfulIdentity (merge
|
||||
|
||||
@[simp, grind] theorem elim_some (x : β) (f : α → β) (a : α) : (some a).elim x f = f a := rfl
|
||||
|
||||
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
|
||||
| some a =>
|
||||
match h : p a with
|
||||
| false => by simp [filter_some_neg h, h]
|
||||
| true => by simp [filter_some_pos, h]
|
||||
|
||||
@[simp, grind] theorem getD_map (f : α → β) (x : α) (o : Option α) :
|
||||
(o.map f).getD (f x) = f (getD o x) := by cases o <;> rfl
|
||||
|
||||
@@ -585,23 +709,38 @@ Otherwise, it is `none`.
|
||||
noncomputable def choice (α : Type _) : Option α :=
|
||||
if h : Nonempty α then some (Classical.choice h) else none
|
||||
|
||||
theorem choice_eq {α : Type _} [Subsingleton α] (a : α) : choice α = some a := by
|
||||
theorem choice_eq_some [Subsingleton α] (a : α) : choice α = some a := by
|
||||
simp [choice]
|
||||
rw [dif_pos (⟨a⟩ : Nonempty α)]
|
||||
simp; apply Subsingleton.elim
|
||||
|
||||
theorem isSome_choice_iff_nonempty {α : Type _} : (choice α).isSome ↔ Nonempty α :=
|
||||
@[deprecated choice_eq_some (since := "2025-05-12")]
|
||||
abbrev choice_eq := @choice_eq_some
|
||||
|
||||
@[simp]
|
||||
theorem choice_eq_default [Subsingleton α] [Inhabited α] : choice α = some default :=
|
||||
choice_eq_some _
|
||||
|
||||
theorem choice_eq_none_iff_not_nonempty : choice α = none ↔ ¬Nonempty α := by
|
||||
simp [choice]
|
||||
|
||||
theorem isSome_choice_iff_nonempty : (choice α).isSome ↔ Nonempty α :=
|
||||
⟨fun h => ⟨(choice α).get h⟩, fun h => by simp only [choice, dif_pos h, isSome_some]⟩
|
||||
|
||||
@[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]
|
||||
|
||||
end choice
|
||||
|
||||
@[simp, grind] theorem toList_some (a : α) : (some a).toList = [a] := rfl
|
||||
|
||||
@[simp, grind] theorem toList_none (α : Type _) : (none : Option α).toList = [] := rfl
|
||||
|
||||
@[simp, grind] theorem toArray_some (a : α) : (some a).toArray = #[a] := rfl
|
||||
@[simp, grind] theorem toArray_none (α : Type _) : (none : Option α).toArray = #[] := rfl
|
||||
|
||||
-- See `Init.Data.Option.List` for lemmas about `toList`.
|
||||
|
||||
@[simp, grind] theorem some_or : (some a).or o = some a := rfl
|
||||
@@ -610,10 +749,14 @@ end choice
|
||||
theorem or_eq_right_of_none {o o' : Option α} (h : o = none) : o.or o' = o' := by
|
||||
cases h; simp
|
||||
|
||||
@[deprecated some_or (since := "2024-11-03")] theorem or_some : (some a).or o = some a := rfl
|
||||
@[simp, grind] theorem or_some {o : Option α} : o.or (some a) = some (o.getD a) := by
|
||||
cases o <;> rfl
|
||||
|
||||
/-- This will be renamed to `or_some` once the existing deprecated lemma is removed. -/
|
||||
@[simp, grind] theorem or_some' {o : Option α} : o.or (some a) = some (o.getD a) := by
|
||||
@[deprecated or_some (since := "2025-05-03")]
|
||||
abbrev or_some' := @or_some
|
||||
|
||||
@[simp, grind]
|
||||
theorem or_none : or o none = o := by
|
||||
cases o <;> rfl
|
||||
|
||||
theorem or_eq_bif : or o o' = bif o.isSome then o else o' := by
|
||||
@@ -637,14 +780,10 @@ abbrev or_eq_none := @or_eq_none_iff
|
||||
@[deprecated or_eq_some_iff (since := "2025-04-10")]
|
||||
abbrev or_eq_some := @or_eq_some_iff
|
||||
|
||||
theorem or_assoc : or (or o₁ o₂) o₃ = or o₁ (or o₂ o₃) := by
|
||||
@[grind] theorem or_assoc : or (or o₁ o₂) o₃ = or o₁ (or o₂ o₃) := by
|
||||
cases o₁ <;> cases o₂ <;> rfl
|
||||
instance : Std.Associative (or (α := α)) := ⟨@or_assoc _⟩
|
||||
|
||||
@[simp, grind]
|
||||
theorem or_none : or o none = o := by
|
||||
cases o <;> rfl
|
||||
|
||||
theorem or_eq_left_of_none {o o' : Option α} (h : o' = none) : o.or o' = o := by
|
||||
cases h; simp
|
||||
|
||||
@@ -679,16 +818,24 @@ theorem getD_or {o o' : Option α} {fallback : α} :
|
||||
(o.or o').getD fallback = o.getD (o'.getD fallback) := by
|
||||
cases o <;> simp
|
||||
|
||||
@[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
|
||||
|
||||
/-! ### beq -/
|
||||
|
||||
section beq
|
||||
|
||||
variable [BEq α]
|
||||
|
||||
@[simp] theorem none_beq_none : ((none : Option α) == none) = true := rfl
|
||||
@[simp] theorem none_beq_some (a : α) : ((none : Option α) == some a) = false := rfl
|
||||
@[simp] theorem some_beq_none (a : α) : ((some a : Option α) == none) = false := rfl
|
||||
@[simp] theorem some_beq_some {a b : α} : (some a == some b) = (a == b) := rfl
|
||||
@[simp, grind] theorem none_beq_none : ((none : Option α) == none) = true := rfl
|
||||
@[simp, grind] theorem none_beq_some (a : α) : ((none : Option α) == some a) = false := rfl
|
||||
@[simp, grind] theorem some_beq_none (a : α) : ((some a : Option α) == none) = false := rfl
|
||||
@[simp, grind] theorem some_beq_some {a b : α} : (some a == some b) = (a == b) := rfl
|
||||
|
||||
/-- We simplify away `isEqSome` in terms of `==`. -/
|
||||
@[simp, grind] theorem isEqSome_eq_beq_some {o : Option α} : isEqSome o y = (o == some y) := by
|
||||
cases o <;> simp [isEqSome]
|
||||
|
||||
@[simp] theorem reflBEq_iff : ReflBEq (Option α) ↔ ReflBEq α := by
|
||||
constructor
|
||||
@@ -802,14 +949,7 @@ theorem mem_ite_none_right {x : α} {_ : Decidable p} {l : Option α} :
|
||||
|
||||
end ite
|
||||
|
||||
theorem isSome_filter {α : Type _} {x : Option α} {f : α → Bool} :
|
||||
(x.filter f).isSome = x.any f := by
|
||||
cases x
|
||||
· rfl
|
||||
· rw [Bool.eq_iff_iff]
|
||||
simp only [Option.any_some, Option.filter, Option.isSome_ite]
|
||||
|
||||
@[simp] theorem get_filter {α : Type _} {x : Option α} {f : α → Bool} (h : (x.filter f).isSome) :
|
||||
@[simp, grind] theorem get_filter {α : Type _} {x : Option α} {f : α → Bool} (h : (x.filter f).isSome) :
|
||||
(x.filter f).get h = x.get (isSome_of_isSome_filter f x h) := by
|
||||
cases x
|
||||
· contradiction
|
||||
@@ -821,16 +961,16 @@ theorem isSome_filter {α : Type _} {x : Option α} {f : α → Bool} :
|
||||
@[simp, grind] theorem pbind_none : pbind none f = none := rfl
|
||||
@[simp, grind] theorem pbind_some : pbind (some a) f = f a rfl := rfl
|
||||
|
||||
@[simp] theorem map_pbind {o : Option α} {f : (a : α) → o = some a → Option β}
|
||||
@[simp, grind] theorem map_pbind {o : Option α} {f : (a : α) → o = some a → Option β}
|
||||
{g : β → γ} : (o.pbind f).map g = o.pbind (fun a h => (f a h).map g) := by
|
||||
cases o <;> rfl
|
||||
|
||||
@[simp] theorem pbind_map {α β γ : Type _} (o : Option α)
|
||||
@[simp, grind] theorem pbind_map {α β γ : Type _} (o : Option α)
|
||||
(f : α → β) (g : (x : β) → o.map f = some x → Option γ) :
|
||||
(o.map f).pbind g = o.pbind (fun x h => g (f x) (h ▸ rfl)) := by
|
||||
cases o <;> rfl
|
||||
|
||||
@[simp] theorem pbind_eq_bind {α β : Type _} (o : Option α)
|
||||
@[simp, grind] theorem pbind_eq_bind {α β : Type _} (o : Option α)
|
||||
(f : α → Option β) : o.pbind (fun x _ => f x) = o.bind f := by
|
||||
cases o <;> rfl
|
||||
|
||||
@@ -890,16 +1030,16 @@ theorem pbind_eq_some_iff {o : Option α} {f : (a : α) → o = some a → Optio
|
||||
· 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
|
||||
|
||||
theorem map_pmap {p : α → Prop} (g : β → γ) (f : ∀ a, p a → β) (o H) :
|
||||
@[grind] theorem map_pmap {p : α → Prop} (g : β → γ) (f : ∀ a, p a → β) (o H) :
|
||||
Option.map g (pmap f o H) = pmap (fun a h => g (f a h)) o H := by
|
||||
cases o <;> simp
|
||||
|
||||
theorem pmap_map (o : Option α) (f : α → β) {p : β → Prop} (g : ∀ b, p b → γ) (H) :
|
||||
@[grind] theorem pmap_map (o : Option α) (f : α → β) {p : β → Prop} (g : ∀ b, p b → γ) (H) :
|
||||
pmap g (o.map f) H =
|
||||
pmap (fun a h => g (f a) h) o (fun a m => H (f a) (map_eq_some_iff.2 ⟨_, m, rfl⟩)) := by
|
||||
cases o <;> simp
|
||||
@@ -938,15 +1078,29 @@ theorem pmap_congr {α : Type u} {β : Type v}
|
||||
@[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] theorem elim_pmap {p : α → Prop} (f : (a : α) → p a → β) (o : Option α)
|
||||
@[simp, grind] theorem elim_pmap {p : α → Prop} (f : (a : α) → p a → β) (o : Option α)
|
||||
(H : ∀ (a : α), o = some a → p a) (g : γ) (g' : β → γ) :
|
||||
(o.pmap f H).elim g g' =
|
||||
o.pelim g (fun a h => g' (f a (H a h))) := by
|
||||
cases o <;> simp
|
||||
|
||||
theorem pelim_congr_left {o o' : Option α } {b : β} {f : (a : α) → (a ∈ o) → β} (h : o = o') :
|
||||
pelim o b f = pelim o' b (fun a ha => f a (h ▸ ha)) := by
|
||||
cases h; rfl
|
||||
|
||||
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
|
||||
| none => rfl
|
||||
| some a =>
|
||||
match h : p a with
|
||||
| false => by simp [pelim_congr_left (filter_some_neg h), h]
|
||||
| true => by simp [pelim_congr_left (filter_some_pos h), h]
|
||||
|
||||
/-! ### pfilter -/
|
||||
|
||||
@[congr]
|
||||
@@ -978,7 +1132,7 @@ theorem isSome_of_isSome_pfilter {α : Type _} {o : Option α} {p : (a : α) →
|
||||
(h : (o.pfilter p).isSome) : o.isSome :=
|
||||
(isSome_pfilter_iff_get.mp h).1
|
||||
|
||||
@[simp] theorem get_pfilter {α : Type _} {o : Option α} {p : (a : α) → o = some a → Bool}
|
||||
@[simp, grind] theorem get_pfilter {α : Type _} {o : Option α} {p : (a : α) → o = some a → Bool}
|
||||
(h : (o.pfilter p).isSome) :
|
||||
(o.pfilter p).get h = o.get (isSome_of_isSome_pfilter h) := by
|
||||
cases o <;> simp
|
||||
@@ -996,13 +1150,54 @@ theorem pfilter_eq_some_iff {α : Type _} {o : Option α} {p : (a : α) → o =
|
||||
· rintro ⟨⟨h, rfl⟩, h'⟩
|
||||
exact ⟨⟨o.get h, ⟨h, rfl⟩, h'⟩, rfl⟩
|
||||
|
||||
@[simp] theorem pfilter_eq_filter {α : Type _} {o : Option α} {p : α → Bool} :
|
||||
theorem eq_some_of_pfilter_eq_some {o : Option α} {p : (a : α) → o = some a → Bool}
|
||||
{a : α} (h : o.pfilter p = some a) : o = some a :=
|
||||
pfilter_eq_some_iff.1 h |>.1
|
||||
|
||||
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
|
||||
| none => simp
|
||||
| some a =>
|
||||
simp only [pbind_some, pfilter_some]
|
||||
obtain (h|⟨b, h⟩) := Option.eq_none_or_eq_some (f a rfl)
|
||||
· simp [h]
|
||||
· simp only [h, filter_some, any_some]
|
||||
split <;> simp [h]
|
||||
|
||||
@[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
|
||||
| some a =>
|
||||
simp only [pfilter, Option.filter, Bool.cond_eq_ite_iff]
|
||||
|
||||
@[simp] theorem pfilter_filter {o : Option α} {p : α → Bool} {q : (a : α) → o.filter p = some a → Bool} :
|
||||
(o.filter p).pfilter q = o.pfilter (fun a h => if h' : p a then q a (Option.filter_eq_some_iff.2 ⟨h, h'⟩) else false) := by
|
||||
cases o with
|
||||
| none => simp
|
||||
| some a =>
|
||||
simp only [filter_some, pfilter_some]
|
||||
split <;> simp
|
||||
|
||||
@[simp] theorem filter_pfilter {o : Option α} {p : (a : α) → o = some a → Bool} {q : α → Bool} :
|
||||
(o.pfilter p).filter q = o.pfilter (fun a h => p a h && q a) := by
|
||||
cases o with
|
||||
| none => simp
|
||||
| some a =>
|
||||
simp only [pfilter_some, Bool.and_eq_true]
|
||||
split <;> simp [filter_some, *]
|
||||
|
||||
@[simp] theorem pfilter_pfilter {o : Option α} {p : (a : α) → o = some a → Bool}
|
||||
{q : (a : α) → o.pfilter p = some a → Bool} :
|
||||
(o.pfilter p).pfilter q = o.pfilter (fun a h => if h' : p a h then q a (Option.pfilter_eq_some_iff.2 ⟨h, h'⟩) else false) := by
|
||||
cases o with
|
||||
| none => simp
|
||||
| some a =>
|
||||
simp only [pfilter_some]
|
||||
split <;> simp
|
||||
|
||||
theorem pfilter_eq_pbind_ite {α : Type _} {o : Option α}
|
||||
{p : (a : α) → o = some a → Bool} :
|
||||
o.pfilter p = o.pbind (fun a h => if p a h then some a else none) := by
|
||||
@@ -1012,13 +1207,23 @@ theorem pfilter_eq_pbind_ite {α : Type _} {o : Option α}
|
||||
|
||||
/-! ### LT and LE -/
|
||||
|
||||
@[simp] theorem not_lt_none [LT α] {a : Option α} : ¬ a < none := by cases a <;> simp [LT.lt, Option.lt]
|
||||
@[simp] theorem none_lt_some [LT α] {a : α} : none < some a := by simp [LT.lt, Option.lt]
|
||||
@[simp] theorem some_lt_some [LT α] {a b : α} : some a < some b ↔ a < b := by simp [LT.lt, Option.lt]
|
||||
@[simp, grind] theorem not_lt_none [LT α] {a : Option α} : ¬ a < none := by cases a <;> simp [LT.lt, Option.lt]
|
||||
@[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] theorem none_le [LE α] {a : Option α} : none ≤ a := by cases a <;> simp [LE.le, Option.le]
|
||||
@[simp] theorem not_some_le_none [LE α] {a : α} : ¬ some a ≤ none := by simp [LE.le, Option.le]
|
||||
@[simp] theorem some_le_some [LE α] {a b : α} : some a ≤ some b ↔ a ≤ b := by simp [LE.le, Option.le]
|
||||
@[simp, grind] theorem none_le [LE α] {a : Option α} : none ≤ a := by cases a <;> simp [LE.le, Option.le]
|
||||
@[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]
|
||||
|
||||
/-! ### Rel -/
|
||||
|
||||
@[simp] theorem rel_some_some {r : α → β → Prop} : Rel r (some a) (some b) ↔ r a b :=
|
||||
⟨fun | .some h => h, .some⟩
|
||||
@[simp] theorem not_rel_some_none {r : α → β → Prop} : ¬Rel r (some a) none := nofun
|
||||
@[simp] theorem not_rel_none_some {r : α → β → Prop} : ¬Rel r none (some a) := nofun
|
||||
@[simp] theorem rel_none_none {r : α → β → Prop} : Rel r none none := .none
|
||||
|
||||
/-! ### min and max -/
|
||||
|
||||
@@ -1086,4 +1291,11 @@ theorem max_le [LE α] [Max α] (max_le : ∀ x y z : α, max x y ≤ z ↔ x
|
||||
{a b c : Option α} : max a b ≤ c ↔ a ≤ c ∧ b ≤ c := by
|
||||
cases a <;> cases b <;> cases c <;> simp_all
|
||||
|
||||
@[simp]
|
||||
theorem merge_max [Max α] : merge (α := α) max = max := by
|
||||
funext a b; cases a <;> cases b <;> rfl
|
||||
|
||||
instance [Max α] : Std.LawfulIdentity (α := Option α) max none := by
|
||||
rw [← merge_max]; infer_instance
|
||||
|
||||
end Option
|
||||
|
||||
@@ -10,63 +10,54 @@ import Init.Data.List.Lemmas
|
||||
|
||||
namespace Option
|
||||
|
||||
@[simp] theorem mem_toList {a : α} {o : Option α} : a ∈ o.toList ↔ o = some a := by
|
||||
@[simp, grind] theorem mem_toList {a : α} {o : Option α} : a ∈ o.toList ↔ o = some a := by
|
||||
cases o <;> simp [eq_comm]
|
||||
|
||||
@[simp] theorem forIn'_none [Monad m] (b : β) (f : (a : α) → a ∈ none → β → m (ForInStep β)) :
|
||||
forIn' none b f = pure b := by
|
||||
rfl
|
||||
|
||||
@[simp] theorem forIn'_some [Monad m] [LawfulMonad m] (a : α) (b : β) (f : (a' : α) → a' ∈ some a → β → m (ForInStep β)) :
|
||||
forIn' (some a) b f = bind (f a rfl b) (fun r => pure (ForInStep.value r)) := by
|
||||
simp only [forIn', bind_pure_comp]
|
||||
rw [map_eq_pure_bind]
|
||||
congr
|
||||
funext x
|
||||
split <;> rfl
|
||||
|
||||
@[simp] theorem forIn_none [Monad m] (b : β) (f : α → β → m (ForInStep β)) :
|
||||
forIn none b f = pure b := by
|
||||
rfl
|
||||
|
||||
@[simp] theorem forIn_some [Monad m] [LawfulMonad m] (a : α) (b : β) (f : α → β → m (ForInStep β)) :
|
||||
forIn (some a) b f = bind (f a b) (fun r => pure (ForInStep.value r)) := by
|
||||
simp only [forIn, forIn', bind_pure_comp]
|
||||
rw [map_eq_pure_bind]
|
||||
congr
|
||||
funext x
|
||||
split <;> rfl
|
||||
|
||||
@[simp] theorem forIn'_toList [Monad m] (o : Option α) (b : β) (f : (a : α) → a ∈ o.toList → β → m (ForInStep β)) :
|
||||
@[simp, grind] theorem forIn'_toList [Monad m] (o : Option α) (b : β) (f : (a : α) → a ∈ o.toList → β → m (ForInStep β)) :
|
||||
forIn' o.toList b f = forIn' o b fun a m b => f a (by simpa using m) b := by
|
||||
cases o <;> rfl
|
||||
|
||||
@[simp] theorem forIn_toList [Monad m] (o : Option α) (b : β) (f : α → β → m (ForInStep β)) :
|
||||
@[simp, grind] theorem forIn_toList [Monad m] (o : Option α) (b : β) (f : α → β → m (ForInStep β)) :
|
||||
forIn o.toList b f = forIn o b f := by
|
||||
cases o <;> rfl
|
||||
|
||||
@[simp] theorem foldlM_toList [Monad m] [LawfulMonad m] (o : Option β) (a : α) (f : α → β → m α) :
|
||||
@[simp, grind] theorem foldlM_toList [Monad m] [LawfulMonad m] (o : Option β) (a : α) (f : α → β → m α) :
|
||||
o.toList.foldlM f a = o.elim (pure a) (fun b => f a b) := by
|
||||
cases o <;> simp
|
||||
|
||||
@[simp] theorem foldrM_toList [Monad m] [LawfulMonad m] (o : Option β) (a : α) (f : β → α → m α) :
|
||||
@[simp, grind] theorem foldrM_toList [Monad m] [LawfulMonad m] (o : Option β) (a : α) (f : β → α → m α) :
|
||||
o.toList.foldrM f a = o.elim (pure a) (fun b => f b a) := by
|
||||
cases o <;> simp
|
||||
|
||||
@[simp] theorem foldl_toList (o : Option β) (a : α) (f : α → β → α) :
|
||||
@[simp, grind] theorem foldl_toList (o : Option β) (a : α) (f : α → β → α) :
|
||||
o.toList.foldl f a = o.elim a (fun b => f a b) := by
|
||||
cases o <;> simp
|
||||
|
||||
@[simp] theorem foldr_toList (o : Option β) (a : α) (f : β → α → α) :
|
||||
@[simp, grind] theorem foldr_toList (o : Option β) (a : α) (f : β → α → α) :
|
||||
o.toList.foldr f a = o.elim a (fun b => f b a) := by
|
||||
cases o <;> simp
|
||||
|
||||
@[simp]
|
||||
@[simp, grind]
|
||||
theorem pairwise_toList {P : α → α → Prop} {o : Option α} : o.toList.Pairwise P := by
|
||||
cases o <;> simp
|
||||
|
||||
@[simp]
|
||||
@[simp, grind]
|
||||
theorem head?_toList {o : Option α} : o.toList.head? = o := by
|
||||
cases o <;> simp
|
||||
|
||||
theorem toList_filter {o : Option α} {p : α → Bool} : (o.filter p).toList = o.toList.filter p :=
|
||||
match o with
|
||||
| none => rfl
|
||||
| some a =>
|
||||
match h : p a with
|
||||
| false => by simp [filter_some_neg h, h]
|
||||
| true => by simp [filter_some_pos h, h]
|
||||
|
||||
theorem toList_bind {o : Option α} {f : α → Option β} :
|
||||
(o.bind f).toList = o.toList.flatMap (Option.toList ∘ f) := by
|
||||
cases o <;> simp
|
||||
|
||||
theorem toList_join {o : Option (Option α)} : o.join.toList = o.toList.flatMap Option.toList := by
|
||||
simp [toList_bind, join_eq_bind_id]
|
||||
|
||||
end Option
|
||||
|
||||
@@ -12,16 +12,47 @@ import Init.Control.Lawful.Basic
|
||||
|
||||
namespace Option
|
||||
|
||||
@[simp] theorem forM_none [Monad m] (f : α → m PUnit) :
|
||||
none.forM f = pure .unit := rfl
|
||||
@[simp, grind] theorem bindM_none [Monad m] (f : α → m (Option β)) : none.bindM f = pure none := rfl
|
||||
@[simp, grind] theorem bindM_some [Monad m] [LawfulMonad m] (a) (f : α → m (Option β)) : (some a).bindM f = f a := by
|
||||
simp [Option.bindM]
|
||||
|
||||
@[simp] theorem forM_some [Monad m] (f : α → m PUnit) (a : α) :
|
||||
(some a).forM f = f a := rfl
|
||||
-- We simplify `Option.forM` to `forM`.
|
||||
@[simp] theorem forM_eq_forM [Monad m] : @Option.forM m α _ = forM := rfl
|
||||
|
||||
@[simp] theorem forM_map [Monad m] [LawfulMonad m] (o : Option α) (g : α → β) (f : β → m PUnit) :
|
||||
(o.map g).forM f = o.forM (fun a => f (g a)) := by
|
||||
@[simp, grind] theorem forM_none [Monad m] (f : α → m PUnit) :
|
||||
forM none f = pure .unit := rfl
|
||||
|
||||
@[simp, grind] theorem forM_some [Monad m] (f : α → m PUnit) (a : α) :
|
||||
forM (some a) f = f a := rfl
|
||||
|
||||
@[simp, grind] theorem forM_map [Monad m] [LawfulMonad m] (o : Option α) (g : α → β) (f : β → m PUnit) :
|
||||
forM (o.map g) f = forM o (fun a => f (g a)) := by
|
||||
cases o <;> simp
|
||||
|
||||
@[simp, grind] theorem forIn'_none [Monad m] (b : β) (f : (a : α) → a ∈ none → β → m (ForInStep β)) :
|
||||
forIn' none b f = pure b := by
|
||||
rfl
|
||||
|
||||
@[simp, grind] theorem forIn'_some [Monad m] [LawfulMonad m] (a : α) (b : β) (f : (a' : α) → a' ∈ some a → β → m (ForInStep β)) :
|
||||
forIn' (some a) b f = bind (f a rfl b) (fun r => pure (ForInStep.value r)) := by
|
||||
simp only [forIn', bind_pure_comp]
|
||||
rw [map_eq_pure_bind]
|
||||
congr
|
||||
funext x
|
||||
split <;> rfl
|
||||
|
||||
@[simp, grind] theorem forIn_none [Monad m] (b : β) (f : α → β → m (ForInStep β)) :
|
||||
forIn none b f = pure b := by
|
||||
rfl
|
||||
|
||||
@[simp, grind] theorem forIn_some [Monad m] [LawfulMonad m] (a : α) (b : β) (f : α → β → m (ForInStep β)) :
|
||||
forIn (some a) b f = bind (f a b) (fun r => pure (ForInStep.value r)) := by
|
||||
simp only [forIn, forIn', bind_pure_comp]
|
||||
rw [map_eq_pure_bind]
|
||||
congr
|
||||
funext x
|
||||
split <;> rfl
|
||||
|
||||
@[congr] theorem forIn'_congr [Monad m] [LawfulMonad m] {as bs : Option α} (w : as = bs)
|
||||
{b b' : β} (hb : b = b')
|
||||
{f : (a' : α) → a' ∈ as → β → m (ForInStep β)}
|
||||
@@ -60,7 +91,7 @@ theorem forIn'_eq_pelim [Monad m] [LawfulMonad m]
|
||||
o.pelim b (fun a h => f a h b) := by
|
||||
cases o <;> simp
|
||||
|
||||
@[simp] theorem forIn'_map [Monad m] [LawfulMonad m]
|
||||
@[simp, grind] theorem forIn'_map [Monad m] [LawfulMonad m]
|
||||
(o : Option α) (g : α → β) (f : (b : β) → b ∈ o.map g → γ → m (ForInStep γ)) :
|
||||
forIn' (o.map g) init f = forIn' o init fun a h y => f (g a) (mem_map_of_mem g h) y := by
|
||||
cases o <;> simp
|
||||
@@ -89,11 +120,34 @@ theorem forIn_eq_elim [Monad m] [LawfulMonad m]
|
||||
o.elim b (fun a => f a b) := by
|
||||
cases o <;> simp
|
||||
|
||||
@[simp] theorem forIn_map [Monad m] [LawfulMonad m]
|
||||
@[simp, grind] theorem forIn_map [Monad m] [LawfulMonad m]
|
||||
(o : Option α) (g : α → β) (f : β → γ → m (ForInStep γ)) :
|
||||
forIn (o.map g) init f = forIn o init fun a y => f (g a) y := by
|
||||
cases o <;> simp
|
||||
|
||||
@[simp] theorem mapA_eq_mapM : @Option.mapA = @Option.mapM := rfl
|
||||
@[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] 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] 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] theorem tryCatch_none (alternative : Unit → Option α) :
|
||||
(tryCatch none alternative) = alternative () := rfl
|
||||
|
||||
@[simp] theorem tryCatch_some (a : α) (alternative : Unit → Option α) :
|
||||
(tryCatch (some a) alternative) = some a := rfl
|
||||
|
||||
@[simp] theorem throw_eq_none : throw () = (none : Option α) := rfl
|
||||
|
||||
@[simp, grind] theorem filterM_none [Applicative m] (p : α → m Bool) :
|
||||
none.filterM p = pure none := rfl
|
||||
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
|
||||
|
||||
end Option
|
||||
|
||||
@@ -7,7 +7,7 @@ Authors: Dany Fabian, Sebastian Ullrich
|
||||
module
|
||||
|
||||
prelude
|
||||
import Init.Data.String
|
||||
import Init.Data.String.Basic
|
||||
import Init.Data.Array.Basic
|
||||
import Init.Data.SInt.Basic
|
||||
import Init.Data.Vector.Basic
|
||||
|
||||
@@ -55,10 +55,12 @@ This instance allows us to use `Empty` as a type parameter without causing insta
|
||||
instance : Repr Empty where
|
||||
reprPrec := nofun
|
||||
|
||||
protected def Bool.repr : Bool → Nat → Format
|
||||
| true, _ => "true"
|
||||
| false, _ => "false"
|
||||
|
||||
instance : Repr Bool where
|
||||
reprPrec
|
||||
| true, _ => "true"
|
||||
| false, _ => "false"
|
||||
reprPrec := Bool.repr
|
||||
|
||||
def Repr.addAppParen (f : Format) (prec : Nat) : Format :=
|
||||
if prec >= max_prec then
|
||||
@@ -66,10 +68,12 @@ def Repr.addAppParen (f : Format) (prec : Nat) : Format :=
|
||||
else
|
||||
f
|
||||
|
||||
protected def Decidable.repr : Decidable p → Nat → Format
|
||||
| .isTrue _, prec => Repr.addAppParen "isTrue _" prec
|
||||
| .isFalse _, prec => Repr.addAppParen "isFalse _" prec
|
||||
|
||||
instance : Repr (Decidable p) where
|
||||
reprPrec
|
||||
| Decidable.isTrue _, prec => Repr.addAppParen "isTrue _" prec
|
||||
| Decidable.isFalse _, prec => Repr.addAppParen "isFalse _" prec
|
||||
reprPrec := Decidable.repr
|
||||
|
||||
instance : Repr PUnit.{u+1} where
|
||||
reprPrec _ _ := "PUnit.unit"
|
||||
@@ -109,8 +113,11 @@ export ReprTuple (reprTuple)
|
||||
instance [Repr α] : ReprTuple α where
|
||||
reprTuple a xs := repr a :: xs
|
||||
|
||||
protected def Prod.reprTuple [Repr α] [ReprTuple β] : α × β → List Format → List Format
|
||||
| (a, b), xs => reprTuple b (repr a :: xs)
|
||||
|
||||
instance [Repr α] [ReprTuple β] : ReprTuple (α × β) where
|
||||
reprTuple | (a, b), xs => reprTuple b (repr a :: xs)
|
||||
reprTuple := Prod.reprTuple
|
||||
|
||||
protected def Prod.repr [Repr α] [ReprTuple β] : α × β → Nat → Format
|
||||
| (a, b), _ => Format.bracket "(" (Format.joinSep (reprTuple b [repr a]).reverse ("," ++ Format.line)) ")"
|
||||
@@ -118,8 +125,11 @@ protected def Prod.repr [Repr α] [ReprTuple β] : α × β → Nat → Format
|
||||
instance [Repr α] [ReprTuple β] : Repr (α × β) where
|
||||
reprPrec := Prod.repr
|
||||
|
||||
protected def Sigma.repr {β : α → Type v} [Repr α] [(x : α) → Repr (β x)] : Sigma β → Nat → Format
|
||||
| ⟨a, b⟩, _ => Format.bracket "⟨" (repr a ++ ", " ++ repr b) "⟩"
|
||||
|
||||
instance {β : α → Type v} [Repr α] [(x : α) → Repr (β x)] : Repr (Sigma β) where
|
||||
reprPrec | ⟨a, b⟩, _ => Format.bracket "⟨" (repr a ++ ", " ++ repr b) "⟩"
|
||||
reprPrec := Sigma.repr
|
||||
|
||||
instance {p : α → Prop} [Repr α] : Repr (Subtype p) where
|
||||
reprPrec s prec := reprPrec s.val prec
|
||||
|
||||
@@ -85,6 +85,8 @@ Examples:
|
||||
-/
|
||||
@[extern "lean_uint8_mod"]
|
||||
protected def UInt8.mod (a b : UInt8) : UInt8 := ⟨BitVec.umod a.toBitVec b.toBitVec⟩
|
||||
|
||||
-- Note: This is deprecated, but still used in the `HMod` instance below.
|
||||
set_option linter.missingDocs false in
|
||||
@[deprecated UInt8.mod (since := "2024-09-23")]
|
||||
protected def UInt8.modn (a : UInt8) (n : Nat) : UInt8 := ⟨Fin.modn a.toFin n⟩
|
||||
@@ -297,6 +299,8 @@ Examples:
|
||||
-/
|
||||
@[extern "lean_uint16_mod"]
|
||||
protected def UInt16.mod (a b : UInt16) : UInt16 := ⟨BitVec.umod a.toBitVec b.toBitVec⟩
|
||||
|
||||
-- Note: This is deprecated, but still used in the `HMod` instance below.
|
||||
set_option linter.missingDocs false in
|
||||
@[deprecated UInt16.mod (since := "2024-09-23")]
|
||||
protected def UInt16.modn (a : UInt16) (n : Nat) : UInt16 := ⟨Fin.modn a.toFin n⟩
|
||||
@@ -511,6 +515,8 @@ Examples:
|
||||
-/
|
||||
@[extern "lean_uint32_mod"]
|
||||
protected def UInt32.mod (a b : UInt32) : UInt32 := ⟨BitVec.umod a.toBitVec b.toBitVec⟩
|
||||
|
||||
-- Note: This is deprecated, but still used in the `HMod` instance below.
|
||||
set_option linter.missingDocs false in
|
||||
@[deprecated UInt32.mod (since := "2024-09-23")]
|
||||
protected def UInt32.modn (a : UInt32) (n : Nat) : UInt32 := ⟨Fin.modn a.toFin n⟩
|
||||
@@ -687,6 +693,8 @@ Examples:
|
||||
-/
|
||||
@[extern "lean_uint64_mod"]
|
||||
protected def UInt64.mod (a b : UInt64) : UInt64 := ⟨BitVec.umod a.toBitVec b.toBitVec⟩
|
||||
|
||||
-- Note: This is deprecated, but still used in the `HMod` instance below.
|
||||
set_option linter.missingDocs false in
|
||||
@[deprecated UInt64.mod (since := "2024-09-23")]
|
||||
protected def UInt64.modn (a : UInt64) (n : Nat) : UInt64 := ⟨Fin.modn a.toFin n⟩
|
||||
@@ -894,6 +902,8 @@ Examples:
|
||||
-/
|
||||
@[extern "lean_usize_mod"]
|
||||
protected def USize.mod (a b : USize) : USize := ⟨a.toBitVec % b.toBitVec⟩
|
||||
|
||||
-- Note: This is deprecated, but still used in the `HMod` instance below.
|
||||
set_option linter.missingDocs false in
|
||||
@[deprecated USize.mod (since := "2024-09-23")]
|
||||
protected def USize.modn (a : USize) (n : Nat) : USize := ⟨Fin.modn a.toFin n⟩
|
||||
|
||||
@@ -575,15 +575,15 @@ expression `(a >>> b).toUInt8` is not a function of `a.toUInt8` and `b.toUInt8`.
|
||||
BitVec.toNat_umod, toNat_toBitVec, toNat_ofNat', BitVec.toNat_ofNat, Nat.mod_two_pow_self]
|
||||
rw [Nat.mod_mod_of_dvd _ (by cases System.Platform.numBits_eq <;> simp_all)]
|
||||
|
||||
@[simp] theorem UInt8.ofFin_shiftLeft (a b : Fin UInt8.size) (hb : b < 8) : UInt8.ofFin (a <<< b) = UInt8.ofFin a <<< UInt8.ofFin b :=
|
||||
@[simp] theorem UInt8.ofFin_shiftLeft (a b : Fin UInt8.size) (hb : b.val < 8) : UInt8.ofFin (a <<< b) = UInt8.ofFin a <<< UInt8.ofFin b :=
|
||||
UInt8.toFin_inj.1 (by simp [UInt8.toFin_shiftLeft (ofFin a) (ofFin b) hb])
|
||||
@[simp] theorem UInt16.ofFin_shiftLeft (a b : Fin UInt16.size) (hb : b < 16) : UInt16.ofFin (a <<< b) = UInt16.ofFin a <<< UInt16.ofFin b :=
|
||||
@[simp] theorem UInt16.ofFin_shiftLeft (a b : Fin UInt16.size) (hb : b.val < 16) : UInt16.ofFin (a <<< b) = UInt16.ofFin a <<< UInt16.ofFin b :=
|
||||
UInt16.toFin_inj.1 (by simp [UInt16.toFin_shiftLeft (ofFin a) (ofFin b) hb])
|
||||
@[simp] theorem UInt32.ofFin_shiftLeft (a b : Fin UInt32.size) (hb : b < 32) : UInt32.ofFin (a <<< b) = UInt32.ofFin a <<< UInt32.ofFin b :=
|
||||
@[simp] theorem UInt32.ofFin_shiftLeft (a b : Fin UInt32.size) (hb : b.val < 32) : UInt32.ofFin (a <<< b) = UInt32.ofFin a <<< UInt32.ofFin b :=
|
||||
UInt32.toFin_inj.1 (by simp [UInt32.toFin_shiftLeft (ofFin a) (ofFin b) hb])
|
||||
@[simp] theorem UInt64.ofFin_shiftLeft (a b : Fin UInt64.size) (hb : b < 64) : UInt64.ofFin (a <<< b) = UInt64.ofFin a <<< UInt64.ofFin b :=
|
||||
@[simp] theorem UInt64.ofFin_shiftLeft (a b : Fin UInt64.size) (hb : b.val < 64) : UInt64.ofFin (a <<< b) = UInt64.ofFin a <<< UInt64.ofFin b :=
|
||||
UInt64.toFin_inj.1 (by simp [UInt64.toFin_shiftLeft (ofFin a) (ofFin b) hb])
|
||||
@[simp] theorem USize.ofFin_shiftLeft (a b : Fin USize.size) (hb : b < System.Platform.numBits) : USize.ofFin (a <<< b) = USize.ofFin a <<< USize.ofFin b :=
|
||||
@[simp] theorem USize.ofFin_shiftLeft (a b : Fin USize.size) (hb : b.val < System.Platform.numBits) : USize.ofFin (a <<< b) = USize.ofFin a <<< USize.ofFin b :=
|
||||
USize.toFin_inj.1 (by simp [USize.toFin_shiftLeft (ofFin a) (ofFin b) hb])
|
||||
|
||||
@[simp] theorem UInt8.ofFin_shiftLeft_mod (a b : Fin UInt8.size) : UInt8.ofFin (a <<< (b % 8)) = UInt8.ofFin a <<< UInt8.ofFin b :=
|
||||
@@ -670,15 +670,15 @@ expression `(a >>> b).toUInt8` is not a function of `a.toUInt8` and `b.toUInt8`.
|
||||
BitVec.toNat_umod, toNat_toBitVec, toNat_ofNat', BitVec.toNat_ofNat, Nat.mod_two_pow_self]
|
||||
rw [Nat.mod_mod_of_dvd _ (by cases System.Platform.numBits_eq <;> simp_all)]
|
||||
|
||||
@[simp] theorem UInt8.ofFin_shiftRight (a b : Fin UInt8.size) (hb : b < 8) : UInt8.ofFin (a >>> b) = UInt8.ofFin a >>> UInt8.ofFin b :=
|
||||
@[simp] theorem UInt8.ofFin_shiftRight (a b : Fin UInt8.size) (hb : b.val < 8) : UInt8.ofFin (a >>> b) = UInt8.ofFin a >>> UInt8.ofFin b :=
|
||||
UInt8.toFin_inj.1 (by simp [UInt8.toFin_shiftRight (ofFin a) (ofFin b) hb])
|
||||
@[simp] theorem UInt16.ofFin_shiftRight (a b : Fin UInt16.size) (hb : b < 16) : UInt16.ofFin (a >>> b) = UInt16.ofFin a >>> UInt16.ofFin b :=
|
||||
@[simp] theorem UInt16.ofFin_shiftRight (a b : Fin UInt16.size) (hb : b.val < 16) : UInt16.ofFin (a >>> b) = UInt16.ofFin a >>> UInt16.ofFin b :=
|
||||
UInt16.toFin_inj.1 (by simp [UInt16.toFin_shiftRight (ofFin a) (ofFin b) hb])
|
||||
@[simp] theorem UInt32.ofFin_shiftRight (a b : Fin UInt32.size) (hb : b < 32) : UInt32.ofFin (a >>> b) = UInt32.ofFin a >>> UInt32.ofFin b :=
|
||||
@[simp] theorem UInt32.ofFin_shiftRight (a b : Fin UInt32.size) (hb : b.val < 32) : UInt32.ofFin (a >>> b) = UInt32.ofFin a >>> UInt32.ofFin b :=
|
||||
UInt32.toFin_inj.1 (by simp [UInt32.toFin_shiftRight (ofFin a) (ofFin b) hb])
|
||||
@[simp] theorem UInt64.ofFin_shiftRight (a b : Fin UInt64.size) (hb : b < 64) : UInt64.ofFin (a >>> b) = UInt64.ofFin a >>> UInt64.ofFin b :=
|
||||
@[simp] theorem UInt64.ofFin_shiftRight (a b : Fin UInt64.size) (hb : b.val < 64) : UInt64.ofFin (a >>> b) = UInt64.ofFin a >>> UInt64.ofFin b :=
|
||||
UInt64.toFin_inj.1 (by simp [UInt64.toFin_shiftRight (ofFin a) (ofFin b) hb])
|
||||
@[simp] theorem USize.ofFin_shiftRight (a b : Fin USize.size) (hb : b < System.Platform.numBits) : USize.ofFin (a >>> b) = USize.ofFin a >>> USize.ofFin b :=
|
||||
@[simp] theorem USize.ofFin_shiftRight (a b : Fin USize.size) (hb : b.val < System.Platform.numBits) : USize.ofFin (a >>> b) = USize.ofFin a >>> USize.ofFin b :=
|
||||
USize.toFin_inj.1 (by simp [USize.toFin_shiftRight (ofFin a) (ofFin b) hb])
|
||||
|
||||
@[simp] theorem UInt8.ofFin_shiftRight_mod (a b : Fin UInt8.size) : UInt8.ofFin (a >>> (b % 8)) = UInt8.ofFin a >>> UInt8.ofFin b :=
|
||||
|
||||
@@ -184,20 +184,6 @@ macro "declare_uint_theorems" typeName:ident bits:term:arg : command => do
|
||||
· apply toNat_lt_size
|
||||
· simpa using h2
|
||||
|
||||
open $typeName (toNat_mod_lt modn) in
|
||||
set_option linter.deprecated false in
|
||||
@[deprecated toNat_mod_lt (since := "2024-09-24")]
|
||||
protected theorem modn_lt {m : Nat} : ∀ (u : $typeName), m > 0 → toNat (u % m) < m := by
|
||||
intro u
|
||||
simp only [(· % ·)]
|
||||
simp only [gt_iff_lt, toNat, modn, Fin.modn_val, BitVec.natCast_eq_ofNat, BitVec.toNat_ofNat,
|
||||
Nat.reducePow]
|
||||
rw [Nat.mod_eq_of_lt]
|
||||
· apply Nat.mod_lt
|
||||
· apply Nat.lt_of_le_of_lt
|
||||
· apply Nat.mod_le
|
||||
· apply Fin.is_lt
|
||||
|
||||
protected theorem mod_lt (a : $typeName) {b : $typeName} : 0 < b → a % b < b := by
|
||||
simp only [lt_iff_toBitVec_lt, mod_def]
|
||||
apply BitVec.umod_lt
|
||||
|
||||
@@ -69,7 +69,8 @@ Unsafe implementation of `attachWith`, taking advantage of the fact that the rep
|
||||
|
||||
@[simp] theorem toList_attachWith {xs : Vector α n} {P : α → Prop} {H : ∀ x ∈ xs, P x} :
|
||||
(xs.attachWith P H).toList = xs.toList.attachWith P (by simpa using H) := by
|
||||
simp [attachWith]
|
||||
rcases xs with ⟨xs, rfl⟩
|
||||
simp
|
||||
|
||||
@[simp] theorem toList_attach {xs : Vector α n} :
|
||||
xs.attach.toList = xs.toList.attachWith (· ∈ xs) (by simp) := by
|
||||
@@ -77,7 +78,8 @@ Unsafe implementation of `attachWith`, taking advantage of the fact that the rep
|
||||
|
||||
@[simp] theorem toList_pmap {xs : Vector α n} {P : α → Prop} {f : ∀ a, P a → β} {H : ∀ a ∈ xs, P a} :
|
||||
(xs.pmap f H).toList = xs.toList.pmap f (fun a m => H a (by simpa using m)) := by
|
||||
simp [pmap]
|
||||
rcases xs with ⟨xs, rfl⟩
|
||||
simp
|
||||
|
||||
/-- Implementation of `pmap` using the zero-copy version of `attach`. -/
|
||||
@[inline] private def pmapImpl {P : α → Prop} (f : ∀ a, P a → β) (xs : Vector α n) (H : ∀ a ∈ xs, P a) :
|
||||
@@ -492,7 +494,8 @@ def unattach {α : Type _} {p : α → Prop} (xs : Vector { x // p x } n) : Vect
|
||||
|
||||
@[simp] theorem toList_unattach {p : α → Prop} {xs : Vector { x // p x } n} :
|
||||
xs.unattach.toList = xs.toList.unattach := by
|
||||
simp [unattach]
|
||||
rcases xs with ⟨xs, rfl⟩
|
||||
simp
|
||||
|
||||
@[simp] theorem unattach_attach {xs : Vector α n} : xs.attach.unattach = xs := by
|
||||
rcases xs with ⟨xs, rfl⟩
|
||||
|
||||
@@ -24,12 +24,14 @@ set_option linter.listVariables true -- Enforce naming conventions for `List`/`A
|
||||
set_option linter.indexVariables true -- Enforce naming conventions for index variables.
|
||||
|
||||
/-- `Vector α n` is an `Array α` with size `n`. -/
|
||||
structure Vector (α : Type u) (n : Nat) extends Array α where
|
||||
structure Vector (α : Type u) (n : Nat) where
|
||||
/-- The underlying array. -/
|
||||
toArray : Array α
|
||||
/-- Array size. -/
|
||||
size_toArray : toArray.size = n
|
||||
deriving Repr, DecidableEq
|
||||
|
||||
attribute [simp] Vector.size_toArray
|
||||
attribute [simp, grind] Vector.size_toArray
|
||||
|
||||
/--
|
||||
Converts an array to a vector. The resulting vector's size is the array's size.
|
||||
@@ -38,6 +40,9 @@ abbrev Array.toVector (xs : Array α) : Vector α xs.size := .mk xs rfl
|
||||
|
||||
namespace Vector
|
||||
|
||||
/-- The size of a vector. -/
|
||||
abbrev size {α n} (_ : Vector α n) : Nat := n
|
||||
|
||||
/-- Syntax for `Vector α n` -/
|
||||
syntax (name := «term#v[_,]») "#v[" withoutPosition(term,*,?) "]" : term
|
||||
|
||||
@@ -48,6 +53,9 @@ macro_rules
|
||||
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. -/
|
||||
def toList (xs : Vector α n) : List α := xs.toArray.toList
|
||||
|
||||
/-- Custom eliminator for `Vector α n` through `Array α` -/
|
||||
@[elab_as_elim]
|
||||
def elimAsArray {motive : Vector α n → Sort u}
|
||||
@@ -469,6 +477,16 @@ to avoid having to have the predicate live in `p : α → m (ULift Bool)`.
|
||||
@[inline] def replace [BEq α] (xs : Vector α n) (a b : α) : Vector α n :=
|
||||
⟨xs.toArray.replace a b, by simp⟩
|
||||
|
||||
/--
|
||||
Computes the sum of the elements of a vector.
|
||||
|
||||
Examples:
|
||||
* `#v[a, b, c].sum = a + (b + (c + 0))`
|
||||
* `#v[1, 2, 5].sum = 8`
|
||||
-/
|
||||
@[inline] def sum [Add α] [Zero α] (xs : Vector α n) : α :=
|
||||
xs.toArray.sum
|
||||
|
||||
/--
|
||||
Pad a vector on the left with a given element.
|
||||
|
||||
|
||||
@@ -66,8 +66,8 @@ theorem countP_le_size {xs : Vector α n} : countP p xs ≤ n := by
|
||||
cases xs
|
||||
simp
|
||||
|
||||
@[simp] theorem countP_eq_size {p} : countP p xs = xs.size ↔ ∀ a ∈ xs, p a := by
|
||||
cases xs
|
||||
@[simp] theorem countP_eq_size {p} {xs : Vector α n} : countP p xs = n ↔ ∀ a ∈ xs, p a := by
|
||||
rcases xs with ⟨xs, rfl⟩
|
||||
simp
|
||||
|
||||
@[simp] theorem countP_cast (p : α → Bool) (xs : Vector α n) : countP p (xs.cast h) = countP p xs := by
|
||||
@@ -213,7 +213,7 @@ theorem not_mem_of_count_eq_zero {a : α} {xs : Vector α n} (h : count a xs = 0
|
||||
theorem count_eq_zero {xs : Vector α n} : count a xs = 0 ↔ a ∉ xs :=
|
||||
⟨not_mem_of_count_eq_zero, count_eq_zero_of_not_mem⟩
|
||||
|
||||
theorem count_eq_size {xs : Vector α n} : count a xs = xs.size ↔ ∀ b ∈ xs, a = b := by
|
||||
theorem count_eq_size {xs : Vector α n} : count a xs = n ↔ ∀ b ∈ xs, a = b := by
|
||||
rcases xs with ⟨xs, rfl⟩
|
||||
simp [Array.count_eq_size]
|
||||
|
||||
|
||||
@@ -58,7 +58,7 @@ theorem beq_eq_decide [BEq α] (xs ys : Vector α n) :
|
||||
(mk xs ha == mk ys hb) = (xs == ys) := by
|
||||
simp [BEq.beq]
|
||||
|
||||
@[simp] theorem beq_toArray [BEq α] (xs ys : Vector α n) : (xs.toArray == ys.toArray) = (xs == ys) := by
|
||||
@[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]
|
||||
|
||||
@[simp] theorem beq_toList [BEq α] (xs ys : Vector α n) : (xs.toList == ys.toList) = (xs == ys) := by
|
||||
|
||||
@@ -88,7 +88,7 @@ theorem extract_set {xs : Vector α n} {i j k : Nat} (h : k < n) {a : α} :
|
||||
(xs.set k a).extract i j =
|
||||
if _ : k < i then
|
||||
xs.extract i j
|
||||
else if _ : k < min j xs.size then
|
||||
else if _ : k < min j n then
|
||||
(xs.extract i j).set (k - i) a (by omega)
|
||||
else xs.extract i j := by
|
||||
rcases xs with ⟨xs, rfl⟩
|
||||
|
||||
@@ -196,20 +196,6 @@ theorem get_find?_mem {xs : Vector α n} (h) : (xs.find? p).get h ∈ xs := by
|
||||
cases xs
|
||||
simp [Array.get_find?_mem]
|
||||
|
||||
@[simp] theorem find?_filter {xs : Vector α n} (p q : α → Bool) :
|
||||
(xs.filter p).find? q = xs.find? (fun a => p a ∧ q a) := by
|
||||
cases xs; simp
|
||||
|
||||
@[simp] theorem getElem?_zero_filter {p : α → Bool} {xs : Vector α n} :
|
||||
(xs.filter p)[0]? = xs.find? p := by
|
||||
cases xs; simp [← List.head?_eq_getElem?]
|
||||
|
||||
@[simp] theorem getElem_zero_filter {p : α → Bool} {xs : Vector α n} (h) :
|
||||
(xs.filter p)[0] =
|
||||
(xs.find? p).get (by cases xs; simpa [← Array.countP_eq_size_filter] using h) := by
|
||||
cases xs
|
||||
simp [List.getElem_zero_eq_head]
|
||||
|
||||
@[simp] theorem find?_map {f : β → α} {xs : Vector β n} :
|
||||
find? p (xs.map f) = (xs.find? (p ∘ f)).map f := by
|
||||
cases xs; simp
|
||||
@@ -323,7 +309,7 @@ theorem findFinIdx?_push {xs : Vector α n} {a : α} {p : α → Bool} :
|
||||
theorem findFinIdx?_append {xs : Vector α n₁} {ys : Vector α n₂} {p : α → Bool} :
|
||||
(xs ++ ys).findFinIdx? p =
|
||||
((xs.findFinIdx? p).map (Fin.castLE (by simp))).or
|
||||
((ys.findFinIdx? p).map (Fin.natAdd xs.size) |>.map (Fin.cast (by simp))) := by
|
||||
((ys.findFinIdx? p).map (Fin.natAdd n₁)) := by
|
||||
rcases xs with ⟨xs, rfl⟩
|
||||
rcases ys with ⟨ys, rfl⟩
|
||||
simp [Array.findFinIdx?_append, Option.map_or, Function.comp_def]
|
||||
|
||||
@@ -104,7 +104,7 @@ theorem getElem?_insertIdx {xs : Vector α n} {x : α} {i k : Nat} (h : i ≤ n)
|
||||
xs[k]?
|
||||
else
|
||||
if k = i then
|
||||
if k ≤ xs.size then some x else none
|
||||
if k ≤ n then some x else none
|
||||
else
|
||||
xs[k-1]? := by
|
||||
rcases xs with ⟨xs, rfl⟩
|
||||
|
||||
@@ -63,9 +63,6 @@ theorem toArray_mk {xs : Array α} (h : xs.size = n) : (Vector.mk xs h).toArray
|
||||
(Vector.mk xs h == Vector.mk ys h') = (xs == ys) := by
|
||||
simp [instBEq, isEqv, Array.instBEq, Array.isEqv, h, h']
|
||||
|
||||
@[simp] theorem allDiff_mk [BEq α] {xs : Array α} (h : xs.size = n) :
|
||||
(Vector.mk xs h).allDiff = xs.allDiff := rfl
|
||||
|
||||
@[simp] theorem mk_append_mk {xs ys : Array α} (h : xs.size = n) (h' : ys.size = m) :
|
||||
Vector.mk xs h ++ Vector.mk ys h' = Vector.mk (xs ++ ys) (by simp [h, h']) := rfl
|
||||
|
||||
@@ -253,6 +250,9 @@ abbrev zipWithIndex_mk := @zipIdx_mk
|
||||
@[simp] theorem replace_mk [BEq α] {xs : Array α} (h : xs.size = n) {a b} :
|
||||
(Vector.mk xs h).replace a b = Vector.mk (xs.replace a b) (by simp [h]) := rfl
|
||||
|
||||
@[simp] theorem sum_mk [Add α] [Zero α] {xs : Array α} (h : xs.size = n) :
|
||||
(Vector.mk xs h).sum = xs.sum := rfl
|
||||
|
||||
@[simp] theorem eq_mk : xs = Vector.mk as h ↔ xs.toArray = as := by
|
||||
cases xs
|
||||
simp
|
||||
@@ -263,57 +263,59 @@ abbrev zipWithIndex_mk := @zipIdx_mk
|
||||
|
||||
/-! ### toArray lemmas -/
|
||||
|
||||
@[simp] theorem getElem_toArray {α n} {xs : Vector α n} {i : Nat} (h : i < xs.toArray.size) :
|
||||
@[simp, grind] theorem getElem_toArray {α n} {xs : Vector α n} {i : Nat} (h : i < xs.toArray.size) :
|
||||
xs.toArray[i] = xs[i]'(by simpa using h) := by
|
||||
cases xs
|
||||
simp
|
||||
|
||||
@[simp] theorem getElem?_toArray {α n} {xs : Vector α n} {i : Nat} :
|
||||
@[simp, grind] theorem getElem?_toArray {α n} {xs : Vector α n} {i : Nat} :
|
||||
xs.toArray[i]? = xs[i]? := by
|
||||
cases xs
|
||||
simp
|
||||
|
||||
@[simp] theorem toArray_append {xs : Vector α m} {ys : Vector α n} :
|
||||
@[simp, grind _=_] theorem toArray_append {xs : Vector α m} {ys : Vector α n} :
|
||||
(xs ++ ys).toArray = xs.toArray ++ ys.toArray := rfl
|
||||
|
||||
@[simp] theorem toArray_drop {xs : Vector α n} {i} :
|
||||
(xs.drop i).toArray = xs.toArray.extract i xs.size := rfl
|
||||
set_option linter.indexVariables false in
|
||||
@[simp, grind] theorem toArray_drop {xs : Vector α n} {i} :
|
||||
(xs.drop i).toArray = xs.toArray.extract i n := by
|
||||
simp [drop]
|
||||
|
||||
@[simp] theorem toArray_empty : (#v[] : Vector α 0).toArray = #[] := rfl
|
||||
@[simp, grind] theorem toArray_empty : (#v[] : Vector α 0).toArray = #[] := rfl
|
||||
|
||||
@[simp] theorem toArray_emptyWithCapacity {cap} :
|
||||
@[simp, grind] theorem toArray_emptyWithCapacity {cap} :
|
||||
(Vector.emptyWithCapacity (α := α) cap).toArray = Array.emptyWithCapacity cap := rfl
|
||||
|
||||
@[deprecated toArray_emptyWithCapacity (since := "2025-03-12")]
|
||||
abbrev toArray_mkEmpty := @toArray_emptyWithCapacity
|
||||
|
||||
@[simp] theorem toArray_eraseIdx {xs : Vector α n} {i} (h) :
|
||||
@[simp, grind] theorem toArray_eraseIdx {xs : Vector α n} {i} (h) :
|
||||
(xs.eraseIdx i h).toArray = xs.toArray.eraseIdx i (by simp [h]) := rfl
|
||||
|
||||
@[simp] theorem toArray_eraseIdx! {xs : Vector α n} {i} (hi : i < n) :
|
||||
@[simp, grind] theorem toArray_eraseIdx! {xs : Vector α n} {i} (hi : i < n) :
|
||||
(xs.eraseIdx! i).toArray = xs.toArray.eraseIdx! i := by
|
||||
cases xs; simp_all [Array.eraseIdx!]
|
||||
|
||||
@[simp] theorem toArray_insertIdx {xs : Vector α n} {i x} (h) :
|
||||
@[simp, grind] theorem toArray_insertIdx {xs : Vector α n} {i x} (h) :
|
||||
(xs.insertIdx i x h).toArray = xs.toArray.insertIdx i x (by simp [h]) := rfl
|
||||
|
||||
@[simp] theorem toArray_insertIdx! {xs : Vector α n} {i x} (hi : i ≤ n) :
|
||||
@[simp, grind] theorem toArray_insertIdx! {xs : Vector α n} {i x} (hi : i ≤ n) :
|
||||
(xs.insertIdx! i x).toArray = xs.toArray.insertIdx! i x := by
|
||||
cases xs; simp_all [Array.insertIdx!]
|
||||
|
||||
@[simp] theorem toArray_cast {xs : Vector α n} (h : n = m) :
|
||||
@[simp, grind] theorem toArray_cast {xs : Vector α n} (h : n = m) :
|
||||
(xs.cast h).toArray = xs.toArray := rfl
|
||||
|
||||
@[simp] theorem toArray_extract {xs : Vector α n} {start stop} :
|
||||
@[simp, grind] theorem toArray_extract {xs : Vector α n} {start stop} :
|
||||
(xs.extract start stop).toArray = xs.toArray.extract start stop := rfl
|
||||
|
||||
@[simp] theorem toArray_map {f : α → β} {xs : Vector α n} :
|
||||
@[simp, grind] theorem toArray_map {f : α → β} {xs : Vector α n} :
|
||||
(xs.map f).toArray = xs.toArray.map f := rfl
|
||||
|
||||
@[simp] theorem toArray_mapIdx {f : Nat → α → β} {xs : Vector α n} :
|
||||
@[simp, grind] theorem toArray_mapIdx {f : Nat → α → β} {xs : Vector α n} :
|
||||
(xs.mapIdx f).toArray = xs.toArray.mapIdx f := rfl
|
||||
|
||||
@[simp] theorem toArray_mapFinIdx {f : (i : Nat) → α → (h : i < n) → β} {xs : Vector α n} :
|
||||
@[simp, grind] theorem toArray_mapFinIdx {f : (i : Nat) → α → (h : i < n) → β} {xs : Vector α n} :
|
||||
(xs.mapFinIdx f).toArray =
|
||||
xs.toArray.mapFinIdx (fun i a h => f i a (by simpa [xs.size_toArray] using h)) :=
|
||||
rfl
|
||||
@@ -331,145 +333,145 @@ theorem toArray_mapM_go [Monad m] [LawfulMonad m] {f : α → m β} {xs : Vector
|
||||
rfl
|
||||
· simp
|
||||
|
||||
@[simp] theorem toArray_mapM [Monad m] [LawfulMonad m] {f : α → m β} {xs : Vector α n} :
|
||||
@[simp, grind] theorem toArray_mapM [Monad m] [LawfulMonad m] {f : α → m β} {xs : Vector α n} :
|
||||
toArray <$> xs.mapM f = xs.toArray.mapM f := by
|
||||
rcases xs with ⟨xs, rfl⟩
|
||||
unfold mapM
|
||||
rw [toArray_mapM_go]
|
||||
rfl
|
||||
|
||||
@[simp] theorem toArray_ofFn {f : Fin n → α} : (Vector.ofFn f).toArray = Array.ofFn f := rfl
|
||||
@[simp, grind] theorem toArray_ofFn {f : Fin n → α} : (Vector.ofFn f).toArray = Array.ofFn f := rfl
|
||||
|
||||
@[simp] theorem toArray_pop {xs : Vector α n} : xs.pop.toArray = xs.toArray.pop := rfl
|
||||
@[simp, grind] theorem toArray_pop {xs : Vector α n} : xs.pop.toArray = xs.toArray.pop := rfl
|
||||
|
||||
@[simp] theorem toArray_push {xs : Vector α n} {x} : (xs.push x).toArray = xs.toArray.push x := rfl
|
||||
@[simp, grind] theorem toArray_push {xs : Vector α n} {x} : (xs.push x).toArray = xs.toArray.push x := rfl
|
||||
|
||||
@[simp] theorem toArray_beq_toArray [BEq α] {xs : Vector α n} {ys : Vector α n} :
|
||||
@[simp, grind] theorem toArray_beq_toArray [BEq α] {xs : Vector α n} {ys : Vector α n} :
|
||||
(xs.toArray == ys.toArray) = (xs == ys) := by
|
||||
simp [instBEq, isEqv, Array.instBEq, Array.isEqv, xs.2, ys.2]
|
||||
|
||||
@[simp] theorem toArray_range : (Vector.range n).toArray = Array.range n := rfl
|
||||
@[simp, grind] theorem toArray_range : (Vector.range n).toArray = Array.range n := rfl
|
||||
|
||||
@[simp] theorem toArray_reverse (xs : Vector α n) : xs.reverse.toArray = xs.toArray.reverse := rfl
|
||||
@[simp, grind] theorem toArray_reverse (xs : Vector α n) : xs.reverse.toArray = xs.toArray.reverse := rfl
|
||||
|
||||
@[simp] theorem toArray_set {xs : Vector α n} {i x} (h) :
|
||||
@[simp, grind] theorem toArray_set {xs : Vector α n} {i x} (h) :
|
||||
(xs.set i x).toArray = xs.toArray.set i x (by simpa using h):= rfl
|
||||
|
||||
@[simp] theorem toArray_set! {xs : Vector α n} {i x} :
|
||||
@[simp, grind] theorem toArray_set! {xs : Vector α n} {i x} :
|
||||
(xs.set! i x).toArray = xs.toArray.set! i x := rfl
|
||||
|
||||
@[simp] theorem toArray_setIfInBounds {xs : Vector α n} {i x} :
|
||||
@[simp, grind] theorem toArray_setIfInBounds {xs : Vector α n} {i x} :
|
||||
(xs.setIfInBounds i x).toArray = xs.toArray.setIfInBounds i x := rfl
|
||||
|
||||
@[simp] theorem toArray_singleton {x : α} : (Vector.singleton x).toArray = #[x] := rfl
|
||||
@[simp, grind] theorem toArray_singleton {x : α} : (Vector.singleton x).toArray = #[x] := rfl
|
||||
|
||||
@[simp] theorem toArray_swap {xs : Vector α n} {i j} (hi hj) : (xs.swap i j).toArray =
|
||||
@[simp, grind] theorem toArray_swap {xs : Vector α n} {i j} (hi hj) : (xs.swap i j).toArray =
|
||||
xs.toArray.swap i j (by simp [hi, hj]) (by simp [hi, hj]) := rfl
|
||||
|
||||
@[simp] theorem toArray_swapIfInBounds {xs : Vector α n} {i j} :
|
||||
@[simp, grind] theorem toArray_swapIfInBounds {xs : Vector α n} {i j} :
|
||||
(xs.swapIfInBounds i j).toArray = xs.toArray.swapIfInBounds i j := rfl
|
||||
|
||||
@[simp] theorem toArray_swapAt {xs : Vector α n} {i x} (h) :
|
||||
theorem toArray_swapAt {xs : Vector α n} {i x} (h) :
|
||||
((xs.swapAt i x).fst, (xs.swapAt i x).snd.toArray) =
|
||||
((xs.toArray.swapAt i x (by simpa using h)).fst,
|
||||
(xs.toArray.swapAt i x (by simpa using h)).snd) := rfl
|
||||
|
||||
@[simp] theorem toArray_swapAt! {xs : Vector α n} {i x} :
|
||||
theorem toArray_swapAt! {xs : Vector α n} {i x} :
|
||||
((xs.swapAt! i x).fst, (xs.swapAt! i x).snd.toArray) =
|
||||
((xs.toArray.swapAt! i x).fst, (xs.toArray.swapAt! i x).snd) := rfl
|
||||
|
||||
@[simp] theorem toArray_take {xs : Vector α n} {i} : (xs.take i).toArray = xs.toArray.take i := rfl
|
||||
@[simp, grind] theorem toArray_take {xs : Vector α n} {i} : (xs.take i).toArray = xs.toArray.take i := rfl
|
||||
|
||||
@[simp] theorem toArray_zipIdx {xs : Vector α n} (k : Nat := 0) :
|
||||
@[simp, grind] theorem toArray_zipIdx {xs : Vector α n} (k : Nat := 0) :
|
||||
(xs.zipIdx k).toArray = xs.toArray.zipIdx k := rfl
|
||||
|
||||
@[simp] theorem toArray_zipWith {f : α → β → γ} {as : Vector α n} {bs : Vector β n} :
|
||||
@[simp, grind] theorem toArray_zipWith {f : α → β → γ} {as : Vector α n} {bs : Vector β n} :
|
||||
(Vector.zipWith f as bs).toArray = Array.zipWith f as.toArray bs.toArray := rfl
|
||||
|
||||
@[simp] theorem anyM_toArray [Monad m] {p : α → m Bool} {xs : Vector α n} :
|
||||
@[simp, grind] theorem anyM_toArray [Monad m] {p : α → m Bool} {xs : Vector α n} :
|
||||
xs.toArray.anyM p = xs.anyM p := by
|
||||
cases xs
|
||||
simp
|
||||
|
||||
@[simp] theorem allM_toArray [Monad m] {p : α → m Bool} {xs : Vector α n} :
|
||||
@[simp, grind] theorem allM_toArray [Monad m] {p : α → m Bool} {xs : Vector α n} :
|
||||
xs.toArray.allM p = xs.allM p := by
|
||||
cases xs
|
||||
simp
|
||||
|
||||
@[simp] theorem any_toArray {p : α → Bool} {xs : Vector α n} :
|
||||
@[simp, grind] theorem any_toArray {p : α → Bool} {xs : Vector α n} :
|
||||
xs.toArray.any p = xs.any p := by
|
||||
cases xs
|
||||
simp
|
||||
|
||||
@[simp] theorem all_toArray {p : α → Bool} {xs : Vector α n} :
|
||||
@[simp, grind] theorem all_toArray {p : α → Bool} {xs : Vector α n} :
|
||||
xs.toArray.all p = xs.all p := by
|
||||
cases xs
|
||||
simp
|
||||
|
||||
@[simp] theorem countP_toArray {p : α → Bool} {xs : Vector α n} :
|
||||
@[simp, grind] theorem countP_toArray {p : α → Bool} {xs : Vector α n} :
|
||||
xs.toArray.countP p = xs.countP p := by
|
||||
cases xs
|
||||
simp
|
||||
|
||||
@[simp] theorem count_toArray [BEq α] {a : α} {xs : Vector α n} :
|
||||
@[simp, grind] theorem count_toArray [BEq α] {a : α} {xs : Vector α n} :
|
||||
xs.toArray.count a = xs.count a := by
|
||||
cases xs
|
||||
simp
|
||||
|
||||
@[simp] theorem replace_toArray [BEq α] {xs : Vector α n} {a b} :
|
||||
@[simp, grind] theorem replace_toArray [BEq α] {xs : Vector α n} {a b} :
|
||||
xs.toArray.replace a b = (xs.replace a b).toArray := rfl
|
||||
|
||||
@[simp] theorem find?_toArray {p : α → Bool} {xs : Vector α n} :
|
||||
@[simp, grind] theorem find?_toArray {p : α → Bool} {xs : Vector α n} :
|
||||
xs.toArray.find? p = xs.find? p := by
|
||||
cases xs
|
||||
simp
|
||||
|
||||
@[simp] theorem findSome?_toArray {f : α → Option β} {xs : Vector α n} :
|
||||
@[simp, grind] theorem findSome?_toArray {f : α → Option β} {xs : Vector α n} :
|
||||
xs.toArray.findSome? f = xs.findSome? f := by
|
||||
cases xs
|
||||
simp
|
||||
|
||||
@[simp] theorem findRev?_toArray {p : α → Bool} {xs : Vector α n} :
|
||||
@[simp, grind] theorem findRev?_toArray {p : α → Bool} {xs : Vector α n} :
|
||||
xs.toArray.findRev? p = xs.findRev? p := by
|
||||
cases xs
|
||||
simp
|
||||
|
||||
@[simp] theorem findSomeRev?_toArray {f : α → Option β} {xs : Vector α n} :
|
||||
@[simp, grind] theorem findSomeRev?_toArray {f : α → Option β} {xs : Vector α n} :
|
||||
xs.toArray.findSomeRev? f = xs.findSomeRev? f := by
|
||||
cases xs
|
||||
simp
|
||||
|
||||
@[simp] theorem findM?_toArray [Monad m] {p : α → m Bool} {xs : Vector α n} :
|
||||
@[simp, grind] theorem findM?_toArray [Monad m] {p : α → m Bool} {xs : Vector α n} :
|
||||
xs.toArray.findM? p = xs.findM? p := by
|
||||
cases xs
|
||||
simp
|
||||
|
||||
@[simp] theorem findSomeM?_toArray [Monad m] {f : α → m (Option β)} {xs : Vector α n} :
|
||||
@[simp, grind] theorem findSomeM?_toArray [Monad m] {f : α → m (Option β)} {xs : Vector α n} :
|
||||
xs.toArray.findSomeM? f = xs.findSomeM? f := by
|
||||
cases xs
|
||||
simp
|
||||
|
||||
@[simp] theorem findRevM?_toArray [Monad m] {p : α → m Bool} {xs : Vector α n} :
|
||||
@[simp, grind] theorem findRevM?_toArray [Monad m] {p : α → m Bool} {xs : Vector α n} :
|
||||
xs.toArray.findRevM? p = xs.findRevM? p := by
|
||||
rcases xs with ⟨xs, rfl⟩
|
||||
simp
|
||||
|
||||
@[simp] theorem findSomeRevM?_toArray [Monad m] {f : α → m (Option β)} {xs : Vector α n} :
|
||||
@[simp, grind] theorem findSomeRevM?_toArray [Monad m] {f : α → m (Option β)} {xs : Vector α n} :
|
||||
xs.toArray.findSomeRevM? f = xs.findSomeRevM? f := by
|
||||
rcases xs with ⟨xs, rfl⟩
|
||||
simp
|
||||
|
||||
@[simp] theorem finIdxOf?_toArray [BEq α] {a : α} {xs : Vector α n} :
|
||||
@[simp, grind] theorem finIdxOf?_toArray [BEq α] {a : α} {xs : Vector α n} :
|
||||
xs.toArray.finIdxOf? a = (xs.finIdxOf? a).map (Fin.cast xs.size_toArray.symm) := by
|
||||
rcases xs with ⟨xs, rfl⟩
|
||||
simp
|
||||
|
||||
@[simp] theorem findFinIdx?_toArray {p : α → Bool} {xs : Vector α n} :
|
||||
@[simp, grind] theorem findFinIdx?_toArray {p : α → Bool} {xs : Vector α n} :
|
||||
xs.toArray.findFinIdx? p = (xs.findFinIdx? p).map (Fin.cast xs.size_toArray.symm) := by
|
||||
rcases xs with ⟨xs, rfl⟩
|
||||
simp
|
||||
|
||||
@[simp] theorem toArray_replicate : (replicate n a).toArray = Array.replicate n a := rfl
|
||||
@[simp, grind] theorem toArray_replicate : (replicate n a).toArray = Array.replicate n a := rfl
|
||||
|
||||
@[deprecated toArray_replicate (since := "2025-03-18")]
|
||||
abbrev toArray_mkVector := @toArray_replicate
|
||||
@@ -483,7 +485,7 @@ abbrev toArray_mkVector := @toArray_replicate
|
||||
`Vector.ext` is an extensionality theorem.
|
||||
Vectors `a` and `b` are equal to each other if their elements are equal for each valid index.
|
||||
-/
|
||||
@[ext, grind ext]
|
||||
@[ext]
|
||||
protected theorem ext {xs ys : Vector α n} (h : (i : Nat) → (_ : i < n) → xs[i] = ys[i]) : xs = ys := by
|
||||
apply Vector.toArray_inj.1
|
||||
apply Array.ext
|
||||
@@ -498,7 +500,13 @@ protected theorem ext {xs ys : Vector α n} (h : (i : Nat) → (_ : i < n) → x
|
||||
|
||||
/-! ### toList -/
|
||||
|
||||
theorem toArray_toList {xs : Vector α n} : xs.toArray.toList = xs.toList := rfl
|
||||
@[simp, grind] theorem length_toList {xs : Vector α n} : xs.toList.length = n := by
|
||||
rcases xs with ⟨xs, rfl⟩
|
||||
simp [toList]
|
||||
|
||||
@[grind =_] theorem toList_toArray {xs : Vector α n} : xs.toArray.toList = xs.toList := rfl
|
||||
|
||||
@[simp, grind] theorem toList_mk : (Vector.mk xs h).toList = xs.toList := rfl
|
||||
|
||||
@[simp] theorem getElem_toList {xs : Vector α n} {i : Nat} (h : i < xs.toList.length) :
|
||||
xs.toList[i] = xs[i]'(by simpa using h) := by
|
||||
@@ -511,11 +519,11 @@ theorem toArray_toList {xs : Vector α n} : xs.toArray.toList = xs.toList := rfl
|
||||
simp
|
||||
|
||||
theorem toList_append {xs : Vector α m} {ys : Vector α n} :
|
||||
(xs ++ ys).toList = xs.toList ++ ys.toList := by simp
|
||||
(xs ++ ys).toList = xs.toList ++ ys.toList := by simp [toList]
|
||||
|
||||
@[simp] theorem toList_drop {xs : Vector α n} {i} :
|
||||
(xs.drop i).toList = xs.toList.drop i := by
|
||||
simp [List.take_of_length_le]
|
||||
simp [toList, List.take_of_length_le]
|
||||
|
||||
theorem toList_empty : (#v[] : Vector α 0).toList = [] := rfl
|
||||
|
||||
@@ -526,14 +534,14 @@ theorem toList_emptyWithCapacity {cap} :
|
||||
abbrev toList_mkEmpty := @toList_emptyWithCapacity
|
||||
|
||||
theorem toList_eraseIdx {xs : Vector α n} {i} (h) :
|
||||
(xs.eraseIdx i h).toList = xs.toList.eraseIdx i := by simp
|
||||
(xs.eraseIdx i h).toList = xs.toList.eraseIdx i := by simp [toList]
|
||||
|
||||
@[simp] theorem toList_eraseIdx! {xs : Vector α n} {i} (hi : i < n) :
|
||||
(xs.eraseIdx! i).toList = xs.toList.eraseIdx i := by
|
||||
cases xs; simp_all [Array.eraseIdx!]
|
||||
|
||||
theorem toList_insertIdx {xs : Vector α n} {i x} (h) :
|
||||
(xs.insertIdx i x h).toList = xs.toList.insertIdx i x := by simp
|
||||
(xs.insertIdx i x h).toList = xs.toList.insertIdx i x := by simp [toList]
|
||||
|
||||
theorem toList_insertIdx! {xs : Vector α n} {i x} (hi : i ≤ n) :
|
||||
(xs.insertIdx! i x).toList = xs.toList.insertIdx i x := by
|
||||
@@ -544,39 +552,39 @@ theorem toList_cast {xs : Vector α n} (h : n = m) :
|
||||
|
||||
theorem toList_extract {xs : Vector α n} {start stop} :
|
||||
(xs.extract start stop).toList = (xs.toList.drop start).take (stop - start) := by
|
||||
simp
|
||||
simp [toList]
|
||||
|
||||
theorem toList_map {f : α → β} {xs : Vector α n} :
|
||||
(xs.map f).toList = xs.toList.map f := by simp
|
||||
(xs.map f).toList = xs.toList.map f := by simp [toList]
|
||||
|
||||
theorem toList_mapIdx {f : Nat → α → β} {xs : Vector α n} :
|
||||
(xs.mapIdx f).toList = xs.toList.mapIdx f := by simp
|
||||
(xs.mapIdx f).toList = xs.toList.mapIdx f := by simp [toList]
|
||||
|
||||
theorem toList_mapFinIdx {f : (i : Nat) → α → (h : i < n) → β} {xs : Vector α n} :
|
||||
(xs.mapFinIdx f).toList =
|
||||
xs.toList.mapFinIdx (fun i a h => f i a (by simpa [xs.size_toArray] using h)) := by
|
||||
simp
|
||||
simp [toList]
|
||||
|
||||
theorem toList_ofFn {f : Fin n → α} : (Vector.ofFn f).toList = List.ofFn f := by simp
|
||||
theorem toList_ofFn {f : Fin n → α} : (Vector.ofFn f).toList = List.ofFn f := by simp [toList]
|
||||
|
||||
theorem toList_pop {xs : Vector α n} : xs.pop.toList = xs.toList.dropLast := rfl
|
||||
theorem toList_pop {xs : Vector α n} : xs.pop.toList = xs.toList.dropLast := by simp [toList]
|
||||
|
||||
theorem toList_push {xs : Vector α n} {x} : (xs.push x).toList = xs.toList ++ [x] := by simp
|
||||
theorem toList_push {xs : Vector α n} {x} : (xs.push x).toList = xs.toList ++ [x] := by simp [toList]
|
||||
|
||||
@[simp] theorem toList_beq_toList [BEq α] {xs : Vector α n} {ys : Vector α n} :
|
||||
(xs.toList == ys.toList) = (xs == ys) := by
|
||||
simp [instBEq, isEqv, Array.instBEq, Array.isEqv, xs.2, ys.2]
|
||||
simp [toList]
|
||||
|
||||
theorem toList_range : (Vector.range n).toList = List.range n := by simp
|
||||
theorem toList_range : (Vector.range n).toList = List.range n := by simp [toList]
|
||||
|
||||
theorem toList_reverse {xs : Vector α n} : xs.reverse.toList = xs.toList.reverse := by simp
|
||||
theorem toList_reverse {xs : Vector α n} : xs.reverse.toList = xs.toList.reverse := by simp [toList]
|
||||
|
||||
theorem toList_set {xs : Vector α n} {i x} (h) :
|
||||
(xs.set i x).toList = xs.toList.set i x := rfl
|
||||
|
||||
@[simp] theorem toList_setIfInBounds {xs : Vector α n} {i x} :
|
||||
(xs.setIfInBounds i x).toList = xs.toList.set i x := by
|
||||
simp [Vector.setIfInBounds]
|
||||
simp [toList, Vector.setIfInBounds]
|
||||
|
||||
theorem toList_singleton {x : α} : (Vector.singleton x).toList = [x] := rfl
|
||||
|
||||
@@ -584,7 +592,7 @@ theorem toList_swap {xs : Vector α n} {i j} (hi hj) :
|
||||
(xs.swap i j).toList = (xs.toList.set i xs[j]).set j xs[i] := rfl
|
||||
|
||||
@[simp] theorem toList_take {xs : Vector α n} {i} : (xs.take i).toList = xs.toList.take i := by
|
||||
simp [List.take_of_length_le]
|
||||
simp [toList, List.take_of_length_le]
|
||||
|
||||
@[simp] theorem toList_zipWith {f : α → β → γ} {as : Vector α n} {bs : Vector β n} :
|
||||
(Vector.zipWith f as bs).toList = List.zipWith f as.toList bs.toList := by
|
||||
@@ -664,16 +672,14 @@ theorem toList_inj {xs ys : Vector α n} : xs.toList = ys.toList ↔ xs = ys :=
|
||||
|
||||
@[simp] theorem toList_eq_nil_iff {xs : Vector α n} : xs.toList = [] ↔ n = 0 := by
|
||||
rcases xs with ⟨xs, h⟩
|
||||
simp only [Array.toList_eq_nil_iff]
|
||||
simp only [toList, Array.toList_eq_nil_iff]
|
||||
exact ⟨by rintro rfl; simp_all, by rintro rfl; simpa using h⟩
|
||||
|
||||
@[deprecated toList_eq_nil_iff (since := "2025-04-04")]
|
||||
abbrev toList_eq_empty_iff {α n} (xs) := @toList_eq_nil_iff α n xs
|
||||
|
||||
@[simp] theorem mem_toList_iff {a : α} {xs : Vector α n} : a ∈ xs.toList ↔ a ∈ xs := by
|
||||
simp
|
||||
|
||||
theorem length_toList {α n} (xs : Vector α n) : xs.toList.length = n := by simp
|
||||
simp [toList]
|
||||
|
||||
/-! ### empty -/
|
||||
|
||||
@@ -1320,7 +1326,7 @@ theorem getElem?_setIfInBounds_self {xs : Vector α n} {x : α} :
|
||||
@[simp] theorem getElem?_setIfInBounds_ne {xs : Vector α n} {x : α} (h : i ≠ j) :
|
||||
(xs.setIfInBounds i x)[j]? = xs[j]? := by simp [getElem?_setIfInBounds, h]
|
||||
|
||||
theorem setIfInBounds_eq_of_size_le {xs : Vector α n} {i : Nat} (h : xs.size ≤ i) {a : α} :
|
||||
theorem setIfInBounds_eq_of_size_le {xs : Vector α n} {i : Nat} (h : n ≤ i) {a : α} :
|
||||
xs.setIfInBounds i a = xs := by
|
||||
rcases xs with ⟨xs, rfl⟩
|
||||
simp [Array.setIfInBounds_eq_of_size_le (by simpa using h)]
|
||||
@@ -1864,7 +1870,7 @@ set_option linter.listVariables false in
|
||||
induction l generalizing i with
|
||||
| nil => simp at hi
|
||||
| cons xs l ih =>
|
||||
simp only [List.map_cons, List.map_map, List.flatten_cons]
|
||||
simp only [List.map_cons, List.map_map, List.flatten_cons, toList_toArray]
|
||||
by_cases h : i < m
|
||||
· rw [List.getElem_append_left (by simpa)]
|
||||
have h₁ : i / m = 0 := Nat.div_eq_of_lt h
|
||||
@@ -1872,13 +1878,13 @@ set_option linter.listVariables false in
|
||||
simp [h₁, h₂]
|
||||
· have h₁ : xs.toList.length ≤ i := by simp; omega
|
||||
rw [List.getElem_append_right h₁]
|
||||
simp only [Array.length_toList, size_toArray]
|
||||
simp only [length_toList]
|
||||
specialize ih (i := i - m) (by simp_all [Nat.add_one_mul]; omega)
|
||||
have h₂ : i / m = (i - m) / m + 1 := by
|
||||
conv => lhs; rw [show i = i - m + m by omega]
|
||||
rw [Nat.add_div_right]
|
||||
exact Nat.pos_of_lt_mul_left hi
|
||||
simp only [Array.length_toList, size_toArray] at h₁
|
||||
simp only [length_toList] at h₁
|
||||
have h₃ : (i - m) % m = i % m := (Nat.mod_eq_sub_mod h₁).symm
|
||||
simp_all
|
||||
|
||||
@@ -2215,7 +2221,7 @@ theorem flatMap_replicate {f : α → Vector β m} : (replicate n a).flatMap f =
|
||||
abbrev flatMap_mkVector := @flatMap_replicate
|
||||
|
||||
@[simp] theorem sum_replicate_nat {n : Nat} {a : Nat} : (replicate n a).sum = n * a := by
|
||||
simp [toArray_replicate]
|
||||
simp [sum, toArray_replicate]
|
||||
|
||||
@[deprecated sum_replicate_nat (since := "2025-03-18")]
|
||||
abbrev sum_mkVector := @sum_replicate_nat
|
||||
@@ -2233,10 +2239,6 @@ theorem reverse_empty : reverse (#v[] : Vector α 0) = #v[] := rfl
|
||||
cases as
|
||||
simp
|
||||
|
||||
@[simp] theorem isEmpty_reverse {xs : Vector α n} : xs.reverse.isEmpty = xs.isEmpty := by
|
||||
rcases xs with ⟨xs, rfl⟩
|
||||
simp
|
||||
|
||||
@[simp, grind] theorem getElem_reverse {xs : Vector α n} {i : Nat} (hi : i < n) :
|
||||
(xs.reverse)[i] = xs[n - 1 - i] := by
|
||||
rcases xs with ⟨xs, rfl⟩
|
||||
@@ -2448,14 +2450,16 @@ theorem foldr_map {f : α₁ → α₂} {g : α₂ → β → β} {xs : Vector
|
||||
(xs.map f).foldr g init = xs.foldr (fun x y => g (f x) y) init := by
|
||||
cases xs; simp [Array.foldr_map']
|
||||
|
||||
@[deprecated "Deprecated without replacement; `filterMap` is not part of the `Vector` API." (since := "2025-05-09")]
|
||||
theorem foldl_filterMap {f : α → Option β} {g : γ → β → γ} {xs : Vector α n} {init : γ} :
|
||||
(xs.filterMap f).foldl g init = xs.foldl (fun x y => match f y with | some b => g x b | none => x) init := by
|
||||
(xs.toArray.filterMap f).foldl g init = xs.foldl (fun x y => match f y with | some b => g x b | none => x) init := by
|
||||
rcases xs with ⟨xs, rfl⟩
|
||||
simp [Array.foldl_filterMap']
|
||||
rfl
|
||||
|
||||
@[deprecated "Deprecated without replacement; `filterMap` is not part of the `Vector` API." (since := "2025-05-09")]
|
||||
theorem foldr_filterMap {f : α → Option β} {g : β → γ → γ} {xs : Vector α n} {init : γ} :
|
||||
(xs.filterMap f).foldr g init = xs.foldr (fun x y => match f x with | some b => g b y | none => y) init := by
|
||||
(xs.toArray.filterMap f).foldr g init = xs.foldr (fun x y => match f x with | some b => g b y | none => y) init := by
|
||||
cases xs; simp [Array.foldr_filterMap']
|
||||
rfl
|
||||
|
||||
@@ -2555,12 +2559,12 @@ theorem foldr_rel {xs : Vector α n} {f g : α → β → β} {a b : β} {r : β
|
||||
simpa using Array.foldr_rel h (by simpa using h')
|
||||
|
||||
@[simp] theorem foldl_add_const {xs : Vector α n} {a b : Nat} :
|
||||
xs.foldl (fun x _ => x + a) b = b + a * xs.size := by
|
||||
xs.foldl (fun x _ => x + a) b = b + a * n := by
|
||||
rcases xs with ⟨xs, rfl⟩
|
||||
simp
|
||||
|
||||
@[simp] theorem foldr_add_const {xs : Vector α n} {a b : Nat} :
|
||||
xs.foldr (fun _ x => x + a) b = b + a * xs.size := by
|
||||
xs.foldr (fun _ x => x + a) b = b + a * n := by
|
||||
rcases xs with ⟨xs, rfl⟩
|
||||
simp
|
||||
|
||||
@@ -2697,15 +2701,15 @@ theorem contains_map [BEq β] {xs : Vector α n} {x : β} {f : α → β} :
|
||||
rcases xs with ⟨xs⟩
|
||||
simp
|
||||
|
||||
@[simp, grind]
|
||||
@[deprecated "Deprecated without replacement; `filter` is not part of the `Vector` API." (since := "2025-05-09")]
|
||||
theorem contains_filter [BEq α] {xs : Vector α n} {x : α} {p : α → Bool} :
|
||||
(xs.filter p).contains x = xs.any (fun a => x == a && p a) := by
|
||||
(xs.toArray.filter p).contains x = xs.any (fun a => x == a && p a) := by
|
||||
rcases xs with ⟨xs, rfl⟩
|
||||
simp
|
||||
|
||||
@[simp, grind]
|
||||
@[deprecated "Deprecated without replacement; `filterMap` is not part of the `Vector` API." (since := "2025-05-09")]
|
||||
theorem contains_filterMap [BEq β] {xs : Vector α n} {x : β} {f : α → Option β} :
|
||||
(xs.filterMap f).contains x = xs.any (fun a => (f a).any fun b => x == b) := by
|
||||
(xs.toArray.filterMap f).contains x = xs.any (fun a => (f a).any fun b => x == b) := by
|
||||
rcases xs with ⟨xs, rfl⟩
|
||||
simp
|
||||
|
||||
@@ -2835,24 +2839,28 @@ theorem any_eq_not_all_not {xs : Vector α n} {p : α → Bool} : xs.any p = !xs
|
||||
rcases xs with ⟨xs, rfl⟩
|
||||
simp
|
||||
|
||||
@[simp] theorem any_filter {xs : Vector α n} {p q : α → Bool} :
|
||||
(xs.filter p).any q = xs.any fun a => p a && q a := by
|
||||
@[deprecated "Deprecated without replacement; `filter` is not part of the `Vector` API." (since := "2025-05-09")]
|
||||
theorem any_filter {xs : Vector α n} {p q : α → Bool} :
|
||||
(xs.toArray.filter p).any q = xs.any fun a => p a && q a := by
|
||||
rcases xs with ⟨xs, rfl⟩
|
||||
simp
|
||||
|
||||
@[simp] theorem all_filter {xs : Vector α n} {p q : α → Bool} :
|
||||
(xs.filter p).all q = xs.all fun a => !(p a) || q a := by
|
||||
@[deprecated "Deprecated without replacement; `filter` is not part of the `Vector` API." (since := "2025-05-09")]
|
||||
theorem all_filter {xs : Vector α n} {p q : α → Bool} :
|
||||
(xs.toArray.filter p).all q = xs.all fun a => !(p a) || q a := by
|
||||
rcases xs with ⟨xs, rfl⟩
|
||||
simp
|
||||
|
||||
@[simp] theorem any_filterMap {xs : Vector α n} {f : α → Option β} {p : β → Bool} :
|
||||
(xs.filterMap f).any p = xs.any fun a => match f a with | some b => p b | none => false := by
|
||||
@[deprecated "Deprecated without replacement; `filterMap` is not part of the `Vector` API." (since := "2025-05-09")]
|
||||
theorem any_filterMap {xs : Vector α n} {f : α → Option β} {p : β → Bool} :
|
||||
(xs.toArray.filterMap f).any p = xs.any fun a => match f a with | some b => p b | none => false := by
|
||||
rcases xs with ⟨xs, rfl⟩
|
||||
simp
|
||||
rfl
|
||||
|
||||
@[simp] theorem all_filterMap {xs : Vector α n} {f : α → Option β} {p : β → Bool} :
|
||||
(xs.filterMap f).all p = xs.all fun a => match f a with | some b => p b | none => true := by
|
||||
@[deprecated "Deprecated without replacement; `filterMap` is not part of the `Vector` API." (since := "2025-05-09")]
|
||||
theorem all_filterMap {xs : Vector α n} {f : α → Option β} {p : β → Bool} :
|
||||
(xs.toArray.filterMap f).all p = xs.all fun a => match f a with | some b => p b | none => true := by
|
||||
rcases xs with ⟨xs, rfl⟩
|
||||
simp
|
||||
rfl
|
||||
@@ -3051,7 +3059,7 @@ set_option linter.indexVariables false in
|
||||
ext i
|
||||
by_cases h : i < n
|
||||
· simp [h]
|
||||
· replace h : i = xs.size - 1 := by rw [size_toArray]; omega
|
||||
· replace h : i = n := by omega
|
||||
subst h
|
||||
simp [back]
|
||||
|
||||
@@ -3082,7 +3090,7 @@ set_option linter.indexVariables false in
|
||||
|
||||
/-! ### swap -/
|
||||
|
||||
theorem getElem_swap {xs : Vector α n} {i j : Nat} (hi hj) {k : Nat} (hk : k < n) :
|
||||
@[grind] theorem getElem_swap {xs : Vector α n} {i j : Nat} (hi hj) {k : Nat} (hk : k < n) :
|
||||
(xs.swap i j hi hj)[k] = if k = i then xs[j] else if k = j then xs[i] else xs[k] := by
|
||||
cases xs
|
||||
simp_all [Array.getElem_swap]
|
||||
@@ -3099,6 +3107,13 @@ theorem getElem_swap {xs : Vector α n} {i j : Nat} (hi hj) {k : Nat} (hk : k <
|
||||
(hi' : k ≠ i) (hj' : k ≠ j) : (xs.swap i j hi hj)[k] = xs[k] := by
|
||||
simp_all [getElem_swap]
|
||||
|
||||
@[grind]
|
||||
theorem getElem?_swap {xs : Vector α n} {i j : Nat} (hi hj) {k : Nat} : (xs.swap i j hi hj)[k]? =
|
||||
if j = k then some xs[i] else if i = k then some xs[j] else xs[k]? := by
|
||||
rcases xs with ⟨xs, rfl⟩
|
||||
simp [Array.getElem?_swap]
|
||||
|
||||
|
||||
@[simp] theorem swap_swap {xs : Vector α n} {i j : Nat} (hi hj) :
|
||||
(xs.swap i j hi hj).swap i j hi hj = xs := by
|
||||
cases xs
|
||||
@@ -3112,14 +3127,14 @@ theorem swap_comm {xs : Vector α n} {i j : Nat} (hi hj) :
|
||||
|
||||
/-! ### take -/
|
||||
|
||||
@[simp] theorem getElem_take {xs : Vector α n} {j : Nat} (hi : i < min j n) :
|
||||
@[simp, grind =] theorem getElem_take {xs : Vector α n} {j : Nat} (hi : i < min j n) :
|
||||
(xs.take j)[i] = xs[i] := by
|
||||
cases xs
|
||||
simp
|
||||
|
||||
/-! ### drop -/
|
||||
|
||||
@[simp] 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
|
||||
|
||||
@@ -18,8 +18,8 @@ namespace Vector
|
||||
|
||||
/-! ### Lexicographic ordering -/
|
||||
|
||||
@[simp] theorem lt_toArray [LT α] {xs ys : Vector α n} : xs.toArray < ys.toArray ↔ xs < ys := Iff.rfl
|
||||
@[simp] theorem le_toArray [LT α] {xs ys : Vector α n} : xs.toArray ≤ ys.toArray ↔ xs ≤ ys := Iff.rfl
|
||||
@[simp, grind =] theorem lt_toArray [LT α] {xs ys : Vector α n} : xs.toArray < ys.toArray ↔ xs < ys := Iff.rfl
|
||||
@[simp, grind =] theorem le_toArray [LT α] {xs ys : Vector α n} : xs.toArray ≤ ys.toArray ↔ xs ≤ ys := Iff.rfl
|
||||
|
||||
@[simp] theorem lt_toList [LT α] {xs ys : Vector α n} : xs.toList < ys.toList ↔ xs < ys := Iff.rfl
|
||||
@[simp] theorem le_toList [LT α] {xs ys : Vector α n} : xs.toList ≤ ys.toList ↔ xs ≤ ys := Iff.rfl
|
||||
@@ -40,7 +40,7 @@ protected theorem not_le_iff_gt [DecidableEq α] [LT α] [DecidableLT α] {xs ys
|
||||
simp [Vector.lex, Array.lex, n₁, n₂]
|
||||
rfl
|
||||
|
||||
@[simp] theorem lex_toArray [BEq α] {lt : α → α → Bool} {xs ys : Vector α n} :
|
||||
@[simp, grind =] theorem lex_toArray [BEq α] {lt : α → α → Bool} {xs ys : Vector α n} :
|
||||
xs.toArray.lex ys.toArray lt = xs.lex ys lt := by
|
||||
cases xs
|
||||
cases ys
|
||||
|
||||
@@ -134,7 +134,7 @@ theorem mapFinIdx_append {xs : Vector α n} {ys : Vector α m} {f : (i : Nat)
|
||||
@[simp]
|
||||
theorem mapFinIdx_push {xs : Vector α n} {a : α} {f : (i : Nat) → α → (h : i < n + 1) → β} :
|
||||
mapFinIdx (xs.push a) f =
|
||||
(mapFinIdx xs (fun i a h => f i a (by omega))).push (f xs.size a (by simp)) := by
|
||||
(mapFinIdx xs (fun i a h => f i a (by omega))).push (f n a (by simp)) := by
|
||||
simp [← append_singleton, mapFinIdx_append]
|
||||
|
||||
theorem mapFinIdx_singleton {a : α} {f : (i : Nat) → α → (h : i < 1) → β} :
|
||||
@@ -255,14 +255,14 @@ theorem mapIdx_eq_zipIdx_map {xs : Vector α n} {f : Nat → α → β} :
|
||||
abbrev mapIdx_eq_zipWithIndex_map := @mapIdx_eq_zipIdx_map
|
||||
|
||||
theorem mapIdx_append {xs : Vector α n} {ys : Vector α m} :
|
||||
(xs ++ ys).mapIdx f = xs.mapIdx f ++ ys.mapIdx fun i => f (i + xs.size) := by
|
||||
(xs ++ ys).mapIdx f = xs.mapIdx f ++ ys.mapIdx fun i => f (i + n) := by
|
||||
rcases xs with ⟨xs, rfl⟩
|
||||
rcases ys with ⟨ys, rfl⟩
|
||||
simp [Array.mapIdx_append]
|
||||
|
||||
@[simp]
|
||||
theorem mapIdx_push {xs : Vector α n} {a : α} :
|
||||
mapIdx f (xs.push a) = (mapIdx f xs).push (f xs.size a) := by
|
||||
mapIdx f (xs.push a) = (mapIdx f xs).push (f n a) := by
|
||||
simp [← append_singleton, mapIdx_append]
|
||||
|
||||
theorem mapIdx_singleton {a : α} : mapIdx f #v[a] = #v[f 0 a] := by
|
||||
@@ -284,7 +284,7 @@ theorem exists_of_mem_mapIdx {b : β} {xs : Vector α n}
|
||||
|
||||
theorem mapIdx_eq_push_iff {xs : Vector α (n + 1)} {b : β} :
|
||||
mapIdx f xs = ys.push b ↔
|
||||
∃ (a : α) (zs : Vector α n), xs = zs.push a ∧ mapIdx f zs = ys ∧ f zs.size a = b := by
|
||||
∃ (a : α) (zs : Vector α n), xs = zs.push a ∧ mapIdx f zs = ys ∧ f n a = b := by
|
||||
rw [mapIdx_eq_mapFinIdx, mapFinIdx_eq_push_iff]
|
||||
simp only [mapFinIdx_eq_mapIdx, exists_and_left, exists_prop]
|
||||
constructor
|
||||
@@ -302,7 +302,7 @@ theorem mapIdx_eq_append_iff {xs : Vector α (n + m)} {f : Nat → α → β} {y
|
||||
mapIdx f xs = ys ++ zs ↔
|
||||
∃ (ys' : Vector α n) (zs' : Vector α m), xs = ys' ++ zs' ∧
|
||||
ys'.mapIdx f = ys ∧
|
||||
zs'.mapIdx (fun i => f (i + ys'.size)) = zs := by
|
||||
zs'.mapIdx (fun i => f (i + n)) = zs := by
|
||||
rcases xs with ⟨xs, h⟩
|
||||
rcases ys with ⟨ys, rfl⟩
|
||||
rcases zs with ⟨zs, rfl⟩
|
||||
@@ -342,12 +342,12 @@ theorem mapIdx_eq_mapIdx_iff {xs : Vector α n} :
|
||||
simp
|
||||
|
||||
@[simp] theorem back?_mapIdx {xs : Vector α n} {f : Nat → α → β} :
|
||||
(mapIdx f xs).back? = (xs.back?).map (f (xs.size - 1)) := by
|
||||
(mapIdx f xs).back? = (xs.back?).map (f (n - 1)) := by
|
||||
rcases xs with ⟨xs, rfl⟩
|
||||
simp
|
||||
|
||||
@[simp] theorem back_mapIdx [NeZero n] {xs : Vector α n} {f : Nat → α → β} :
|
||||
(mapIdx f xs).back = f (xs.size - 1) (xs.back) := by
|
||||
(mapIdx f xs).back = f (n - 1) (xs.back) := by
|
||||
rcases xs with ⟨xs, rfl⟩
|
||||
simp
|
||||
|
||||
@@ -364,7 +364,7 @@ theorem mapIdx_eq_replicate_iff {xs : Vector α n} {f : Nat → α → β} {b :
|
||||
abbrev mapIdx_eq_mkVector_iff := @mapIdx_eq_replicate_iff
|
||||
|
||||
@[simp] theorem mapIdx_reverse {xs : Vector α n} {f : Nat → α → β} :
|
||||
xs.reverse.mapIdx f = (mapIdx (fun i => f (xs.size - 1 - i)) xs).reverse := by
|
||||
xs.reverse.mapIdx f = (mapIdx (fun i => f (n - 1 - i)) xs).reverse := by
|
||||
rcases xs with ⟨xs, rfl⟩
|
||||
simp [Array.mapIdx_reverse]
|
||||
|
||||
|
||||
@@ -70,32 +70,6 @@ theorem foldrM_map [Monad m] [LawfulMonad m] {f : β₁ → β₂} {g : β₂
|
||||
rcases xs with ⟨xs, rfl⟩
|
||||
simp [Array.foldrM_map]
|
||||
|
||||
theorem foldlM_filterMap [Monad m] [LawfulMonad m] {f : α → Option β} {g : γ → β → m γ} {xs : Vector α n} {init : γ} :
|
||||
(xs.filterMap f).foldlM g init =
|
||||
xs.foldlM (fun x y => match f y with | some b => g x b | none => pure x) init := by
|
||||
rcases xs with ⟨xs, rfl⟩
|
||||
simp [Array.foldlM_filterMap]
|
||||
rfl
|
||||
|
||||
theorem foldrM_filterMap [Monad m] [LawfulMonad m] {f : α → Option β} {g : β → γ → m γ} {xs : Vector α n} {init : γ} :
|
||||
(xs.filterMap f).foldrM g init =
|
||||
xs.foldrM (fun x y => match f x with | some b => g b y | none => pure y) init := by
|
||||
rcases xs with ⟨xs, rfl⟩
|
||||
simp [Array.foldrM_filterMap]
|
||||
rfl
|
||||
|
||||
theorem foldlM_filter [Monad m] [LawfulMonad m] {p : α → Bool} {g : β → α → m β} {xs : Vector α n} {init : β} :
|
||||
(xs.filter p).foldlM g init =
|
||||
xs.foldlM (fun x y => if p y then g x y else pure x) init := by
|
||||
rcases xs with ⟨xs, rfl⟩
|
||||
simp [Array.foldlM_filter]
|
||||
|
||||
theorem foldrM_filter [Monad m] [LawfulMonad m] {p : α → Bool} {g : α → β → m β} {xs : Vector α n} {init : β} :
|
||||
(xs.filter p).foldrM g init =
|
||||
xs.foldrM (fun x y => if p x then g x y else pure y) init := by
|
||||
rcases xs with ⟨xs, rfl⟩
|
||||
simp [Array.foldrM_filter]
|
||||
|
||||
@[simp] theorem foldlM_attachWith [Monad m]
|
||||
{xs : Vector α n} {q : α → Prop} (H : ∀ a, a ∈ xs → q a) {f : β → { x // q x} → m β} {b} :
|
||||
(xs.attachWith q H).foldlM f b = xs.attach.foldlM (fun b ⟨a, h⟩ => f b ⟨a, H _ h⟩) b := by
|
||||
|
||||
@@ -140,7 +140,7 @@ theorem range_add {n m : Nat} : range (n + m) = range n ++ (range m).map (n + ·
|
||||
simpa [range_eq_range', Nat.add_comm] using (range'_append_1 (s := 0)).symm
|
||||
|
||||
theorem reverse_range' {s n : Nat} : reverse (range' s n) = map (s + n - 1 - ·) (range n) := by
|
||||
simp [← toList_inj, List.reverse_range']
|
||||
simp [← toArray_inj, Array.reverse_range']
|
||||
|
||||
@[simp]
|
||||
theorem mem_range {m n : Nat} : m ∈ range n ↔ m < n := by
|
||||
|
||||
@@ -243,7 +243,7 @@ theorem map_prod_right_eq_zip {xs : Vector α n} {f : α → β} :
|
||||
|
||||
theorem zip_eq_append_iff {as : Vector α (n + m)} {bs : Vector β (n + m)} {xs : Vector (α × β) n} {ys : Vector (α × β) m} :
|
||||
zip as bs = xs ++ ys ↔
|
||||
∃ as₁ as₂ bs₁ bs₂, as₁.size = bs₁.size ∧ as = as₁ ++ as₂ ∧ bs = bs₁ ++ bs₂ ∧ xs = zip as₁ bs₁ ∧ ys = zip as₂ bs₂ := by
|
||||
∃ as₁ as₂ bs₁ bs₂, as = as₁ ++ as₂ ∧ bs = bs₁ ++ bs₂ ∧ xs = zip as₁ bs₁ ∧ ys = zip as₂ bs₂ := by
|
||||
simp [zip_eq_zipWith, zipWith_eq_append_iff]
|
||||
|
||||
@[simp] theorem zip_replicate {a : α} {b : β} {n : Nat} :
|
||||
|
||||
@@ -27,3 +27,23 @@ instance (priority := 300) One.toOfNat1 {α} [One α] : OfNat α (nat_lit 1) whe
|
||||
|
||||
instance (priority := 200) One.ofOfNat1 {α} [OfNat α (nat_lit 1)] : One α where
|
||||
one := 1
|
||||
|
||||
/--
|
||||
The fundamental power operation in a monoid.
|
||||
`npowRec n a = a*a*...*a` n times.
|
||||
This function should not be used directly; it is often used to implement a `Pow M Nat` instance,
|
||||
but end users should use the `a ^ n` notation instead.
|
||||
-/
|
||||
def npowRec [One M] [Mul M] : Nat → M → M
|
||||
| 0, _ => 1
|
||||
| n + 1, a => npowRec n a * a
|
||||
|
||||
/--
|
||||
The fundamental scalar multiplication in an additive monoid.
|
||||
`nsmulRec n a = a+a+...+a` n times.
|
||||
This function should not be used directly;
|
||||
it is often used to implement an instance for scalar multiplication.
|
||||
-/
|
||||
def nsmulRec [Zero M] [Add M] : Nat → M → M
|
||||
| 0, _ => 0
|
||||
| n + 1, a => nsmulRec n a + a
|
||||
|
||||
@@ -81,7 +81,6 @@ end Lean
|
||||
|
||||
attribute [ext] Prod PProd Sigma PSigma
|
||||
attribute [ext] funext propext Subtype.eq Array.ext
|
||||
attribute [grind ext] Array.ext
|
||||
|
||||
@[ext] protected theorem PUnit.ext (x y : PUnit) : x = y := rfl
|
||||
protected theorem Unit.ext (x y : Unit) : x = y := rfl
|
||||
|
||||
@@ -10,5 +10,6 @@ import Init.Grind.CommRing.Basic
|
||||
import Init.Grind.CommRing.Int
|
||||
import Init.Grind.CommRing.UInt
|
||||
import Init.Grind.CommRing.SInt
|
||||
import Init.Grind.CommRing.Fin
|
||||
import Init.Grind.CommRing.BitVec
|
||||
import Init.Grind.CommRing.Poly
|
||||
|
||||
110
src/Init/Grind/CommRing/Fin.lean
Normal file
110
src/Init/Grind/CommRing/Fin.lean
Normal file
@@ -0,0 +1,110 @@
|
||||
/-
|
||||
Copyright (c) 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
Released under Apache 2.0 license as described in the file LICENSE.
|
||||
Authors: Leonardo de Moura
|
||||
-/
|
||||
module
|
||||
|
||||
prelude
|
||||
import Init.Grind.CommRing.Basic
|
||||
import Init.Data.Fin.Lemmas
|
||||
|
||||
namespace Lean.Grind
|
||||
|
||||
namespace Fin
|
||||
|
||||
instance (n : Nat) [NeZero n] : NatCast (Fin n) where
|
||||
natCast a := Fin.ofNat' n a
|
||||
|
||||
def intCast [NeZero n] (a : Int) : Fin n :=
|
||||
if 0 ≤ a then
|
||||
Fin.ofNat' n a.natAbs
|
||||
else
|
||||
- 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
|
||||
|
||||
-- TODO: we should replace this at runtime with either repeated squaring,
|
||||
-- or a GMP accelerated function.
|
||||
def npow [NeZero n] (x : Fin n) (y : Nat) : Fin n := npowRec y x
|
||||
|
||||
instance [NeZero n] : HPow (Fin n) Nat (Fin n) where
|
||||
hPow := Fin.npow
|
||||
|
||||
@[simp] theorem pow_zero [NeZero n] (a : Fin n) : a ^ 0 = 1 := rfl
|
||||
@[simp] theorem pow_succ [NeZero n] (a : Fin n) (n : Nat) : a ^ (n+1) = a ^ n * a := rfl
|
||||
|
||||
theorem add_assoc (a b c : Fin n) : a + b + c = a + (b + c) := by
|
||||
cases a; cases b; cases c; simp [Fin.add_def, Nat.add_assoc]
|
||||
|
||||
theorem add_comm (a b : Fin n) : a + b = b + a := by
|
||||
cases a; cases b; simp [Fin.add_def, Nat.add_comm]
|
||||
|
||||
theorem add_zero [NeZero n] (a : Fin n) : a + 0 = a := by
|
||||
cases a; simp [Fin.add_def]
|
||||
next h => rw [Nat.mod_eq_of_lt h]
|
||||
|
||||
theorem neg_add_cancel [NeZero n] (a : Fin n) : -a + a = 0 := by
|
||||
cases a; simp [Fin.add_def, Fin.neg_def, Fin.sub_def]
|
||||
next h => rw [Nat.sub_add_cancel (Nat.le_of_lt h), Nat.mod_self]
|
||||
|
||||
theorem mul_assoc (a b c : Fin n) : a * b * c = a * (b * c) := by
|
||||
cases a; cases b; cases c; simp [Fin.mul_def, Nat.mul_assoc]
|
||||
|
||||
theorem mul_comm (a b : Fin n) : a * b = b * a := by
|
||||
cases a; cases b; simp [Fin.mul_def, Nat.mul_comm]
|
||||
|
||||
theorem zero_mul [NeZero n] (a : Fin n) : 0 * a = 0 := by
|
||||
cases a; simp [Fin.mul_def]
|
||||
|
||||
theorem mul_one [NeZero n] (a : Fin n) : a * 1 = a := by
|
||||
cases a; simp [Fin.mul_def, OfNat.ofNat]
|
||||
next h => rw [Nat.mod_eq_of_lt h]
|
||||
|
||||
theorem left_distrib (a b c : Fin n) : a * (b + c) = a * b + a * c := by
|
||||
cases a; cases b; cases c; simp [Fin.mul_def, Fin.add_def, Nat.left_distrib]
|
||||
|
||||
theorem ofNat_succ [NeZero n] (a : Nat) : OfNat.ofNat (α := Fin n) (a+1) = OfNat.ofNat a + 1 := by
|
||||
simp [OfNat.ofNat, Fin.add_def, Fin.ofNat']
|
||||
|
||||
theorem sub_eq_add_neg [NeZero n] (a b : Fin n) : a - b = a + -b := by
|
||||
cases a; cases b; simp [Fin.neg_def, Fin.sub_def, Fin.add_def, Nat.add_comm]
|
||||
|
||||
private theorem neg_neg [NeZero n] (a : Fin n) : - - a = a := by
|
||||
cases a; simp [Fin.neg_def, Fin.sub_def];
|
||||
next a h => cases a; simp; next a =>
|
||||
rw [Nat.self_sub_mod n (a+1)]
|
||||
have : NeZero (n - (a + 1)) := ⟨by omega⟩
|
||||
rw [Nat.self_sub_mod, Nat.sub_sub_eq_min, Nat.min_eq_right (Nat.le_of_lt h)]
|
||||
|
||||
theorem intCast_neg [NeZero n] (i : Int) : Int.cast (R := Fin n) (-i) = - Int.cast (R := Fin n) i := by
|
||||
simp [Int.cast, IntCast.intCast, Fin.intCast]; split <;> split <;> try omega
|
||||
next h₁ h₂ => simp [Int.le_antisymm h₁ h₂, Fin.neg_def]
|
||||
next => simp [Fin.neg_neg]
|
||||
|
||||
instance (n : Nat) [NeZero n] : CommRing (Fin n) where
|
||||
add_assoc := Fin.add_assoc
|
||||
add_comm := Fin.add_comm
|
||||
add_zero := Fin.add_zero
|
||||
neg_add_cancel := Fin.neg_add_cancel
|
||||
mul_assoc := Fin.mul_assoc
|
||||
mul_comm := Fin.mul_comm
|
||||
mul_one := Fin.mul_one
|
||||
left_distrib := Fin.left_distrib
|
||||
zero_mul := Fin.zero_mul
|
||||
pow_zero _ := rfl
|
||||
pow_succ _ _ := rfl
|
||||
ofNat_succ := Fin.ofNat_succ
|
||||
sub_eq_add_neg := Fin.sub_eq_add_neg
|
||||
intCast_neg := Fin.intCast_neg
|
||||
|
||||
instance (n : Nat) [NeZero n] : IsCharP (Fin n) n where
|
||||
ofNat_eq_zero_iff x := by simp only [OfNat.ofNat, Fin.ofNat']; simp
|
||||
|
||||
end Fin
|
||||
|
||||
end Lean.Grind
|
||||
@@ -584,12 +584,14 @@ theorem Mon.eq_of_revlexWF {m₁ m₂ : Mon} : m₁.revlexWF m₂ = .eq → m₁
|
||||
simp [h, eq_of_powerRevlex h₂]
|
||||
|
||||
theorem Mon.eq_of_revlexFuel {fuel : Nat} {m₁ m₂ : Mon} : revlexFuel fuel m₁ m₂ = .eq → m₁ = m₂ := by
|
||||
fun_induction revlexFuel <;> simp [revlexFuel, *, then_gt, then_lt, then_eq]
|
||||
next => apply eq_of_revlexWF
|
||||
next p₁ m₁ p₂ m₂ h ih =>
|
||||
fun_induction revlexFuel
|
||||
case case1 => apply eq_of_revlexWF
|
||||
case case5 p₁ m₁ p₂ m₂ h ih =>
|
||||
simp [then_eq]
|
||||
cases p₁; cases p₂; intro h₁ h₂; simp [ih h₁, h]
|
||||
simp at h h₂
|
||||
simp [h, eq_of_powerRevlex h₂]
|
||||
all_goals simp [then_eq]
|
||||
|
||||
theorem Mon.eq_of_revlex {m₁ m₂ : Mon} : revlex m₁ m₂ = .eq → m₁ = m₂ := by
|
||||
apply eq_of_revlexFuel
|
||||
@@ -665,11 +667,11 @@ theorem Poly.denote_combine {α} [CommRing α] (ctx : Context α) (p₁ p₂ : P
|
||||
unfold combine; generalize hugeFuel = fuel
|
||||
fun_induction combine.go
|
||||
<;> simp [combine.go, *, denote_concat, denote_addConst, denote, intCast_add, cond_eq_if, add_comm, add_left_comm, add_assoc]
|
||||
next hg _ h _ =>
|
||||
simp +zetaDelta at h; simp [*]
|
||||
case case5 hg _ h _ =>
|
||||
simp +zetaDelta at h
|
||||
rw [← add_assoc, Mon.eq_of_grevlex hg, ← right_distrib, ← intCast_add, h, intCast_zero, zero_mul, zero_add]
|
||||
next hg _ h _ =>
|
||||
simp +zetaDelta at h; simp [*, denote, intCast_add]
|
||||
case case6 hg k h _ =>
|
||||
simp +zetaDelta [k, intCast_add]
|
||||
rw [right_distrib, Mon.eq_of_grevlex hg, add_assoc]
|
||||
|
||||
theorem Poly.denote_mul_go {α} [CommRing α] (ctx : Context α) (p₁ p₂ acc : Poly)
|
||||
@@ -683,7 +685,8 @@ theorem Poly.denote_mul {α} [CommRing α] (ctx : Context α) (p₁ p₂ : Poly)
|
||||
|
||||
theorem Poly.denote_pow {α} [CommRing α] (ctx : Context α) (p : Poly) (k : Nat)
|
||||
: (pow p k).denote ctx = p.denote ctx ^ k := by
|
||||
fun_induction pow <;> simp [pow, denote, intCast_one, pow_zero]
|
||||
fun_induction pow
|
||||
next => simp [denote, intCast_one, pow_zero]
|
||||
next => simp [pow_succ, pow_zero, one_mul]
|
||||
next => simp [denote_mul, *, pow_succ, mul_comm]
|
||||
|
||||
@@ -810,12 +813,11 @@ theorem Poly.denote_mulConstC {α c} [CommRing α] [IsCharP α c] (ctx : Context
|
||||
fun_induction mulConstC.go <;> simp [mulConstC.go, denote, IsCharP.intCast_emod, cond_eq_if, *]
|
||||
next => rw [intCast_mul]
|
||||
next h _ =>
|
||||
simp +zetaDelta at h; simp [*]
|
||||
simp +zetaDelta at h
|
||||
rw [left_distrib, ← mul_assoc, ← intCast_mul, ← IsCharP.intCast_emod (x := k * _) (p := c),
|
||||
h, intCast_zero, zero_mul, zero_add]
|
||||
next h _ =>
|
||||
simp +zetaDelta at h
|
||||
simp [*, denote, IsCharP.intCast_emod, intCast_mul, mul_assoc, left_distrib]
|
||||
simp +zetaDelta [IsCharP.intCast_emod, intCast_mul, mul_assoc, left_distrib]
|
||||
|
||||
theorem Poly.denote_mulMonC {α c} [CommRing α] [IsCharP α c] (ctx : Context α) (k : Int) (m : Mon) (p : Poly)
|
||||
: (mulMonC k m p c).denote ctx = k * m.denote ctx * p.denote ctx := by
|
||||
@@ -828,14 +830,13 @@ theorem Poly.denote_mulMonC {α c} [CommRing α] [IsCharP α c] (ctx : Context
|
||||
next h =>
|
||||
simp at h; simp [*, Mon.denote, mul_one, denote_mulConstC, IsCharP.intCast_emod]
|
||||
next =>
|
||||
fun_induction mulMonC.go <;> simp [mulMonC.go, denote, *, cond_eq_if]
|
||||
fun_induction mulMonC.go <;> simp [denote, cond_eq_if]
|
||||
next h =>
|
||||
simp +zetaDelta at h; simp [*, denote]
|
||||
simp +zetaDelta at h
|
||||
rw [mul_assoc, mul_left_comm, ← intCast_mul, ← IsCharP.intCast_emod (x := k * _) (p := c), h]
|
||||
simp [intCast_zero, mul_zero]
|
||||
next h =>
|
||||
simp +zetaDelta at h; simp [*, denote, IsCharP.intCast_emod]
|
||||
simp [intCast_mul, intCast_zero, add_zero, mul_comm, mul_left_comm, mul_assoc]
|
||||
simp +zetaDelta [IsCharP.intCast_emod, intCast_mul, intCast_zero, add_zero, mul_comm, mul_left_comm, mul_assoc]
|
||||
next h _ =>
|
||||
simp +zetaDelta at h; simp [*, denote, left_distrib]
|
||||
rw [mul_left_comm]
|
||||
@@ -843,8 +844,7 @@ theorem Poly.denote_mulMonC {α c} [CommRing α] [IsCharP α c] (ctx : Context
|
||||
rw [Int.mul_comm] at h
|
||||
simp [h, intCast_zero, zero_mul, zero_add]
|
||||
next h _ =>
|
||||
simp +zetaDelta at h
|
||||
simp [*, denote, IsCharP.intCast_emod, Mon.denote_mul, intCast_mul, left_distrib,
|
||||
simp +zetaDelta [*, denote, IsCharP.intCast_emod, Mon.denote_mul, intCast_mul, left_distrib,
|
||||
mul_comm, mul_left_comm, mul_assoc]
|
||||
|
||||
theorem Poly.denote_combineC {α c} [CommRing α] [IsCharP α c] (ctx : Context α) (p₁ p₂ : Poly)
|
||||
@@ -854,12 +854,12 @@ theorem Poly.denote_combineC {α c} [CommRing α] [IsCharP α c] (ctx : Context
|
||||
<;> simp [combineC.go, *, denote_concat, denote_addConstC, denote, intCast_add,
|
||||
cond_eq_if, add_comm, add_left_comm, add_assoc, IsCharP.intCast_emod]
|
||||
next hg _ h _ =>
|
||||
simp +zetaDelta at h; simp [*]
|
||||
simp +zetaDelta at h
|
||||
rw [← add_assoc, Mon.eq_of_grevlex hg, ← right_distrib, ← intCast_add,
|
||||
← IsCharP.intCast_emod (p := c),
|
||||
h, intCast_zero, zero_mul, zero_add]
|
||||
next hg _ h _ =>
|
||||
simp +zetaDelta at h; simp [*, denote, intCast_add, IsCharP.intCast_emod]
|
||||
simp +zetaDelta only [IsCharP.intCast_emod, intCast_add]
|
||||
rw [right_distrib, Mon.eq_of_grevlex hg, add_assoc]
|
||||
|
||||
theorem Poly.denote_mulC_go {α c} [CommRing α] [IsCharP α c] (ctx : Context α) (p₁ p₂ acc : Poly)
|
||||
@@ -873,7 +873,8 @@ theorem Poly.denote_mulC {α c} [CommRing α] [IsCharP α c] (ctx : Context α)
|
||||
|
||||
theorem Poly.denote_powC {α c} [CommRing α] [IsCharP α c] (ctx : Context α) (p : Poly) (k : Nat)
|
||||
: (powC p k c).denote ctx = p.denote ctx ^ k := by
|
||||
fun_induction powC <;> simp [powC, denote, intCast_one, pow_zero]
|
||||
fun_induction powC
|
||||
next => simp [denote, intCast_one, pow_zero]
|
||||
next => simp [pow_succ, pow_zero, one_mul]
|
||||
next => simp [denote_mulC, *, pow_succ, mul_comm]
|
||||
|
||||
|
||||
@@ -76,6 +76,12 @@ structure Config where
|
||||
/-- If `extAll` is `true`, `grind` uses any extensionality theorems available in the environment. -/
|
||||
extAll : Bool := false
|
||||
/--
|
||||
If `etaStruct` is `true`, then for each term `t : S` such that `S` is a structure,
|
||||
and is tagged with `[grind ext]`, `grind` adds the equation `t = ⟨t.1, ..., t.n⟩`
|
||||
which holds by reflexivity. Moreover, the extensionality theorem for `S` is not used.
|
||||
-/
|
||||
etaStruct : Bool := true
|
||||
/--
|
||||
If `funext` is `true`, `grind` creates new opportunities for applying function extensionality by case-splitting
|
||||
on equalities between lambda expressions.
|
||||
-/
|
||||
|
||||
@@ -621,9 +621,6 @@ This is the same as `#eval show MetaM Unit from do discard doSeq`.
|
||||
-/
|
||||
syntax (name := runMeta) "run_meta " doSeq : command
|
||||
|
||||
set_option linter.missingDocs false in
|
||||
syntax guardMsgsFilterSeverity := &"info" <|> &"warning" <|> &"error" <|> &"all"
|
||||
|
||||
/--
|
||||
`#reduce <expression>` reduces the expression `<expression>` to its normal form. This
|
||||
involves applying reduction rules until no further reduction is possible.
|
||||
@@ -640,15 +637,27 @@ of expressions.
|
||||
-/
|
||||
syntax (name := reduceCmd) "#reduce " (atomic("(" &"proofs" " := " &"true" ")"))? (atomic("(" &"types" " := " &"true" ")"))? term : command
|
||||
|
||||
set_option linter.missingDocs false in
|
||||
syntax guardMsgsFilterAction := &"check" <|> &"drop" <|> &"pass"
|
||||
|
||||
set_option linter.missingDocs false in
|
||||
syntax guardMsgsFilterSeverity := &"trace" <|> &"info" <|> &"warning" <|> &"error" <|> &"all"
|
||||
|
||||
/--
|
||||
A message filter specification for `#guard_msgs`.
|
||||
- `info`, `warning`, `error`: capture messages with the given severity level.
|
||||
- `all`: capture all messages (the default).
|
||||
- `drop info`, `drop warning`, `drop error`: drop messages with the given severity level.
|
||||
- `drop all`: drop every message.
|
||||
These filters are processed in left-to-right order.
|
||||
- `info`, `warning`, `error`: capture (non-trace) messages with the given severity level.
|
||||
- `trace`: captures trace messages
|
||||
- `all`: capture all messages.
|
||||
|
||||
The filters can be prefixed with
|
||||
- `check` (the default): capture and check the message
|
||||
- `drop`: drop the message
|
||||
- `pass`: let the message pass through
|
||||
|
||||
If no filter is specified, `check all` is assumed. Otherwise, these filters are processed in
|
||||
left-to-right order, with an implicit `pass all` at the end.
|
||||
-/
|
||||
syntax guardMsgsFilter := &"drop"? guardMsgsFilterSeverity
|
||||
syntax guardMsgsFilter := guardMsgsFilterAction ? guardMsgsFilterSeverity
|
||||
|
||||
set_option linter.missingDocs false in
|
||||
syntax guardMsgsWhitespaceArg := &"exact" <|> &"normalized" <|> &"lax"
|
||||
@@ -719,13 +728,20 @@ In general, `#guard_msgs` accepts a comma-separated list of configuration clause
|
||||
```
|
||||
#guard_msgs (configElt,*) in cmd
|
||||
```
|
||||
By default, the configuration list is `(all, whitespace := normalized, ordering := exact)`.
|
||||
By default, the configuration list is `(check all, whitespace := normalized, ordering := exact)`.
|
||||
|
||||
Message filters (processed in left-to-right order):
|
||||
- `info`, `warning`, `error`: capture messages with the given severity level.
|
||||
- `all`: capture all messages (the default).
|
||||
- `drop info`, `drop warning`, `drop error`: drop messages with the given severity level.
|
||||
- `drop all`: drop every message.
|
||||
Message filters select messages by severity:
|
||||
- `info`, `warning`, `error`: (non-trace) messages with the given severity level.
|
||||
- `trace`: trace messages
|
||||
- `all`: all messages.
|
||||
|
||||
The filters can be prefixed with the action to take:
|
||||
- `check` (the default): capture and check the message
|
||||
- `drop`: drop the message
|
||||
- `pass`: let the message pass through
|
||||
|
||||
If no filter is specified, `check all` is assumed. Otherwise, these filters are processed in
|
||||
left-to-right order, with an implicit `pass all` at the end.
|
||||
|
||||
Whitespace handling (after trimming leading and trailing whitespace):
|
||||
- `whitespace := exact` requires an exact whitespace match.
|
||||
|
||||
@@ -121,7 +121,7 @@ theorem ofNat_natAbs (a : Int) : (a.natAbs : Int) = if 0 ≤ a then a else -a :=
|
||||
rw [Int.natAbs.eq_def]
|
||||
split <;> rename_i n
|
||||
· simp only [Int.ofNat_eq_coe]
|
||||
rw [if_pos (Int.ofNat_nonneg n)]
|
||||
rw [if_pos (Int.natCast_nonneg n)]
|
||||
· simp; rfl
|
||||
|
||||
theorem natAbs_dichotomy {a : Int} : 0 ≤ a ∧ a.natAbs = a ∨ a < 0 ∧ a.natAbs = -a := by
|
||||
|
||||
@@ -10,6 +10,7 @@ import Init.System.IOError
|
||||
import Init.System.FilePath
|
||||
import Init.System.ST
|
||||
import Init.Data.Ord
|
||||
import Init.Data.String.Extra
|
||||
|
||||
open System
|
||||
|
||||
|
||||
@@ -940,8 +940,8 @@ You can use `with` to provide the variables names for each constructor.
|
||||
syntax (name := cases) "cases " elimTarget,+ (" using " term)? (inductionAlts)? : tactic
|
||||
|
||||
/--
|
||||
The `fun_induction` tactic is a convenience wrapper of the `induction` tactic when using a functional
|
||||
induction principle.
|
||||
The `fun_induction` tactic is a convenience wrapper around the `induction` tactic to use the the
|
||||
functional induction principle.
|
||||
|
||||
The tactic invocation
|
||||
```
|
||||
@@ -949,10 +949,10 @@ fun_induction f x₁ ... xₙ y₁ ... yₘ
|
||||
```
|
||||
where `f` is a function defined by non-mutual structural or well-founded recursion, is equivalent to
|
||||
```
|
||||
induction y₁, ... yₘ using f.induct x₁ ... xₙ
|
||||
induction y₁, ... yₘ using f.induct_unfolding x₁ ... xₙ
|
||||
```
|
||||
where the arguments of `f` are used as arguments to `f.induct` or targets of the induction, as
|
||||
appropriate.
|
||||
where the arguments of `f` are used as arguments to `f.induct_unfolding` or targets of the
|
||||
induction, as appropriate.
|
||||
|
||||
The form
|
||||
```
|
||||
@@ -964,6 +964,10 @@ become targets are free variables.
|
||||
|
||||
The forms `fun_induction f x y generalizing z₁ ... zₙ` and
|
||||
`fun_induction f x y with | case1 => tac₁ | case2 x' ih => tac₂` work like with `induction.`
|
||||
|
||||
Under `set_option tactic.fun_induction.unfolding true` (the default), `fun_induction` uses the
|
||||
`f.induct_unfolding` induction principle, which will try to automatically unfold the call to `f` in
|
||||
the goal. With `set_option tactic.fun_induction.unfolding false`, it uses `f.induct` instead.
|
||||
-/
|
||||
syntax (name := funInduction) "fun_induction " term
|
||||
(" generalizing" (ppSpace colGt term:max)+)? (inductionAlts)? : tactic
|
||||
@@ -978,10 +982,10 @@ fun_cases f x ... y ...`
|
||||
```
|
||||
is equivalent to
|
||||
```
|
||||
cases y, ... using f.fun_cases x ...
|
||||
cases y, ... using f.fun_cases_unfolding x ...
|
||||
```
|
||||
where the arguments of `f` are used as arguments to `f.fun_cases` or targets of the case analysis, as
|
||||
appropriate.
|
||||
where the arguments of `f` are used as arguments to `f.fun_cases_unfolding` or targets of the case
|
||||
analysis, as appropriate.
|
||||
|
||||
The form
|
||||
```
|
||||
@@ -992,6 +996,10 @@ these arguments. An application of `f` is eligible if it is saturated and the ar
|
||||
become targets are free variables.
|
||||
|
||||
The form `fun_cases f x y with | case1 => tac₁ | case2 x' ih => tac₂` works like with `cases`.
|
||||
|
||||
Under `set_option tactic.fun_induction.unfolding true` (the default), `fun_induction` uses the
|
||||
`f.fun_cases_unfolding` theorem, which will try to automatically unfold the call to `f` in
|
||||
the goal. With `set_option tactic.fun_induction.unfolding false`, it uses `f.fun_cases` instead.
|
||||
-/
|
||||
syntax (name := funCases) "fun_cases " term (inductionAlts)? : tactic
|
||||
|
||||
|
||||
@@ -93,9 +93,13 @@ def addDecl (decl : Declaration) : CoreM Unit := do
|
||||
let mut exportedKind? := none
|
||||
let (name, info, kind) ← match decl with
|
||||
| .thmDecl thm =>
|
||||
if (← getEnv).header.isModule && !isSimpleRflProof thm.value &&
|
||||
-- TODO: this is horrible...
|
||||
!looksLikeRelevantTheoremProofType thm.type then
|
||||
let exportProof := !(← getEnv).header.isModule ||
|
||||
-- We should preserve rfl theorems but also we should not override a decision to hide by the
|
||||
-- MutualDef elaborator via `withoutExporting`
|
||||
(← getEnv).isExporting && isSimpleRflProof thm.value ||
|
||||
-- TODO: this is horrible...
|
||||
looksLikeRelevantTheoremProofType thm.type
|
||||
if !exportProof then
|
||||
exportedInfo? := some <| .axiomInfo { thm with isUnsafe := false }
|
||||
exportedKind? := some .axiom
|
||||
pure (thm.name, .thmInfo thm, .thm)
|
||||
|
||||
@@ -22,6 +22,7 @@ import Lean.Compiler.IR.ElimDeadBranches
|
||||
import Lean.Compiler.IR.EmitC
|
||||
import Lean.Compiler.IR.CtorLayout
|
||||
import Lean.Compiler.IR.Sorry
|
||||
import Lean.Compiler.IR.ToIR
|
||||
|
||||
-- The following imports are not required by the compiler. They are here to ensure that there
|
||||
-- are no orphaned modules.
|
||||
|
||||
412
src/Lean/Compiler/IR/ToIR.lean
Normal file
412
src/Lean/Compiler/IR/ToIR.lean
Normal file
@@ -0,0 +1,412 @@
|
||||
/-
|
||||
Copyright (c) 2024 Lean FRO, LLC. All rights reserved.
|
||||
Released under Apache 2.0 license as described in the file LICENSE.
|
||||
Authors: Cameron Zwarich
|
||||
-/
|
||||
prelude
|
||||
import Lean.Compiler.LCNF.Basic
|
||||
import Lean.Compiler.LCNF.CompilerM
|
||||
import Lean.Compiler.LCNF.PhaseExt
|
||||
import Lean.Compiler.IR.Basic
|
||||
import Lean.Compiler.IR.CompilerM
|
||||
import Lean.Compiler.IR.CtorLayout
|
||||
import Lean.CoreM
|
||||
import Lean.Environment
|
||||
|
||||
namespace Lean.IR
|
||||
|
||||
open Lean.Compiler (LCNF.AltCore LCNF.Arg LCNF.Code LCNF.Decl LCNF.DeclValue LCNF.LCtx LCNF.LetDecl
|
||||
LCNF.LetValue LCNF.LitValue LCNF.Param LCNF.getMonoDecl?)
|
||||
|
||||
namespace ToIR
|
||||
|
||||
inductive FVarClassification where
|
||||
| var (id : VarId)
|
||||
| joinPoint (id : JoinPointId)
|
||||
| erased
|
||||
|
||||
structure BuilderState where
|
||||
fvars : Std.HashMap FVarId FVarClassification := {}
|
||||
nextId : Nat := 1
|
||||
|
||||
abbrev M := StateRefT BuilderState CoreM
|
||||
|
||||
def M.run (x : M α) : CoreM α := do
|
||||
x.run' {}
|
||||
|
||||
def bindVar (fvarId : FVarId) : M VarId := do
|
||||
modifyGet fun s =>
|
||||
let varId := { idx := s.nextId }
|
||||
⟨varId, { s with fvars := s.fvars.insertIfNew fvarId (.var varId),
|
||||
nextId := s.nextId + 1 }⟩
|
||||
|
||||
def bindVarToVarId (fvarId : FVarId) (varId : VarId) : M Unit := do
|
||||
modify fun s => { s with fvars := s.fvars.insertIfNew fvarId (.var varId) }
|
||||
|
||||
def newVar : M VarId := do
|
||||
modifyGet fun s =>
|
||||
let varId := { idx := s.nextId }
|
||||
⟨varId, { s with nextId := s.nextId + 1 }⟩
|
||||
|
||||
def bindJoinPoint (fvarId : FVarId) : M JoinPointId := do
|
||||
modifyGet fun s =>
|
||||
let joinPointId := { idx := s.nextId }
|
||||
⟨joinPointId, { s with fvars := s.fvars.insertIfNew fvarId (.joinPoint joinPointId),
|
||||
nextId := s.nextId + 1 }⟩
|
||||
|
||||
def bindErased (fvarId : FVarId) : M Unit := do
|
||||
modify fun s => { s with fvars := s.fvars.insertIfNew fvarId .erased }
|
||||
|
||||
def findDecl (n : Name) : M (Option Decl) :=
|
||||
return findEnvDecl (← Lean.getEnv) n
|
||||
|
||||
def addDecl (d : Decl) : M Unit :=
|
||||
Lean.modifyEnv fun env => declMapExt.addEntry (env.addExtraName d.name) d
|
||||
|
||||
def lowerLitValue (v : LCNF.LitValue) : LitVal :=
|
||||
match v with
|
||||
| .natVal n => .num n
|
||||
| .strVal s => .str s
|
||||
|
||||
-- TODO: This should be cached.
|
||||
def lowerEnumToScalarType (name : Name) : M (Option IRType) := do
|
||||
let env ← Lean.getEnv
|
||||
let some (.inductInfo inductiveVal) := env.find? name | return none
|
||||
let ctorNames := inductiveVal.ctors
|
||||
let numCtors := ctorNames.length
|
||||
for ctorName in ctorNames do
|
||||
let some (.ctorInfo ctorVal) := env.find? ctorName | panic! "expected valid constructor name"
|
||||
if ctorVal.type.isForall then return none
|
||||
return if numCtors == 1 then
|
||||
none
|
||||
else if numCtors < Nat.pow 2 8 then
|
||||
some .uint8
|
||||
else if numCtors < Nat.pow 2 16 then
|
||||
some .uint16
|
||||
else if numCtors < Nat.pow 2 32 then
|
||||
some .uint32
|
||||
else
|
||||
none
|
||||
|
||||
def lowerType (e : Lean.Expr) : M IRType := do
|
||||
match e with
|
||||
| .const name .. =>
|
||||
match name with
|
||||
| ``UInt8 | ``Bool => return .uint8
|
||||
| ``UInt16 => return .uint16
|
||||
| ``UInt32 => return .uint32
|
||||
| ``UInt64 => return .uint64
|
||||
| ``USize => return .usize
|
||||
| ``Float => return .float
|
||||
| ``Float32 => return .float32
|
||||
| ``lcErased => return .irrelevant
|
||||
| _ =>
|
||||
if let some scalarType ← lowerEnumToScalarType name then
|
||||
return scalarType
|
||||
else
|
||||
return .object
|
||||
| .app f _ =>
|
||||
if let .const name _ := f.headBeta then
|
||||
if let some scalarType ← lowerEnumToScalarType name then
|
||||
return scalarType
|
||||
else
|
||||
return .object
|
||||
else
|
||||
return .object
|
||||
| .forallE .. => return .object
|
||||
| _ => panic! "invalid type"
|
||||
|
||||
-- TODO: This should be cached.
|
||||
def getCtorInfo (name : Name) : M (CtorInfo × (Array CtorFieldInfo)) := do
|
||||
match getCtorLayout (← Lean.getEnv) name with
|
||||
| .ok ctorLayout =>
|
||||
return ⟨{
|
||||
name,
|
||||
cidx := ctorLayout.cidx,
|
||||
size := ctorLayout.numObjs,
|
||||
usize := ctorLayout.numUSize,
|
||||
ssize := ctorLayout.scalarSize
|
||||
}, ctorLayout.fieldInfo.toArray⟩
|
||||
| .error .. => panic! "unrecognized constructor"
|
||||
|
||||
def lowerArg (a : LCNF.Arg) : M Arg := do
|
||||
match a with
|
||||
| .fvar fvarId =>
|
||||
match (← get).fvars[fvarId]? with
|
||||
| some (.var varId) => return .var varId
|
||||
| some .erased => return .irrelevant
|
||||
| some (.joinPoint ..) | none => panic! "unexpected value"
|
||||
| .erased | .type .. => return .irrelevant
|
||||
|
||||
inductive TranslatedProj where
|
||||
| expr (e : Expr)
|
||||
| erased
|
||||
deriving Inhabited
|
||||
|
||||
def lowerProj (base : VarId) (ctorInfo : CtorInfo) (field : CtorFieldInfo)
|
||||
: TranslatedProj × IRType :=
|
||||
match field with
|
||||
| .object i => ⟨.expr (.proj i base), .object⟩
|
||||
| .usize i => ⟨.expr (.uproj i base), .usize⟩
|
||||
| .scalar _ offset irType => ⟨.expr (.sproj (ctorInfo.size + ctorInfo.usize) offset base), irType⟩
|
||||
| .irrelevant => ⟨.erased, .irrelevant⟩
|
||||
|
||||
def lowerParam (p : LCNF.Param) : M Param := do
|
||||
let x ← bindVar p.fvarId
|
||||
let ty ← lowerType p.type
|
||||
return { x, borrow := p.borrow, ty }
|
||||
|
||||
mutual
|
||||
partial def lowerCode (c : LCNF.Code) : M FnBody := do
|
||||
match c with
|
||||
| .let decl k => lowerLet decl k
|
||||
| .jp decl k =>
|
||||
let joinPoint ← bindJoinPoint decl.fvarId
|
||||
let params ← decl.params.mapM lowerParam
|
||||
let body ← lowerCode decl.value
|
||||
return .jdecl joinPoint params body (← lowerCode k)
|
||||
| .jmp fvarId args =>
|
||||
match (← get).fvars[fvarId]? with
|
||||
| some (.joinPoint joinPointId) =>
|
||||
return .jmp joinPointId (← args.mapM lowerArg)
|
||||
| some (.var ..) | some .erased | none => panic! "unexpected value"
|
||||
| .cases cases =>
|
||||
match (← get).fvars[cases.discr]? with
|
||||
| some (.var varId) =>
|
||||
return .case cases.typeName
|
||||
varId
|
||||
(← lowerType cases.resultType)
|
||||
(← cases.alts.mapM (lowerAlt varId))
|
||||
| some (.joinPoint ..) | some .erased | none => panic! "unexpected value"
|
||||
| .return fvarId =>
|
||||
let arg := match (← get).fvars[fvarId]? with
|
||||
| some (.var varId) => .var varId
|
||||
| some .erased => .irrelevant
|
||||
| some (.joinPoint ..) | none => panic! "unexpected value"
|
||||
return .ret arg
|
||||
| .unreach .. => return .unreachable
|
||||
| .fun .. => panic! "all local functions should be λ-lifted"
|
||||
|
||||
partial def lowerLet (decl : LCNF.LetDecl) (k : LCNF.Code) : M FnBody := do
|
||||
-- temporary fix: the old compiler inlines these too much as regular `let`s
|
||||
let rec mkVar (v : VarId) : M FnBody := do
|
||||
bindVarToVarId decl.fvarId v
|
||||
lowerCode k
|
||||
let rec mkExpr (e : Expr) : M FnBody := do
|
||||
let var ← bindVar decl.fvarId
|
||||
let type ← match e with
|
||||
| .ctor .. | .pap .. | .proj .. => pure <| .object
|
||||
| _ => lowerType decl.type
|
||||
return .vdecl var type e (← lowerCode k)
|
||||
let rec mkErased (_ : Unit) : M FnBody := do
|
||||
bindErased decl.fvarId
|
||||
lowerCode k
|
||||
let rec mkPartialApp (e : Expr) (restArgs : Array Arg) : M FnBody := do
|
||||
let var ← bindVar decl.fvarId
|
||||
let tmpVar ← newVar
|
||||
let type ← match e with
|
||||
| .ctor .. | .pap .. | .proj .. => pure <| .object
|
||||
| _ => lowerType decl.type
|
||||
return .vdecl tmpVar .object e (.vdecl var type (.ap tmpVar restArgs) (← lowerCode k))
|
||||
let rec tryIrDecl? (name : Name) (args : Array Arg) : M (Option FnBody) := do
|
||||
if let some decl ← LCNF.getMonoDecl? name then
|
||||
let numArgs := args.size
|
||||
let numParams := decl.params.size
|
||||
if numArgs < numParams then
|
||||
return some (← mkExpr (.pap name args))
|
||||
else if numArgs == numParams then
|
||||
return some (← mkExpr (.fap name args))
|
||||
else
|
||||
let firstArgs := args.extract 0 numParams
|
||||
let restArgs := args.extract numParams numArgs
|
||||
return some (← mkPartialApp (.fap name firstArgs) restArgs)
|
||||
else
|
||||
return none
|
||||
|
||||
match decl.value with
|
||||
| .value litValue =>
|
||||
mkExpr (.lit (lowerLitValue litValue))
|
||||
| .proj typeName i fvarId =>
|
||||
match (← get).fvars[fvarId]? with
|
||||
| some (.var varId) =>
|
||||
-- TODO: have better pattern matching here
|
||||
let some (.inductInfo { ctors, .. }) := (← Lean.getEnv).find? typeName
|
||||
| panic! "projection of non-inductive type"
|
||||
let ctorName := ctors[0]!
|
||||
let ⟨ctorInfo, fields⟩ ← getCtorInfo ctorName
|
||||
let ⟨result, type⟩ := lowerProj varId ctorInfo fields[i]!
|
||||
match result with
|
||||
| .expr e =>
|
||||
let var ← bindVar decl.fvarId
|
||||
return .vdecl var type e (← lowerCode k)
|
||||
| .erased =>
|
||||
bindErased decl.fvarId
|
||||
lowerCode k
|
||||
| some .erased =>
|
||||
bindErased decl.fvarId
|
||||
lowerCode k
|
||||
| some (.joinPoint ..) | none => panic! "unexpected value"
|
||||
| .const ``Nat.succ _ args =>
|
||||
let irArgs ← args.mapM lowerArg
|
||||
let var ← bindVar decl.fvarId
|
||||
let tmpVar ← newVar
|
||||
let k := (.vdecl var .object (.fap ``Nat.add #[irArgs[0]!, (.var tmpVar)]) (← lowerCode k))
|
||||
return .vdecl tmpVar .object (.lit (.num 1)) k
|
||||
| .const name _ args =>
|
||||
let irArgs ← args.mapM lowerArg
|
||||
if let some code ← tryIrDecl? name irArgs then
|
||||
return code
|
||||
else
|
||||
let env ← Lean.getEnv
|
||||
match env.find? name with
|
||||
| some (.ctorInfo ctorVal) =>
|
||||
if isExtern env name then
|
||||
if let some code ← tryIrDecl? name irArgs then
|
||||
return code
|
||||
else
|
||||
mkExpr (.fap name irArgs)
|
||||
else
|
||||
let ⟨ctorInfo, fields⟩ ← getCtorInfo name
|
||||
let args := args.extract (start := ctorVal.numParams)
|
||||
let objArgs : Array Arg ← do
|
||||
let mut result : Array Arg := #[]
|
||||
for i in [0:fields.size] do
|
||||
match args[i]! with
|
||||
| .fvar fvarId =>
|
||||
if let some (.var varId) := (← get).fvars[fvarId]? then
|
||||
if fields[i]! matches .object .. then
|
||||
result := result.push (.var varId)
|
||||
| .type _ | .erased =>
|
||||
if fields[i]! matches .object .. then
|
||||
result := result.push .irrelevant
|
||||
pure result
|
||||
let objVar ← bindVar decl.fvarId
|
||||
let rec lowerNonObjectFields (_ : Unit) : M FnBody :=
|
||||
let rec loop (usizeCount : Nat) (i : Nat) : M FnBody := do
|
||||
match args[i]? with
|
||||
| some (.fvar fvarId) =>
|
||||
match (← get).fvars[fvarId]? with
|
||||
| some (.var varId) =>
|
||||
match fields[i]! with
|
||||
| .usize .. =>
|
||||
let k ← loop (usizeCount + 1) (i + 1)
|
||||
return .uset objVar (ctorInfo.size + usizeCount) varId k
|
||||
| .scalar _ offset argType =>
|
||||
let k ← loop usizeCount (i + 1)
|
||||
return .sset objVar (ctorInfo.size + ctorInfo.usize) offset varId argType k
|
||||
| .object .. | .irrelevant => loop usizeCount (i + 1)
|
||||
| _ => loop usizeCount (i + 1)
|
||||
| some (.type _) | some .erased => loop usizeCount (i + 1)
|
||||
| none => lowerCode k
|
||||
loop 0 0
|
||||
return .vdecl objVar .object (.ctor ctorInfo objArgs) (← lowerNonObjectFields ())
|
||||
| some (.axiomInfo ..) =>
|
||||
if name == ``Quot.lcInv then
|
||||
match irArgs[2]! with
|
||||
| .var varId => mkVar varId
|
||||
| .irrelevant => mkErased ()
|
||||
else if name == ``lcUnreachable then
|
||||
return .unreachable
|
||||
else if let some irDecl ← findDecl name then
|
||||
let numArgs := irArgs.size
|
||||
let numParams := irDecl.params.size
|
||||
if numArgs < numParams then
|
||||
mkExpr (.pap name irArgs)
|
||||
else if numArgs == numParams then
|
||||
mkExpr (.fap name irArgs)
|
||||
else
|
||||
let firstArgs := irArgs.extract 0 numParams
|
||||
let restArgs := irArgs.extract numParams irArgs.size
|
||||
mkPartialApp (.fap name firstArgs) restArgs
|
||||
else
|
||||
throwError f!"axiom '{name}' not supported by code generator; consider marking definition as 'noncomputable'"
|
||||
| some (.quotInfo ..) =>
|
||||
if name == ``Quot.mk then
|
||||
match irArgs[2]! with
|
||||
| .var varId => mkVar varId
|
||||
| .irrelevant => mkErased ()
|
||||
else
|
||||
throwError f!"quot {name} unsupported by code generator"
|
||||
| some (.defnInfo ..) | some (.opaqueInfo ..) =>
|
||||
if let some code ← tryIrDecl? name irArgs then
|
||||
return code
|
||||
else
|
||||
mkExpr (.fap name irArgs)
|
||||
| some (.recInfo ..) =>
|
||||
throwError f!"code generator does not support recursor '{name}' yet, consider using 'match ... with' and/or structural recursion"
|
||||
| some (.inductInfo ..) => panic! "induct unsupported by code generator"
|
||||
| some (.thmInfo ..) => panic! "thm unsupported by code generator"
|
||||
| none => panic! "reference to unbound name"
|
||||
| .fvar fvarId args =>
|
||||
match (← get).fvars[fvarId]? with
|
||||
| some (.var id) =>
|
||||
let irArgs ← args.mapM lowerArg
|
||||
mkExpr (.ap id irArgs)
|
||||
| some .erased => mkErased ()
|
||||
| some (.joinPoint ..) | none => panic! "unexpected value"
|
||||
| .erased => mkErased ()
|
||||
|
||||
partial def lowerAlt (discr : VarId) (a : LCNF.AltCore LCNF.Code) : M (AltCore FnBody) := do
|
||||
match a with
|
||||
| .alt ctorName params code =>
|
||||
let ⟨ctorInfo, fields⟩ ← getCtorInfo ctorName
|
||||
let lowerParams (params : Array LCNF.Param) (fields : Array CtorFieldInfo) : M FnBody := do
|
||||
let rec loop (i : Nat) : M FnBody := do
|
||||
match params[i]?, fields[i]? with
|
||||
| some param, some field =>
|
||||
let ⟨result, type⟩ := lowerProj discr ctorInfo field
|
||||
match result with
|
||||
| .expr e =>
|
||||
return .vdecl (← bindVar param.fvarId)
|
||||
type
|
||||
e
|
||||
(← loop (i + 1))
|
||||
| .erased =>
|
||||
bindErased param.fvarId
|
||||
loop (i + 1)
|
||||
| none, none => lowerCode code
|
||||
| _, _ => panic! "mismatched fields and params"
|
||||
loop 0
|
||||
let body ← lowerParams params fields
|
||||
return .ctor ctorInfo body
|
||||
| .default code =>
|
||||
return .default (← lowerCode code)
|
||||
end
|
||||
|
||||
def lowerResultType (type : Lean.Expr) (arity : Nat) : M IRType :=
|
||||
lowerType (resultTypeForArity type arity)
|
||||
where resultTypeForArity (type : Lean.Expr) (arity : Nat) : Lean.Expr :=
|
||||
if arity == 0 then
|
||||
type
|
||||
else
|
||||
match type with
|
||||
| .forallE _ _ b _ => resultTypeForArity b (arity - 1)
|
||||
| .const ``lcErased _ => mkConst ``lcErased
|
||||
| _ => panic! "invalid arity"
|
||||
|
||||
def lowerDecl (d : LCNF.Decl) : M (Option Decl) := do
|
||||
let params ← d.params.mapM lowerParam
|
||||
let resultType ← lowerResultType d.type d.params.size
|
||||
match d.value with
|
||||
| .code code =>
|
||||
let body ← lowerCode code
|
||||
pure <| some <| .fdecl d.name params resultType body {}
|
||||
| .extern externAttrData =>
|
||||
if externAttrData.entries.isEmpty then
|
||||
-- TODO: This matches the behavior of the old compiler, but we should
|
||||
-- find a better way to handle this.
|
||||
addDecl (mkDummyExternDecl d.name params resultType)
|
||||
pure <| none
|
||||
else
|
||||
pure <| some <| .extern d.name params resultType externAttrData
|
||||
|
||||
end ToIR
|
||||
|
||||
def toIR (decls: Array LCNF.Decl) : CoreM (Array Decl) := do
|
||||
let mut irDecls := #[]
|
||||
for decl in decls do
|
||||
if let some irDecl ← ToIR.lowerDecl decl |>.run then
|
||||
irDecls := irDecls.push irDecl
|
||||
return irDecls
|
||||
|
||||
end Lean.IR
|
||||
@@ -29,6 +29,10 @@ structure Context where
|
||||
Remark: the lambda lifting pass abstracts all `let`/`fun`-declarations.
|
||||
-/
|
||||
abstract : FVarId → Bool
|
||||
/--
|
||||
Indicates whether we are processing terms beneath a binder.
|
||||
-/
|
||||
isUnderBinder : Bool
|
||||
|
||||
/--
|
||||
State for the `ClosureM` monad.
|
||||
@@ -93,7 +97,11 @@ mutual
|
||||
-/
|
||||
partial def collectCode (c : Code) : ClosureM Unit := do
|
||||
match c with
|
||||
| .let decl k => collectType decl.type; collectLetValue decl.value; collectCode k
|
||||
| .let decl k =>
|
||||
collectType decl.type
|
||||
withReader (fun ctx => { ctx with isUnderBinder := ctx.isUnderBinder || decl.type.isForall })
|
||||
do collectLetValue decl.value
|
||||
collectCode k
|
||||
| .fun decl k | .jp decl k => collectFunDecl decl; collectCode k
|
||||
| .cases c =>
|
||||
collectType c.resultType
|
||||
@@ -110,7 +118,8 @@ mutual
|
||||
partial def collectFunDecl (decl : FunDecl) : ClosureM Unit := do
|
||||
collectType decl.type
|
||||
collectParams decl.params
|
||||
collectCode decl.value
|
||||
withReader (fun ctx => { ctx with isUnderBinder := true }) do
|
||||
collectCode decl.value
|
||||
|
||||
/--
|
||||
Process the given free variable.
|
||||
@@ -119,10 +128,11 @@ mutual
|
||||
partial def collectFVar (fvarId : FVarId) : ClosureM Unit := do
|
||||
unless (← get).visited.contains fvarId do
|
||||
markVisited fvarId
|
||||
if (← read).inScope fvarId then
|
||||
let ctx ← read
|
||||
if ctx.inScope fvarId then
|
||||
/- We only collect the variables in the scope of the function application being specialized. -/
|
||||
if let some funDecl ← findFunDecl? fvarId then
|
||||
if (← read).abstract funDecl.fvarId then
|
||||
if ctx.isUnderBinder || ctx.abstract funDecl.fvarId then
|
||||
modify fun s => { s with params := s.params.push <| { funDecl with borrow := false } }
|
||||
else
|
||||
collectFunDecl funDecl
|
||||
@@ -132,7 +142,7 @@ mutual
|
||||
modify fun s => { s with params := s.params.push param }
|
||||
else if let some letDecl ← findLetDecl? fvarId then
|
||||
collectType letDecl.type
|
||||
if (← read).abstract letDecl.fvarId then
|
||||
if ctx.isUnderBinder || ctx.abstract letDecl.fvarId then
|
||||
modify fun s => { s with params := s.params.push <| { letDecl with borrow := false } }
|
||||
else
|
||||
collectLetValue letDecl.value
|
||||
@@ -147,9 +157,16 @@ mutual
|
||||
end
|
||||
|
||||
def run (x : ClosureM α) (inScope : FVarId → Bool) (abstract : FVarId → Bool := fun _ => true) : CompilerM (α × Array Param × Array CodeDecl) := do
|
||||
let (a, s) ← x { inScope, abstract } |>.run {}
|
||||
return (a, s.params, s.decls)
|
||||
let (a, s) ← x { inScope, abstract, isUnderBinder := false } |>.run {}
|
||||
-- If we've abstracted an fvar into a param, exclude its definition. Note that this still allows
|
||||
-- for other decls the removed decl depends upon to be included, but they will be removed later
|
||||
-- for having no users.
|
||||
let mut paramFVars : FVarIdSet := {}
|
||||
for param in s.params do
|
||||
paramFVars := paramFVars.insert param.fvarId
|
||||
let filteredDecls := s.decls.filter fun decl => !(paramFVars.contains decl.fvarId)
|
||||
return (a, s.params, filteredDecls)
|
||||
|
||||
end Closure
|
||||
|
||||
end Lean.Compiler.LCNF
|
||||
end Lean.Compiler.LCNF
|
||||
|
||||
@@ -6,6 +6,10 @@ Authors: Leonardo de Moura
|
||||
prelude
|
||||
import Lean.Compiler.Options
|
||||
import Lean.Compiler.ExternAttr
|
||||
import Lean.Compiler.IR
|
||||
import Lean.Compiler.IR.Basic
|
||||
import Lean.Compiler.IR.Checker
|
||||
import Lean.Compiler.IR.ToIR
|
||||
import Lean.Compiler.LCNF.PassManager
|
||||
import Lean.Compiler.LCNF.Passes
|
||||
import Lean.Compiler.LCNF.PrettyPrinter
|
||||
@@ -62,7 +66,7 @@ def checkpoint (stepName : Name) (decls : Array Decl) : CompilerM Unit := do
|
||||
|
||||
namespace PassManager
|
||||
|
||||
def run (declNames : Array Name) : CompilerM (Array Decl) := withAtLeastMaxRecDepth 8192 do
|
||||
def run (declNames : Array Name) : CompilerM (Array IR.Decl) := withAtLeastMaxRecDepth 8192 do
|
||||
/-
|
||||
Note: we need to increase the recursion depth because we currently do to save phase1
|
||||
declarations in .olean files. Then, we have to recursively compile all dependencies,
|
||||
@@ -83,11 +87,25 @@ def run (declNames : Array Name) : CompilerM (Array Decl) := withAtLeastMaxRecDe
|
||||
-- We display the declaration saved in the environment because the names have been normalized
|
||||
let some decl' ← getDeclAt? decl.name .mono | unreachable!
|
||||
Lean.addTrace `Compiler.result m!"size: {decl.size}\n{← ppDecl' decl'}"
|
||||
return decls
|
||||
let opts ← getOptions
|
||||
-- If the new compiler is disabled, then all of the saved IR was built with the old compiler,
|
||||
-- which causes IR type mismatches with IR generated by the new compiler.
|
||||
if !(compiler.enableNew.get opts) then
|
||||
return #[]
|
||||
let irDecls ← IR.toIR decls
|
||||
let env ← getEnv
|
||||
let ⟨log, res⟩ := IR.compile env opts irDecls
|
||||
for msg in log do
|
||||
addTrace `Compiler.IR m!"{msg}"
|
||||
match res with
|
||||
| .ok env =>
|
||||
setEnv env
|
||||
return irDecls
|
||||
| .error s => throwError s
|
||||
|
||||
end PassManager
|
||||
|
||||
def compile (declNames : Array Name) : CoreM (Array Decl) :=
|
||||
def compile (declNames : Array Name) : CoreM (Array IR.Decl) :=
|
||||
CompilerM.run <| PassManager.run declNames
|
||||
|
||||
def showDecl (phase : Phase) (declName : Name) : CoreM Format := do
|
||||
|
||||
@@ -77,7 +77,7 @@ def getCtorArity? (declName : Name) : CoreM (Option Nat) := do
|
||||
/--
|
||||
List of types that have builtin runtime support
|
||||
-/
|
||||
def builtinRuntimeTypes : List Name := [
|
||||
def builtinRuntimeTypes : Array Name := #[
|
||||
``String,
|
||||
``UInt8, ``UInt16, ``UInt32, ``UInt64, ``USize,
|
||||
``Float, ``Float32,
|
||||
|
||||
@@ -612,20 +612,21 @@ where doCompile := do
|
||||
return
|
||||
let opts ← getOptions
|
||||
if compiler.enableNew.get opts then
|
||||
compileDeclsNew decls
|
||||
|
||||
let res ← withTraceNode `compiler (fun _ => return m!"compiling old: {decls}") do
|
||||
return compileDeclsOld (← getEnv) opts decls
|
||||
match res with
|
||||
| Except.ok env => setEnv env
|
||||
| Except.error (.other msg) =>
|
||||
if logErrors then
|
||||
if let some decl := ref? then
|
||||
checkUnsupported decl -- Generate nicer error message for unsupported recursors and axioms
|
||||
throwError msg
|
||||
| Except.error ex =>
|
||||
if logErrors then
|
||||
throwKernelException ex
|
||||
try compileDeclsNew decls catch e =>
|
||||
if logErrors then throw e else return ()
|
||||
else
|
||||
let res ← withTraceNode `compiler (fun _ => return m!"compiling old: {decls}") do
|
||||
return compileDeclsOld (← getEnv) opts decls
|
||||
match res with
|
||||
| Except.ok env => setEnv env
|
||||
| Except.error (.other msg) =>
|
||||
if logErrors then
|
||||
if let some decl := ref? then
|
||||
checkUnsupported decl -- Generate nicer error message for unsupported recursors and axioms
|
||||
throwError msg
|
||||
| Except.error ex =>
|
||||
if logErrors then
|
||||
throwKernelException ex
|
||||
|
||||
def compileDecl (decl : Declaration) (logErrors := true) : CoreM Unit := do
|
||||
compileDecls (Compiler.getDeclNamesForCodeGen decl) decl logErrors
|
||||
|
||||
@@ -47,54 +47,97 @@ instance : ToJson String := ⟨fun s => s⟩
|
||||
instance : FromJson System.FilePath := ⟨fun j => System.FilePath.mk <$> Json.getStr? j⟩
|
||||
instance : ToJson System.FilePath := ⟨fun p => p.toString⟩
|
||||
|
||||
instance [FromJson α] : FromJson (Array α) where
|
||||
fromJson?
|
||||
| Json.arr a => a.mapM fromJson?
|
||||
| j => throw s!"expected JSON array, got '{j}'"
|
||||
protected def _root_.Array.fromJson? [FromJson α] : Json → Except String (Array α)
|
||||
| Json.arr a => a.mapM fromJson?
|
||||
| j => throw s!"expected JSON array, got '{j}'"
|
||||
|
||||
instance [ToJson α] : ToJson (Array α) :=
|
||||
⟨fun a => Json.arr (a.map toJson)⟩
|
||||
instance [FromJson α] : FromJson (Array α) where
|
||||
fromJson? := Array.fromJson?
|
||||
|
||||
protected def _root_.Array.toJson [ToJson α] (a : Array α) : Json :=
|
||||
Json.arr (a.map toJson)
|
||||
|
||||
instance [ToJson α] : ToJson (Array α) where
|
||||
toJson := Array.toJson
|
||||
|
||||
protected def _root_.List.fromJson? [FromJson α] (j : Json) : Except String (List α) :=
|
||||
(fromJson? j (α := Array α)).map Array.toList
|
||||
|
||||
instance [FromJson α] : FromJson (List α) where
|
||||
fromJson? j := (fromJson? j (α := Array α)).map Array.toList
|
||||
fromJson? := List.fromJson?
|
||||
|
||||
protected def _root_.List.toJson [ToJson α] (a : List α) : Json :=
|
||||
toJson a.toArray
|
||||
|
||||
instance [ToJson α] : ToJson (List α) where
|
||||
toJson xs := toJson xs.toArray
|
||||
toJson := List.toJson
|
||||
|
||||
protected def _root_.Option.fromJson? [FromJson α] : Json → Except String (Option α)
|
||||
| Json.null => Except.ok none
|
||||
| j => some <$> fromJson? j
|
||||
|
||||
instance [FromJson α] : FromJson (Option α) where
|
||||
fromJson?
|
||||
| Json.null => Except.ok none
|
||||
| j => some <$> fromJson? j
|
||||
fromJson? := Option.fromJson?
|
||||
|
||||
instance [ToJson α] : ToJson (Option α) :=
|
||||
⟨fun
|
||||
| none => Json.null
|
||||
| some a => toJson a⟩
|
||||
protected def _root_.Option.toJson [ToJson α] : Option α → Json
|
||||
| none => Json.null
|
||||
| some a => toJson a
|
||||
|
||||
instance [ToJson α] : ToJson (Option α) where
|
||||
toJson := Option.toJson
|
||||
|
||||
protected def _root_.Prod.fromJson? {α : Type u} {β : Type v} [FromJson α] [FromJson β] : Json → Except String (α × β)
|
||||
| Json.arr #[ja, jb] => do
|
||||
let ⟨a⟩ : ULift.{v} α := ← (fromJson? ja).map ULift.up
|
||||
let ⟨b⟩ : ULift.{u} β := ← (fromJson? jb).map ULift.up
|
||||
return (a, b)
|
||||
| j => throw s!"expected pair, got '{j}'"
|
||||
|
||||
instance {α : Type u} {β : Type v} [FromJson α] [FromJson β] : FromJson (α × β) where
|
||||
fromJson?
|
||||
| Json.arr #[ja, jb] => do
|
||||
let ⟨a⟩ : ULift.{v} α := ← (fromJson? ja).map ULift.up
|
||||
let ⟨b⟩ : ULift.{u} β := ← (fromJson? jb).map ULift.up
|
||||
return (a, b)
|
||||
| j => throw s!"expected pair, got '{j}'"
|
||||
fromJson? := Prod.fromJson?
|
||||
|
||||
protected def _root_.Prod.toJson [ToJson α] [ToJson β] : α × β → Json
|
||||
| (a, b) => Json.arr #[toJson a, toJson b]
|
||||
|
||||
instance [ToJson α] [ToJson β] : ToJson (α × β) where
|
||||
toJson := fun (a, b) => Json.arr #[toJson a, toJson b]
|
||||
toJson := Prod.toJson
|
||||
|
||||
protected def Name.fromJson? (j : Json) : Except String Name := do
|
||||
let s ← j.getStr?
|
||||
if s == "[anonymous]" then
|
||||
return Name.anonymous
|
||||
else
|
||||
let n := s.toName
|
||||
if n.isAnonymous then throw s!"expected a `Name`, got '{j}'"
|
||||
return n
|
||||
|
||||
instance : FromJson Name where
|
||||
fromJson? j := do
|
||||
let s ← j.getStr?
|
||||
if s == "[anonymous]" then
|
||||
return Name.anonymous
|
||||
else
|
||||
let n := s.toName
|
||||
if n.isAnonymous then throw s!"expected a `Name`, got '{j}'"
|
||||
return n
|
||||
fromJson? := Name.fromJson?
|
||||
|
||||
instance : ToJson Name where
|
||||
toJson n := toString n
|
||||
|
||||
protected def NameMap.fromJson? [FromJson α] : Json → Except String (NameMap α)
|
||||
| .obj obj => obj.foldM (init := {}) fun m k v => do
|
||||
if k == "[anonymous]" then
|
||||
return m.insert .anonymous (← fromJson? v)
|
||||
else
|
||||
let n := k.toName
|
||||
if n.isAnonymous then
|
||||
throw s!"expected a `Name`, got '{k}'"
|
||||
else
|
||||
return m.insert n (← fromJson? v)
|
||||
| j => throw s!"expected a `NameMap`, got '{j}'"
|
||||
|
||||
instance [FromJson α] : FromJson (NameMap α) where
|
||||
fromJson? := NameMap.fromJson?
|
||||
|
||||
protected def NameMap.toJson [ToJson α] (m : NameMap α) : Json :=
|
||||
Json.obj <| m.fold (fun n k v => n.insert compare k.toString (toJson v)) .leaf
|
||||
|
||||
instance [ToJson α] : ToJson (NameMap α) where
|
||||
toJson := NameMap.toJson
|
||||
|
||||
/-- Note that `USize`s and `UInt64`s are stored as strings because JavaScript
|
||||
cannot represent 64-bit numbers. -/
|
||||
def bignumFromJson? (j : Json) : Except String Nat := do
|
||||
@@ -106,58 +149,77 @@ def bignumFromJson? (j : Json) : Except String Nat := do
|
||||
def bignumToJson (n : Nat) : Json :=
|
||||
toString n
|
||||
|
||||
protected def _root_.USize.fromJson? (j : Json) : Except String USize := do
|
||||
let n ← bignumFromJson? j
|
||||
if n ≥ USize.size then
|
||||
throw "value '{j}' is too large for `USize`"
|
||||
return USize.ofNat n
|
||||
|
||||
instance : FromJson USize where
|
||||
fromJson? j := do
|
||||
let n ← bignumFromJson? j
|
||||
if n ≥ USize.size then
|
||||
throw "value '{j}' is too large for `USize`"
|
||||
return USize.ofNat n
|
||||
fromJson? := USize.fromJson?
|
||||
|
||||
instance : ToJson USize where
|
||||
toJson v := bignumToJson (USize.toNat v)
|
||||
|
||||
protected def _root_.UInt64.fromJson? (j : Json) : Except String UInt64 := do
|
||||
let n ← bignumFromJson? j
|
||||
if n ≥ UInt64.size then
|
||||
throw "value '{j}' is too large for `UInt64`"
|
||||
return UInt64.ofNat n
|
||||
|
||||
instance : FromJson UInt64 where
|
||||
fromJson? j := do
|
||||
let n ← bignumFromJson? j
|
||||
if n ≥ UInt64.size then
|
||||
throw "value '{j}' is too large for `UInt64`"
|
||||
return UInt64.ofNat n
|
||||
fromJson? := UInt64.fromJson?
|
||||
|
||||
instance : ToJson UInt64 where
|
||||
toJson v := bignumToJson (UInt64.toNat v)
|
||||
|
||||
protected def _root_.Float.toJson (x : Float) : Json :=
|
||||
match JsonNumber.fromFloat? x with
|
||||
| Sum.inl e => Json.str e
|
||||
| Sum.inr n => Json.num n
|
||||
|
||||
instance : ToJson Float where
|
||||
toJson x :=
|
||||
match JsonNumber.fromFloat? x with
|
||||
| Sum.inl e => Json.str e
|
||||
| Sum.inr n => Json.num n
|
||||
toJson := Float.toJson
|
||||
|
||||
protected def _root_.Float.fromJson? : Json → Except String Float
|
||||
| (Json.str "Infinity") => Except.ok (1.0 / 0.0)
|
||||
| (Json.str "-Infinity") => Except.ok (-1.0 / 0.0)
|
||||
| (Json.str "NaN") => Except.ok (0.0 / 0.0)
|
||||
| (Json.num jn) => Except.ok jn.toFloat
|
||||
| _ => Except.error "Expected a number or a string 'Infinity', '-Infinity', 'NaN'."
|
||||
|
||||
instance : FromJson Float where
|
||||
fromJson? := fun
|
||||
| (Json.str "Infinity") => Except.ok (1.0 / 0.0)
|
||||
| (Json.str "-Infinity") => Except.ok (-1.0 / 0.0)
|
||||
| (Json.str "NaN") => Except.ok (0.0 / 0.0)
|
||||
| (Json.num jn) => Except.ok jn.toFloat
|
||||
| _ => Except.error "Expected a number or a string 'Infinity', '-Infinity', 'NaN'."
|
||||
fromJson? := Float.fromJson?
|
||||
|
||||
protected def RBMap.toJson [ToJson α] (m : RBMap String α cmp) : Json :=
|
||||
Json.obj <| RBNode.map (fun _ => toJson) <| m.val
|
||||
|
||||
instance [ToJson α] : ToJson (RBMap String α cmp) where
|
||||
toJson m := Json.obj <| RBNode.map (fun _ => toJson) <| m.val
|
||||
toJson := RBMap.toJson
|
||||
|
||||
protected def RBMap.fromJson? [FromJson α] (j : Json) : Except String (RBMap String α cmp) := do
|
||||
let o ← j.getObj?
|
||||
o.foldM (fun x k v => x.insert k <$> fromJson? v) ∅
|
||||
|
||||
instance {cmp} [FromJson α] : FromJson (RBMap String α cmp) where
|
||||
fromJson? j := do
|
||||
let o ← j.getObj?
|
||||
o.foldM (fun x k v => x.insert k <$> fromJson? v) ∅
|
||||
fromJson? := RBMap.fromJson?
|
||||
|
||||
namespace Json
|
||||
|
||||
instance : FromJson Structured := ⟨fun
|
||||
| arr a => return Structured.arr a
|
||||
| obj o => return Structured.obj o
|
||||
| j => throw s!"expected structured object, got '{j}'"⟩
|
||||
protected def Structured.fromJson? : Json → Except String Structured
|
||||
| .arr a => return Structured.arr a
|
||||
| .obj o => return Structured.obj o
|
||||
| j => throw s!"expected structured object, got '{j}'"
|
||||
|
||||
instance : ToJson Structured := ⟨fun
|
||||
| Structured.arr a => arr a
|
||||
| Structured.obj o => obj o⟩
|
||||
instance : FromJson Structured where
|
||||
fromJson? := Structured.fromJson?
|
||||
|
||||
protected def Structured.toJson : Structured → Json
|
||||
| .arr a => .arr a
|
||||
| .obj o => .obj o
|
||||
|
||||
instance : ToJson Structured where
|
||||
toJson := Structured.toJson
|
||||
|
||||
def toStructured? [ToJson α] (v : α) : Except String Structured :=
|
||||
fromJson? (toJson v)
|
||||
|
||||
@@ -18,6 +18,8 @@ def NameMap (α : Type) := RBMap Name α Name.quickCmp
|
||||
namespace NameMap
|
||||
variable {α : Type}
|
||||
|
||||
instance [Repr α] : Repr (NameMap α) := inferInstanceAs (Repr (RBMap Name α Name.quickCmp))
|
||||
|
||||
instance (α : Type) : EmptyCollection (NameMap α) := ⟨mkNameMap α⟩
|
||||
|
||||
instance (α : Type) : Inhabited (NameMap α) where
|
||||
|
||||
@@ -25,25 +25,34 @@ namespace Lean.Elab.Command
|
||||
modifyEnv fun env => addMainModuleDoc env ⟨doc, range⟩
|
||||
| _ => throwErrorAt stx "unexpected module doc string{indentD stx[1]}"
|
||||
|
||||
private def addScope (isNewNamespace : Bool) (isNoncomputable : Bool) (header : String) (newNamespace : Name) : CommandElabM Unit := do
|
||||
private def addScope (isNewNamespace : Bool) (header : String) (newNamespace : Name)
|
||||
(isNoncomputable : Bool := false) (attrs : List (TSyntax ``Parser.Term.attrInstance) := []) :
|
||||
CommandElabM Unit := do
|
||||
modify fun s => { s with
|
||||
env := s.env.registerNamespace newNamespace,
|
||||
scopes := { s.scopes.head! with header := header, currNamespace := newNamespace, isNoncomputable := s.scopes.head!.isNoncomputable || isNoncomputable } :: s.scopes
|
||||
scopes := { s.scopes.head! with
|
||||
header := header, currNamespace := newNamespace
|
||||
isNoncomputable := s.scopes.head!.isNoncomputable || isNoncomputable
|
||||
attrs := s.scopes.head!.attrs ++ attrs
|
||||
} :: s.scopes
|
||||
}
|
||||
pushScope
|
||||
if isNewNamespace then
|
||||
activateScoped newNamespace
|
||||
|
||||
private def addScopes (isNewNamespace : Bool) (isNoncomputable : Bool) : Name → CommandElabM Unit
|
||||
private def addScopes (header : Name) (isNewNamespace : Bool) (isNoncomputable : Bool := false)
|
||||
(attrs : List (TSyntax ``Parser.Term.attrInstance) := []) : CommandElabM Unit :=
|
||||
go header
|
||||
where go
|
||||
| .anonymous => pure ()
|
||||
| .str p header => do
|
||||
addScopes isNewNamespace isNoncomputable p
|
||||
go p
|
||||
let currNamespace ← getCurrNamespace
|
||||
addScope isNewNamespace isNoncomputable header (if isNewNamespace then Name.mkStr currNamespace header else currNamespace)
|
||||
addScope isNewNamespace header (if isNewNamespace then Name.mkStr currNamespace header else currNamespace) isNoncomputable attrs
|
||||
| _ => throwError "invalid scope"
|
||||
|
||||
private def addNamespace (header : Name) : CommandElabM Unit :=
|
||||
addScopes (isNewNamespace := true) (isNoncomputable := false) header
|
||||
addScopes (isNewNamespace := true) (isNoncomputable := false) (attrs := []) header
|
||||
|
||||
def withNamespace {α} (ns : Name) (elabFn : CommandElabM α) : CommandElabM α := do
|
||||
addNamespace ns
|
||||
@@ -76,14 +85,16 @@ private def checkEndHeader : Name → List Scope → Option Name
|
||||
|
||||
@[builtin_command_elab «section»] def elabSection : CommandElab := fun stx => do
|
||||
match stx with
|
||||
| `(section $header:ident) => addScopes (isNewNamespace := false) (isNoncomputable := false) header.getId
|
||||
| `(section) => addScope (isNewNamespace := false) (isNoncomputable := false) "" (← getCurrNamespace)
|
||||
| _ => throwUnsupportedSyntax
|
||||
|
||||
@[builtin_command_elab noncomputableSection] def elabNonComputableSection : CommandElab := fun stx => do
|
||||
match stx with
|
||||
| `(noncomputable section $header:ident) => addScopes (isNewNamespace := false) (isNoncomputable := true) header.getId
|
||||
| `(noncomputable section) => addScope (isNewNamespace := false) (isNoncomputable := true) "" (← getCurrNamespace)
|
||||
| `($[@[expose%$expTk]]? $[noncomputable%$ncTk]? section $(header?)?) =>
|
||||
-- TODO: allow more attributes?
|
||||
let attrs ← if expTk.isSome then
|
||||
pure [← `(Parser.Term.attrInstance| expose)]
|
||||
else
|
||||
pure []
|
||||
if let some header := header? then
|
||||
addScopes (isNewNamespace := false) (isNoncomputable := ncTk.isSome) (attrs := attrs) header.getId
|
||||
else
|
||||
addScope (isNewNamespace := false) (isNoncomputable := ncTk.isSome) (attrs := attrs) "" (← getCurrNamespace)
|
||||
| _ => throwUnsupportedSyntax
|
||||
|
||||
@[builtin_command_elab «end»] def elabEnd : CommandElab := fun stx => do
|
||||
@@ -448,7 +459,7 @@ def failIfSucceeds (x : CommandElabM Unit) : CommandElabM Unit := do
|
||||
let mut msg : Array MessageData := #[]
|
||||
-- Noncomputable
|
||||
if scope.isNoncomputable then
|
||||
msg := msg.push <| ← `(command| noncomputable section)
|
||||
msg := msg.push <| ← `(Parser.Command.section| noncomputable section)
|
||||
-- Namespace
|
||||
if !scope.currNamespace.isAnonymous then
|
||||
msg := msg.push <| ← `(command| namespace $(mkIdent scope.currNamespace))
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user