Compare commits

...

110 Commits

Author SHA1 Message Date
Leonardo de Moura
9d75976b15 refactor: simplify inferface between core and offset module
`processNewEqLit` optimization is not worth the extra complexity.
2025-05-31 07:53:49 -07:00
Cameron Zwarich
adc7b1ed87 fix: increase maxHeartbeats in isDefEqProjIssue test for the new compiler (#8561)
This PR increases maxHeartbeats in the isDefEqProjIssue test, because
when running under the new compiler the `run_meta` call includes the
allocations of the compiler itself. With the old compiler, many of the
corresponding allocations were internal to C++ code and would not
increase the heartbeat count.
2025-05-31 04:56:29 +00:00
Leonardo de Moura
837193b5ec fix: block potential adversarial exploit of non-aborting assert! (#8560)
This PR is similar to #8559 but for `Expr.mkData`. This vulnerability
has not been exploited yet, but adversarial users may find a way.
2025-05-31 03:14:01 +00:00
Leonardo de Moura
6940d2c4ff fix: block adversarial exploit of non-aborting assert! (#8559)
This PR fixes an adversarial soundness attack described in #8554. The
attack exploits the fact that `assert!` no longer aborts execution, and
that users can redirect error messages.
Another PR will implement the same fix for `Expr.Data`.
2025-05-31 00:08:30 +00:00
Paul Reichert
ed4252f8c9 feat: array iterators, repeat/unfold, ForM for iterators (#8552)
This PR provides array iterators (`Array.iter(M)`,
`Array.iterFromIdx(M)`), infinite iterators produced by a step function
(`Iter.repeat`), and a `ForM` instance for finite iterators that is
implemented in terms of `ForIn`.
2025-05-30 18:17:53 +00:00
Leonardo de Moura
8883ca0965 chore: move test (#8550)
It is working now.
2025-05-30 17:13:38 +00:00
Leonardo de Moura
999fcd2d95 fix: hash function for congruence closure in grind (#8549)
This PR fixes the hash function used to implement congruence closure in
`grind`. The hash of an `Expr` must not depend on whether the expression
has been internalized or not.
2025-05-30 17:07:26 +00:00
Paul Reichert
a8ab3f230c feat: introduce iterator combinators takeWhile and dropWhile (#8493)
This PR provides the iterator combinators `takeWhile` (forwarding all
emitted values of another iterator until a predicate becomes false)
`dropWhile` (dropping values until some predicate on these values
becomes false, then forwarding all the others).
2025-05-30 16:35:40 +00:00
Paul Reichert
4f77e05225 feat: introduce zip iterator combinator (#8484)
This PR provides the iterator combinator `zip` in a pure and monadic
version.
2025-05-30 15:20:28 +00:00
Paul Reichert
90462e2551 feat: introduce iterator combinators filterMap, filter and map (#8451)
This PR provides the iterator combinator `filterMap` in a pure and
monadic version and specializations `map` and `filter`. This new
combinator allows to apply a function to the emitted values of a stream
while filtering out certain elements.

`map` should have an optimized `IteratorCollect` implementation but it
turns out that this is not possible without a major refactor of
`IteratorCollect`: `toArrayMapped` requires a proof that the iterator is
finite. If `it.mapM f` is `Finite` but `it` is not, then such a proof
does not exist. `IteratorCollect` needs to take a proof that the loop
will terminate for the given monadic function `f` instead. This will not
be done in this PR.
2025-05-30 13:43:41 +00:00
Paul Reichert
a12f89aefa feat: introduce take iterator combinator (#8418)
This PR provides the `take` iterator combinator that transforms any
iterator into an iterator that stops after a given number of steps. The
change contains the implementation and lemmas.

`take` has a special implementation of `IteratorLoop` that relies on a
potentially more efficient `forIn` implementation of the inner iterator.

The mysterious `@[specialize]` on a test has been removed because it is
not necessary anymore according to a manual inspection of the IR. Either
I erroneously concluded from experiments that it was necessary of
something has changed in the meantime that makes it unnecessary.
2025-05-30 10:34:12 +00:00
Paul Reichert
2d5e8ca311 feat: upstream LawfulMonadLift(T) from Batteries (#8435)
This PR upstreams the `LawfulMonadLift(T)` classes, lemmas and instances
from Batteries into Core because the iterator library needs them in
order to prove lemmas about the `mapM` operator, which relies on
`MonadLiftT`.
2025-05-30 09:14:01 +00:00
Paul Reichert
d60cb88e62 feat: ForIn, fold(M), drain lemmas for iterators (#8405)
This PR provides lemmas about the loop constructs `ForIn`, `fold`,
`foldM` and `drain` and their relation to each other in the context of
iterators.
2025-05-30 09:10:31 +00:00
Leonardo de Moura
d2e01bbd09 feat: overapplied ite and dite applications in grind (#8544)
This PR implements support for over-applied `ite` and `dite`
applications in the `grind` tactic. It adds support for propagation and
case-split.
2025-05-30 06:34:04 +00:00
Leonardo de Moura
069fb4351c fix: inappropriate whnfD uses in grind (#8542)
This PR fixes two inappropriate uses of `whnfD` in `grind`. They were
potential performance foot guns, and were producing unexpected errors
since `whnfD` is not consistently used (and it should not be) in all
modules.
2025-05-30 04:35:29 +00:00
Leonardo de Moura
f54a65f72f feat: nested proof propagation in grind (#8541)
This PR ensures that for any nested proof `h : p` in a goal, we
propagate that `p` is true in the `grind` tactic.
2025-05-30 03:25:14 +00:00
Mac Malone
3817dd57bd fix: lake: precompile imports of non-workspace files by library (#8529)
This PR changes `lake lean` and `lake setup-file` to precompile the
imports of non-workspace files using the the import's whole library.
This ensures that additional link objects are linked and available
during elaboration.

Closes #8448.
2025-05-30 02:28:28 +00:00
Mac Malone
e68c6a38fb feat: lake: relative paths for Lean build messages (#8539)
This PR changes Lake to use relative path for the Lean messages produced
by a module build. This makes the message portable across different
machines, which is useful for Mathlib's cache.
2025-05-30 02:02:35 +00:00
Cameron Zwarich
b7ec369863 fix: allow ground variables to depend on fun decls in LCNF specialize pass (#8540)
This PR changes the LCNF specialize pass to allow ground variables to
depend on local fun decls (with no non-ground free variables). This
enables specialization of Monad instances that depend on local lambdas.
2025-05-30 00:45:00 +00:00
Mac Malone
3fdaf24b49 fix: lake: ensure valid use of (sync := true) (#8531)
This PR fixes some places in Lake where `(sync := true)` was incorrectly
used on code that could block, and more generally improves `(sync :;=
true)` usage.
2025-05-30 00:19:25 +00:00
Kim Morrison
77e16407e4 chore: add test case where grind causes a PANIC (#8538)
Minimized from #8518, thanks @wkrozowski!
2025-05-30 00:12:37 +00:00
Kim Morrison
efd8d149ea chore: add missing lemma for List.range 1 (#8537) 2025-05-30 00:09:51 +00:00
Leonardo de Moura
4316629119 fix: BEq support in grind (#8536)
This PR fixes the support for `LawfulBEq` and `BEq` in `grind`.
2025-05-29 23:47:40 +00:00
jrr6
020da5bffb fix: behavior of hard line breaks in Format strings (#8457)
This PR fixes an issue when including a hard line break in a `Format`
that caused subsequent (ordinary) line breaks to be erroneously
flattened to spaces.

This issue is especially important for displaying notes and hints in
error messages, as these components could appear garbled due to improper
line-break rendering.
2025-05-29 22:10:27 +00:00
Sebastian Ullrich
bc8189b61d perf: avoid Environment.find? block in addDecl (#8533) 2025-05-29 21:32:37 +00:00
Cameron Zwarich
e30303e33c fix: extract more Nats in extractClosed (#8535)
This PR extracts more Nats (and their downstream users) in extractClosed
by fixing a silly oversight in the logic.
2025-05-29 21:11:21 +00:00
Sebastian Ullrich
1879a2bafc fix: SnapshotTree.waitAll (#8532) 2025-05-29 20:12:23 +00:00
Mac Malone
3b72c7d193 fix: lake: better library plugin heuristic (#8528)
This PR fixes the heuristic Lake uses to determine whether a `lean_lib`
can be loaded via `lean --plugin` rather than `lean --load-dynlib`.
Previously, a mismatch between the single root's name and the library's
name would not be caught and cause loading to fail.
2025-05-29 17:48:05 +00:00
Kim Morrison
22d4c1d803 chore: failing grind tests (subset of #8518) (#8526)
This is a subset of tests from #8518 that are fully minimized. I'll
merge this first.

---------

Co-authored-by: Wojciech Rozowski <wojciech@lean-fro.org>
2025-05-29 11:48:19 +00:00
Kim Morrison
0fe23b7fd6 feat: initial @[grind] annotations for List.count (#8527)
This PR adds `grind` annotations for theorems about `List.countP` and
`List.count`.
2025-05-29 11:46:44 +00:00
Kim Morrison
72141b05fd chore: add failing grind test (#8524) 2025-05-29 05:59:58 +00:00
Leonardo de Moura
1fd7206f00 feat: match-expressions with congruence equation theorems (#8506)
This PR implements `match`-expressions in `grind` using `match`
congruence equations. The goal is to minimize the number of `cast`
operations that need to be inserted, and avoid `cast` over functions.
The new approach support `match`-expressions of the form `match h : ...
with ...`.
2025-05-29 02:23:26 +00:00
Cameron Zwarich
a6e76b424c fix: move the new compiler's noncomputable check into toMono (#8523)
This PR moves the new compiler's noncomputable check into toMono,
matching the recent change in the old compiler. This is mildly more
complicated because we can't throw an error at the mere use of a
constant, we need to check for a later relevant use. This is still a bit
more conservative than it could theoretically be around join points and
local functions, but it's hard to imagine that mattering in practice
(and we can easily enable it if it does).
2025-05-29 00:40:25 +00:00
Kyle Miller
4dd8648a25 feat: different syntax for new clear_value tactic (#8516)
This PR is a followup to #8449 to refine the syntax of `clear_value`.
The syntax for adding equality hypotheses before clearing values is now
`clear_value (h : x = _)`. Any expression definitionally equal to `x`
can be used in place of the underscore.

This syntax was developed in a [Zulip
discussion](https://leanprover.zulipchat.com/#narrow/channel/270676-lean4/topic/.60clear_value.60.20syntax.20request.20for.20comments/near/520704290).
2025-05-28 22:33:35 +00:00
Cameron Zwarich
5814c1e757 fix: recursively process jmp args in LCNF.toMono (#8521)
This PR makes LCNF.toMono recursively process jmp args.
2025-05-28 20:56:03 +00:00
Kyle Miller
c3a010a938 feat: use dot notation for class parent projections (#8504)
This PR modifies the pretty printer so that dot notation is used for
class parent projections. Previously, dot notation was never used for
classes.

We still need to modify dot notation to take the method resolution order
into account when collapsing parent projections.
2025-05-28 20:34:40 +00:00
Kim Morrison
bd14e7079b fix: make Array.size not reducible (#8513)
This PR removes the `@[reducible]` annotation on `Array.size`. This is
probably best gone anyway in order to keep separation between the `List`
and `Array` APIs, but it also helps avoid uselessly instantiating
`Array` theorems when `grind` is working on `List` problems.
2025-05-28 12:37:24 +00:00
Sebastian Ullrich
f214708636 chore: update stage0 2025-05-28 14:27:31 +02:00
Sebastian Ullrich
5d7e09ddad feat: [no_expose] attribute 2025-05-28 14:26:22 +02:00
Kim Morrison
c6194e05b8 chore: remove prime from Fin.ofNat' (#8515)
This PR removes the prime from `Fin.ofNat'`: the old `Fin.ofNat` has
completed its 6 month deprecation cycle and is being removed.
2025-05-28 11:51:00 +00:00
Kim Morrison
1087ec9225 chore: remove >6 month old deprecations (#8514) 2025-05-28 11:28:03 +00:00
Kyle Miller
c5bea23a54 feat: value_of% elaborator (#8512)
This PR adds a `value_of% ident` term that elaborates to the value of
the local or global constant `ident`. This is useful for creating
definition hypotheses:
```lean
let x := ... complicated expression ...
have hx : x = value_of% x := rfl
```
2025-05-28 11:12:11 +00:00
Kim Morrison
ede085ae74 chore: add failing grind test (#8509) 2025-05-28 08:56:23 +00:00
Sebastian Ullrich
067fa83b1a chore: update stage0 2025-05-28 10:18:04 +02:00
Sebastian Ullrich
af1d8dd070 feat: := private instance syntax 2025-05-28 10:18:04 +02:00
Joachim Breitner
803dc3e687 refactor: Init: expose lots of functions (#8501)
This PR adds the `@[expose]` attribute to many functions (and changes
some theorems to be by `:= (rfl)`) in preparation for the `@[defeq]`
attribute change in #8419.
2025-05-28 07:37:54 +00:00
Kyle Miller
921ce7682e feat: use omission dots for hidden let values in Infoview (#8041)
This PR changes the behavior of `pp.showLetValues` to use a hoverable
`⋯` to hide let values. This is now false by default, and there is a new
option `pp.showLetValues.threshold` for allowing small expressions to be
shown anyway. For tactic metavariables, there is an additional option
`pp.showLetValues.tactic.threshold`, which by default is set to the
maximal value, since in tactic states local values are usually
significant.
2025-05-27 23:09:11 +00:00
Leonardo de Moura
5187cb37a9 chore: notation for HEq (#8503) 2025-05-27 19:22:57 +00:00
Cameron Zwarich
632d078a70 fix: use kernel environment to find definitions in the new compiler (#8502)
This PR changes the new compiler to use the kernel environment to find
definitions, which causes compilation to be skipped when the decl had a
kernel error (e.g. due to an unresolved metavariable). This matches the
behavior of the old compiler.

This will need to be revisited in the future when we want to make
compilation more asynchronous.
2025-05-27 16:56:00 +00:00
Luisa Cicolini
5fda4c1023 feat: BitVec.[toNat|toInt] non-overflow simp lemmas (#8492)
This PR adds `simp` lemmas for `toInt_*` and `toNat_*` with arithmetic
operation given the hypothesis of no-overflow
(`toNat_add_of_not_uaddOverflow`, `toInt_add_of_not_saddOverflow`,
`toNat_sub_of_not_usubOverflow`, `toInt_sub_of_not_ssubOverflow`,
`toInt_neg_of_not_negOverflow`, `toNat_mul_of_not_umulOverflow`,
`toInt_mul_of_not_smulOverflow`). In particular, these are `simp` since
(1) the `rhs` is strictly simpler than the `lhs` and (2) this version is
also simpler than the standard operation when the hypothesis is
available.
 
co-authored by @tobiasgrosser

---------

Co-authored-by: Henrik Böving <hargonix@gmail.com>
2025-05-27 15:13:43 +00:00
Kim Morrison
a4fb2eef47 feat: make Array.ofFn.go use fuel (#8499)
This PR changes the definition of `Array.ofFn.go` to use recursion on
`Nat` (rather than well-founded recursion). This resolves a problem
reported on [zulip]([#lean4 > Memory issues with &#96;Vector.ofFn&#96;.
@
💬](https://leanprover.zulipchat.com/#narrow/channel/270676-lean4/topic/Memory.20issues.20with.20.60Vector.2EofFn.60.2E/near/520622564)).
2025-05-27 13:44:28 +00:00
Kim Morrison
87152a3fae feat: grind annotations for List.Sublist/IsInfix/IsPrefix/IsSuffix (#8497)
This PR adds preliminary grind annotations for
`List.Sublist`/`IsInfix`/`IsPrefix`/`IsSuffix`, along with test cases.
2025-05-27 12:56:43 +00:00
Tobias Grosser
ed6c78048e chore: skip OS X aarch64 CI only in merge groups (#8334)
This PR enables the build of all artifacts for custom releases, e.g.,
releases outside the main lean4 repository.

This resolves https://github.com/leanprover/lean4/issues/8333.
2025-05-27 11:51:59 +00:00
Kim Morrison
3ab60c59fe chore: missing @[grind] annotations for Array (#8495) 2025-05-27 09:56:10 +00:00
Kim Morrison
eaa1bc14ed chore: more simp lemmas for LawfulGetElem (#8470)
This PR adds `@[simp]` to `getElem_pos/neg` (similarly for `getElem!`).
These are often already simp lemmas for concrete types.
2025-05-27 09:41:22 +00:00
Rob23oba
a912652b7d fix: simp_all? and simp_all?! (#8491)
This PR fixes the behavior of `simp_all?` and `simp_all?!`, aligning
them with `simp_all` and `simp_all!` respectively.

Closes #8490
2025-05-27 07:07:12 +00:00
Kyle Miller
3af9ab64ed feat: subst tactic can substitute let values (#8450)
This PR adds a feature to the `subst` tactic so that when `x : X := v`
is a local definition, `subst x` substitutes `v` for `x` in the goal and
removes `x`. Previously the tactic would throw an error.
2025-05-27 06:06:35 +00:00
Kyle Miller
a6dd6a4656 feat: clear_value tactic (#8449)
This PR upstreams and extends the Mathlib `clear_value` tactic. Given a
local definition `x : T := v`, the tactic `clear_value x` replaces it
with a hypothesis `x : T`, or throws an error if the goal does not
depend on the value `v`. The syntax `clear_value x with h` creates a
hypothesis `h : x = v` before clearing the value of `x`. Furthermore,
`clear_value *` clears all values that can be cleared, or throws an
error if none can be cleared.
2025-05-27 01:52:08 +00:00
Kim Morrison
1e752b0a01 chore: cleanup simp lemmas, following the simpNF linter (#8481) 2025-05-26 04:13:17 +00:00
Leonardo de Moura
11f7d6da39 feat: reuse simp cache in grind (#8483)
This PR ensures `grind` reuses the `simp` cache between different calls.
Recall that `grind` uses `simp` to normalize terms during
internalization.
2025-05-26 04:10:58 +00:00
Kim Morrison
e2fc9ba92e feat: grind annotations for List.Pairwise/Nodup (#8482)
This PR adds preliminary `@[grind]` annotations for `List.Pairwise` and
`List.Nodup`.
2025-05-26 03:13:18 +00:00
Kim Morrison
c1866a7b7e chore: fix awaiting-mathlib.yml (#8480)
This PR hopefully fixes a problem from #8471, which even the most
cursory testing (by me!) should have detected.
2025-05-26 02:13:00 +00:00
Leonardo de Moura
03e905d994 feat: hash consing with alpha equivalence in grind (#8479)
This PR implements hash-consing for `grind` that takes alpha equivalence
into account.
2025-05-26 00:51:18 +00:00
Kim Morrison
383f68f806 chore: add grind_trig test case (#8476) 2025-05-26 00:03:53 +00:00
Kim Morrison
41c2ae12f3 chore: update syntax in grind_ite example (#8475) 2025-05-25 23:21:11 +00:00
Sebastian Ullrich
9982bab93e perf: Environment.find? should not block on privacy mismatch (#8472)
This PR avoids name resolution blocking on the elaboration of a
theorem's proof when looking up the theorem name.
2025-05-25 16:18:57 +00:00
Cameron Zwarich
be513656b0 fix: use a custom environment extension for LCNF decls (#8468)
This PR switches the LCNF baseExt/monoExt environment extensions to use
a custom environment extension that uses a PersistentHashMap. The
optimizer relies upon the ability to update a decl multiple times, which
does not work with SimplePersistentEnvExtension.
2025-05-25 15:11:54 +00:00
Kim Morrison
bdbb659765 chore: while awaiting-mathlib, show yellow status not red (#8471)
This PR changes the CI check when the `awaiting-mathlib` label is
present. If `breaks-mathlib` is present, it shows a red cross, but if
neither `breaks-mathlib` nor `builds-mathlib` is present it shows a
yellow circle.
2025-05-25 12:38:56 +00:00
Leonardo de Moura
2a1354b3cc chore: add seal to workaround performance issue (#8469)
This PR adds `seal` commands at `grind_ite.lean` to workaround expensive
definitionally equality tests in the canonicalizer. The new module
system will automatically hide definitions such as `HashMap.insert` and
`TreeMap.insert` which are being unfolded by the canonicalizer in this
test.
This PR also adds a `profileItM` for tracking the time spent in the
`grind` canonicalizer.
2025-05-25 00:54:30 +00:00
Leonardo de Moura
a54872f5f6 fix: preprocessLight at ensureInternalized (#8466)
This PR fixes another instance of the `grind` issue "unexpected kernel
projection term during internalization".
2025-05-24 17:13:20 +00:00
Kim Morrison
2b0b1e013f feat: further generic GetElem lemmas (#8465)
This PR adds further lemmas about `LawfulGetElem`, including marking
some with `@[grind]`.
2025-05-24 12:58:29 +00:00
Mario Carneiro
1f000feb80 chore: remove unnecessary partial in Lean.Expr (#8464)
The termination prover has gotten stronger since these definitions were
written, and now they can be proved terminating automatically. (One
definition had to be changed slightly because it wasn't actually
terminating before.)
2025-05-24 07:00:37 +00:00
Cameron Zwarich
d5060e9e66 feat: add extractClosed pass to LCNF pass list (#8462)
This PR enables the LCNF extractClosed pass by default.
2025-05-24 05:20:10 +00:00
Kim Morrison
38ca310fb7 feat: @[grind] annotations for TreeMap (#8446)
This PR adds basic `@[grind]` annotations for `TreeMap` and its
variants. Likely more annotations will be added after we've explored
some examples.
2025-05-24 04:49:54 +00:00
Kim Morrison
3dd12f85f0 feat: further @[grind] annotations for Option (#8460)
This PR adds further `@[grind]` annotations for `Option`, as follow-up
to the recent additions to the `Option` API in #8379 and #8298.

**However**, I am concurrently investigating adding `attribute [grind
cases] Option`, which will result in many (most?) of the annotations for
`Option` being removed again. In any case, I'm going to merge this
first, as if that is viable I would like to test that most/all the
lemmas now marked with `@[grind]` are still provable by `grind`.
2025-05-24 04:25:00 +00:00
Kim Morrison
0f8618f842 chore: remove @[grind] from Array.size_eq_zero_iff` (#8461) 2025-05-24 04:20:52 +00:00
Kim Morrison
acdef6e04b feat: verification of qsort via grind (#7995)
This PR adds a verification of `Array.qsort` properties, trying to use
`grind` and `fun_induction` where possible.
Currently this is in the `tests/` folder, but once `grind` is ready for
production use we will move it out into the library.

Note that the current `qsort` algorithm has quadratic behaviour on
constant lists, and needs to be adjusted. We'll only move the
verification out into the library once this has been fixed (and the
proofs adapted). These verification theorems may be commented out in the
meantime if it's urgent to fix `qsort`.

---------

Co-authored-by: Kyle Miller <kmill31415@gmail.com>
Co-authored-by: Joachim Breitner <mail@joachim-breitner.de>
2025-05-24 04:01:55 +00:00
Cameron Zwarich
7b80cd24a9 feat: closed term extraction in the new compiler (#8458)
This PR adds closed term extraction to the new compiler, closely
following the approach in the old compiler. In the future, we will
explore some ideas to improve upon this approach.
2025-05-24 02:40:37 +00:00
Leonardo de Moura
21846ebdf8 feat: non-chronological backtracking for grind (WIP) (#8440)
This PR implements non-chronological backtracking for the `grind`
tactic. This feature ensures that `grind` does not need to process
irrelevant branches after performing a case-split that is not relevant.
It is not just about performance, but also the size of the final proof
term. The new test demonstrates this feature in practice.
```lean
-- In the following test, the first 8 case-splits are irrelevant,
-- and non-choronological backtracking is used to avoid searching
-- (2^8 - 1) irrelevant branches
/--
trace: 
[grind.split] p8 ∨ q8, generation: 0
[grind.split] p7 ∨ q7, generation: 0
[grind.split] p6 ∨ q6, generation: 0
[grind.split] p5 ∨ q5, generation: 0
[grind.split] p4 ∨ q4, generation: 0
[grind.split] p3 ∨ q3, generation: 0
[grind.split] p2 ∨ q2, generation: 0
[grind.split] p1 ∨ q1, generation: 0
[grind.split] ¬p ∨ ¬q, generation: 0
-/
#guard_msgs (trace) in
set_option trace.grind.split true in
theorem ex
    : p ∨ q →
      ¬ p ∨ q →
      p ∨ ¬ q →
      ¬ p ∨ ¬ q →
      p1 ∨ q1 →
      p2 ∨ q2 →
      p3 ∨ q3 →
      p4 ∨ q4 →
      p5 ∨ q5 →
      p6 ∨ q6 →
      p7 ∨ q7 →
      p8 ∨ q8 →
      False := by
  grind (splits := 10)
```
2025-05-23 19:33:54 +00:00
Cameron Zwarich
9ea4946560 feat: add support for USize literals in LCNF (#8456)
This PR adds support for primitive USize literals in LCNF.
2025-05-23 17:22:31 +00:00
Cameron Zwarich
3b205505ef chore: clean up structProjCases pass (#8455) 2025-05-23 15:46:21 +00:00
Lean stage0 autoupdater
6afa8208ec chore: update stage0 2025-05-23 15:21:08 +00:00
Rob23oba
65a5d0cb9d feat: improve Ord proof api (#8378)
This PR improves and extends the api around `Ord` and `Ordering`. These
changes are split off from #8210.
2025-05-23 14:00:20 +00:00
Joachim Breitner
fc3c82b1c7 chore: denixify stage0-updater workflow (#8452)
This PR lets the stage0 autoupdater build lean using the `cmake`
infrastructure, not the deprecated nix infrastructure.
2025-05-23 13:12:50 +00:00
Sebastian Graf
8fc94c5c90 fix: Make split work with metavariables in the target (#8437)
This PR fixes `split` in the presence of metavariables in the target.

The fix consists of replacing an internal use of `apply` for
instantiating match splitters by a new, simpler variant `applyN`. This
new `applyN` is not prone to #8436, which is the ultimate cause for
`split` failing on targets containing metavariables.

---------

Co-authored-by: Sebastian Graf <sg@lean-fro.org>
Co-authored-by: Joachim Breitner <mail@joachim-breitner.de>
2025-05-23 12:46:27 +00:00
Paul Reichert
96b81f3cc1 feat: lemmas about list iterators (#8384)
This PR provides lemmas about the behavior of `step`, `toArray`,
`toList` and `toListRev` on list iterators created with `List.iter` and
`List.iterM`.
2025-05-23 09:29:59 +00:00
Kim Morrison
44ff70020d feat: add simp lemma writing Vector.tail in terms of Vector.extract (#8445)
This PR adds a `@[simp]` lemma, and comments explaining that there is
intentionally no verification API for `Vector.take`, `Vector.drop`, or
`Vector.tail`, which should all be rewritten in terms of
`Vector.extract`.
2025-05-22 23:22:54 +00:00
Eric Wieser
ae1ab94992 fix: replace bad simp lemmas for Id (#7352)
This PR reworks the `simp` set around the `Id` monad, to not elide or
unfold `pure` and `Id.run`

In particular, it stops encoding the "defeq abuse" of `Id X = X` in the
statements of theorems, instead using `Id.run` and `pure` to pass back
and forth between these two spellings. Often when writing these with
`pure`, they generalize to other lawful monads; though such changes were
split off to other PRs.

This fixes the problem with the current simp set where `Id.run (pure x)`
is simplified to `Id.run x`, instead of the desirable `x`.
This is particularly bad because the` x` is sometimes inferred with type
`Id X` instead of `X`, which prevents other `simp` lemmas about `X` from
firing.

Making `Id` reducible instead is not an option, as then the `Monad`
instances would have nothing to key on.

---------

Co-authored-by: Sebastian Graf <sg@lean-fro.org>
Co-authored-by: Kim Morrison <kim@tqft.net>
Co-authored-by: Paul Reichert <6992158+datokrat@users.noreply.github.com>
2025-05-22 22:45:35 +00:00
Joachim Breitner
5e40f4af52 feat: linear-size noConfusionType construction (#8037)
This PR introduces a `noConfusionType` construction that’s sub-quadratic
in size, and reduces faster.

The previous `noConfusion` construction with two nested `match`
statements is quadratic in size and reduction behavior. Using some
helper definitions, a linear size construction is possible.

With this, processing the RISC-V-AST definition from
https://github.com/opencompl/sail-riscv-lean takes 6s instead of 60s.

The previous construction is still used when processing the early
prelude, and can be enabled elsewhere using `set_option
backwards.linearNoConfusionType false`.
2025-05-22 14:54:05 +00:00
Rob23oba
2594a8edad fix: namespace completion to only use the short name (#8350)
This PR changes namespace completion to use the same algorithm as
declaration identifier completion, which makes it use the short name
(last name component) for completions instead of the full name, avoiding
namespace duplications.

Closes #5654
2025-05-22 11:58:47 +00:00
Kim Morrison
b24e232a7a feat: lemmas about ordered rings and fields for grind (#8443)
This PR adds the lemmas about ordered rings and ordered fields which
will be needed by the new algebraic normalization components of `grind`.
2025-05-22 11:41:51 +00:00
Jakob von Raumer
9ad3974314 feat: add List.drop_cons (#8434)
This PR adds the equivalent of `List.take_cons` about `List.drop`.
2025-05-22 11:29:42 +00:00
Lean stage0 autoupdater
b31bf4e645 chore: update stage0 2025-05-22 11:24:54 +00:00
Marc Huisinga
c8d245a08f fix: unknown identifier ranges (#8362)
This PR fixes a bug where the unknown identifier code actions wouldn't
work correctly for some unknown identifier error spans and adjusts
several unknown identifier spans to actually end on the identifier in
question.

The following additional adjustments are made:
- The fallback mechanism of the unknown identifier code actions is
removed, since it could produce severely incorrect suggestions for
unknown identifier errors on fields.
- A performance bug when using the code action to import all unknown
identifiers is fixed.
- A bug that occurs when the elaborator produces multiple overlapping
completion infos is fixed.
- A bug in the snapshot selection that could cause it to wait for
snapshots in snapshots with non-canonical syntax is fixed.
- Some invariants of the snapshot tree are documented.
- The snapshot tree formatting is adjusted to display the final info
tree again.
2025-05-22 10:05:31 +00:00
Leonardo de Moura
4eccb5b479 fix: grind diagnostics at maxHeartbeats (#8438)
This PR ensures that `grind` diagnostics are obtained even when
`maxHeartbeats` is reached.
This PR also removes some dead code.
2025-05-21 22:14:59 +00:00
Paul Reichert
0a43c138ac feat: lemmas about iterator collectors (#8380)
This PR provides simple lemmas about `toArray`, `toList` and `toListRev`
for the iterator library.

It also changes the definition of `Iter` and `IterM` so that they aren't
equal anymore and in particular not definitionally equal. While it was
very convenient to have them be definitionally equal when working with
dependent code, it was also confusing and annoying that one would
sometimes end up with something like `it.toList = IterM.toList it`,
where `it : Iter β`.
2025-05-21 21:11:26 +00:00
Arthur Adjedj
1138062a70 fix: normalize imax 1 u to u (#7631)
This PR fixes `Lean.Level.mkIMaxAux` (`mk_imax` in the kernel) such that
`imax 1 u` reduces to `u`.

Closes #7096
2025-05-21 20:27:53 +00:00
grunweg
ebf455a137 doc: clarify that .now returns a date(time) in the local time zone (#8331)
This PR improves the docstring for `PlainDateTime.now` and its variants.

---------

Co-authored-by: Markus Himmel <markus@lean-fro.org>
2025-05-21 08:04:36 +00:00
Kim Morrison
87cc330489 feat: ordered ring typeclass for grind (#8429)
This PR adds `Lean.Grind.Ring.IsOrdered`, and cleans up the ring/module
grind API. These typeclasses are at present unused, but will support
future algorithmic improvements in `grind`.
2025-05-21 07:05:01 +00:00
Kim Morrison
47a1355fc4 chore: cleanup grind palindrome test (#8428) 2025-05-21 03:31:56 +00:00
Kim Morrison
79254d039c chore: restore @[simp] to List.ofFn_succ (#8427) 2025-05-21 03:12:26 +00:00
Leonardo de Moura
c28b052576 feat: [grind?] attribute (#8426)
This PR adds the attribute `[grind?]`. It is like `[grind]` but displays
inferred E-matching patterns. It is a more convinient than writing.
Thanks @kim-em for suggesting this feature.
```lean
set_option trace.grind.ematch.pattern true
```
This PR also improves some tests, and adds helper function
`ENode.isRoot`.
2025-05-21 00:32:49 +00:00
Kim Morrison
a541b8e75e chore: fix name of new Fin.foldlM_eq_finRange_foldlM lemmas (#8425) 2025-05-21 00:30:33 +00:00
Li Xuanji
a9a069a0ef doc: Fix doc bug in Resolve.lean (#8411)
This PR fixes a doc bug in the Resolve.lean; in reverse order, B comes
before A
2025-05-20 17:16:18 +00:00
Leonardo de Moura
8753239226 chore: remove Grind.Config.failures options (#8423)
Option is not very useful.
2025-05-20 15:40:51 +00:00
Paul Reichert
f4ee72b18c feat: minimal iterator library (#8358)
This PR introduces a very minimal version of the new iterator library.
It comes with list iterators and various consumers, namely `toArray`,
`toList`, `toListRev`, `ForIn`, `fold`, `foldM` and `drain`. All
consumers also come in a partial variant that can be used without any
proofs. This limited version of the iterator library generates decent
code, even with the old code generator.
2025-05-20 14:53:57 +00:00
Leonardo de Moura
8535a2268b fix: simplify isCasesAttrCandidate? in grind (#8415)
The behavior was counterintuitive.
2025-05-20 14:29:07 +00:00
Kim Morrison
d8e7ca2355 feat: draft typeclasses/tests for grind handling fields (#8417)
This PR introduces `Lean.Grind.Field`, proves that a `IsCharP 0` field
satisfies `NoNatZeroDivisors`, and sets up some basic (currently
failing) tests for `grind`.
2025-05-20 13:44:11 +00:00
Henrik Böving
8e0870beec feat: LT for Timestamp and Duration (#8422)
This PR adds `LT` and `Decidable` `LT` instances for
`Std.Time.Timestamp` and `Std.Time.Duration`.
2025-05-20 11:33:49 +00:00
Kim Morrison
3790f8c78e chore: deduplicate Grind.RatModule and Grind.NoNatZeroDivisors (#8416)
Also adds instances from e.g. `Semiring` to `NatModule` and `Ring` to
`IntModule`.
2025-05-20 07:49:42 +00:00
1193 changed files with 17901 additions and 4837 deletions

View File

@@ -10,11 +10,29 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check awaiting-mathlib label
id: check-awaiting-mathlib-label
if: github.event_name == 'pull_request'
uses: actions/github-script@v7
with:
script: |
const { labels } = context.payload.pull_request;
if (labels.some(label => label.name == "awaiting-mathlib") && !labels.some(label => label.name == "builds-mathlib")) {
core.setFailed('PR is marked "awaiting-mathlib" but "builds-mathlib" label has not been applied yet by the bot');
const { labels, number: prNumber } = context.payload.pull_request;
const hasAwaiting = labels.some(label => label.name == "awaiting-mathlib");
const hasBreaks = labels.some(label => label.name == "breaks-mathlib");
const hasBuilds = labels.some(label => label.name == "builds-mathlib");
if (hasAwaiting && hasBreaks) {
core.setFailed('PR has both "awaiting-mathlib" and "breaks-mathlib" labels.');
} else if (hasAwaiting && !hasBreaks && !hasBuilds) {
core.info('PR is marked "awaiting-mathlib" but neither "breaks-mathlib" nor "builds-mathlib" labels are present.');
core.setOutput('awaiting', 'true');
}
- name: Wait for mathlib compatibility
if: github.event_name == 'pull_request' && steps.check-awaiting-mathlib-label.outputs.awaiting == 'true'
run: |
echo "::notice title=Awaiting mathlib::PR is marked 'awaiting-mathlib' but neither 'breaks-mathlib' nor 'builds-mathlib' labels are present."
echo "This check will remain in progress until the PR is updated with appropriate mathlib compatibility labels."
# Keep the job running indefinitely to show "in progress" status
while true; do
sleep 3600 # Sleep for 1 hour at a time
done

View File

@@ -103,6 +103,13 @@ jobs:
echo "Tag ${TAG_NAME} did not match SemVer regex."
fi
- name: Check for custom releases (e.g., not in the main lean repository)
if: startsWith(github.ref, 'refs/tags/') && github.repository != 'leanprover/lean4'
id: set-release-custom
run: |
TAG_NAME="${GITHUB_REF##*/}"
echo "RELEASE_TAG=$TAG_NAME" >> "$GITHUB_OUTPUT"
- name: Set check level
id: set-level
# We do not use github.event.pull_request.labels.*.name here because
@@ -111,7 +118,7 @@ jobs:
run: |
check_level=0
if [[ -n "${{ steps.set-nightly.outputs.nightly }}" || -n "${{ steps.set-release.outputs.RELEASE_TAG }}" ]]; then
if [[ -n "${{ steps.set-nightly.outputs.nightly }}" || -n "${{ steps.set-release.outputs.RELEASE_TAG }}" || -n "${{ steps.set-release-custom.outputs.RELEASE_TAG }}" ]]; then
check_level=2
elif [[ "${{ github.event_name }}" != "pull_request" ]]; then
check_level=1

View File

@@ -40,34 +40,24 @@ jobs:
run: |
git config --global user.name "Lean stage0 autoupdater"
git config --global user.email "<>"
# Would be nice, but does not work yet:
# https://github.com/DeterminateSystems/magic-nix-cache/issues/39
# This action does not run that often and building runs in a few minutes, so ok for now
#- if: env.should_update_stage0 == 'yes'
# uses: DeterminateSystems/magic-nix-cache-action@v2
- if: env.should_update_stage0 == 'yes'
name: Restore Build Cache
uses: actions/cache/restore@v4
with:
path: nix-store-cache
key: Nix Linux-nix-store-cache-${{ github.sha }}
# fall back to (latest) previous cache
restore-keys: |
Nix Linux-nix-store-cache
- if: env.should_update_stage0 == 'yes'
name: Further Set Up Nix Cache
shell: bash -euxo pipefail {0}
run: |
# Nix seems to mutate the cache, so make a copy
cp -r nix-store-cache nix-store-cache-copy || true
- if: env.should_update_stage0 == 'yes'
name: Install Nix
uses: DeterminateSystems/nix-installer-action@main
with:
extra-conf: |
substituters = file://${{ github.workspace }}/nix-store-cache-copy?priority=10&trusted=true https://cache.nixos.org
- name: Open Nix shell once
if: env.should_update_stage0 == 'yes'
run: true
shell: 'nix develop -c bash -euxo pipefail {0}'
- name: Set up NPROC
if: env.should_update_stage0 == 'yes'
run: |
echo "NPROC=$(nproc 2>/dev/null || sysctl -n hw.logicalcpu 2>/dev/null || echo 4)" >> $GITHUB_ENV
shell: 'nix develop -c bash -euxo pipefail {0}'
- if: env.should_update_stage0 == 'yes'
run: nix run .#update-stage0-commit
run: cmake --preset release
shell: 'nix develop -c bash -euxo pipefail {0}'
- if: env.should_update_stage0 == 'yes'
run: make -j$NPROC -C build/release update-stage0-commit
shell: 'nix develop -c bash -euxo pipefail {0}'
- if: env.should_update_stage0 == 'yes'
run: git show --stat
- if: env.should_update_stage0 == 'yes' && github.event_name == 'push'

View File

@@ -49,7 +49,7 @@ abbrev forIn_eq_forin' := @forIn_eq_forIn'
/--
Extracts the value from a `ForInStep`, ignoring whether it is `ForInStep.done` or `ForInStep.yield`.
-/
def ForInStep.value (x : ForInStep α) : α :=
@[expose] def ForInStep.value (x : ForInStep α) : α :=
match x with
| ForInStep.done b => b
| ForInStep.yield b => b

View File

@@ -136,7 +136,7 @@ may throw the corresponding exception.
This is the inverse of `ExceptT.run`.
-/
@[always_inline, inline]
@[always_inline, inline, expose]
def ExceptT.mk {ε : Type u} {m : Type u Type v} {α : Type u} (x : m (Except ε α)) : ExceptT ε m α := x
/--
@@ -144,7 +144,7 @@ Use a monadic action that may throw an exception as an action that may return an
This is the inverse of `ExceptT.mk`.
-/
@[always_inline, inline]
@[always_inline, inline, expose]
def ExceptT.run {ε : Type u} {m : Type u Type v} {α : Type u} (x : ExceptT ε m α) : m (Except ε α) := x
namespace ExceptT
@@ -154,14 +154,14 @@ variable {ε : Type u} {m : Type u → Type v} [Monad m]
/--
Returns the value `a` without throwing exceptions or having any other effect.
-/
@[always_inline, inline]
@[always_inline, inline, expose]
protected def pure {α : Type u} (a : α) : ExceptT ε m α :=
ExceptT.mk <| pure (Except.ok a)
/--
Handles exceptions thrown by an action that can have no effects _other_ than throwing exceptions.
-/
@[always_inline, inline]
@[always_inline, inline, expose]
protected def bindCont {α β : Type u} (f : α ExceptT ε m β) : Except ε α m (Except ε β)
| Except.ok a => f a
| Except.error e => pure (Except.error e)
@@ -170,14 +170,14 @@ protected def bindCont {α β : Type u} (f : α → ExceptT ε m β) : Except ε
Sequences two actions that may throw exceptions. Typically used via `do`-notation or the `>>=`
operator.
-/
@[always_inline, inline]
@[always_inline, inline, expose]
protected def bind {α β : Type u} (ma : ExceptT ε m α) (f : α ExceptT ε m β) : ExceptT ε m β :=
ExceptT.mk <| ma >>= ExceptT.bindCont f
/--
Transforms a successful computation's value using `f`. Typically used via the `<$>` operator.
-/
@[always_inline, inline]
@[always_inline, inline, expose]
protected def map {α β : Type u} (f : α β) (x : ExceptT ε m α) : ExceptT ε m β :=
ExceptT.mk <| x >>= fun a => match a with
| (Except.ok a) => pure <| Except.ok (f a)
@@ -186,7 +186,7 @@ protected def map {α β : Type u} (f : α → β) (x : ExceptT ε m α) : Excep
/--
Runs a computation from an underlying monad in the transformed monad with exceptions.
-/
@[always_inline, inline]
@[always_inline, inline, expose]
protected def lift {α : Type u} (t : m α) : ExceptT ε m α :=
ExceptT.mk <| Except.ok <$> t
@@ -197,7 +197,7 @@ instance : MonadLift m (ExceptT ε m) := ⟨ExceptT.lift⟩
/--
Handles exceptions produced in the `ExceptT ε` transformer.
-/
@[always_inline, inline]
@[always_inline, inline, expose]
protected def tryCatch {α : Type u} (ma : ExceptT ε m α) (handle : ε ExceptT ε m α) : ExceptT ε m α :=
ExceptT.mk <| ma >>= fun res => match res with
| Except.ok a => pure (Except.ok a)

View File

@@ -25,7 +25,7 @@ namespace ExceptCpsT
/--
Use a monadic action that may throw an exception as an action that may return an exception's value.
-/
@[always_inline, inline]
@[always_inline, inline, expose]
def run {ε α : Type u} [Monad m] (x : ExceptCpsT ε m α) : m (Except ε α) :=
x _ (fun a => pure (Except.ok a)) (fun e => pure (Except.error e))
@@ -43,7 +43,7 @@ Returns the value of a computation, forgetting whether it was an exception or a
This corresponds to early return.
-/
@[always_inline, inline]
@[always_inline, inline, expose]
def runCatch [Monad m] (x : ExceptCpsT α m α) : m α :=
x α pure pure
@@ -63,7 +63,7 @@ instance : MonadExceptOf ε (ExceptCpsT ε m) where
/--
Run an action from the transformed monad in the exception monad.
-/
@[always_inline, inline]
@[always_inline, inline, expose]
def lift [Monad m] (x : m α) : ExceptCpsT ε m α :=
fun _ k _ => x >>= k

View File

@@ -9,3 +9,4 @@ prelude
import Init.Control.Lawful.Basic
import Init.Control.Lawful.Instances
import Init.Control.Lawful.Lemmas
import Init.Control.Lawful.MonadLift

View File

@@ -6,6 +6,7 @@ Authors: Sebastian Ullrich, Leonardo de Moura, Mario Carneiro
module
prelude
import Init.Ext
import Init.SimpLemmas
import Init.Meta
@@ -241,13 +242,23 @@ theorem LawfulMonad.mk' (m : Type u → Type v) [Monad m]
namespace Id
@[simp] theorem map_eq (x : Id α) (f : α β) : f <$> x = f x := rfl
@[simp] theorem bind_eq (x : Id α) (f : α id β) : x >>= f = f x := rfl
@[simp] theorem pure_eq (a : α) : (pure a : Id α) = a := rfl
@[ext] theorem ext {x y : Id α} (h : x.run = y.run) : x = y := h
instance : LawfulMonad Id := by
refine LawfulMonad.mk' _ ?_ ?_ ?_ <;> intros <;> rfl
@[simp] theorem run_map (x : Id α) (f : α β) : (f <$> x).run = f x.run := rfl
@[simp] theorem run_bind (x : Id α) (f : α Id β) : (x >>= f).run = (f x.run).run := rfl
@[simp] theorem run_pure (a : α) : (pure a : Id α).run = a := rfl
@[simp] theorem run_seqRight (x y : Id α) : (x *> y).run = y.run := rfl
@[simp] theorem run_seqLeft (x y : Id α) : (x <* y).run = x.run := rfl
@[simp] theorem run_seq (f : Id (α β)) (x : Id α) : (f <*> x).run = f.run x.run := rfl
-- These lemmas are bad as they abuse the defeq of `Id α` and `α`
@[deprecated run_map (since := "2025-03-05")] theorem map_eq (x : Id α) (f : α β) : f <$> x = f x := rfl
@[deprecated run_bind (since := "2025-03-05")] theorem bind_eq (x : Id α) (f : α id β) : x >>= f = f x := rfl
@[deprecated run_pure (since := "2025-03-05")] theorem pure_eq (a : α) : (pure a : Id α) = a := rfl
end Id
/-! # Option -/

View File

@@ -0,0 +1,11 @@
/-
Copyright (c) 2025 Lean FRO, LLC. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Paul Reichert
-/
module
prelude
import Init.Control.Lawful.MonadLift.Basic
import Init.Control.Lawful.MonadLift.Lemmas
import Init.Control.Lawful.MonadLift.Instances

View File

@@ -0,0 +1,52 @@
/-
Copyright (c) 2025 Quang Dao. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Quang Dao
-/
module
prelude
import Init.Control.Basic
/-!
# LawfulMonadLift and LawfulMonadLiftT
This module provides classes asserting that `MonadLift` and `MonadLiftT` are lawful, which means
that `monadLift` is compatible with `pure` and `bind`.
-/
section MonadLift
/-- The `MonadLift` typeclass only contains the lifting operation. `LawfulMonadLift` further
asserts that lifting commutes with `pure` and `bind`:
```
monadLift (pure a) = pure a
monadLift (ma >>= f) = monadLift ma >>= monadLift ∘ f
```
-/
class LawfulMonadLift (m : semiOutParam (Type u Type v)) (n : Type u Type w)
[Monad m] [Monad n] [inst : MonadLift m n] : Prop where
/-- Lifting preserves `pure` -/
monadLift_pure {α : Type u} (a : α) : inst.monadLift (pure a) = pure a
/-- Lifting preserves `bind` -/
monadLift_bind {α β : Type u} (ma : m α) (f : α m β) :
inst.monadLift (ma >>= f) = inst.monadLift ma >>= (fun x => inst.monadLift (f x))
/-- The `MonadLiftT` typeclass only contains the transitive lifting operation.
`LawfulMonadLiftT` further asserts that lifting commutes with `pure` and `bind`:
```
monadLift (pure a) = pure a
monadLift (ma >>= f) = monadLift ma >>= monadLift ∘ f
```
-/
class LawfulMonadLiftT (m : Type u Type v) (n : Type u Type w) [Monad m] [Monad n]
[inst : MonadLiftT m n] : Prop where
/-- Lifting preserves `pure` -/
monadLift_pure {α : Type u} (a : α) : inst.monadLift (pure a) = pure a
/-- Lifting preserves `bind` -/
monadLift_bind {α β : Type u} (ma : m α) (f : α m β) :
inst.monadLift (ma >>= f) = monadLift ma >>= (fun x => monadLift (f x))
export LawfulMonadLiftT (monadLift_pure monadLift_bind)
end MonadLift

View File

@@ -0,0 +1,137 @@
/-
Copyright (c) 2025 Quang Dao. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Quang Dao, Paul Reichert
-/
module
prelude
import all Init.Control.Option
import all Init.Control.Except
import all Init.Control.ExceptCps
import all Init.Control.StateRef
import all Init.Control.StateCps
import Init.Control.Lawful.MonadLift.Lemmas
import Init.Control.Lawful.Instances
universe u v w x
variable {m : Type u Type v} {n : Type u Type w} {o : Type u Type x}
variable (m n o) in
instance [Monad m] [Monad n] [Monad o] [MonadLift n o] [MonadLiftT m n]
[LawfulMonadLift n o] [LawfulMonadLiftT m n] : LawfulMonadLiftT m o where
monadLift_pure := fun a => by
simp only [monadLift, LawfulMonadLift.monadLift_pure, liftM_pure]
monadLift_bind := fun ma f => by
simp only [monadLift, LawfulMonadLift.monadLift_bind, liftM_bind]
variable (m) in
instance [Monad m] : LawfulMonadLiftT m m where
monadLift_pure _ := rfl
monadLift_bind _ _ := rfl
namespace StateT
variable [Monad m] [LawfulMonad m]
instance {σ : Type u} : LawfulMonadLift m (StateT σ m) where
monadLift_pure _ := by ext; simp [MonadLift.monadLift]
monadLift_bind _ _ := by ext; simp [MonadLift.monadLift]
end StateT
namespace ReaderT
variable [Monad m]
instance {ρ : Type u} : LawfulMonadLift m (ReaderT ρ m) where
monadLift_pure _ := rfl
monadLift_bind _ _ := rfl
end ReaderT
namespace OptionT
variable [Monad m] [LawfulMonad m]
@[simp]
theorem lift_pure {α : Type u} (a : α) : OptionT.lift (pure a : m α) = pure a := by
simp only [OptionT.lift, OptionT.mk, bind_pure_comp, map_pure, pure, OptionT.pure]
@[simp]
theorem lift_bind {α β : Type u} (ma : m α) (f : α m β) :
OptionT.lift (ma >>= f) = OptionT.lift ma >>= (fun a => OptionT.lift (f a)) := by
simp only [instMonad, OptionT.bind, OptionT.mk, OptionT.lift, bind_pure_comp, bind_map_left,
map_bind]
instance : LawfulMonadLift m (OptionT m) where
monadLift_pure := lift_pure
monadLift_bind := lift_bind
end OptionT
namespace ExceptT
variable [Monad m] [LawfulMonad m]
@[simp]
theorem lift_bind {α β ε : Type u} (ma : m α) (f : α m β) :
ExceptT.lift (ε := ε) (ma >>= f) = ExceptT.lift ma >>= (fun a => ExceptT.lift (f a)) := by
simp only [instMonad, ExceptT.bind, mk, ExceptT.lift, bind_map_left, ExceptT.bindCont, map_bind]
instance : LawfulMonadLift m (ExceptT ε m) where
monadLift_pure := lift_pure
monadLift_bind := lift_bind
instance : LawfulMonadLift (Except ε) (ExceptT ε m) where
monadLift_pure _ := by
simp only [MonadLift.monadLift, mk, pure, Except.pure, ExceptT.pure]
monadLift_bind ma _ := by
simp only [instMonad, ExceptT.bind, mk, MonadLift.monadLift, pure_bind, ExceptT.bindCont,
Except.instMonad, Except.bind]
rcases ma with _ | _ <;> simp
end ExceptT
namespace StateRefT'
instance {ω σ : Type} {m : Type Type} [Monad m] : LawfulMonadLift m (StateRefT' ω σ m) where
monadLift_pure _ := by
simp only [MonadLift.monadLift, pure]
unfold StateRefT'.lift ReaderT.pure
simp only
monadLift_bind _ _ := by
simp only [MonadLift.monadLift, bind]
unfold StateRefT'.lift ReaderT.bind
simp only
end StateRefT'
namespace StateCpsT
instance {σ : Type u} [Monad m] [LawfulMonad m] : LawfulMonadLift m (StateCpsT σ m) where
monadLift_pure _ := by
simp only [MonadLift.monadLift, pure]
unfold StateCpsT.lift
simp only [pure_bind]
monadLift_bind _ _ := by
simp only [MonadLift.monadLift, bind]
unfold StateCpsT.lift
simp only [bind_assoc]
end StateCpsT
namespace ExceptCpsT
instance {ε : Type u} [Monad m] [LawfulMonad m] : LawfulMonadLift m (ExceptCpsT ε m) where
monadLift_pure _ := by
simp only [MonadLift.monadLift, pure]
unfold ExceptCpsT.lift
simp only [pure_bind]
monadLift_bind _ _ := by
simp only [MonadLift.monadLift, bind]
unfold ExceptCpsT.lift
simp only [bind_assoc]
end ExceptCpsT

View File

@@ -0,0 +1,63 @@
/-
Copyright (c) 2025 Quang Dao. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Quang Dao
-/
module
prelude
import Init.Control.Lawful.Basic
import Init.Control.Lawful.MonadLift.Basic
universe u v w
variable {m : Type u Type v} {n : Type u Type w} [Monad m] [Monad n] [MonadLiftT m n]
[LawfulMonadLiftT m n] {α β : Type u}
theorem monadLift_map [LawfulMonad m] [LawfulMonad n] (f : α β) (ma : m α) :
monadLift (f <$> ma) = f <$> (monadLift ma : n α) := by
rw [ bind_pure_comp, bind_pure_comp, monadLift_bind]
simp only [bind_pure_comp, monadLift_pure]
theorem monadLift_seq [LawfulMonad m] [LawfulMonad n] (mf : m (α β)) (ma : m α) :
monadLift (mf <*> ma) = monadLift mf <*> (monadLift ma : n α) := by
simp only [seq_eq_bind, monadLift_map, monadLift_bind]
theorem monadLift_seqLeft [LawfulMonad m] [LawfulMonad n] (x : m α) (y : m β) :
monadLift (x <* y) = (monadLift x : n α) <* (monadLift y : n β) := by
simp only [seqLeft_eq, monadLift_map, monadLift_seq]
theorem monadLift_seqRight [LawfulMonad m] [LawfulMonad n] (x : m α) (y : m β) :
monadLift (x *> y) = (monadLift x : n α) *> (monadLift y : n β) := by
simp only [seqRight_eq, monadLift_map, monadLift_seq]
/-! We duplicate the theorems for `monadLift` to `liftM` since `rw` matches on syntax only. -/
@[simp]
theorem liftM_pure (a : α) : liftM (pure a : m α) = pure (f := n) a :=
monadLift_pure _
@[simp]
theorem liftM_bind (ma : m α) (f : α m β) :
liftM (n := n) (ma >>= f) = liftM ma >>= (fun a => liftM (f a)) :=
monadLift_bind _ _
@[simp]
theorem liftM_map [LawfulMonad m] [LawfulMonad n] (f : α β) (ma : m α) :
liftM (f <$> ma) = f <$> (liftM ma : n α) :=
monadLift_map _ _
@[simp]
theorem liftM_seq [LawfulMonad m] [LawfulMonad n] (mf : m (α β)) (ma : m α) :
liftM (mf <*> ma) = liftM mf <*> (liftM ma : n α) :=
monadLift_seq _ _
@[simp]
theorem liftM_seqLeft [LawfulMonad m] [LawfulMonad n] (x : m α) (y : m β) :
liftM (x <* y) = (liftM x : n α) <* (liftM y : n β) :=
monadLift_seqLeft _ _
@[simp]
theorem liftM_seqRight [LawfulMonad m] [LawfulMonad n] (x : m α) (y : m β) :
liftM (x *> y) = (liftM x : n α) *> (liftM y : n β) :=
monadLift_seqRight _ _

View File

@@ -29,7 +29,7 @@ of a value and a state.
Executes an action from a monad with added state in the underlying monad `m`. Given an initial
state, it returns a value paired with the final state.
-/
@[always_inline, inline]
@[always_inline, inline, expose]
def StateT.run {σ : Type u} {m : Type u Type v} {α : Type u} (x : StateT σ m α) (s : σ) : m (α × σ) :=
x s
@@ -37,7 +37,7 @@ def StateT.run {σ : Type u} {m : Type u → Type v} {α : Type u} (x : StateT
Executes an action from a monad with added state in the underlying monad `m`. Given an initial
state, it returns a value, discarding the final state.
-/
@[always_inline, inline]
@[always_inline, inline, expose]
def StateT.run' {σ : Type u} {m : Type u Type v} [Functor m] {α : Type u} (x : StateT σ m α) (s : σ) : m α :=
(·.1) <$> x s
@@ -66,21 +66,21 @@ variable [Monad m] {α β : Type u}
/--
Returns the given value without modifying the state. Typically used via `Pure.pure`.
-/
@[always_inline, inline]
@[always_inline, inline, expose]
protected def pure (a : α) : StateT σ m α :=
fun s => pure (a, s)
/--
Sequences two actions. Typically used via the `>>=` operator.
-/
@[always_inline, inline]
@[always_inline, inline, expose]
protected def bind (x : StateT σ m α) (f : α StateT σ m β) : StateT σ m β :=
fun s => do let (a, s) x s; f a s
/--
Modifies the value returned by a computation. Typically used via the `<$>` operator.
-/
@[always_inline, inline]
@[always_inline, inline, expose]
protected def map (f : α β) (x : StateT σ m α) : StateT σ m β :=
fun s => do let (a, s) x s; pure (f a, s)
@@ -114,14 +114,14 @@ Retrieves the current value of the monad's mutable state.
This increments the reference count of the state, which may inhibit in-place updates.
-/
@[always_inline, inline]
@[always_inline, inline, expose]
protected def get : StateT σ m σ :=
fun s => pure (s, s)
/--
Replaces the mutable state with a new value.
-/
@[always_inline, inline]
@[always_inline, inline, expose]
protected def set : σ StateT σ m PUnit :=
fun s' _ => pure (, s')
@@ -133,7 +133,7 @@ It is equivalent to `do let (a, s) := f (← StateT.get); StateT.set s; pure a`.
`StateT.modifyGet` may lead to better performance because it doesn't add a new reference to the
state value, and additional references can inhibit in-place updates of data.
-/
@[always_inline, inline]
@[always_inline, inline, expose]
protected def modifyGet (f : σ α × σ) : StateT σ m α :=
fun s => pure (f s)
@@ -143,7 +143,7 @@ Runs an action from the underlying monad in the monad with state. The state is n
This function is typically implicitly accessed via a `MonadLiftT` instance as part of [automatic
lifting](lean-manual://section/monad-lifting).
-/
@[always_inline, inline]
@[always_inline, inline, expose]
protected def lift {α : Type u} (t : m α) : StateT σ m α :=
fun s => do let a t; pure (a, s)

View File

@@ -28,7 +28,7 @@ variable {α σ : Type u} {m : Type u → Type v}
Runs a stateful computation that's represented using continuation passing style by providing it with
an initial state and a continuation.
-/
@[always_inline, inline]
@[always_inline, inline, expose]
def runK (x : StateCpsT σ m α) (s : σ) (k : α σ m β) : m β :=
x _ s k
@@ -39,7 +39,7 @@ state, it returns a value paired with the final state.
While the state is internally represented in continuation passing style, the resulting value is the
same as for a non-CPS state monad.
-/
@[always_inline, inline]
@[always_inline, inline, expose]
def run [Monad m] (x : StateCpsT σ m α) (s : σ) : m (α × σ) :=
runK x s (fun a s => pure (a, s))
@@ -47,7 +47,7 @@ def run [Monad m] (x : StateCpsT σ m α) (s : σ) : m (α × σ) :=
Executes an action from a monad with added state in the underlying monad `m`. Given an initial
state, it returns a value, discarding the final state.
-/
@[always_inline, inline]
@[always_inline, inline, expose]
def run' [Monad m] (x : StateCpsT σ m α) (s : σ) : m α :=
runK x s (fun a _ => pure a)
@@ -72,7 +72,7 @@ Runs an action from the underlying monad in the monad with state. The state is n
This function is typically implicitly accessed via a `MonadLiftT` instance as part of [automatic
lifting](lean-manual://section/monad-lifting).
-/
@[always_inline, inline]
@[always_inline, inline, expose]
protected def lift [Monad m] (x : m α) : StateCpsT σ m α :=
fun _ s k => x >>= (k . s)

View File

@@ -43,14 +43,14 @@ and `flip (·<·)` is the greater-than relation.
theorem Function.comp_def {α β δ} (f : β δ) (g : α β) : f g = fun x => f (g x) := rfl
@[simp] theorem Function.const_comp {f : α β} {c : γ} :
(Function.const β c f) = Function.const α c := by
(Function.const β c f) = Function.const α c :=
rfl
@[simp] theorem Function.comp_const {f : β γ} {b : β} :
(f Function.const α b) = Function.const α (f b) := by
(f Function.const α b) = Function.const α (f b) :=
rfl
@[simp] theorem Function.true_comp {f : α β} : ((fun _ => true) f) = fun _ => true := by
@[simp] theorem Function.true_comp {f : α β} : ((fun _ => true) f) = fun _ => true :=
rfl
@[simp] theorem Function.false_comp {f : α β} : ((fun _ => false) f) = fun _ => false := by
@[simp] theorem Function.false_comp {f : α β} : ((fun _ => false) f) = fun _ => false :=
rfl
@[simp] theorem Function.comp_id (f : α β) : f id = f := rfl
@@ -897,43 +897,43 @@ section
variable {α β φ : Sort u} {a a' : α} {b b' : β} {c : φ}
/-- Non-dependent recursor for `HEq` -/
noncomputable def HEq.ndrec.{u1, u2} {α : Sort u2} {a : α} {motive : {β : Sort u2} β Sort u1} (m : motive a) {β : Sort u2} {b : β} (h : HEq a b) : motive b :=
noncomputable def HEq.ndrec.{u1, u2} {α : Sort u2} {a : α} {motive : {β : Sort u2} β Sort u1} (m : motive a) {β : Sort u2} {b : β} (h : a b) : motive b :=
h.rec m
/-- `HEq.ndrec` variant -/
noncomputable def HEq.ndrecOn.{u1, u2} {α : Sort u2} {a : α} {motive : {β : Sort u2} β Sort u1} {β : Sort u2} {b : β} (h : HEq a b) (m : motive a) : motive b :=
noncomputable def HEq.ndrecOn.{u1, u2} {α : Sort u2} {a : α} {motive : {β : Sort u2} β Sort u1} {β : Sort u2} {b : β} (h : a b) (m : motive a) : motive b :=
h.rec m
/-- `HEq.ndrec` variant -/
noncomputable def HEq.elim {α : Sort u} {a : α} {p : α Sort v} {b : α} (h₁ : HEq a b) (h₂ : p a) : p b :=
noncomputable def HEq.elim {α : Sort u} {a : α} {p : α Sort v} {b : α} (h₁ : a b) (h₂ : p a) : p b :=
eq_of_heq h₁ h₂
/-- Substitution with heterogeneous equality. -/
theorem HEq.subst {p : (T : Sort u) T Prop} (h₁ : HEq a b) (h₂ : p α a) : p β b :=
theorem HEq.subst {p : (T : Sort u) T Prop} (h₁ : a b) (h₂ : p α a) : p β b :=
HEq.ndrecOn h₁ h₂
/-- Heterogeneous equality is symmetric. -/
@[symm] theorem HEq.symm (h : HEq a b) : HEq b a :=
@[symm] theorem HEq.symm (h : a b) : b a :=
h.rec (HEq.refl a)
/-- Propositionally equal terms are also heterogeneously equal. -/
theorem heq_of_eq (h : a = a') : HEq a a' :=
theorem heq_of_eq (h : a = a') : a a' :=
Eq.subst h (HEq.refl a)
/-- Heterogeneous equality is transitive. -/
theorem HEq.trans (h₁ : HEq a b) (h₂ : HEq b c) : HEq a c :=
theorem HEq.trans (h₁ : a b) (h₂ : b c) : a c :=
HEq.subst h₂ h₁
/-- Heterogeneous equality precomposes with propositional equality. -/
theorem heq_of_heq_of_eq (h₁ : HEq a b) (h₂ : b = b') : HEq a b' :=
theorem heq_of_heq_of_eq (h₁ : a b) (h₂ : b = b') : a b' :=
HEq.trans h₁ (heq_of_eq h₂)
/-- Heterogeneous equality postcomposes with propositional equality. -/
theorem heq_of_eq_of_heq (h₁ : a = a') (h₂ : HEq a' b) : HEq a b :=
theorem heq_of_eq_of_heq (h₁ : a = a') (h₂ : a' b) : a b :=
HEq.trans (heq_of_eq h₁) h₂
/-- If two terms are heterogeneously equal then their types are propositionally equal. -/
theorem type_eq_of_heq (h : HEq a b) : α = β :=
theorem type_eq_of_heq (h : a b) : α = β :=
h.rec (Eq.refl α)
end
@@ -942,7 +942,7 @@ end
Rewriting inside `φ` using `Eq.recOn` yields a term that's heterogeneously equal to the original
term.
-/
theorem eqRec_heq {α : Sort u} {φ : α Sort v} {a a' : α} : (h : a = a') (p : φ a) HEq (Eq.recOn (motive := fun x _ => φ x) h p) p
theorem eqRec_heq {α : Sort u} {φ : α Sort v} {a a' : α} : (h : a = a') (p : φ a) Eq.recOn (motive := fun x _ => φ x) h p p
| rfl, p => HEq.refl p
/--
@@ -950,8 +950,8 @@ Heterogeneous equality with an `Eq.rec` application on the left is equivalent to
equality on the original term.
-/
theorem eqRec_heq_iff {α : Sort u} {a : α} {motive : (b : α) a = b Sort v}
{b : α} {refl : motive a (Eq.refl a)} {h : a = b} {c : motive b h} :
HEq (@Eq.rec α a motive refl b h) c HEq refl c :=
{b : α} {refl : motive a (Eq.refl a)} {h : a = b} {c : motive b h}
: @Eq.rec α a motive refl b h c refl c :=
h.rec (fun _ => id, id) c
/--
@@ -960,7 +960,7 @@ equality on the original term.
-/
theorem heq_eqRec_iff {α : Sort u} {a : α} {motive : (b : α) a = b Sort v}
{b : α} {refl : motive a (Eq.refl a)} {h : a = b} {c : motive b h} :
HEq c (@Eq.rec α a motive refl b h) HEq c refl :=
c @Eq.rec α a motive refl b h c refl :=
h.rec (fun _ => id, id) c
/--
@@ -977,7 +977,7 @@ theorem apply_eqRec {α : Sort u} {a : α} (motive : (b : α) → a = b → Sort
If casting a term with `Eq.rec` to another type makes it equal to some other term, then the two
terms are heterogeneously equal.
-/
theorem heq_of_eqRec_eq {α β : Sort u} {a : α} {b : β} (h₁ : α = β) (h₂ : Eq.rec (motive := fun α _ => α) a h₁ = b) : HEq a b := by
theorem heq_of_eqRec_eq {α β : Sort u} {a : α} {b : β} (h₁ : α = β) (h₂ : Eq.rec (motive := fun α _ => α) a h₁ = b) : a b := by
subst h₁
apply heq_of_eq
exact h₂
@@ -985,7 +985,7 @@ theorem heq_of_eqRec_eq {α β : Sort u} {a : α} {b : β} (h₁ : α = β) (h
/--
The result of casting a term with `cast` is heterogeneously equal to the original term.
-/
theorem cast_heq {α β : Sort u} : (h : α = β) (a : α) HEq (cast h a) a
theorem cast_heq {α β : Sort u} : (h : α = β) (a : α) cast h a a
| rfl, a => HEq.refl a
variable {a b c d : Prop}
@@ -1014,8 +1014,8 @@ instance : Trans Iff Iff Iff where
theorem Eq.comm {a b : α} : a = b b = a := Iff.intro Eq.symm Eq.symm
theorem eq_comm {a b : α} : a = b b = a := Eq.comm
theorem HEq.comm {a : α} {b : β} : HEq a b HEq b a := Iff.intro HEq.symm HEq.symm
theorem heq_comm {a : α} {b : β} : HEq a b HEq b a := HEq.comm
theorem HEq.comm {a : α} {b : β} : a b b a := Iff.intro HEq.symm HEq.symm
theorem heq_comm {a : α} {b : β} : a b b a := HEq.comm
@[symm] theorem Iff.symm (h : a b) : b a := Iff.intro h.mpr h.mp
theorem Iff.comm : (a b) (b a) := Iff.intro Iff.symm Iff.symm
@@ -1048,11 +1048,6 @@ theorem Exists.elim {α : Sort u} {p : α → Prop} {b : Prop}
| isFalse _ => rfl
| isTrue h => False.elim h
set_option linter.missingDocs false in
@[deprecated decide_true (since := "2024-11-05")] abbrev decide_true_eq_true := decide_true
set_option linter.missingDocs false in
@[deprecated decide_false (since := "2024-11-05")] abbrev decide_false_eq_false := decide_false
/-- Similar to `decide`, but uses an explicit instance -/
@[inline] def toBoolUsing {p : Prop} (d : Decidable p) : Bool :=
decide (h := d)
@@ -1239,7 +1234,7 @@ protected theorem Subsingleton.elim {α : Sort u} [h : Subsingleton α] : (a b :
If two types are equal and one of them is a subsingleton, then all of their elements are
[heterogeneously equal](lean-manual://section/HEq).
-/
protected theorem Subsingleton.helim {α β : Sort u} [h₁ : Subsingleton α] (h₂ : α = β) (a : α) (b : β) : HEq a b := by
protected theorem Subsingleton.helim {α β : Sort u} [h₁ : Subsingleton α] (h₂ : α = β) (a : α) (b : β) : a b := by
subst h₂
apply heq_of_eq
apply Subsingleton.elim
@@ -1690,7 +1685,7 @@ theorem true_iff_false : (True ↔ False) ↔ False := iff_false_intro (·.mp T
theorem false_iff_true : (False True) False := iff_false_intro (·.mpr True.intro)
theorem iff_not_self : ¬(a ¬a) | H => let f h := H.1 h h; f (H.2 f)
theorem heq_self_iff_true (a : α) : HEq a a True := iff_true_intro HEq.rfl
theorem heq_self_iff_true (a : α) : a a True := iff_true_intro HEq.rfl
/-! ## implies -/
@@ -1890,7 +1885,7 @@ a structure.
protected abbrev hrecOn
(q : Quot r)
(f : (a : α) motive (Quot.mk r a))
(c : (a b : α) (p : r a b) HEq (f a) (f b))
(c : (a b : α) (p : r a b) f a f b)
: motive q :=
Quot.recOn q f fun a b p => eq_of_heq (eqRec_heq_iff.mpr (c a b p))
@@ -2088,7 +2083,7 @@ a structure.
protected abbrev hrecOn
(q : Quotient s)
(f : (a : α) motive (Quotient.mk s a))
(c : (a b : α) (p : a b) HEq (f a) (f b))
(c : (a b : α) (p : a b) f a f b)
: motive q :=
Quot.hrecOn q f c
end

View File

@@ -22,7 +22,7 @@ an array `xs : Array α`, given a proof that every element of `xs` in fact satis
`Array.pmap`, named for “partial map,” is the equivalent of `Array.map` for such partial functions.
-/
@[expose]
def pmap {P : α Prop} (f : a, P a β) (xs : Array α) (H : a xs, P a) : Array β :=
(xs.toList.pmap f (fun a m => H a (mem_def.mpr m))).toArray
@@ -39,7 +39,7 @@ of elements in the corresponding subtype `{ x // P x }`.
`O(1)`.
-/
@[implemented_by attachWithImpl] def attachWith
@[implemented_by attachWithImpl, expose] def attachWith
(xs : Array α) (P : α Prop) (H : x xs, P x) : Array {x // P x} :=
xs.toList.attachWith P fun x h => H x (Array.Mem.mk h)
@@ -54,7 +54,7 @@ recursion](lean-manual://section/well-founded-recursion) that use higher-order f
`Array.map`) to prove that an value taken from a list is smaller than the list. This allows the
well-founded recursion mechanism to prove that the function terminates.
-/
@[inline] def attach (xs : Array α) : Array {x // x xs} := xs.attachWith _ fun _ => id
@[inline, expose] def attach (xs : Array α) : Array {x // x xs} := xs.attachWith _ fun _ => id
@[simp, grind =] theorem _root_.List.attachWith_toArray {l : List α} {P : α Prop} {H : x l.toArray, P x} :
l.toArray.attachWith P H = (l.attachWith P (by simpa using H)).toArray := by
@@ -69,11 +69,11 @@ well-founded recursion mechanism to prove that the function terminates.
simp [pmap]
@[simp] theorem toList_attachWith {xs : Array α} {P : α Prop} {H : x xs, P x} :
(xs.attachWith P H).toList = xs.toList.attachWith P (by simpa [mem_toList] using H) := by
(xs.attachWith P H).toList = xs.toList.attachWith P (by simpa [mem_toList_iff] using H) := by
simp [attachWith]
@[simp] theorem toList_attach {xs : Array α} :
xs.attach.toList = xs.toList.attachWith (· xs) (by simp [mem_toList]) := by
xs.attach.toList = xs.toList.attachWith (· xs) (by simp [mem_toList_iff]) := by
simp [attach]
@[simp] theorem toList_pmap {xs : Array α} {P : α Prop} {f : a, P a β} {H : a xs, P a} :
@@ -574,9 +574,12 @@ state, the right approach is usually the tactic `simp [Array.unattach, -Array.ma
-/
def unattach {α : Type _} {p : α Prop} (xs : Array { x // p x }) : Array α := xs.map (·.val)
@[simp] theorem unattach_nil {p : α Prop} : (#[] : Array { x // p x }).unattach = #[] := by
@[simp] theorem unattach_empty {p : α Prop} : (#[] : Array { x // p x }).unattach = #[] := by
simp [unattach]
@[deprecated unattach_empty (since := "2025-05-26")]
abbrev unattach_nil := @unattach_empty
@[simp] theorem unattach_push {p : α Prop} {a : { x // p x }} {xs : Array { x // p x }} :
(xs.push a).unattach = xs.unattach.push a.1 := by
simp only [unattach, Array.map_push]

View File

@@ -91,7 +91,8 @@ theorem ext' {xs ys : Array α} (h : xs.toList = ys.toList) : xs = ys := by
@[simp, grind =] theorem getElem_toList {xs : Array α} {i : Nat} (h : i < xs.size) : xs.toList[i] = xs[i] := rfl
@[simp, grind =] theorem getElem?_toList {xs : Array α} {i : Nat} : xs.toList[i]? = xs[i]? := by
simp [getElem?_def]
simp only [getElem?_def, getElem_toList]
simp only [Array.size]
/-- `a ∈ as` is a predicate which asserts that `a` is in the array `as`. -/
-- NB: This is defined as a structure rather than a plain def so that a lemma
@@ -112,7 +113,7 @@ theorem mem_def {a : α} {as : Array α} : a ∈ as ↔ a ∈ as.toList :=
rw [Array.mem_def, getElem_toList]
apply List.getElem_mem
@[simp] theorem emptyWithCapacity_eq {α n} : @emptyWithCapacity α n = #[] := rfl
@[simp, grind =] theorem emptyWithCapacity_eq {α n} : @emptyWithCapacity α n = #[] := rfl
@[simp] theorem mkEmpty_eq {α n} : @mkEmpty α n = #[] := rfl
@@ -167,7 +168,7 @@ Low-level indexing operator which is as fast as a C array read.
This avoids overhead due to unboxing a `Nat` used as an index.
-/
@[extern "lean_array_uget", simp]
@[extern "lean_array_uget", simp, expose]
def uget (a : @& Array α) (i : USize) (h : i.toNat < a.size) : α :=
a[i.toNat]
@@ -190,7 +191,7 @@ Examples:
* `#["orange", "yellow"].pop = #["orange"]`
* `(#[] : Array String).pop = #[]`
-/
@[extern "lean_array_pop"]
@[extern "lean_array_pop", expose]
def pop (xs : Array α) : Array α where
toList := xs.toList.dropLast
@@ -209,7 +210,7 @@ Examples:
* `Array.replicate 3 () = #[(), (), ()]`
* `Array.replicate 0 "anything" = #[]`
-/
@[extern "lean_mk_array"]
@[extern "lean_mk_array", expose]
def replicate {α : Type u} (n : Nat) (v : α) : Array α where
toList := List.replicate n v
@@ -237,7 +238,7 @@ Examples:
* `#["red", "green", "blue", "brown"].swap 1 2 = #["red", "blue", "green", "brown"]`
* `#["red", "green", "blue", "brown"].swap 3 0 = #["brown", "green", "blue", "red"]`
-/
@[extern "lean_array_fswap"]
@[extern "lean_array_fswap", expose]
def swap (xs : Array α) (i j : @& Nat) (hi : i < xs.size := by get_elem_tactic) (hj : j < xs.size := by get_elem_tactic) : Array α :=
let v₁ := xs[i]
let v₂ := xs[j]
@@ -267,8 +268,6 @@ def swapIfInBounds (xs : Array α) (i j : @& Nat) : Array α :=
else xs
else xs
@[deprecated swapIfInBounds (since := "2024-11-24")] abbrev swap! := @swapIfInBounds
/-! ### GetElem instance for `USize`, backed by `uget` -/
instance : GetElem (Array α) USize α fun xs i => i.toNat < xs.size where
@@ -290,6 +289,7 @@ Examples:
* `#[1, 2].isEmpty = false`
* `#[()].isEmpty = false`
-/
@[expose]
def isEmpty (xs : Array α) : Bool :=
xs.size = 0
@@ -331,12 +331,14 @@ Examples:
* `Array.ofFn (n := 3) toString = #["0", "1", "2"]`
* `Array.ofFn (fun i => #["red", "green", "blue"].get i.val i.isLt) = #["red", "green", "blue"]`
-/
def ofFn {n} (f : Fin n α) : Array α := go 0 (emptyWithCapacity n) where
/-- Auxiliary for `ofFn`. `ofFn.go f i acc = acc ++ #[f i, ..., f(n - 1)]` -/
@[semireducible] -- This is otherwise irreducible because it uses well-founded recursion.
go (i : Nat) (acc : Array α) : Array α :=
if h : i < n then go (i+1) (acc.push (f i, h)) else acc
decreasing_by simp_wf; decreasing_trivial_pre_omega
def ofFn {n} (f : Fin n α) : Array α := go (emptyWithCapacity n) n (Nat.le_refl n) where
/-- Auxiliary for `ofFn`. `ofFn.go f acc i h = acc ++ #[f (n - i), ..., f(n - 1)]` -/
go (acc : Array α) : (i : Nat) i n Array α
| i + 1, h =>
have w : n - i - 1 < n :=
Nat.lt_of_lt_of_le (Nat.sub_one_lt (Nat.sub_ne_zero_iff_lt.mpr h)) (Nat.sub_le n i)
go (acc.push (f n - i - 1, w)) i (Nat.le_of_succ_le h)
| 0, _ => acc
-- See also `Array.ofFnM` defined in `Init.Data.Array.OfFn`.
@@ -373,7 +375,7 @@ Examples:
* `Array.singleton 5 = #[5]`
* `Array.singleton "one" = #["one"]`
-/
@[inline] protected def singleton (v : α) : Array α := #[v]
@[inline, expose] protected def singleton (v : α) : Array α := #[v]
/--
Returns the last element of an array, or panics if the array is empty.
@@ -402,7 +404,7 @@ that requires a proof the array is non-empty.
def back? (xs : Array α) : Option α :=
xs[xs.size - 1]?
@[deprecated "Use `a[i]?` instead." (since := "2025-02-12")]
@[deprecated "Use `a[i]?` instead." (since := "2025-02-12"), expose]
def get? (xs : Array α) (i : Nat) : Option α :=
if h : i < xs.size then some xs[i] else none
@@ -416,7 +418,7 @@ Examples:
* `#["spinach", "broccoli", "carrot"].swapAt 1 "pepper" = ("broccoli", #["spinach", "pepper", "carrot"])`
* `#["spinach", "broccoli", "carrot"].swapAt 2 "pepper" = ("carrot", #["spinach", "broccoli", "pepper"])`
-/
@[inline] def swapAt (xs : Array α) (i : Nat) (v : α) (hi : i < xs.size := by get_elem_tactic) : α × Array α :=
@[inline, expose] def swapAt (xs : Array α) (i : Nat) (v : α) (hi : i < xs.size := by get_elem_tactic) : α × Array α :=
let e := xs[i]
let xs' := xs.set i v
(e, xs')
@@ -431,7 +433,7 @@ Examples:
* `#["spinach", "broccoli", "carrot"].swapAt! 1 "pepper" = (#["spinach", "pepper", "carrot"], "broccoli")`
* `#["spinach", "broccoli", "carrot"].swapAt! 2 "pepper" = (#["spinach", "broccoli", "pepper"], "carrot")`
-/
@[inline]
@[inline, expose]
def swapAt! (xs : Array α) (i : Nat) (v : α) : α × Array α :=
if h : i < xs.size then
swapAt xs i v
@@ -544,7 +546,7 @@ Examples:
-/
@[inline]
def modify (xs : Array α) (i : Nat) (f : α α) : Array α :=
Id.run <| modifyM xs i f
Id.run <| modifyM xs i (pure <| f ·)
set_option linter.indexVariables false in -- Changing `idx` causes bootstrapping issues, haven't investigated.
/--
@@ -577,7 +579,7 @@ def modifyOp (xs : Array α) (idx : Nat) (f : αα) : Array α :=
loop 0 b
/-- Reference implementation for `forIn'` -/
@[implemented_by Array.forIn'Unsafe]
@[implemented_by Array.forIn'Unsafe, expose]
protected def forIn' {α : Type u} {β : Type v} {m : Type v Type w} [Monad m] (as : Array α) (b : β) (f : (a : α) a as β m (ForInStep β)) : m β :=
let rec loop (i : Nat) (h : i as.size) (b : β) : m β := do
match i, h with
@@ -644,7 +646,7 @@ example [Monad m] (f : α → β → m α) :
```
-/
-- Reference implementation for `foldlM`
@[implemented_by foldlMUnsafe]
@[implemented_by foldlMUnsafe, expose]
def foldlM {α : Type u} {β : Type v} {m : Type v Type w} [Monad m] (f : β α m β) (init : β) (as : Array α) (start := 0) (stop := as.size) : m β :=
let fold (stop : Nat) (h : stop as.size) :=
let rec loop (i : Nat) (j : Nat) (b : β) : m β := do
@@ -709,7 +711,7 @@ example [Monad m] (f : α → β → m β) :
```
-/
-- Reference implementation for `foldrM`
@[implemented_by foldrMUnsafe]
@[implemented_by foldrMUnsafe, expose]
def foldrM {α : Type u} {β : Type v} {m : Type v Type w} [Monad m] (f : α β m β) (init : β) (as : Array α) (start := as.size) (stop := 0) : m β :=
let rec fold (i : Nat) (h : i as.size) (b : β) : m β := do
if i == stop then
@@ -764,13 +766,11 @@ def mapM {α : Type u} {β : Type v} {m : Type v → Type w} [Monad m] (f : α
decreasing_by simp_wf; decreasing_trivial_pre_omega
map 0 (emptyWithCapacity as.size)
@[deprecated mapM (since := "2024-11-11")] abbrev sequenceMap := @mapM
/--
Applies the monadic action `f` to every element in the array, along with the element's index and a
proof that the index is in bounds, from left to right. Returns the array of results.
-/
@[inline]
@[inline, expose]
def mapFinIdxM {α : Type u} {β : Type v} {m : Type v Type w} [Monad m]
(as : Array α) (f : (i : Nat) α (h : i < as.size) m β) : m (Array β) :=
let rec @[specialize] map (i : Nat) (j : Nat) (inv : i + j = as.size) (bs : Array β) : m (Array β) := do
@@ -788,7 +788,7 @@ def mapFinIdxM {α : Type u} {β : Type v} {m : Type v → Type w} [Monad m]
Applies the monadic action `f` to every element in the array, along with the element's index, from
left to right. Returns the array of results.
-/
@[inline]
@[inline, expose]
def mapIdxM {α : Type u} {β : Type v} {m : Type v Type w} [Monad m] (f : Nat α m β) (as : Array α) : m (Array β) :=
as.mapFinIdxM fun i a _ => f i a
@@ -834,7 +834,7 @@ Almost! 5
some 10
```
-/
@[inline]
@[inline, expose]
def findSomeM? {α : Type u} {β : Type v} {m : Type v Type w} [Monad m] (f : α m (Option β)) (as : Array α) : m (Option β) := do
for a in as do
match ( f a) with
@@ -915,7 +915,7 @@ The optional parameters `start` and `stop` control the region of the array to be
elements with indices from `start` (inclusive) to `stop` (exclusive) are checked. By default, the
entire array is checked.
-/
@[implemented_by anyMUnsafe]
@[implemented_by anyMUnsafe, expose]
def anyM {α : Type u} {m : Type Type w} [Monad m] (p : α m Bool) (as : Array α) (start := 0) (stop := as.size) : m Bool :=
let any (stop : Nat) (h : stop as.size) :=
let rec @[semireducible] -- This is otherwise irreducible because it uses well-founded recursion.
@@ -1057,9 +1057,9 @@ Examples:
* `#[1, 2, 3].foldl (· ++ toString ·) "" = "123"`
* `#[1, 2, 3].foldl (s!"({·} {·})") "" = "((( 1) 2) 3)"`
-/
@[inline]
@[inline, expose]
def foldl {α : Type u} {β : Type v} (f : β α β) (init : β) (as : Array α) (start := 0) (stop := as.size) : β :=
Id.run <| as.foldlM f init start stop
Id.run <| as.foldlM (pure <| f · ·) init start stop
/--
Folds a function over an array from the right, accumulating a value starting with `init`. The
@@ -1074,9 +1074,9 @@ Examples:
* `#[1, 2, 3].foldr (toString · ++ ·) "" = "123"`
* `#[1, 2, 3].foldr (s!"({·} {·})") "!" = "(1 (2 (3 !)))"`
-/
@[inline]
@[inline, expose]
def foldr {α : Type u} {β : Type v} (f : α β β) (init : β) (as : Array α) (start := as.size) (stop := 0) : β :=
Id.run <| as.foldrM f init start stop
Id.run <| as.foldrM (pure <| f · ·) init start stop
/--
Computes the sum of the elements of an array.
@@ -1085,7 +1085,7 @@ Examples:
* `#[a, b, c].sum = a + (b + (c + 0))`
* `#[1, 2, 5].sum = 8`
-/
@[inline]
@[inline, expose]
def sum {α} [Add α] [Zero α] : Array α α :=
foldr (· + ·) 0
@@ -1097,7 +1097,7 @@ Examples:
* `#[1, 2, 3, 4, 5].countP (· < 5) = 4`
* `#[1, 2, 3, 4, 5].countP (· > 5) = 0`
-/
@[inline]
@[inline, expose]
def countP {α : Type u} (p : α Bool) (as : Array α) : Nat :=
as.foldr (init := 0) fun a acc => bif p a then acc + 1 else acc
@@ -1109,7 +1109,7 @@ Examples:
* `#[1, 1, 2, 3, 5].count 5 = 1`
* `#[1, 1, 2, 3, 5].count 4 = 0`
-/
@[inline]
@[inline, expose]
def count {α : Type u} [BEq α] (a : α) (as : Array α) : Nat :=
countP (· == a) as
@@ -1122,9 +1122,9 @@ Examples:
* `#["one", "two", "three"].map (·.length) = #[3, 3, 5]`
* `#["one", "two", "three"].map (·.reverse) = #["eno", "owt", "eerht"]`
-/
@[inline]
@[inline, expose]
def map {α : Type u} {β : Type v} (f : α β) (as : Array α) : Array β :=
Id.run <| as.mapM f
Id.run <| as.mapM (pure <| f ·)
instance : Functor Array where
map := map
@@ -1137,9 +1137,9 @@ that the index is valid.
`Array.mapIdx` is a variant that does not provide the function with evidence that the index is
valid.
-/
@[inline]
@[inline, expose]
def mapFinIdx {α : Type u} {β : Type v} (as : Array α) (f : (i : Nat) α (h : i < as.size) β) : Array β :=
Id.run <| as.mapFinIdxM f
Id.run <| as.mapFinIdxM (pure <| f · · ·)
/--
Applies a function to each element of the array along with the index at which that element is found,
@@ -1148,9 +1148,9 @@ returning the array of results.
`Array.mapFinIdx` is a variant that additionally provides the function with a proof that the index
is valid.
-/
@[inline]
@[inline, expose]
def mapIdx {α : Type u} {β : Type v} (f : Nat α β) (as : Array α) : Array β :=
Id.run <| as.mapIdxM f
Id.run <| as.mapIdxM (pure <| f · ·)
/--
Pairs each element of an array with its index, optionally starting from an index other than `0`.
@@ -1159,6 +1159,7 @@ Examples:
* `#[a, b, c].zipIdx = #[(a, 0), (b, 1), (c, 2)]`
* `#[a, b, c].zipIdx 5 = #[(a, 5), (b, 6), (c, 7)]`
-/
@[expose]
def zipIdx (xs : Array α) (start := 0) : Array (α × Nat) :=
xs.mapIdx fun i a => (a, start + i)
@@ -1172,7 +1173,7 @@ Examples:
* `#[7, 6, 5, 8, 1, 2, 6].find? (· < 5) = some 1`
* `#[7, 6, 5, 8, 1, 2, 6].find? (· < 1) = none`
-/
@[inline]
@[inline, expose]
def find? {α : Type u} (p : α Bool) (as : Array α) : Option α :=
Id.run do
for a in as do
@@ -1196,9 +1197,9 @@ Example:
some 10
```
-/
@[inline]
@[inline, expose]
def findSome? {α : Type u} {β : Type v} (f : α Option β) (as : Array α) : Option β :=
Id.run <| as.findSomeM? f
Id.run <| as.findSomeM? (pure <| f ·)
/--
Returns the first non-`none` result of applying the function `f` to each element of the
@@ -1232,7 +1233,7 @@ Examples:
-/
@[inline]
def findSomeRev? {α : Type u} {β : Type v} (f : α Option β) (as : Array α) : Option β :=
Id.run <| as.findSomeRevM? f
Id.run <| as.findSomeRevM? (pure <| f ·)
/--
Returns the last element of the array for which the predicate `p` returns `true`, or `none` if no
@@ -1244,7 +1245,7 @@ Examples:
-/
@[inline]
def findRev? {α : Type} (p : α Bool) (as : Array α) : Option α :=
Id.run <| as.findRevM? p
Id.run <| as.findRevM? (pure <| p ·)
/--
Returns the index of the first element for which `p` returns `true`, or `none` if there is no such
@@ -1254,7 +1255,7 @@ Examples:
* `#[7, 6, 5, 8, 1, 2, 6].findIdx (· < 5) = some 4`
* `#[7, 6, 5, 8, 1, 2, 6].findIdx (· < 1) = none`
-/
@[inline]
@[inline, expose]
def findIdx? {α : Type u} (p : α Bool) (as : Array α) : Option Nat :=
let rec @[semireducible] -- This is otherwise irreducible because it uses well-founded recursion.
loop (j : Nat) :=
@@ -1308,7 +1309,7 @@ Examples:
* `#[7, 6, 5, 8, 1, 2, 6].findIdx (· < 5) = 4`
* `#[7, 6, 5, 8, 1, 2, 6].findIdx (· < 1) = 7`
-/
@[inline]
@[inline, expose]
def findIdx (p : α Bool) (as : Array α) : Nat := (as.findIdx? p).getD as.size
@[semireducible] -- This is otherwise irreducible because it uses well-founded recursion.
@@ -1362,10 +1363,6 @@ Examples:
def idxOf? [BEq α] (xs : Array α) (v : α) : Option Nat :=
(xs.finIdxOf? v).map (·.val)
@[deprecated idxOf? (since := "2024-11-20")]
def getIdx? [BEq α] (xs : Array α) (v : α) : Option Nat :=
xs.findIdx? fun a => a == v
/--
Returns `true` if `p` returns `true` for any element of `as`.
@@ -1381,9 +1378,9 @@ Examples:
* `#[2, 4, 5, 6].any (· % 2 = 0) = true`
* `#[2, 4, 5, 6].any (· % 2 = 1) = true`
-/
@[inline]
@[inline, expose]
def any (as : Array α) (p : α Bool) (start := 0) (stop := as.size) : Bool :=
Id.run <| as.anyM p start stop
Id.run <| as.anyM (pure <| p ·) start stop
/--
Returns `true` if `p` returns `true` for every element of `as`.
@@ -1401,7 +1398,7 @@ Examples:
-/
@[inline]
def all (as : Array α) (p : α Bool) (start := 0) (stop := as.size) : Bool :=
Id.run <| as.allM p start stop
Id.run <| as.allM (pure <| p ·) start stop
/--
Checks whether `a` is an element of `as`, using `==` to compare elements.
@@ -1412,6 +1409,7 @@ Examples:
* `#[1, 4, 2, 3, 3, 7].contains 3 = true`
* `Array.contains #[1, 4, 2, 3, 3, 7] 5 = false`
-/
@[expose]
def contains [BEq α] (as : Array α) (a : α) : Bool :=
as.any (a == ·)
@@ -1460,6 +1458,7 @@ Examples:
* `#[] ++ #[4, 5] = #[4, 5]`.
* `#[1, 2, 3] ++ #[] = #[1, 2, 3]`.
-/
@[expose]
protected def append (as : Array α) (bs : Array α) : Array α :=
bs.foldl (init := as) fun xs v => xs.push v
@@ -1497,7 +1496,7 @@ Examples:
* `#[2, 3, 2].flatMap Array.range = #[0, 1, 0, 1, 2, 0, 1]`
* `#[['a', 'b'], ['c', 'd', 'e']].flatMap List.toArray = #['a', 'b', 'c', 'd', 'e']`
-/
@[inline]
@[inline, expose]
def flatMap (f : α Array β) (as : Array α) : Array β :=
as.foldl (init := empty) fun bs a => bs ++ f a
@@ -1510,7 +1509,7 @@ Examples:
* `#[#[0, 1], #[], #[2], #[1, 0, 1]].flatten = #[0, 1, 2, 1, 0, 1]`
* `(#[] : Array Nat).flatten = #[]`
-/
@[inline] def flatten (xss : Array (Array α)) : Array α :=
@[inline, expose] def flatten (xss : Array (Array α)) : Array α :=
xss.foldl (init := empty) fun acc xs => acc ++ xs
/--
@@ -1523,6 +1522,7 @@ Examples:
* `#[0, 1].reverse = #[1, 0]`
* `#[0, 1, 2].reverse = #[2, 1, 0]`
-/
@[expose]
def reverse (as : Array α) : Array α :=
if h : as.size 1 then
as
@@ -1555,7 +1555,7 @@ Examples:
* `#[1, 2, 5, 2, 7, 7].filter (fun _ => true) (start := 3) = #[2, 7, 7]`
* `#[1, 2, 5, 2, 7, 7].filter (fun _ => true) (stop := 3) = #[1, 2, 5]`
-/
@[inline]
@[inline, expose]
def filter (p : α Bool) (as : Array α) (start := 0) (stop := as.size) : Array α :=
as.foldl (init := #[]) (start := start) (stop := stop) fun acc a =>
if p a then acc.push a else acc
@@ -1648,7 +1648,7 @@ Examining 7
#[10, 14, 14]
```
-/
@[specialize]
@[specialize, expose]
def filterMapM [Monad m] (f : α m (Option β)) (as : Array α) (start := 0) (stop := as.size) : m (Array β) :=
as.foldlM (init := #[]) (start := start) (stop := stop) fun bs a => do
match ( f a) with
@@ -1668,9 +1668,9 @@ Example:
#[10, 14, 14]
```
-/
@[inline]
@[inline, expose]
def filterMap (f : α Option β) (as : Array α) (start := 0) (stop := as.size) : Array β :=
Id.run <| as.filterMapM f (start := start) (stop := stop)
Id.run <| as.filterMapM (pure <| f ·) (start := start) (stop := stop)
/--
Returns the largest element of the array, as determined by the comparison `lt`, or `none` if
@@ -1881,8 +1881,6 @@ Examples:
let as := as.push a
loop as j, size_push .. j.lt_succ_self
@[deprecated insertIdx (since := "2024-11-20")] abbrev insertAt := @insertIdx
/--
Inserts an element into an array at the specified index. Panics if the index is greater than the
size of the array.
@@ -1903,8 +1901,6 @@ def insertIdx! (as : Array α) (i : Nat) (a : α) : Array α :=
insertIdx as i a
else panic! "invalid index"
@[deprecated insertIdx! (since := "2024-11-20")] abbrev insertAt! := @insertIdx!
/--
Inserts an element into an array at the specified index. The array is returned unmodified if the
index is greater than the size of the array.
@@ -2027,11 +2023,6 @@ Examples:
def unzip (as : Array (α × β)) : Array α × Array β :=
as.foldl (init := (#[], #[])) fun (as, bs) (a, b) => (as.push a, bs.push b)
@[deprecated partition (since := "2024-11-06")]
def split (as : Array α) (p : α Bool) : Array α × Array α :=
as.foldl (init := (#[], #[])) fun (as, bs) a =>
if p a then (as.push a, bs) else (as, bs.push a)
/--
Replaces the first occurrence of `a` with `b` in an array. The modification is performed in-place
when the reference to the array is unique. Returns the array unmodified when `a` is not present.

View File

@@ -88,4 +88,4 @@ pointer equality, and does not allocate a new array if the result of each functi
pointer-equal to its argument.
-/
@[inline] def Array.mapMono (as : Array α) (f : α α) : Array α :=
Id.run <| as.mapMonoM f
Id.run <| as.mapMonoM (pure <| f ·)

View File

@@ -129,6 +129,6 @@ Examples:
* `#[].binInsert (· < ·) 1 = #[1]`
-/
@[inline] def binInsert {α : Type u} (lt : α α Bool) (as : Array α) (k : α) : Array α :=
Id.run <| binInsertM lt (fun _ => k) (fun _ => k) as k
Id.run <| binInsertM lt (fun _ => pure k) (fun _ => pure k) as k
end Array

View File

@@ -40,7 +40,7 @@ Use the indexing notation `a[i]!` instead.
Access an element from an array, or panic if the index is out of bounds.
-/
@[deprecated "Use indexing notation `as[i]!` instead" (since := "2025-02-17")]
@[deprecated "Use indexing notation `as[i]!` instead" (since := "2025-02-17"), expose]
def get! {α : Type u} [Inhabited α] (a : @& Array α) (i : @& Nat) : α :=
Array.getD a i default
@@ -78,7 +78,8 @@ theorem foldrM_eq_reverse_foldlM_toList [Monad m] {f : α → β → m β} {init
have : xs = #[] 0 < xs.size :=
match xs with | [] => .inl rfl | a::l => .inr (Nat.zero_lt_succ _)
match xs, this with | _, .inl rfl => simp [foldrM] | xs, .inr h => ?_
simp [foldrM, h, foldrM_eq_reverse_foldlM_toList.aux, List.take_length]
simp only [foldrM, h, foldrM_eq_reverse_foldlM_toList.aux]
simp [Array.size]
@[simp, grind =] theorem foldrM_toList [Monad m]
{f : α β m β} {init : β} {xs : Array α} :
@@ -89,9 +90,13 @@ theorem foldrM_eq_reverse_foldlM_toList [Monad m] {f : α → β → m β} {init
xs.toList.foldr f init = xs.foldr f init :=
List.foldr_eq_foldrM .. foldrM_toList ..
@[simp, grind =] theorem push_toList {xs : Array α} {a : α} : (xs.push a).toList = xs.toList ++ [a] := by
@[simp, grind =] theorem toList_push {xs : Array α} {x : α} : (xs.push x).toList = xs.toList ++ [x] := by
rcases xs with xs
simp [push, List.concat_eq_append]
@[deprecated toList_push (since := "2025-05-26")]
abbrev push_toList := @toList_push
@[simp, grind =] theorem toListAppend_eq {xs : Array α} {l : List α} : xs.toListAppend l = xs.toList ++ l := by
simp [toListAppend, foldr_toList]
@@ -138,26 +143,4 @@ abbrev nil_append := @empty_append
@[deprecated toList_appendList (since := "2024-12-11")]
abbrev appendList_toList := @toList_appendList
@[deprecated "Use the reverse direction of `foldrM_toList`." (since := "2024-11-13")]
theorem foldrM_eq_foldrM_toList [Monad m]
{f : α β m β} {init : β} {xs : Array α} :
xs.foldrM f init = xs.toList.foldrM f init := by
simp
@[deprecated "Use the reverse direction of `foldlM_toList`." (since := "2024-11-13")]
theorem foldlM_eq_foldlM_toList [Monad m]
{f : β α m β} {init : β} {xs : Array α} :
xs.foldlM f init = xs.toList.foldlM f init:= by
simp
@[deprecated "Use the reverse direction of `foldr_toList`." (since := "2024-11-13")]
theorem foldr_eq_foldr_toList {f : α β β} {init : β} {xs : Array α} :
xs.foldr f init = xs.toList.foldr f init := by
simp
@[deprecated "Use the reverse direction of `foldl_toList`." (since := "2024-11-13")]
theorem foldl_eq_foldl_toList {f : β α β} {init : β} {xs : Array α} :
xs.foldl f init = xs.toList.foldl f init:= by
simp
end Array

View File

@@ -52,8 +52,8 @@ theorem countP_push {a : α} {xs : Array α} : countP p (xs.push a) = countP p x
rcases xs with xs
simp_all
@[simp] theorem countP_singleton {a : α} : countP p #[a] = if p a then 1 else 0 := by
simp [countP_push]
theorem countP_singleton {a : α} : countP p #[a] = if p a then 1 else 0 := by
simp
theorem size_eq_countP_add_countP {xs : Array α} : xs.size = countP p xs + countP (fun a => ¬p a) xs := by
rcases xs with xs
@@ -105,6 +105,7 @@ theorem boole_getElem_le_countP {xs : Array α} {i : Nat} (h : i < xs.size) :
theorem countP_set {xs : Array α} {i : Nat} {a : α} (h : i < xs.size) :
(xs.set i a).countP p = xs.countP p - (if p xs[i] then 1 else 0) + (if p a then 1 else 0) := by
rcases xs with xs
simp at h
simp [List.countP_set, h]
theorem countP_filter {xs : Array α} :

View File

@@ -69,7 +69,7 @@ theorem isEqv_eq_decide (xs ys : Array α) (r) :
simpa [isEqv_iff_rel] using h'
@[simp, grind =] theorem isEqv_toList [BEq α] (xs ys : Array α) : (xs.toList.isEqv ys.toList r) = (xs.isEqv ys r) := by
simp [isEqv_eq_decide, List.isEqv_eq_decide]
simp [isEqv_eq_decide, List.isEqv_eq_decide, Array.size]
theorem eq_of_isEqv [DecidableEq α] (xs ys : Array α) (h : Array.isEqv xs ys (fun x y => x = y)) : xs = ys := by
have h, h' := rel_of_isEqv h
@@ -100,7 +100,7 @@ theorem beq_eq_decide [BEq α] (xs ys : Array α) :
simp [BEq.beq, isEqv_eq_decide]
@[simp, grind =] theorem beq_toList [BEq α] (xs ys : Array α) : (xs.toList == ys.toList) = (xs == ys) := by
simp [beq_eq_decide, List.beq_eq_decide]
simp [beq_eq_decide, List.beq_eq_decide, Array.size]
end Array

View File

@@ -24,7 +24,7 @@ open Nat
/-! ### eraseP -/
@[simp] theorem eraseP_empty : #[].eraseP p = #[] := by simp
theorem eraseP_empty : #[].eraseP p = #[] := by simp
theorem eraseP_of_forall_mem_not {xs : Array α} (h : a, a xs ¬p a) : xs.eraseP p = xs := by
rcases xs with xs

View File

@@ -238,11 +238,9 @@ theorem extract_append_left {as bs : Array α} :
(as ++ bs).extract 0 as.size = as.extract 0 as.size := by
simp
@[simp] theorem extract_append_right {as bs : Array α} :
theorem extract_append_right {as bs : Array α} :
(as ++ bs).extract as.size (as.size + i) = bs.extract 0 i := by
simp only [extract_append, extract_size_left, Nat.sub_self, empty_append]
congr 1
omega
simp
@[simp] theorem map_extract {as : Array α} {i j : Nat} :
(as.extract i j).map f = (as.map f).extract i j := by

View File

@@ -142,9 +142,9 @@ abbrev findSome?_mkArray_of_isNone := @findSome?_replicate_of_isNone
@[simp] theorem find?_empty : find? p #[] = none := rfl
@[simp] theorem find?_singleton {a : α} {p : α Bool} :
theorem find?_singleton {a : α} {p : α Bool} :
#[a].find? p = if p a then some a else none := by
simp [singleton_eq_toArray_singleton]
simp
@[simp] theorem findRev?_push_of_pos {xs : Array α} (h : p a) :
findRev? p (xs.push a) = some a := by
@@ -347,7 +347,8 @@ theorem find?_eq_some_iff_getElem {xs : Array α} {p : α → Bool} {b : α} :
/-! ### findIdx -/
@[simp] theorem findIdx_empty : findIdx p #[] = 0 := rfl
theorem findIdx_empty : findIdx p #[] = 0 := rfl
theorem findIdx_singleton {a : α} {p : α Bool} :
#[a].findIdx p = if p a then 0 else 1 := by
simp
@@ -600,7 +601,8 @@ theorem findIdx?_eq_some_le_of_findIdx?_eq_some {xs : Array α} {p q : α → Bo
/-! ### findFinIdx? -/
@[simp] theorem findFinIdx?_empty {p : α Bool} : findFinIdx? p #[] = none := by simp
theorem findFinIdx?_empty {p : α Bool} : findFinIdx? p #[] = none := by simp
theorem findFinIdx?_singleton {a : α} {p : α Bool} :
#[a].findFinIdx? p = if p a then some 0, by simp else none := by
simp
@@ -653,13 +655,13 @@ theorem findFinIdx?_append {xs ys : Array α} {p : α → Bool} :
theorem isSome_findFinIdx? {xs : Array α} {p : α Bool} :
(xs.findFinIdx? p).isSome = xs.any p := by
rcases xs with xs
simp
simp [Array.size]
@[simp]
theorem isNone_findFinIdx? {xs : Array α} {p : α Bool} :
(xs.findFinIdx? p).isNone = xs.all (fun x => ¬ p x) := by
rcases xs with xs
simp
simp [Array.size]
@[simp] theorem findFinIdx?_subtype {p : α Prop} {xs : Array { x // p x }}
{f : { x // p x } Bool} {g : α Bool} (hf : x h, f x, h = g x) :
@@ -667,7 +669,8 @@ theorem isNone_findFinIdx? {xs : Array α} {p : α → Bool} :
cases xs
simp only [List.findFinIdx?_toArray, hf, List.findFinIdx?_subtype]
rw [findFinIdx?_congr List.unattach_toArray]
simp [Function.comp_def]
simp only [Option.map_map, Function.comp_def, Fin.cast_trans]
simp [Array.size]
/-! ### idxOf
@@ -699,7 +702,7 @@ The verification API for `idxOf?` is still incomplete.
The lemmas below should be made consistent with those for `findIdx?` (and proved using them).
-/
@[simp] theorem idxOf?_empty [BEq α] : (#[] : Array α).idxOf? a = none := by simp
theorem idxOf?_empty [BEq α] : (#[] : Array α).idxOf? a = none := by simp
@[simp] theorem idxOf?_eq_none_iff [BEq α] [LawfulBEq α] {xs : Array α} {a : α} :
xs.idxOf? a = none a xs := by
@@ -712,14 +715,10 @@ theorem isSome_idxOf? [BEq α] [LawfulBEq α] {xs : Array α} {a : α} :
rcases xs with xs
simp
@[simp]
theorem isNone_idxOf? [BEq α] [LawfulBEq α] {xs : Array α} {a : α} :
(xs.idxOf? a).isNone = ¬ a xs := by
rcases xs with xs
simp
/-! ### finIdxOf?
The verification API for `finIdxOf?` is still incomplete.
@@ -730,28 +729,27 @@ theorem idxOf?_eq_map_finIdxOf?_val [BEq α] {xs : Array α} {a : α} :
xs.idxOf? a = (xs.finIdxOf? a).map (·.val) := by
simp [idxOf?, finIdxOf?, findIdx?_eq_map_findFinIdx?_val]
@[simp] theorem finIdxOf?_empty [BEq α] : (#[] : Array α).finIdxOf? a = none := by simp
theorem finIdxOf?_empty [BEq α] : (#[] : Array α).finIdxOf? a = none := by simp
@[simp] theorem finIdxOf?_eq_none_iff [BEq α] [LawfulBEq α] {xs : Array α} {a : α} :
xs.finIdxOf? a = none a xs := by
rcases xs with xs
simp [List.finIdxOf?_eq_none_iff]
simp [List.finIdxOf?_eq_none_iff, Array.size]
@[simp] theorem finIdxOf?_eq_some_iff [BEq α] [LawfulBEq α] {xs : Array α} {a : α} {i : Fin xs.size} :
xs.finIdxOf? a = some i xs[i] = a j (_ : j < i), ¬xs[j] = a := by
rcases xs with xs
unfold Array.size at i
simp [List.finIdxOf?_eq_some_iff]
@[simp]
theorem isSome_finIdxOf? [BEq α] [LawfulBEq α] {xs : Array α} {a : α} :
(xs.finIdxOf? a).isSome a xs := by
rcases xs with xs
simp
simp [Array.size]
@[simp]
theorem isNone_finIdxOf? [BEq α] [LawfulBEq α] {xs : Array α} {a : α} :
(xs.finIdxOf? a).isNone = ¬ a xs := by
rcases xs with xs
simp
end Array

View File

@@ -44,6 +44,7 @@ theorem insertIdx_zero {xs : Array α} {x : α} : xs.insertIdx 0 x = #[x] ++ xs
@[simp] theorem size_insertIdx {xs : Array α} (h : i xs.size) : (xs.insertIdx i a).size = xs.size + 1 := by
rcases xs with xs
simp at h
simp [List.length_insertIdx, h]
theorem eraseIdx_insertIdx {i : Nat} {xs : Array α} (h : i xs.size) :

View File

@@ -63,7 +63,7 @@ theorem toArray_eq : List.toArray as = xs ↔ as = xs.toList := by
/-! ### size -/
@[grind ] theorem eq_empty_of_size_eq_zero (h : xs.size = 0) : xs = #[] := by
theorem eq_empty_of_size_eq_zero (h : xs.size = 0) : xs = #[] := by
cases xs
simp_all
@@ -75,8 +75,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 = #[] :=
@[simp] theorem size_eq_zero_iff : xs.size = 0 xs = #[] :=
eq_empty_of_size_eq_zero, fun h => h rfl
@[deprecated size_eq_zero_iff (since := "2025-02-24")]
@@ -117,14 +116,11 @@ abbrev size_eq_one := @size_eq_one_iff
/-! ## L[i] and L[i]? -/
@[simp] theorem getElem?_eq_none_iff {xs : Array α} : xs[i]? = none xs.size i := by
by_cases h : i < xs.size
· simp [getElem?_pos, h]
· rw [getElem?_neg xs i h]
simp_all
theorem getElem?_eq_none_iff {xs : Array α} : xs[i]? = none xs.size i := by
simp
@[simp] theorem none_eq_getElem?_iff {xs : Array α} {i : Nat} : none = xs[i]? xs.size i := by
simp [eq_comm (a := none)]
theorem none_eq_getElem?_iff {xs : Array α} {i : Nat} : none = xs[i]? xs.size i := by
simp
theorem getElem?_eq_none {xs : Array α} (h : xs.size i) : xs[i]? = none := by
simp [getElem?_eq_none_iff, h]
@@ -134,8 +130,8 @@ grind_pattern Array.getElem?_eq_none => xs.size ≤ i, xs[i]?
@[simp] theorem getElem?_eq_getElem {xs : Array α} {i : Nat} (h : i < xs.size) : xs[i]? = some xs[i] :=
getElem?_pos ..
theorem getElem?_eq_some_iff {xs : Array α} : xs[i]? = some b h : i < xs.size, xs[i] = b := by
simp [getElem?_def]
theorem getElem?_eq_some_iff {xs : Array α} : xs[i]? = some b h : i < xs.size, xs[i] = b :=
_root_.getElem?_eq_some_iff
@[grind ]
theorem getElem_of_getElem? {xs : Array α} : xs[i]? = some a h : i < xs.size, xs[i] = a :=
@@ -144,13 +140,13 @@ theorem getElem_of_getElem? {xs : Array α} : xs[i]? = some a → ∃ h : i < xs
theorem some_eq_getElem?_iff {xs : Array α} : some b = xs[i]? h : i < xs.size, xs[i] = b := by
rw [eq_comm, getElem?_eq_some_iff]
@[simp] theorem some_getElem_eq_getElem?_iff (xs : Array α) (i : Nat) (h : i < xs.size) :
theorem some_getElem_eq_getElem?_iff (xs : Array α) (i : Nat) (h : i < xs.size) :
(some xs[i] = xs[i]?) True := by
simp [h]
simp
@[simp] theorem getElem?_eq_some_getElem_iff (xs : Array α) (i : Nat) (h : i < xs.size) :
theorem getElem?_eq_some_getElem_iff (xs : Array α) (i : Nat) (h : i < xs.size) :
(xs[i]? = some xs[i]) True := by
simp [h]
simp
theorem getElem_eq_iff {xs : Array α} {i : Nat} {h : i < xs.size} : xs[i] = x xs[i]? = some x := by
simp only [getElem?_eq_some_iff]
@@ -173,6 +169,7 @@ theorem getD_getElem? {xs : Array α} {i : Nat} {d : α} :
theorem getElem_push_lt {xs : Array α} {x : α} {i : Nat} (h : i < xs.size) :
have : i < (xs.push x).size := by simp [*, Nat.lt_succ_of_le, Nat.le_of_lt]
(xs.push x)[i] = xs[i] := by
rw [Array.size] at h
simp only [push, getElem_toList, List.concat_eq_append, List.getElem_append_left, h]
@[simp] theorem getElem_push_eq {xs : Array α} {x : α} : (xs.push x)[xs.size] = x := by
@@ -186,16 +183,15 @@ theorem getElem_push {xs : Array α} {x : α} {i : Nat} (h : i < (xs.push x).siz
· simp at h
simp [getElem_push_lt, Nat.le_antisymm (Nat.le_of_lt_succ h) (Nat.ge_of_not_lt h')]
theorem getElem?_push {xs : Array α} {x} : (xs.push x)[i]? = if i = xs.size then some x else xs[i]? := by
@[grind =] theorem getElem?_push {xs : Array α} {x} : (xs.push x)[i]? = if i = xs.size then some x else xs[i]? := by
simp [getElem?_def, getElem_push]
(repeat' split) <;> first | rfl | omega
@[simp] theorem getElem?_push_size {xs : Array α} {x} : (xs.push x)[xs.size]? = some x := by
simp [getElem?_push]
theorem getElem?_push_size {xs : Array α} {x} : (xs.push x)[xs.size]? = some x := by
simp
@[simp] theorem getElem_singleton {a : α} {i : Nat} (h : i < 1) : #[a][i] = a :=
match i, h with
| 0, _ => rfl
theorem getElem_singleton {a : α} {i : Nat} (h : i < 1) : #[a][i] = a := by
simp
@[grind]
theorem getElem?_singleton {a : α} {i : Nat} : #[a][i]? = if i = 0 then some a else none := by
@@ -244,10 +240,6 @@ theorem back?_pop {xs : Array α} :
@[simp] theorem push_empty : #[].push x = #[x] := rfl
@[simp] theorem toList_push {xs : Array α} {x : α} : (xs.push x).toList = xs.toList ++ [x] := by
rcases xs with xs
simp
@[simp] theorem push_ne_empty {a : α} {xs : Array α} : xs.push a #[] := by
cases xs
simp
@@ -427,8 +419,7 @@ theorem eq_empty_iff_forall_not_mem {xs : Array α} : xs = #[] ↔ ∀ a, a ∉
theorem eq_of_mem_singleton (h : a #[b]) : a = b := by
simpa using h
@[simp] theorem mem_singleton {a b : α} : a #[b] a = b :=
eq_of_mem_singleton, (by simp [·])
theorem mem_singleton {a b : α} : a #[b] a = b := by simp
theorem forall_mem_push {p : α Prop} {xs : Array α} {a : α} :
( x, x xs.push a p x) p a x, x xs p x := by
@@ -613,13 +604,13 @@ theorem anyM_loop_cons [Monad m] {p : α → m Bool} {a : α} {as : List α} {st
-- Auxiliary for `any_iff_exists`.
theorem anyM_loop_iff_exists {p : α Bool} {as : Array α} {start stop} (h : stop as.size) :
anyM.loop (m := Id) p as stop h start = true
(anyM.loop (m := Id) (pure <| p ·) as stop h start).run = true
(i : Nat) (_ : i < as.size), start i i < stop p as[i] = true := by
unfold anyM.loop
split <;> rename_i h₁
· dsimp
split <;> rename_i h₂
· simp only [true_iff]
· simp only [true_iff, Id.run_pure]
refine start, by omega, by omega, by omega, h₂
· rw [anyM_loop_iff_exists]
constructor
@@ -636,9 +627,9 @@ termination_by stop - start
-- This could also be proved from `SatisfiesM_anyM_iff_exists` in `Batteries.Data.Array.Init.Monadic`
theorem any_iff_exists {p : α Bool} {as : Array α} {start stop} :
as.any p start stop (i : Nat) (_ : i < as.size), start i i < stop p as[i] := by
dsimp [any, anyM, Id.run]
dsimp [any, anyM]
split
· rw [anyM_loop_iff_exists]
· rw [anyM_loop_iff_exists (p := p)]
· rw [anyM_loop_iff_exists]
constructor
· rintro i, hi, ge, _, h
@@ -872,8 +863,8 @@ theorem elem_eq_mem [BEq α] [LawfulBEq α] {a : α} {xs : Array α} :
@[simp, grind] theorem contains_eq_mem [BEq α] [LawfulBEq α] {a : α} {xs : Array α} :
xs.contains a = decide (a xs) := by rw [ elem_eq_contains, elem_eq_mem]
@[simp, grind] theorem any_empty [BEq α] {p : α Bool} : (#[] : Array α).any p = false := by simp
@[simp, grind] theorem all_empty [BEq α] {p : α Bool} : (#[] : Array α).all p = true := by simp
@[grind] theorem any_empty [BEq α] {p : α Bool} : (#[] : Array α).any p = false := by simp
@[grind] theorem all_empty [BEq α] {p : α Bool} : (#[] : Array α).all p = true := by simp
/-- Variant of `any_push` with a side condition on `stop`. -/
@[simp, grind] theorem any_push' [BEq α] {xs : Array α} {a : α} {p : α Bool} (h : stop = xs.size + 1) :
@@ -1232,7 +1223,7 @@ where
@[simp] theorem mapM_empty [Monad m] (f : α m β) : mapM f #[] = pure #[] := by
rw [mapM, mapM.map]; rfl
@[simp, grind] theorem map_empty {f : α β} : map f #[] = #[] := mapM_empty f
@[grind] theorem map_empty {f : α β} : map f #[] = #[] := by simp
@[simp, grind] theorem map_push {f : α β} {as : Array α} {x : α} :
(as.push x).map f = (as.map f).push (f x) := by
@@ -1370,17 +1361,17 @@ theorem mapM_eq_mapM_toList [Monad m] [LawfulMonad m] {f : α → m β} {xs : Ar
@[deprecated "Use `mapM_eq_foldlM` instead" (since := "2025-01-08")]
theorem mapM_map_eq_foldl {as : Array α} {f : α β} {i : Nat} :
mapM.map (m := Id) f as i b = as.foldl (start := i) (fun acc a => acc.push (f a)) b := by
mapM.map (m := Id) (pure <| f ·) as i b = pure (as.foldl (start := i) (fun acc a => acc.push (f a)) b) := by
unfold mapM.map
split <;> rename_i h
· simp only [Id.bind_eq]
dsimp [foldl, Id.run, foldlM]
· ext : 1
dsimp [foldl, foldlM]
rw [mapM_map_eq_foldl, dif_pos (by omega), foldlM.loop, dif_pos h]
-- Calling `split` here gives a bad goal.
have : size as - i = Nat.succ (size as - i - 1) := by omega
rw [this]
simp [foldl, foldlM, Id.run, Nat.sub_add_eq]
· dsimp [foldl, Id.run, foldlM]
simp [foldl, foldlM, Nat.sub_add_eq]
· dsimp [foldl, foldlM]
rw [dif_pos (by omega), foldlM.loop, dif_neg h]
rfl
termination_by as.size - i
@@ -1602,8 +1593,8 @@ theorem filterMap_congr {as bs : Array α} (h : as = bs)
as.toList ++ List.filterMap f xs := ?_
exact this #[]
induction xs
· simp_all [Id.run]
· simp_all [Id.run, List.filterMap_cons]
· simp_all
· simp_all [List.filterMap_cons]
split <;> simp_all
@[grind] theorem toList_filterMap {f : α Option β} {xs : Array α} :
@@ -1817,7 +1808,8 @@ theorem toArray_append {xs : List α} {ys : Array α} :
theorem singleton_eq_toArray_singleton {a : α} : #[a] = [a].toArray := rfl
@[simp] theorem empty_append_fun : ((#[] : Array α) ++ ·) = id := by
@[deprecated empty_append (since := "2025-05-26")]
theorem empty_append_fun : ((#[] : Array α) ++ ·) = id := by
funext l
simp
@@ -1867,7 +1859,7 @@ theorem getElem_append_right {xs ys : Array α} {h : i < (xs ++ ys).size} (hle :
(xs ++ ys)[i] = ys[i - xs.size]'(Nat.sub_lt_left_of_lt_add hle (size_append .. h)) := by
simp only [ getElem_toList]
have h' : i < (xs.toList ++ ys.toList).length := by rwa [ length_toList, toList_append] at h
conv => rhs; rw [ List.getElem_append_right (h₁ := hle) (h₂ := h')]
conv => rhs; unfold Array.size; rw [ List.getElem_append_right (h₁ := hle) (h₂ := h')]
apply List.get_of_eq; rw [toList_append]
theorem getElem?_append_left {xs ys : Array α} {i : Nat} (hn : i < xs.size) :
@@ -1968,8 +1960,8 @@ theorem append_left_inj {xs₁ xs₂ : Array α} (ys) : xs₁ ++ ys = xs₂ ++ y
theorem eq_empty_of_append_eq_empty {xs ys : Array α} (h : xs ++ ys = #[]) : xs = #[] ys = #[] :=
append_eq_empty_iff.mp h
@[simp] theorem empty_eq_append_iff {xs ys : Array α} : #[] = xs ++ ys xs = #[] ys = #[] := by
rw [eq_comm, append_eq_empty_iff]
theorem empty_eq_append_iff {xs ys : Array α} : #[] = xs ++ ys xs = #[] ys = #[] := by
simp
theorem append_ne_empty_of_left_ne_empty {xs ys : Array α} (h : xs #[]) : xs ++ ys #[] := by
simp_all
@@ -2034,10 +2026,10 @@ theorem append_eq_append_iff {ws xs ys zs : Array α} :
xs ++ ys.set (i - xs.size) x (by simp at h; omega) := by
rcases xs with s
rcases ys with t
simp only [List.append_toArray, List.set_toArray, List.set_append]
simp only [List.append_toArray, List.set_toArray, List.set_append, Array.size]
split <;> simp
@[simp] theorem set_append_left {xs ys : Array α} {i : Nat} {x : α} (h : i < xs.size) :
@[simp] theorem set_append_left {xs ys : Array α} {i : Nat} {x : α} (h : i < xs.size) :
(xs ++ ys).set i x (by simp; omega) = xs.set i x ++ ys := by
simp [set_append, h]
@@ -2054,7 +2046,7 @@ theorem append_eq_append_iff {ws xs ys zs : Array α} :
xs ++ ys.setIfInBounds (i - xs.size) x := by
rcases xs with s
rcases ys with t
simp only [List.append_toArray, List.setIfInBounds_toArray, List.set_append]
simp only [List.append_toArray, List.setIfInBounds_toArray, List.set_append, Array.size]
split <;> simp
@[simp] theorem setIfInBounds_append_left {xs ys : Array α} {i : Nat} {x : α} (h : i < xs.size) :
@@ -2112,14 +2104,13 @@ theorem append_eq_map_iff {f : α → β} :
| nil => simp
| cons as => induction as.toList <;> simp [*]
@[simp] theorem flatten_map_toArray {L : List (List α)} :
(L.toArray.map List.toArray).flatten = L.flatten.toArray := by
@[simp] theorem flatten_toArray_map {L : List (List α)} :
(L.map List.toArray).toArray.flatten = L.flatten.toArray := by
apply ext'
simp [Function.comp_def]
@[simp] theorem flatten_toArray_map {L : List (List α)} :
(L.map List.toArray).toArray.flatten = L.flatten.toArray := by
rw [ flatten_map_toArray]
theorem flatten_map_toArray {L : List (List α)} :
(L.toArray.map List.toArray).flatten = L.flatten.toArray := by
simp
-- We set this to lower priority so that `flatten_toArray_map` is applied first when relevant.
@@ -2147,8 +2138,8 @@ theorem mem_flatten : ∀ {xss : Array (Array α)}, a ∈ xss.flatten ↔ ∃ xs
induction xss using array₂_induction
simp
@[simp] theorem empty_eq_flatten_iff {xss : Array (Array α)} : #[] = xss.flatten xs xss, xs = #[] := by
rw [eq_comm, flatten_eq_empty_iff]
theorem empty_eq_flatten_iff {xss : Array (Array α)} : #[] = xss.flatten xs xss, xs = #[] := by
simp
theorem flatten_ne_empty_iff {xss : Array (Array α)} : xss.flatten #[] xs, xs xss xs #[] := by
simp
@@ -2288,15 +2279,9 @@ theorem eq_iff_flatten_eq {xss₁ xss₂ : Array (Array α)} :
rw [List.map_inj_right]
simp +contextual
@[simp] theorem flatten_toArray_map_toArray {xss : List (List α)} :
theorem flatten_toArray_map_toArray {xss : List (List α)} :
(xss.map List.toArray).toArray.flatten = xss.flatten.toArray := by
simp [flatten]
suffices as, List.foldl (fun acc bs => acc ++ bs) as (List.map List.toArray xss) = as ++ xss.flatten.toArray by
simpa using this #[]
intro as
induction xss generalizing as with
| nil => simp
| cons xs xss ih => simp [ih]
simp
/-! ### flatMap -/
@@ -2326,13 +2311,9 @@ theorem flatMap_toArray_cons {β} {f : α → Array β} {a : α} {as : List α}
intro cs
induction as generalizing cs <;> simp_all
@[simp, grind =] theorem flatMap_toArray {β} {f : α Array β} {as : List α} :
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
| cons a as ih =>
apply ext'
simp [ih, flatMap_toArray_cons]
simp
@[simp] theorem flatMap_id {xss : Array (Array α)} : xss.flatMap id = xss.flatten := by simp [flatMap_def]
@@ -2798,7 +2779,7 @@ theorem reverse_eq_iff {xs ys : Array α} : xs.reverse = ys ↔ xs = ys.reverse
cases xs
simp
@[grind _=_]theorem filterMap_reverse {f : α Option β} {xs : Array α} : (xs.reverse.filterMap f) = (xs.filterMap f).reverse := by
@[grind _=_] theorem filterMap_reverse {f : α Option β} {xs : Array α} : (xs.reverse.filterMap f) = (xs.filterMap f).reverse := by
cases xs
simp
@@ -3034,19 +3015,21 @@ theorem take_size {xs : Array α} : xs.take xs.size = xs := by
| succ n ih =>
simp [shrink.loop, ih]
@[simp] theorem size_shrink {xs : Array α} {i : Nat} : (xs.shrink i).size = min i xs.size := by
-- This doesn't need to be a simp lemma, as shortly we will simplify `shrink` to `take`.
theorem size_shrink {xs : Array α} {i : Nat} : (xs.shrink i).size = min i xs.size := by
simp [shrink]
omega
@[simp] theorem getElem_shrink {xs : Array α} {i j : Nat} (h : j < (xs.shrink i).size) :
(xs.shrink i)[j] = xs[j]'(by simp at h; omega) := by
-- This doesn't need to be a simp lemma, as shortly we will simplify `shrink` to `take`.
theorem getElem_shrink {xs : Array α} {i j : Nat} (h : j < (xs.shrink i).size) :
(xs.shrink i)[j] = xs[j]'(by simp [size_shrink] at h; omega) := by
simp [shrink]
@[simp] theorem toList_shrink {xs : Array α} {i : Nat} : (xs.shrink i).toList = xs.toList.take i := by
apply List.ext_getElem <;> simp
@[simp] theorem shrink_eq_take {xs : Array α} {i : Nat} : xs.shrink i = xs.take i := by
ext <;> simp
ext <;> simp [size_shrink, getElem_shrink]
theorem toList_shrink {xs : Array α} {i : Nat} : (xs.shrink i).toList = xs.toList.take i := by
simp
/-! ### foldlM and foldrM -/
@@ -3215,18 +3198,16 @@ theorem foldlM_push [Monad m] [LawfulMonad m] {xs : Array α} {a : α} {f : β
rw [foldr, foldrM_start_stop, foldrM_toList, List.foldrM_pure, foldr_toList, foldr, foldrM_start_stop]
theorem foldl_eq_foldlM {f : β α β} {b} {xs : Array α} {start stop : Nat} :
xs.foldl f b start stop = xs.foldlM (m := Id) f b start stop := by
simp [foldl, Id.run]
xs.foldl f b start stop = (xs.foldlM (m := Id) (pure <| f · ·) b start stop).run := rfl
theorem foldr_eq_foldrM {f : α β β} {b} {xs : Array α} {start stop : Nat} :
xs.foldr f b start stop = xs.foldrM (m := Id) f b start stop := by
simp [foldr, Id.run]
xs.foldr f b start stop = (xs.foldrM (m := Id) (pure <| f · ·) b start stop).run := rfl
@[simp] theorem id_run_foldlM {f : β α Id β} {b} {xs : Array α} {start stop : Nat} :
Id.run (xs.foldlM f b start stop) = xs.foldl f b start stop := foldl_eq_foldlM.symm
Id.run (xs.foldlM f b start stop) = xs.foldl (f · · |>.run) b start stop := rfl
@[simp] theorem id_run_foldrM {f : α β Id β} {b} {xs : Array α} {start stop : Nat} :
Id.run (xs.foldrM f b start stop) = xs.foldr f b start stop := foldr_eq_foldrM.symm
Id.run (xs.foldrM f b start stop) = xs.foldr (f · · |>.run) b start stop := rfl
/-- Variant of `foldlM_reverse` with a side condition for the `stop` argument. -/
@[simp] theorem foldlM_reverse' [Monad m] {xs : Array α} {f : β α m β} {b} {stop : Nat}
@@ -3255,7 +3236,7 @@ theorem foldrM_reverse [Monad m] {xs : Array α} {f : α → β → m β} {b} :
theorem foldrM_push [Monad m] {f : α β m β} {init : β} {xs : Array α} {a : α} :
(xs.push a).foldrM f init = f a init >>= xs.foldrM f := by
simp only [foldrM_eq_reverse_foldlM_toList, push_toList, List.reverse_append, List.reverse_cons,
simp only [foldrM_eq_reverse_foldlM_toList, toList_push, List.reverse_append, List.reverse_cons,
List.reverse_nil, List.nil_append, List.singleton_append, List.foldlM_cons, List.foldlM_reverse]
/--
@@ -3526,17 +3507,16 @@ theorem foldrM_append [Monad m] [LawfulMonad m] {f : α → β → m β} {b} {xs
@[simp] theorem foldr_append' {f : α β β} {b} {xs ys : Array α} {start : Nat}
(w : start = xs.size + ys.size) :
(xs ++ ys).foldr f b start 0 = xs.foldr f (ys.foldr f b) := by
subst w
simp [foldr_eq_foldrM]
(xs ++ ys).foldr f b start 0 = xs.foldr f (ys.foldr f b) :=
foldrM_append' w
@[grind _=_]theorem foldl_append {β : Type _} {f : β α β} {b} {xs ys : Array α} :
(xs ++ ys).foldl f b = ys.foldl f (xs.foldl f b) := by
simp [foldl_eq_foldlM]
@[grind _=_] theorem foldl_append {β : Type _} {f : β α β} {b} {xs ys : Array α} :
(xs ++ ys).foldl f b = ys.foldl f (xs.foldl f b) :=
foldlM_append
@[grind _=_] theorem foldr_append {f : α β β} {b} {xs ys : Array α} :
(xs ++ ys).foldr f b = xs.foldr f (ys.foldr f b) := by
simp [foldr_eq_foldrM]
(xs ++ ys).foldr f b = xs.foldr f (ys.foldr f b) :=
foldrM_append
@[simp] theorem foldl_flatten' {f : β α β} {b} {xss : Array (Array α)} {stop : Nat}
(w : stop = xss.flatten.size) :
@@ -3565,21 +3545,22 @@ theorem foldrM_append [Monad m] [LawfulMonad m] {f : α → β → m β} {b} {xs
/-- Variant of `foldl_reverse` with a side condition for the `stop` argument. -/
@[simp] theorem foldl_reverse' {xs : Array α} {f : β α β} {b} {stop : Nat}
(w : stop = xs.size) :
xs.reverse.foldl f b 0 stop = xs.foldr (fun x y => f y x) b := by
simp [w, foldl_eq_foldlM, foldr_eq_foldrM]
xs.reverse.foldl f b 0 stop = xs.foldr (fun x y => f y x) b :=
foldlM_reverse' w
/-- Variant of `foldr_reverse` with a side condition for the `start` argument. -/
@[simp] theorem foldr_reverse' {xs : Array α} {f : α β β} {b} {start : Nat}
(w : start = xs.size) :
xs.reverse.foldr f b start 0 = xs.foldl (fun x y => f y x) b := by
simp [w, foldl_eq_foldlM, foldr_eq_foldrM]
xs.reverse.foldr f b start 0 = xs.foldl (fun x y => f y x) b :=
foldrM_reverse' w
@[grind] theorem foldl_reverse {xs : Array α} {f : β α β} {b} :
xs.reverse.foldl f b = xs.foldr (fun x y => f y x) b := by simp [foldl_eq_foldlM, foldr_eq_foldrM]
xs.reverse.foldl f b = xs.foldr (fun x y => f y x) b :=
foldlM_reverse
@[grind] theorem foldr_reverse {xs : Array α} {f : α β β} {b} :
xs.reverse.foldr f b = xs.foldl (fun x y => f y x) b :=
(foldl_reverse ..).symm.trans <| by simp
foldrM_reverse
theorem foldl_eq_foldr_reverse {xs : Array α} {f : β α β} {b} :
xs.foldl f b = xs.reverse.foldr (fun x y => f y x) b := by simp
@@ -3660,7 +3641,7 @@ theorem foldr_rel {xs : Array α} {f g : α → β → β} {a b : β} {r : β
theorem back?_eq_some_iff {xs : Array α} {a : α} :
xs.back? = some a ys : Array α, xs = ys.push a := by
rcases xs with xs
simp only [List.back?_toArray, List.getLast?_eq_some_iff, toArray_eq, push_toList]
simp only [List.back?_toArray, List.getLast?_eq_some_iff, toArray_eq, toList_push]
constructor
· rintro ys, rfl
exact ys.toArray, by simp
@@ -3785,7 +3766,7 @@ theorem contains_iff_exists_mem_beq [BEq α] {xs : Array α} {a : α} :
rcases xs with xs
simp [List.contains_iff_exists_mem_beq]
@[grind]
@[grind _=_]
theorem contains_iff_mem [BEq α] [LawfulBEq α] {xs : Array α} {a : α} :
xs.contains a a xs := by
simp
@@ -4094,15 +4075,16 @@ abbrev all_mkArray := @all_replicate
/-! ### modify -/
@[simp] theorem size_modify {xs : Array α} {i : Nat} {f : α α} : (xs.modify i f).size = xs.size := by
unfold modify modifyM Id.run
unfold modify modifyM
split <;> simp
theorem getElem_modify {xs : Array α} {j i} (h : i < (xs.modify j f).size) :
(xs.modify j f)[i] = if j = i then f (xs[i]'(by simpa using h)) else xs[i]'(by simpa using h) := by
simp only [modify, modifyM, Id.run, Id.pure_eq]
simp only [modify, modifyM]
split
· simp only [Id.bind_eq, getElem_set]; split <;> simp [*]
· rw [if_neg (mt (by rintro rfl; exact h) (by simp_all))]
· simp only [getElem_set, Id.run_pure, Id.run_bind]; split <;> simp [*]
· simp only [Id.run_pure]
rw [if_neg (mt (by rintro rfl; exact h) (by simp_all))]
@[simp] theorem toList_modify {xs : Array α} {f : α α} {i : Nat} :
(xs.modify i f).toList = xs.toList.modify i f := by
@@ -4171,8 +4153,6 @@ theorem swap_comm {xs : Array α} {i j : Nat} (hi hj) : xs.swap i j hi hj = xs.s
@[simp] theorem size_swapIfInBounds {xs : Array α} {i j : Nat} :
(xs.swapIfInBounds i j).size = xs.size := by unfold swapIfInBounds; split <;> (try split) <;> simp [size_swap]
@[deprecated size_swapIfInBounds (since := "2024-11-24")] abbrev size_swap! := @size_swapIfInBounds
/-! ### swapAt -/
@[simp] theorem swapAt_def {xs : Array α} {i : Nat} {v : α} (hi) :
@@ -4304,42 +4284,44 @@ Examples:
/-! ### Preliminaries about `ofFn` -/
@[simp] theorem size_ofFn_go {n} {f : Fin n α} {i acc} :
(ofFn.go f i acc).size = acc.size + (n - i) := by
if hin : i < n then
unfold ofFn.go
have : 1 + (n - (i + 1)) = n - i :=
Nat.sub_sub .. Nat.add_sub_cancel' (Nat.le_sub_of_add_le (Nat.add_comm .. hin))
rw [dif_pos hin, size_ofFn_go, size_push, Nat.add_assoc, this]
else
have : n - i = 0 := Nat.sub_eq_zero_of_le (Nat.le_of_not_lt hin)
unfold ofFn.go
simp [hin, this]
termination_by n - i
@[simp] theorem size_ofFn_go {n} {f : Fin n α} {i acc h} :
(ofFn.go f acc i h).size = acc.size + i := by
induction i generalizing acc with
| zero => simp [ofFn.go]
| succ i ih =>
simpa [ofFn.go, ih] using Nat.succ_add_eq_add_succ acc.size i
@[simp] theorem size_ofFn {n : Nat} {f : Fin n α} : (ofFn f).size = n := by simp [ofFn]
theorem getElem_ofFn_go {f : Fin n α} {i} {acc k}
(hki : k < n) (hin : i n) (hi : i = acc.size)
(hacc : j, hj : j < acc.size, acc[j] = f j, Nat.lt_of_lt_of_le hj (hi hin)) :
haveI : acc.size + (n - acc.size) = n := Nat.add_sub_cancel' (hi hin)
(ofFn.go f i acc)[k]'(by simp [*]) = f k, hki := by
unfold ofFn.go
if hin : i < n then
have : 1 + (n - (i + 1)) = n - i :=
Nat.sub_sub .. Nat.add_sub_cancel' (Nat.le_sub_of_add_le (Nat.add_comm .. hin))
simp only [dif_pos hin]
rw [getElem_ofFn_go _ hin (by simp [*]) (fun j hj => ?hacc)]
cases (Nat.lt_or_eq_of_le <| Nat.le_of_lt_succ (by simpa using hj)) with
| inl hj => simp [getElem_push, hj, hacc j hj]
| inr hj => simp [getElem_push, *]
else
simp [hin, hacc k (Nat.lt_of_lt_of_le hki (Nat.le_of_not_lt (hi hin)))]
termination_by n - i
-- Recall `ofFn.go f acc i h = acc ++ #[f (n - i), ..., f(n - 1)]`
theorem getElem_ofFn_go {f : Fin n α} {acc i k} (h : i n) (w₁ : k < acc.size + i) :
(ofFn.go f acc i h)[k]'(by simpa using w₁) =
if w₂ : k < acc.size then acc[k] else f n - i + k - acc.size, by omega := by
induction i generalizing acc k with
| zero =>
simp at w₁
simp_all [ofFn.go]
| succ i ih =>
unfold ofFn.go
rw [ih]
· simp only [size_push]
split <;> rename_i h'
· rw [Array.getElem_push]
split
· rfl
· congr 2
omega
· split
· omega
· congr 2
omega
· simp
omega
@[simp] theorem getElem_ofFn {f : Fin n α} {i : Nat} (h : i < (ofFn f).size) :
(ofFn f)[i] = f i, size_ofFn (f := f) h :=
getElem_ofFn_go _ (by simp) (by simp) nofun
(ofFn f)[i] = f i, size_ofFn (f := f) h := by
unfold ofFn
rw [getElem_ofFn_go] <;> simp_all
theorem getElem?_ofFn {f : Fin n α} {i : Nat} :
(ofFn f)[i]? = if h : i < n then some (f i, h) else none := by
@@ -4430,7 +4412,8 @@ theorem getElem!_eq_getD [Inhabited α] {xs : Array α} {i} : xs[i]! = xs.getD i
/-! # mem -/
@[simp, grind =] theorem mem_toList {a : α} {xs : Array α} : a xs.toList a xs := mem_def.symm
@[deprecated mem_toList_iff (since := "2025-05-26")]
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
@@ -4450,7 +4433,7 @@ theorem getElem?_size_le {xs : Array α} {i : Nat} (h : xs.size ≤ i) : xs[i]?
simp [getElem?_neg, h]
theorem getElem_mem_toList {xs : Array α} {i : Nat} (h : i < xs.size) : xs[i] xs.toList := by
simp only [ getElem_toList, List.getElem_mem]
simp only [ getElem_toList, List.getElem_mem, ugetElem_eq_getElem]
theorem back!_eq_back? [Inhabited α] {xs : Array α} : xs.back! = xs.back?.getD default := by
simp [back!, back?, getElem!_def, Option.getD]; rfl
@@ -4479,7 +4462,7 @@ theorem getElem?_push_eq {xs : Array α} {x : α} : (xs.push x)[xs.size]? = some
simp
@[simp, grind =] theorem forIn'_toList [Monad m] {xs : Array α} {b : β} {f : (a : α) a xs.toList β m (ForInStep β)} :
forIn' xs.toList b f = forIn' xs b (fun a m b => f a (mem_toList.mpr m) b) := by
forIn' xs.toList b f = forIn' xs b (fun a m b => f a (mem_toList_iff.mpr m) b) := by
cases xs
simp
@@ -4518,6 +4501,7 @@ abbrev contains_def [DecidableEq α] {a : α} {xs : Array α} : xs.contains a
@[simp] theorem size_zipWith {xs : Array α} {ys : Array β} {f : α β γ} :
(zipWith f xs ys).size = min xs.size ys.size := by
rw [size_eq_length_toList, toList_zipWith, List.length_zipWith]
simp only [Array.size]
@[simp] theorem size_zip {xs : Array α} {ys : Array β} :
(zip xs ys).size = min xs.size ys.size :=
@@ -4576,8 +4560,8 @@ Our goal is to have `simp` "pull `List.toArray` outwards" as much as possible.
theorem toListRev_toArray {l : List α} : l.toArray.toListRev = l.reverse := by simp
@[simp, grind =] theorem take_toArray {l : List α} {i : Nat} : l.toArray.take i = (l.take i).toArray := by
apply Array.ext <;> simp
@[grind =] theorem take_toArray {l : List α} {i : Nat} : l.toArray.take i = (l.take i).toArray := by
simp
@[simp, grind =] theorem mapM_toArray [Monad m] [LawfulMonad m] {f : α m β} {l : List α} :
l.toArray.mapM f = List.toArray <$> l.mapM f := by
@@ -4590,7 +4574,7 @@ theorem toListRev_toArray {l : List α} : l.toArray.toListRev = l.reverse := by
| nil => simp
| cons a l ih =>
simp only [foldlM_toArray] at ih
rw [size_toArray, mapM'_cons, foldlM_toArray]
rw [size_toArray, mapM'_cons]
simp [ih]
theorem uset_toArray {l : List α} {i : USize} {a : α} {h : i.toNat < l.toArray.size} :
@@ -4643,12 +4627,12 @@ namespace Array
@[simp] theorem findSomeRev?_eq_findSome?_reverse {f : α Option β} {xs : Array α} :
xs.findSomeRev? f = xs.reverse.findSome? f := by
cases xs
simp [findSomeRev?, Id.run]
simp [findSomeRev?]
@[simp] theorem findRev?_eq_find?_reverse {f : α Bool} {xs : Array α} :
xs.findRev? f = xs.reverse.find? f := by
cases xs
simp [findRev?, Id.run]
simp [findRev?]
/-! ### unzip -/
@@ -4704,13 +4688,6 @@ namespace List
end List
/-! ### Deprecations -/
namespace List
@[deprecated setIfInBounds_toArray (since := "2024-11-24")] abbrev setD_toArray := @setIfInBounds_toArray
end List
namespace Array
@[deprecated size_toArray (since := "2024-12-11")]
@@ -4763,17 +4740,6 @@ theorem get_set_eq (xs : Array α) (i : Nat) (v : α) (h : i < xs.size) :
(xs.set i v h)[i]'(by simp [h]) = v := by
simp only [set, getElem_toList, List.getElem_set_self]
@[deprecated set!_is_setIfInBounds (since := "2024-11-24")] abbrev set_is_setIfInBounds := @set!_eq_setIfInBounds
@[deprecated size_setIfInBounds (since := "2024-11-24")] abbrev size_setD := @size_setIfInBounds
@[deprecated getElem_setIfInBounds_eq (since := "2024-11-24")] abbrev getElem_setD_eq := @getElem_setIfInBounds_self
@[deprecated getElem?_setIfInBounds_eq (since := "2024-11-24")] abbrev get?_setD_eq := @getElem?_setIfInBounds_self
@[deprecated getD_getElem?_setIfInBounds (since := "2025-04-04")] abbrev getD_get?_setIfInBounds := @getD_getElem?_setIfInBounds
@[deprecated getD_getElem?_setIfInBounds (since := "2024-11-24")] abbrev getD_setD := @getD_getElem?_setIfInBounds
@[deprecated getElem_setIfInBounds (since := "2024-11-24")] abbrev getElem_setD := @getElem_setIfInBounds
@[deprecated List.getElem_toArray (since := "2024-11-29")]
theorem getElem_mk {xs : List α} {i : Nat} (h : i < xs.length) : (Array.mk xs)[i] = xs[i] := rfl
@[deprecated Array.getElem_toList (since := "2024-12-08")]
theorem getElem_eq_getElem_toList {xs : Array α} (h : i < xs.size) : xs[i] = xs.toList[i] := rfl

View File

@@ -29,16 +29,12 @@ protected theorem not_le_iff_gt [DecidableEq α] [LT α] [DecidableLT α] {xs ys
Decidable.not_not
@[simp] theorem lex_empty [BEq α] {lt : α α Bool} {xs : Array α} : xs.lex #[] lt = false := by
simp [lex, Id.run]
@[simp] theorem singleton_lex_singleton [BEq α] {lt : α α Bool} : #[a].lex #[b] lt = lt a b := by
simp only [lex, List.getElem_toArray, List.getElem_singleton]
cases lt a b <;> cases a != b <;> simp [Id.run]
simp [lex]
private theorem cons_lex_cons [BEq α] {lt : α α Bool} {a b : α} {xs ys : Array α} :
(#[a] ++ xs).lex (#[b] ++ ys) lt =
(lt a b || a == b && xs.lex ys lt) := by
simp only [lex, Id.run]
simp only [lex]
simp only [Std.Range.forIn'_eq_forIn'_range', size_append, List.size_toArray, List.length_singleton,
Nat.add_comm 1]
simp [Nat.add_min_add_right, List.range'_succ, getElem_append_left, List.range'_succ_left,
@@ -51,13 +47,16 @@ private theorem cons_lex_cons [BEq α] {lt : αα → Bool} {a b : α} {xs
@[simp, grind =] theorem _root_.List.lex_toArray [BEq α] {lt : α α Bool} {l₁ l₂ : List α} :
l₁.toArray.lex l₂.toArray lt = l₁.lex l₂ lt := by
induction l₁ generalizing l₂ with
| nil => cases l₂ <;> simp [lex, Id.run]
| nil => cases l₂ <;> simp [lex]
| cons x l₁ ih =>
cases l₂ with
| nil => simp [lex, Id.run]
| nil => simp [lex]
| cons y l₂ =>
rw [List.toArray_cons, List.toArray_cons y, cons_lex_cons, List.lex, ih]
theorem singleton_lex_singleton [BEq α] {lt : α α Bool} : #[a].lex #[b] lt = lt a b := by
simp
@[simp, grind =] theorem lex_toList [BEq α] {lt : α α Bool} {xs ys : Array α} :
xs.toList.lex ys.toList lt = xs.lex ys lt := by
cases xs <;> cases ys <;> simp

View File

@@ -27,7 +27,7 @@ theorem mapFinIdx_induction (xs : Array α) (f : (i : Nat) → α → (h : i < x
motive xs.size eq : (Array.mapFinIdx xs f).size = xs.size,
i h, p i ((Array.mapFinIdx xs f)[i]) h := by
let rec go {bs i j h} (h₁ : j = bs.size) (h₂ : i h h', p i bs[i] h) (hm : motive j) :
let as : Array β := Array.mapFinIdxM.map (m := Id) xs f i j h bs
let as : Array β := Id.run <| Array.mapFinIdxM.map xs (pure <| f · · ·) i j h bs
motive xs.size eq : as.size = xs.size, i h, p i as[i] h := by
induction i generalizing j bs with simp [mapFinIdxM.map]
| zero =>
@@ -192,7 +192,8 @@ theorem mapFinIdx_empty {f : (i : Nat) → α → (h : i < 0) → β} : mapFinId
theorem mapFinIdx_eq_ofFn {xs : Array α} {f : (i : Nat) α (h : i < xs.size) β} :
xs.mapFinIdx f = Array.ofFn fun i : Fin xs.size => f i xs[i] i.2 := by
cases xs
simp [List.mapFinIdx_eq_ofFn]
simp only [List.mapFinIdx_toArray, List.mapFinIdx_eq_ofFn, Fin.getElem_fin, List.getElem_toArray]
simp [Array.size]
theorem mapFinIdx_append {xs ys : Array α} {f : (i : Nat) α (h : i < (xs ++ ys).size) β} :
(xs ++ ys).mapFinIdx f =
@@ -200,7 +201,7 @@ theorem mapFinIdx_append {xs ys : Array α} {f : (i : Nat) → α → (h : i < (
ys.mapFinIdx (fun i a h => f (i + xs.size) a (by simp; omega)) := by
cases xs
cases ys
simp [List.mapFinIdx_append]
simp [List.mapFinIdx_append, Array.size]
@[simp]
theorem mapFinIdx_push {xs : Array α} {a : α} {f : (i : Nat) α (h : i < (xs.push a).size) β} :
@@ -264,12 +265,12 @@ theorem mapFinIdx_eq_append_iff {xs : Array α} {f : (i : Nat) → α → (h : i
toArray_eq_append_iff]
constructor
· rintro l₁, l₂, rfl, rfl, rfl
refine l₁.toArray, l₂.toArray, by simp_all
refine l₁.toArray, l₂.toArray, by simp_all [Array.size]
· rintro l₁, l₂, rfl, h₁, h₂
simp [ toList_inj] at h₁ h₂
obtain rfl := h₁
obtain rfl := h₂
refine l₁, l₂, by simp_all
refine l₁, l₂, by simp_all [Array.size]
theorem mapFinIdx_eq_push_iff {xs : Array α} {b : β} {f : (i : Nat) α (h : i < xs.size) β} :
xs.mapFinIdx f = ys.push b
@@ -307,7 +308,7 @@ abbrev mapFinIdx_eq_mkArray_iff := @mapFinIdx_eq_replicate_iff
@[simp] theorem mapFinIdx_reverse {xs : Array α} {f : (i : Nat) α (h : i < xs.reverse.size) β} :
xs.reverse.mapFinIdx f = (xs.mapFinIdx (fun i a h => f (xs.size - 1 - i) a (by simp; omega))).reverse := by
rcases xs with l
simp [List.mapFinIdx_reverse]
simp [List.mapFinIdx_reverse, Array.size]
/-! ### mapIdx -/
@@ -486,7 +487,7 @@ namespace List
| x :: xs => simp only [mapFinIdxM.go, mapIdxM.go, go]
unfold Array.mapIdxM
rw [mapFinIdxM_toArray]
simp only [mapFinIdxM, mapIdxM]
simp only [mapFinIdxM, mapIdxM, Array.size]
rw [go]
end List

View File

@@ -25,10 +25,10 @@ open Nat
/-! ## Monadic operations -/
@[simp] theorem map_toList_inj [Monad m] [LawfulMonad m]
theorem map_toList_inj [Monad m] [LawfulMonad m]
{xs : m (Array α)} {ys : m (Array α)} :
toList <$> xs = toList <$> ys xs = ys :=
_root_.map_inj_right (by simp)
toList <$> xs = toList <$> ys xs = ys := by
simp
/-! ### mapM -/
@@ -36,7 +36,11 @@ open Nat
xs.mapM (m := m) (pure <| f ·) = pure (xs.map f) := by
induction xs; simp_all
@[simp] theorem mapM_id {xs : Array α} {f : α Id β} : xs.mapM f = xs.map f :=
@[simp] theorem idRun_mapM {xs : Array α} {f : α Id β} : (xs.mapM f).run = xs.map (f · |>.run) :=
mapM_pure
@[deprecated idRun_mapM (since := "2025-05-21")]
theorem mapM_id {xs : Array α} {f : α Id β} : xs.mapM f = xs.map f :=
mapM_pure
@[simp] theorem mapM_map [Monad m] [LawfulMonad m] {f : α β} {g : β m γ} {xs : Array α} :
@@ -191,12 +195,18 @@ theorem forIn'_eq_foldlM [Monad m] [LawfulMonad m]
rcases xs with xs
simp [List.forIn'_pure_yield_eq_foldl, List.foldl_map]
@[simp] theorem forIn'_yield_eq_foldl
theorem idRun_forIn'_yield_eq_foldl
{xs : Array α} (f : (a : α) a xs β Id β) (init : β) :
(forIn' xs init (fun a m b => .yield <$> f a m b)).run =
xs.attach.foldl (fun b a, h => f a h b |>.run) init := by
simp
@[deprecated idRun_forIn'_yield_eq_foldl (since := "2025-05-21")]
theorem forIn'_yield_eq_foldl
{xs : Array α} (f : (a : α) a xs β β) (init : β) :
forIn' (m := Id) xs init (fun a m b => .yield (f a m b)) =
xs.attach.foldl (fun b a, h => f a h b) init := by
rcases xs with xs
simp [List.foldl_map]
xs.attach.foldl (fun b a, h => f a h b) init :=
forIn'_pure_yield_eq_foldl _ _
@[simp] theorem forIn'_map [Monad m] [LawfulMonad m]
{xs : Array α} (g : α β) (f : (b : β) b xs.map g γ m (ForInStep γ)) :
@@ -233,12 +243,18 @@ theorem forIn_eq_foldlM [Monad m] [LawfulMonad m]
rcases xs with xs
simp [List.forIn_pure_yield_eq_foldl, List.foldl_map]
@[simp] theorem forIn_yield_eq_foldl
theorem idRun_forIn_yield_eq_foldl
{xs : Array α} (f : α β Id β) (init : β) :
(forIn xs init (fun a b => .yield <$> f a b)).run =
xs.foldl (fun b a => f a b |>.run) init := by
simp
@[deprecated idRun_forIn_yield_eq_foldl (since := "2025-05-21")]
theorem forIn_yield_eq_foldl
{xs : Array α} (f : α β β) (init : β) :
forIn (m := Id) xs init (fun a b => .yield (f a b)) =
xs.foldl (fun b a => f a b) init := by
rcases xs with xs
simp [List.foldl_map]
xs.foldl (fun b a => f a b) init :=
forIn_pure_yield_eq_foldl _ _
@[simp] theorem forIn_map [Monad m] [LawfulMonad m]
{xs : Array α} {g : α β} {f : β γ m (ForInStep γ)} :
@@ -294,7 +310,7 @@ namespace List
@[simp] theorem filterM_toArray' [Monad m] [LawfulMonad m] {l : List α} {p : α m Bool} (w : stop = l.length) :
l.toArray.filterM p 0 stop = toArray <$> l.filterM p := by
subst w
rw [filterM_toArray]
simp [ filterM_toArray]
@[grind =] theorem filterRevM_toArray [Monad m] [LawfulMonad m] {l : List α} {p : α m Bool} :
l.toArray.filterRevM p = toArray <$> l.filterRevM p := by
@@ -306,7 +322,7 @@ namespace List
@[simp] theorem filterRevM_toArray' [Monad m] [LawfulMonad m] {l : List α} {p : α m Bool} (w : start = l.length) :
l.toArray.filterRevM p start 0 = toArray <$> l.filterRevM p := by
subst w
rw [filterRevM_toArray]
simp [ filterRevM_toArray]
@[grind =] theorem filterMapM_toArray [Monad m] [LawfulMonad m] {l : List α} {f : α m (Option β)} :
l.toArray.filterMapM f = toArray <$> l.filterMapM f := by
@@ -324,7 +340,7 @@ namespace List
@[simp] theorem filterMapM_toArray' [Monad m] [LawfulMonad m] {l : List α} {f : α m (Option β)} (w : stop = l.length) :
l.toArray.filterMapM f 0 stop = toArray <$> l.filterMapM f := by
subst w
rw [filterMapM_toArray]
simp [ filterMapM_toArray]
@[simp, grind =] theorem flatMapM_toArray [Monad m] [LawfulMonad m] {l : List α} {f : α m (Array β)} :
l.toArray.flatMapM f = toArray <$> l.flatMapM (fun a => Array.toList <$> f a) := by

View File

@@ -82,7 +82,7 @@ theorem ofFnM_succ' {n} [Monad m] [LawfulMonad m] {f : Fin (n + 1) → m α} :
let a f 0
let as ofFnM fun i => f i.succ
pure (#[a] ++ as)) := by
simp [ofFnM, Fin.foldlM_eq_finRange_foldlM, List.foldlM_push_eq_append, List.finRange_succ, Function.comp_def]
simp [ofFnM, Fin.foldlM_eq_foldlM_finRange, List.foldlM_push_eq_append, List.finRange_succ, Function.comp_def]
theorem ofFnM_succ {n} [Monad m] [LawfulMonad m] {f : Fin (n + 1) m α} :
ofFnM f = (do
@@ -129,7 +129,6 @@ theorem ofFnM_pure [Monad m] [LawfulMonad m] {n} {f : Fin n → α} :
@[simp, grind =] theorem idRun_ofFnM {f : Fin n Id α} :
Id.run (ofFnM f) = ofFn (fun i => Id.run (f i)) := by
unfold Id.run
induction n with
| zero => simp
| succ n ih => simp [ofFnM_succ', ofFn_succ', ih]

View File

@@ -27,23 +27,27 @@ Internal implementation of `Array.qsort`.
It does so by first swapping the elements at indices `lo`, `mid := (lo + hi) / 2`, and `hi`
if necessary so that the middle (pivot) element is at index `hi`.
We then iterate from `j = lo` to `j = hi`, with a pointer `i` starting at `lo`, and
We then iterate from `k = lo` to `k = hi`, with a pointer `i` starting at `lo`, and
swapping each element which is less than the pivot to position `i`, and then incrementing `i`.
-/
def qpartition {n} (as : Vector α n) (lt : α α Bool) (lo hi : Nat)
(hlo : lo < n := by omega) (hhi : hi < n := by omega) : {m : Nat // lo m m < n} × Vector α n :=
def qpartition {n} (as : Vector α n) (lt : α α Bool) (lo hi : Nat) (w : lo hi := by omega)
(hlo : lo < n := by omega) (hhi : hi < n := by omega) : {m : Nat // lo m m hi} × Vector α n :=
let mid := (lo + hi) / 2
let as := if lt as[mid] as[lo] then as.swap lo mid else as
let as := if lt as[hi] as[lo] then as.swap lo hi else as
let as := if lt as[mid] as[hi] then as.swap mid hi else as
let pivot := as[hi]
let rec loop (as : Vector α n) (i j : Nat)
(ilo : lo i := by omega) (jh : j < n := by omega) (w : i j := by omega) :=
if h : j < hi then
if lt as[j] pivot then
loop (as.swap i j) (i+1) (j+1)
-- During this loop, elements below in `[lo, i)` are less than `pivot`,
-- elements in `[i, k)` are greater than or equal to `pivot`,
-- elements in `[k, hi)` are unexamined,
-- while `as[hi]` is (by definition) the pivot.
let rec loop (as : Vector α n) (i k : Nat)
(ilo : lo i := by omega) (ik : i k := by omega) (w : k hi := by omega) :=
if h : k < hi then
if lt as[k] pivot then
loop (as.swap i k) (i+1) (k+1)
else
loop as i (j+1)
loop as i (k+1)
else
(i, ilo, by omega, as.swap i hi)
loop as lo lo
@@ -51,25 +55,28 @@ def qpartition {n} (as : Vector α n) (lt : αα → Bool) (lo hi : Nat)
/--
In-place quicksort.
`qsort as lt low high` sorts the subarray `as[low:high+1]` in-place using `lt` to compare elements.
`qsort as lt lo hi` sorts the subarray `as[lo:hi+1]` in-place using `lt` to compare elements.
-/
@[inline] def qsort (as : Array α) (lt : α α Bool := by exact (· < ·))
(low := 0) (high := as.size - 1) : Array α :=
let rec @[specialize] sort {n} (as : Vector α n) (lo hi : Nat)
(lo := 0) (hi := as.size - 1) : Array α :=
let rec @[specialize] sort {n} (as : Vector α n) (lo hi : Nat) (w : lo hi := by omega)
(hlo : lo < n := by omega) (hhi : hi < n := by omega) :=
if h₁ : lo < hi then
let mid, hmid, as := qpartition as lt lo hi
if h₂ : mid hi then
-- This only occurs when `hi ≤ lo`,
-- and thus `as[lo:hi+1]` is trivially already sorted.
as
else
-- Otherwise, we recursively sort the two subarrays.
sort (sort as lo mid) (mid+1) hi
else as
if h : as.size = 0 then
as
else
let low := min low (as.size - 1)
let high := min high (as.size - 1)
sort as.toVector low high |>.toArray
let lo := min lo (as.size - 1)
let hi := max lo (min hi (as.size - 1))
sort as.toVector lo hi |>.toArray
set_option linter.unusedVariables.funArgs false in
/--

View File

@@ -24,7 +24,7 @@ Examples:
* `#[0, 1, 2].set 1 5 = #[0, 5, 2]`
* `#["orange", "apple"].set 1 "grape" = #["orange", "grape"]`
-/
@[extern "lean_array_fset"]
@[extern "lean_array_fset", expose]
def Array.set (xs : Array α) (i : @& Nat) (v : α) (h : i < xs.size := by get_elem_tactic) :
Array α where
toList := xs.toList.set i v
@@ -40,17 +40,15 @@ Examples:
* `#["orange", "apple"].setIfInBounds 1 "grape" = #["orange", "grape"]`
* `#["orange", "apple"].setIfInBounds 5 "grape" = #["orange", "apple"]`
-/
@[inline] def Array.setIfInBounds (xs : Array α) (i : Nat) (v : α) : Array α :=
@[inline, expose] def Array.setIfInBounds (xs : Array α) (i : Nat) (v : α) : Array α :=
dite (LT.lt i xs.size) (fun h => xs.set i v h) (fun _ => xs)
@[deprecated Array.setIfInBounds (since := "2024-11-24")] abbrev Array.setD := @Array.setIfInBounds
/--
Set an element in an array, or panic if the index is out of bounds.
This will perform the update destructively provided that `a` has a reference
count of 1 when called.
-/
@[extern "lean_array_set"]
@[extern "lean_array_set", expose]
def Array.set! (xs : Array α) (i : @& Nat) (v : α) : Array α :=
Array.setIfInBounds xs i v

View File

@@ -290,7 +290,7 @@ Examples:
-/
@[inline]
def foldl {α : Type u} {β : Type v} (f : β α β) (init : β) (as : Subarray α) : β :=
Id.run <| as.foldlM f (init := init)
Id.run <| as.foldlM (pure <| f · ·) (init := init)
/--
Folds an operation from right to left over the elements in a subarray.
@@ -304,7 +304,7 @@ Examples:
-/
@[inline]
def foldr {α : Type u} {β : Type v} (f : α β β) (init : β) (as : Subarray α) : β :=
Id.run <| as.foldrM f (init := init)
Id.run <| as.foldrM (pure <| f · ·) (init := init)
/--
Checks whether any of the elements in a subarray satisfy a Boolean predicate.
@@ -314,7 +314,7 @@ an element that satisfies the predicate is found.
-/
@[inline]
def any {α : Type u} (p : α Bool) (as : Subarray α) : Bool :=
Id.run <| as.anyM p
Id.run <| as.anyM (pure <| p ·)
/--
Checks whether all of the elements in a subarray satisfy a Boolean predicate.
@@ -324,7 +324,7 @@ an element that does not satisfy the predicate is found.
-/
@[inline]
def all {α : Type u} (p : α Bool) (as : Subarray α) : Bool :=
Id.run <| as.allM p
Id.run <| as.allM (pure <| p ·)
/--
Applies a monadic function to each element in a subarray in reverse order, stopping at the first
@@ -394,7 +394,7 @@ Examples:
-/
@[inline]
def findRev? {α : Type} (as : Subarray α) (p : α Bool) : Option α :=
Id.run <| as.findRevM? p
Id.run <| as.findRevM? (pure <| p ·)
end Subarray

View File

@@ -334,11 +334,13 @@ abbrev zipWithAll_mkArray := @zipWithAll_replicate
/-! ### unzip -/
@[simp] theorem unzip_fst : (unzip l).fst = l.map Prod.fst := by
induction l <;> simp_all
@[deprecated fst_unzip (since := "2025-05-26")]
theorem unzip_fst : (unzip l).fst = l.map Prod.fst := by
simp
@[simp] theorem unzip_snd : (unzip l).snd = l.map Prod.snd := by
induction l <;> simp_all
@[deprecated snd_unzip (since := "2025-05-26")]
theorem unzip_snd : (unzip l).snd = l.map Prod.snd := by
simp
theorem unzip_eq_map {xs : Array (α × β)} : unzip xs = (xs.map Prod.fst, xs.map Prod.snd) := by
cases xs
@@ -371,7 +373,7 @@ theorem unzip_zip {as : Array α} {bs : Array β} (h : as.size = bs.size) :
theorem zip_of_prod {as : Array α} {bs : Array β} {xs : Array (α × β)} (hl : xs.map Prod.fst = as)
(hr : xs.map Prod.snd = bs) : xs = as.zip bs := by
rw [ hl, hr, zip_unzip xs, unzip_fst, unzip_snd, zip_unzip, zip_unzip]
rw [ hl, hr, zip_unzip xs, fst_unzip, snd_unzip, zip_unzip, zip_unzip]
@[simp] theorem unzip_replicate {n : Nat} {a : α} {b : β} :
unzip (replicate n (a, b)) = (replicate n a, replicate n b) := by

View File

@@ -27,7 +27,7 @@ class EquivBEq (α) [BEq α] : Prop extends PartialEquivBEq α, ReflBEq α
theorem BEq.symm [BEq α] [PartialEquivBEq α] {a b : α} : a == b b == a :=
PartialEquivBEq.symm
@[grind] theorem BEq.comm [BEq α] [PartialEquivBEq α] {a b : α} : (a == b) = (b == a) :=
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

View File

@@ -61,7 +61,7 @@ end subsingleton
section zero_allOnes
/-- Returns a bitvector of size `n` where all bits are `0`. -/
protected def zero (n : Nat) : BitVec n := .ofNatLT 0 (Nat.two_pow_pos n)
@[expose] protected def zero (n : Nat) : BitVec n := .ofNatLT 0 (Nat.two_pow_pos n)
instance : Inhabited (BitVec n) where default := .zero n
/-- Returns a bitvector of size `n` where all bits are `1`. -/
@@ -77,10 +77,10 @@ Returns the `i`th least significant bit.
This will be renamed `getLsb` after the existing deprecated alias is removed.
-/
@[inline] def getLsb' (x : BitVec w) (i : Fin w) : Bool := x.toNat.testBit i
@[inline, expose] def getLsb' (x : BitVec w) (i : Fin w) : Bool := x.toNat.testBit i
/-- Returns the `i`th least significant bit, or `none` if `i ≥ w`. -/
@[inline] def getLsb? (x : BitVec w) (i : Nat) : Option Bool :=
@[inline, expose] def getLsb? (x : BitVec w) (i : Nat) : Option Bool :=
if h : i < w then some (getLsb' x i, h) else none
/--
@@ -95,7 +95,7 @@ This will be renamed `BitVec.getMsb` after the existing deprecated alias is remo
if h : i < w then some (getMsb' x i, h) else none
/-- Returns the `i`th least significant bit or `false` if `i ≥ w`. -/
@[inline] def getLsbD (x : BitVec w) (i : Nat) : Bool :=
@[inline, expose] def getLsbD (x : BitVec w) (i : Nat) : Bool :=
x.toNat.testBit i
/-- Returns the `i`th most significant bit, or `false` if `i ≥ w`. -/
@@ -134,6 +134,7 @@ section Int
/--
Interprets the bitvector as an integer stored in two's complement form.
-/
@[expose]
protected def toInt (x : BitVec n) : Int :=
if 2 * x.toNat < 2^n then
x.toNat
@@ -147,6 +148,7 @@ over- and underflowing as needed.
The underlying `Nat` is `(2^n + (i mod 2^n)) mod 2^n`. Converting the bitvector back to an `Int`
with `BitVec.toInt` results in the value `i.bmod (2^n)`.
-/
@[expose]
protected def ofInt (n : Nat) (i : Int) : BitVec n := .ofNatLT (i % (Int.ofNat (2^n))).toNat (by
apply (Int.toNat_lt _).mpr
· apply Int.emod_lt_of_pos
@@ -218,12 +220,14 @@ Usually accessed via the `-` prefix operator.
SMT-LIB name: `bvneg`.
-/
@[expose]
protected def neg (x : BitVec n) : BitVec n := .ofNat n (2^n - x.toNat)
instance : Neg (BitVec n) := .neg
/--
Returns the absolute value of a signed bitvector.
-/
@[expose]
protected def abs (x : BitVec n) : BitVec n := if x.msb then .neg x else x
/--
@@ -232,6 +236,7 @@ modulo `2^n`. Usually accessed via the `*` operator.
SMT-LIB name: `bvmul`.
-/
@[expose]
protected def mul (x y : BitVec n) : BitVec n := BitVec.ofNat n (x.toNat * y.toNat)
instance : Mul (BitVec n) := .mul
@@ -242,6 +247,7 @@ Note that this is currently an inefficient implementation,
and should be replaced via an `@[extern]` with a native implementation.
See https://github.com/leanprover/lean4/issues/7887.
-/
@[expose]
protected def pow (x : BitVec n) (y : Nat) : BitVec n :=
match y with
| 0 => 1
@@ -253,6 +259,7 @@ instance : Pow (BitVec n) Nat where
Unsigned division of bitvectors using the Lean convention where division by zero returns zero.
Usually accessed via the `/` operator.
-/
@[expose]
def udiv (x y : BitVec n) : BitVec n :=
(x.toNat / y.toNat)#'(Nat.lt_of_le_of_lt (Nat.div_le_self _ _) x.isLt)
instance : Div (BitVec n) := .udiv
@@ -262,6 +269,7 @@ Unsigned modulo for bitvectors. Usually accessed via the `%` operator.
SMT-LIB name: `bvurem`.
-/
@[expose]
def umod (x y : BitVec n) : BitVec n :=
(x.toNat % y.toNat)#'(Nat.lt_of_le_of_lt (Nat.mod_le _ _) x.isLt)
instance : Mod (BitVec n) := .umod
@@ -273,6 +281,7 @@ where division by zero returns `BitVector.allOnes n`.
SMT-LIB name: `bvudiv`.
-/
@[expose]
def smtUDiv (x y : BitVec n) : BitVec n := if y = 0 then allOnes n else udiv x y
/--
@@ -342,6 +351,7 @@ end arithmetic
section bool
/-- Turns a `Bool` into a bitvector of length `1`. -/
@[expose]
def ofBool (b : Bool) : BitVec 1 := cond b 1 0
@[simp] theorem ofBool_false : ofBool false = 0 := by trivial
@@ -359,6 +369,7 @@ Unsigned less-than for bitvectors.
SMT-LIB name: `bvult`.
-/
@[expose]
protected def ult (x y : BitVec n) : Bool := x.toNat < y.toNat
/--
@@ -366,6 +377,7 @@ Unsigned less-than-or-equal-to for bitvectors.
SMT-LIB name: `bvule`.
-/
@[expose]
protected def ule (x y : BitVec n) : Bool := x.toNat y.toNat
/--
@@ -377,6 +389,7 @@ Examples:
* `BitVec.slt 6#4 7 = true`
* `BitVec.slt 7#4 8 = false`
-/
@[expose]
protected def slt (x y : BitVec n) : Bool := x.toInt < y.toInt
/--
@@ -384,6 +397,7 @@ Signed less-than-or-equal-to for bitvectors.
SMT-LIB name: `bvsle`.
-/
@[expose]
protected def sle (x y : BitVec n) : Bool := x.toInt y.toInt
end relations
@@ -397,7 +411,7 @@ width `m`.
Using `x.cast eq` should be preferred over `eq ▸ x` because there are special-purpose `simp` lemmas
that can more consistently simplify `BitVec.cast` away.
-/
@[inline] protected def cast (eq : n = m) (x : BitVec n) : BitVec m := .ofNatLT x.toNat (eq x.isLt)
@[inline, expose] protected def cast (eq : n = m) (x : BitVec n) : BitVec m := .ofNatLT x.toNat (eq x.isLt)
@[simp] theorem cast_ofNat {n m : Nat} (h : n = m) (x : Nat) :
(BitVec.ofNat n x).cast h = BitVec.ofNat m x := by
@@ -413,6 +427,7 @@ that can more consistently simplify `BitVec.cast` away.
Extracts the bits `start` to `start + len - 1` from a bitvector of size `n` to yield a
new bitvector of size `len`. If `start + len > n`, then the bitvector is zero-extended.
-/
@[expose]
def extractLsb' (start len : Nat) (x : BitVec n) : BitVec len := .ofNat _ (x.toNat >>> start)
/--
@@ -423,6 +438,7 @@ The resulting bitvector has size `hi - lo + 1`.
SMT-LIB name: `extract`.
-/
@[expose]
def extractLsb (hi lo : Nat) (x : BitVec n) : BitVec (hi - lo + 1) := extractLsb' lo _ x
/--
@@ -431,6 +447,7 @@ Increases the width of a bitvector to one that is at least as large by zero-exte
This is a constant-time operation because the underlying `Nat` is unmodified; because the new width
is at least as large as the old one, no overflow is possible.
-/
@[expose]
def setWidth' {n w : Nat} (le : n w) (x : BitVec n) : BitVec w :=
x.toNat#'(by
apply Nat.lt_of_lt_of_le x.isLt
@@ -439,6 +456,7 @@ def setWidth' {n w : Nat} (le : n ≤ w) (x : BitVec n) : BitVec w :=
/--
Returns `zeroExtend (w+n) x <<< n` without needing to compute `x % 2^(2+n)`.
-/
@[expose]
def shiftLeftZeroExtend (msbs : BitVec w) (m : Nat) : BitVec (w + m) :=
let shiftLeftLt {x : Nat} (p : x < 2^w) (m : Nat) : x <<< m < 2^(w + m) := by
simp [Nat.shiftLeft_eq, Nat.pow_add]
@@ -495,6 +513,7 @@ SMT-LIB name: `bvand`.
Example:
* `0b1010#4 &&& 0b0110#4 = 0b0010#4`
-/
@[expose]
protected def and (x y : BitVec n) : BitVec n :=
(x.toNat &&& y.toNat)#'(Nat.and_lt_two_pow x.toNat y.isLt)
instance : AndOp (BitVec w) := .and
@@ -507,6 +526,7 @@ SMT-LIB name: `bvor`.
Example:
* `0b1010#4 ||| 0b0110#4 = 0b1110#4`
-/
@[expose]
protected def or (x y : BitVec n) : BitVec n :=
(x.toNat ||| y.toNat)#'(Nat.or_lt_two_pow x.isLt y.isLt)
instance : OrOp (BitVec w) := .or
@@ -519,6 +539,7 @@ SMT-LIB name: `bvxor`.
Example:
* `0b1010#4 ^^^ 0b0110#4 = 0b1100#4`
-/
@[expose]
protected def xor (x y : BitVec n) : BitVec n :=
(x.toNat ^^^ y.toNat)#'(Nat.xor_lt_two_pow x.isLt y.isLt)
instance : Xor (BitVec w) := .xor
@@ -531,6 +552,7 @@ SMT-LIB name: `bvnot`.
Example:
* `~~~(0b0101#4) == 0b1010`
-/
@[expose]
protected def not (x : BitVec n) : BitVec n := allOnes n ^^^ x
instance : Complement (BitVec w) := .not
@@ -540,6 +562,7 @@ equivalent to `x * 2^s`, modulo `2^n`.
SMT-LIB name: `bvshl` except this operator uses a `Nat` shift value.
-/
@[expose]
protected def shiftLeft (x : BitVec n) (s : Nat) : BitVec n := BitVec.ofNat n (x.toNat <<< s)
instance : HShiftLeft (BitVec w) Nat (BitVec w) := .shiftLeft
@@ -551,6 +574,7 @@ As a numeric operation, this is equivalent to `x / 2^s`, rounding down.
SMT-LIB name: `bvlshr` except this operator uses a `Nat` shift value.
-/
@[expose]
def ushiftRight (x : BitVec n) (s : Nat) : BitVec n :=
(x.toNat >>> s)#'(by
let x, lt := x
@@ -568,6 +592,7 @@ As a numeric operation, this is equivalent to `x.toInt >>> s`.
SMT-LIB name: `bvashr` except this operator uses a `Nat` shift value.
-/
@[expose]
def sshiftRight (x : BitVec n) (s : Nat) : BitVec n := .ofInt n (x.toInt >>> s)
instance {n} : HShiftLeft (BitVec m) (BitVec n) (BitVec m) := fun x y => x <<< y.toNat
@@ -581,10 +606,12 @@ As a numeric operation, this is equivalent to `a.toInt >>> s.toNat`.
SMT-LIB name: `bvashr`.
-/
@[expose]
def sshiftRight' (a : BitVec n) (s : BitVec m) : BitVec n := a.sshiftRight s.toNat
/-- Auxiliary function for `rotateLeft`, which does not take into account the case where
the rotation amount is greater than the bitvector width. -/
@[expose]
def rotateLeftAux (x : BitVec w) (n : Nat) : BitVec w :=
x <<< n ||| x >>> (w - n)
@@ -599,6 +626,7 @@ SMT-LIB name: `rotate_left`, except this operator uses a `Nat` shift amount.
Example:
* `(0b0011#4).rotateLeft 3 = 0b1001`
-/
@[expose]
def rotateLeft (x : BitVec w) (n : Nat) : BitVec w := rotateLeftAux x (n % w)
@@ -606,6 +634,7 @@ def rotateLeft (x : BitVec w) (n : Nat) : BitVec w := rotateLeftAux x (n % w)
Auxiliary function for `rotateRight`, which does not take into account the case where
the rotation amount is greater than the bitvector width.
-/
@[expose]
def rotateRightAux (x : BitVec w) (n : Nat) : BitVec w :=
x >>> n ||| x <<< (w - n)
@@ -620,6 +649,7 @@ SMT-LIB name: `rotate_right`, except this operator uses a `Nat` shift amount.
Example:
* `rotateRight 0b01001#5 1 = 0b10100`
-/
@[expose]
def rotateRight (x : BitVec w) (n : Nat) : BitVec w := rotateRightAux x (n % w)
/--
@@ -631,6 +661,7 @@ SMT-LIB name: `concat`.
Example:
* `0xAB#8 ++ 0xCD#8 = 0xABCD#16`.
-/
@[expose]
def append (msbs : BitVec n) (lsbs : BitVec m) : BitVec (n+m) :=
shiftLeftZeroExtend msbs m ||| setWidth' (Nat.le_add_left m n) lsbs
@@ -653,6 +684,7 @@ result of appending a single bit to the front in the naive implementation).
/-- Append a single bit to the end of a bitvector, using big endian order (see `append`).
That is, the new bit is the least significant bit. -/
@[expose]
def concat {n} (msbs : BitVec n) (lsb : Bool) : BitVec (n+1) := msbs ++ (ofBool lsb)
/--
@@ -660,6 +692,7 @@ Shifts all bits of `x` to the left by `1` and sets the least significant bit to
This is a non-dependent version of `BitVec.concat` that does not change the total bitwidth.
-/
@[expose]
def shiftConcat (x : BitVec n) (b : Bool) : BitVec n :=
(x.concat b).truncate n
@@ -668,6 +701,7 @@ Prepends a single bit to the front of a bitvector, using big-endian order (see `
The new bit is the most significant bit.
-/
@[expose]
def cons {n} (msb : Bool) (lsbs : BitVec n) : BitVec (n+1) :=
((ofBool msb) ++ lsbs).cast (Nat.add_comm ..)
@@ -752,6 +786,7 @@ Checks whether subtraction of `x` and `y` results in *unsigned* overflow.
SMT-Lib name: `bvusubo`.
-/
@[expose]
def usubOverflow {w : Nat} (x y : BitVec w) : Bool := x.toNat < y.toNat
/--
@@ -760,6 +795,7 @@ Checks whether the subtraction of `x` and `y` results in *signed* overflow, trea
SMT-Lib name: `bvssubo`.
-/
@[expose]
def ssubOverflow {w : Nat} (x y : BitVec w) : Bool :=
(x.toInt - y.toInt 2 ^ (w - 1)) || (x.toInt - y.toInt < - 2 ^ (w - 1))
@@ -770,6 +806,7 @@ For a bitvector `x` with nonzero width, this only happens if `x = intMin`.
SMT-Lib name: `bvnego`.
-/
@[expose]
def negOverflow {w : Nat} (x : BitVec w) : Bool :=
x.toInt == - 2 ^ (w - 1)
@@ -779,6 +816,7 @@ For BitVecs `x` and `y` with nonzero width, this only happens if `x = intMin` an
SMT-LIB name: `bvsdivo`.
-/
@[expose]
def sdivOverflow {w : Nat} (x y : BitVec w) : Bool :=
(2 ^ (w - 1) x.toInt / y.toInt) || (x.toInt / y.toInt < - 2 ^ (w - 1))

View File

@@ -24,7 +24,7 @@ The bitvector with value `i mod 2^n`.
-/
@[expose, match_pattern]
protected def ofNat (n : Nat) (i : Nat) : BitVec n where
toFin := Fin.ofNat' (2^n) i
toFin := Fin.ofNat (2^n) i
instance instOfNat : OfNat (BitVec n) i where ofNat := .ofNat n i
@@ -41,6 +41,7 @@ Usually accessed via the `+` operator.
SMT-LIB name: `bvadd`.
-/
@[expose]
protected def add (x y : BitVec n) : BitVec n := .ofNat n (x.toNat + y.toNat)
instance : Add (BitVec n) := BitVec.add
@@ -49,6 +50,7 @@ Subtracts one bitvector from another. This can be interpreted as either signed o
modulo `2^n`. Usually accessed via the `-` operator.
-/
@[expose]
protected def sub (x y : BitVec n) : BitVec n := .ofNat n ((2^n - y.toNat) + x.toNat)
instance : Sub (BitVec n) := BitVec.sub

View File

@@ -631,6 +631,7 @@ A recurrence that describes multiplication as repeated addition.
This function is useful for bit blasting multiplication.
-/
@[expose]
def mulRec (x y : BitVec w) (s : Nat) : BitVec w :=
let cur := if y.getLsbD s then (x <<< s) else 0
match s with
@@ -1091,6 +1092,7 @@ theorem lawful_divSubtractShift (qr : DivModState w) (h : qr.Poised args) :
/-! ### Core division algorithm circuit -/
/-- A recursive definition of division for bit blasting, in terms of a shift-subtraction circuit. -/
@[expose]
def divRec {w : Nat} (m : Nat) (args : DivModArgs w) (qr : DivModState w) :
DivModState w :=
match m with

View File

@@ -68,11 +68,11 @@ theorem lt_of_getMsbD {x : BitVec w} {i : Nat} : getMsbD x i = true → i < w :=
@[simp] theorem getElem?_eq_getElem {l : BitVec w} {n} (h : n < w) : l[n]? = some l[n] := by
simp only [getElem?_def, h, reduceDIte]
theorem getElem?_eq_some_iff {l : BitVec w} : l[n]? = some a h : n < w, l[n] = a := by
simp only [getElem?_def]
split
· simp_all
· simp; omega
theorem getElem?_eq_some_iff {l : BitVec w} : l[n]? = some a h : n < w, l[n] = a :=
_root_.getElem?_eq_some_iff
theorem some_eq_getElem?_iff {l : BitVec w} : some a = l[n]? h : n < w, l[n] = a :=
_root_.some_eq_getElem?_iff
theorem getElem_of_getElem? {l : BitVec w} : l[n]? = some a h : n < w, l[n] = a :=
getElem?_eq_some_iff.mp
@@ -81,11 +81,11 @@ set_option linter.missingDocs false in
@[deprecated getElem?_eq_some_iff (since := "2025-02-17")]
abbrev getElem?_eq_some := @getElem?_eq_some_iff
@[simp] theorem getElem?_eq_none_iff {l : BitVec w} : l[n]? = none w n := by
simp only [getElem?_def]
split
· simp_all
· simp; omega
theorem getElem?_eq_none_iff {l : BitVec w} : l[n]? = none w n := by
simp
theorem none_eq_getElem?_iff {l : BitVec w} : none = l[n]? w n := by
simp
theorem getElem?_eq_none {l : BitVec w} (h : w n) : l[n]? = none := getElem?_eq_none_iff.mpr h
@@ -93,13 +93,13 @@ theorem getElem?_eq (l : BitVec w) (i : Nat) :
l[i]? = if h : i < w then some l[i] else none := by
split <;> simp_all
@[simp] theorem some_getElem_eq_getElem? (l : BitVec w) (i : Nat) (h : i < w) :
theorem some_getElem_eq_getElem? (l : BitVec w) (i : Nat) (h : i < w) :
(some l[i] = l[i]?) True := by
simp [h]
simp
@[simp] theorem getElem?_eq_some_getElem (l : BitVec w) (i : Nat) (h : i < w) :
theorem getElem?_eq_some_getElem (l : BitVec w) (i : Nat) (h : i < w) :
(l[i]? = some l[i]) True := by
simp [h]
simp
theorem getElem_eq_iff {l : BitVec w} {n : Nat} {h : n < w} : l[n] = x l[n]? = some x := by
simp only [getElem?_eq_some_iff]
@@ -125,7 +125,7 @@ theorem getElem_of_getLsbD_eq_true {x : BitVec w} {i : Nat} (h : x.getLsbD i = t
This normalized a bitvec using `ofFin` to `ofNat`.
-/
theorem ofFin_eq_ofNat : @BitVec.ofFin w (Fin.mk x lt) = BitVec.ofNat w x := by
simp only [BitVec.ofNat, Fin.ofNat', lt, Nat.mod_eq_of_lt]
simp only [BitVec.ofNat, Fin.ofNat, lt, Nat.mod_eq_of_lt]
/-- Prove equality of bitvectors in terms of nat operations. -/
theorem eq_of_toNat_eq {n} : {x y : BitVec n}, x.toNat = y.toNat x = y
@@ -314,7 +314,7 @@ theorem length_pos_of_ne {x y : BitVec w} (h : x ≠ y) : 0 < w :=
theorem ofFin_ofNat (n : Nat) :
ofFin (no_index (OfNat.ofNat n : Fin (2^w))) = OfNat.ofNat n := by
simp only [OfNat.ofNat, Fin.ofNat', BitVec.ofNat, Nat.and_two_pow_sub_one_eq_mod]
simp only [OfNat.ofNat, Fin.ofNat, BitVec.ofNat, Nat.and_two_pow_sub_one_eq_mod]
@[simp] theorem ofFin_neg {x : Fin (2 ^ w)} : ofFin (-x) = -(ofFin x) := by
rfl
@@ -346,11 +346,11 @@ theorem toFin_one : toFin (1 : BitVec w) = 1 := by
@[simp] theorem toInt_ofBool (b : Bool) : (ofBool b).toInt = -b.toInt := by
cases b <;> simp
@[simp] theorem toFin_ofBool (b : Bool) : (ofBool b).toFin = Fin.ofNat' 2 (b.toNat) := by
@[simp] theorem toFin_ofBool (b : Bool) : (ofBool b).toFin = Fin.ofNat 2 (b.toNat) := by
cases b <;> rfl
theorem ofNat_one (n : Nat) : BitVec.ofNat 1 n = BitVec.ofBool (n % 2 = 1) := by
rcases (Nat.mod_two_eq_zero_or_one n) with h | h <;> simp [h, BitVec.ofNat, Fin.ofNat']
rcases (Nat.mod_two_eq_zero_or_one n) with h | h <;> simp [h, BitVec.ofNat, Fin.ofNat]
theorem ofBool_eq_iff_eq : {b b' : Bool}, BitVec.ofBool b = BitVec.ofBool b' b = b' := by
decide
@@ -390,12 +390,12 @@ theorem getMsbD_ofNatLt {n x i : Nat} (h : x < 2^n) :
getMsbD (x#'h) i = (decide (i < n) && x.testBit (n - 1 - i)) := getMsbD_ofNatLT h
@[simp, bitvec_to_nat] theorem toNat_ofNat (x w : Nat) : (BitVec.ofNat w x).toNat = x % 2^w := by
simp [BitVec.toNat, BitVec.ofNat, Fin.ofNat']
simp [BitVec.toNat, BitVec.ofNat, Fin.ofNat]
theorem ofNatLT_eq_ofNat {w : Nat} {n : Nat} (hn) : BitVec.ofNatLT n hn = BitVec.ofNat w n :=
eq_of_toNat_eq (by simp [Nat.mod_eq_of_lt hn])
@[simp] theorem toFin_ofNat (x : Nat) : toFin (BitVec.ofNat w x) = Fin.ofNat' (2^w) x := rfl
@[simp] theorem toFin_ofNat (x : Nat) : toFin (BitVec.ofNat w x) = Fin.ofNat (2^w) x := rfl
@[simp] theorem finMk_toNat (x : BitVec w) : Fin.mk x.toNat x.isLt = x.toFin := rfl
@@ -415,7 +415,7 @@ theorem ofNatLT_eq_ofNat {w : Nat} {n : Nat} (hn) : BitVec.ofNatLT n hn = BitVec
-- If `x` and `n` are not literals, applying this theorem eagerly may not be a good idea.
theorem getLsbD_ofNat (n : Nat) (x : Nat) (i : Nat) :
getLsbD (BitVec.ofNat n x) i = (i < n && x.testBit i) := by
simp [getLsbD, BitVec.ofNat, Fin.val_ofNat']
simp [getLsbD, BitVec.ofNat, Fin.val_ofNat]
@[simp] theorem getLsbD_zero : (0#w).getLsbD i = false := by simp [getLsbD]
@@ -505,7 +505,7 @@ theorem getLsbD_ofBool (b : Bool) (i : Nat) : (ofBool b).getLsbD i = ((i = 0) &&
· simp only [ofBool, ofNat_eq_ofNat, cond_true, getLsbD_ofNat, Bool.and_true]
by_cases hi : i = 0 <;> simp [hi] <;> omega
@[simp] theorem getElem_ofBool_zero {b : Bool} : (ofBool b)[0] = b := by simp
theorem getElem_ofBool_zero {b : Bool} : (ofBool b)[0] = b := by simp
@[simp]
theorem getElem_ofBool {b : Bool} {h : i < 1}: (ofBool b)[i] = b := by
@@ -909,7 +909,7 @@ theorem zeroExtend_eq_setWidth {v : Nat} {x : BitVec w} :
simp [toInt_eq_toNat_bmod, toNat_setWidth, Int.emod_bmod, -Int.natCast_pow]
@[simp] theorem toFin_setWidth {x : BitVec w} :
(x.setWidth v).toFin = Fin.ofNat' (2^v) x.toNat := by
(x.setWidth v).toFin = Fin.ofNat (2^v) x.toNat := by
ext; simp
@[simp] theorem setWidth_eq (x : BitVec n) : setWidth n x = x := by
@@ -1105,7 +1105,7 @@ theorem toInt_setWidth' {m n : Nat} (p : m ≤ n) {x : BitVec m} :
@[simp] theorem toFin_setWidth' {m n : Nat} (p : m n) (x : BitVec m) :
(setWidth' p x).toFin = x.toFin.castLE (Nat.pow_le_pow_right (by omega) (by omega)) := by
ext
rw [setWidth'_eq, toFin_setWidth, Fin.val_ofNat', Fin.coe_castLE, val_toFin,
rw [setWidth'_eq, toFin_setWidth, Fin.val_ofNat, Fin.coe_castLE, val_toFin,
Nat.mod_eq_of_lt (by apply BitVec.toNat_lt_twoPow_of_le p)]
/-! ## extractLsb -/
@@ -1135,11 +1135,11 @@ protected theorem extractLsb_ofNat (x n : Nat) (hi lo : Nat) :
simp [extractLsb, toInt_ofNat]
@[simp] theorem toFin_extractLsb' {s m : Nat} {x : BitVec n} :
(extractLsb' s m x).toFin = Fin.ofNat' (2 ^ m) (x.toNat >>> s) := by
(extractLsb' s m x).toFin = Fin.ofNat (2 ^ m) (x.toNat >>> s) := by
simp [extractLsb', toInt_ofNat]
@[simp] theorem toFin_extractLsb {hi lo : Nat} {x : BitVec n} :
(extractLsb hi lo x).toFin = Fin.ofNat' (2 ^ (hi - lo + 1)) (x.toNat >>> lo) := by
(extractLsb hi lo x).toFin = Fin.ofNat (2 ^ (hi - lo + 1)) (x.toNat >>> lo) := by
simp [extractLsb, toInt_ofNat]
@[simp] theorem getElem_extractLsb' {start len : Nat} {x : BitVec n} {i : Nat} (h : i < len) :
@@ -1310,7 +1310,7 @@ theorem extractLsb'_eq_zero {x : BitVec w} {start : Nat} :
simp [BitVec.toInt, -Int.natCast_pow]
omega
@[simp] theorem toFin_allOnes : (allOnes w).toFin = Fin.ofNat' (2^w) (2^w - 1) := by
@[simp] theorem toFin_allOnes : (allOnes w).toFin = Fin.ofNat (2^w) (2^w - 1) := by
ext
simp
@@ -1847,7 +1847,7 @@ theorem not_xor_right {x y : BitVec w} : ~~~ (x ^^^ y) = x ^^^ ~~~ y := by
simp [-Int.natCast_pow]
@[simp] theorem toFin_shiftLeft {n : Nat} (x : BitVec w) :
(x <<< n).toFin = Fin.ofNat' (2^w) (x.toNat <<< n) := rfl
(x <<< n).toFin = Fin.ofNat (2^w) (x.toNat <<< n) := rfl
@[simp]
theorem shiftLeft_zero (x : BitVec w) : x <<< 0 = x := by
@@ -2089,7 +2089,7 @@ theorem toInt_ushiftRight {x : BitVec w} {n : Nat} :
@[simp]
theorem toFin_ushiftRight {x : BitVec w} {n : Nat} :
(x >>> n).toFin = x.toFin / (Fin.ofNat' (2^w) (2^n)) := by
(x >>> n).toFin = x.toFin / (Fin.ofNat (2^w) (2^n)) := by
apply Fin.eq_of_val_eq
by_cases hn : n < w
· simp [Nat.shiftRight_eq_div_pow, Nat.mod_eq_of_lt (Nat.pow_lt_pow_of_lt Nat.one_lt_two hn)]
@@ -2340,26 +2340,26 @@ theorem toNat_sshiftRight {x : BitVec w} {n : Nat} :
simp [toNat_sshiftRight_of_msb_false, h]
theorem toFin_sshiftRight_of_msb_true {x : BitVec w} {n : Nat} (h : x.msb = true) :
(x.sshiftRight n).toFin = Fin.ofNat' (2^w) (2 ^ w - 1 - (2 ^ w - 1 - x.toNat) >>> n) := by
(x.sshiftRight n).toFin = Fin.ofNat (2^w) (2 ^ w - 1 - (2 ^ w - 1 - x.toNat) >>> n) := by
apply Fin.eq_of_val_eq
simp only [val_toFin, toNat_sshiftRight, h, reduceIte, Fin.val_ofNat']
simp only [val_toFin, toNat_sshiftRight, h, reduceIte, Fin.val_ofNat]
rw [Nat.mod_eq_of_lt]
have := x.isLt
have ineq : y, 2 ^ w - 1 - y < 2 ^ w := by omega
exact ineq ((2 ^ w - 1 - x.toNat) >>> n)
theorem toFin_sshiftRight_of_msb_false {x : BitVec w} {n : Nat} (h : x.msb = false) :
(x.sshiftRight n).toFin = Fin.ofNat' (2^w) (x.toNat >>> n) := by
(x.sshiftRight n).toFin = Fin.ofNat (2^w) (x.toNat >>> n) := by
apply Fin.eq_of_val_eq
simp only [val_toFin, toNat_sshiftRight, h, Bool.false_eq_true, reduceIte, Fin.val_ofNat']
simp only [val_toFin, toNat_sshiftRight, h, Bool.false_eq_true, reduceIte, Fin.val_ofNat]
have := Nat.shiftRight_le x.toNat n
rw [Nat.mod_eq_of_lt (by omega)]
theorem toFin_sshiftRight {x : BitVec w} {n : Nat} :
(x.sshiftRight n).toFin =
if x.msb
then Fin.ofNat' (2^w) (2 ^ w - 1 - (2 ^ w - 1 - x.toNat) >>> n)
else Fin.ofNat' (2^w) (x.toNat >>> n) := by
then Fin.ofNat (2^w) (2 ^ w - 1 - (2 ^ w - 1 - x.toNat) >>> n)
else Fin.ofNat (2^w) (x.toNat >>> n) := by
by_cases h : x.msb
· simp [toFin_sshiftRight_of_msb_true, h]
· simp [toFin_sshiftRight_of_msb_false, h]
@@ -2397,18 +2397,18 @@ theorem toNat_sshiftRight' {x y : BitVec w} :
rw [sshiftRight_eq', toNat_sshiftRight]
theorem toFin_sshiftRight'_of_msb_true {x y : BitVec w} (h : x.msb = true) :
(x.sshiftRight' y).toFin = Fin.ofNat' (2^w) (2 ^ w - 1 - (2 ^ w - 1 - x.toNat) >>> y.toNat) := by
(x.sshiftRight' y).toFin = Fin.ofNat (2^w) (2 ^ w - 1 - (2 ^ w - 1 - x.toNat) >>> y.toNat) := by
rw [sshiftRight_eq', toFin_sshiftRight_of_msb_true h]
theorem toFin_sshiftRight'_of_msb_false {x y : BitVec w} (h : x.msb = false) :
(x.sshiftRight' y).toFin = Fin.ofNat' (2^w) (x.toNat >>> y.toNat) := by
(x.sshiftRight' y).toFin = Fin.ofNat (2^w) (x.toNat >>> y.toNat) := by
rw [sshiftRight_eq', toFin_sshiftRight_of_msb_false h]
theorem toFin_sshiftRight' {x y : BitVec w} :
(x.sshiftRight' y).toFin =
if x.msb
then Fin.ofNat' (2^w) (2 ^ w - 1 - (2 ^ w - 1 - x.toNat) >>> y.toNat)
else Fin.ofNat' (2^w) (x.toNat >>> y.toNat) := by
then Fin.ofNat (2^w) (2 ^ w - 1 - (2 ^ w - 1 - x.toNat) >>> y.toNat)
else Fin.ofNat (2^w) (x.toNat >>> y.toNat) := by
rw [sshiftRight_eq', toFin_sshiftRight]
theorem toInt_sshiftRight' {x y : BitVec w} :
@@ -2614,16 +2614,16 @@ theorem toInt_signExtend_eq_toInt_bmod_of_le (x : BitVec w) (h : v ≤ w) :
rw [BitVec.toInt_signExtend, Nat.min_eq_left h]
theorem toFin_signExtend_of_le {x : BitVec w} (hv : v w):
(x.signExtend v).toFin = Fin.ofNat' (2 ^ v) x.toNat := by
(x.signExtend v).toFin = Fin.ofNat (2 ^ v) x.toNat := by
simp [signExtend_eq_setWidth_of_le _ hv]
theorem toFin_signExtend (x : BitVec w) :
(x.signExtend v).toFin = Fin.ofNat' (2 ^ v) (x.toNat + if x.msb = true then 2 ^ v - 2 ^ w else 0):= by
(x.signExtend v).toFin = Fin.ofNat (2 ^ v) (x.toNat + if x.msb = true then 2 ^ v - 2 ^ w else 0):= by
by_cases hv : v w
· simp [toFin_signExtend_of_le hv, show 2 ^ v - 2 ^ w = 0 by rw [@Nat.sub_eq_zero_iff_le]; apply Nat.pow_le_pow_of_le (by decide) (by omega)]
· simp only [Nat.not_le] at hv
apply Fin.eq_of_val_eq
simp only [val_toFin, Fin.val_ofNat']
simp only [val_toFin, Fin.val_ofNat]
rw [toNat_signExtend_of_le _ (by omega)]
have : 2 ^ w < 2 ^ v := by apply Nat.pow_lt_pow_of_lt <;> omega
rw [Nat.mod_eq_of_lt]
@@ -3179,12 +3179,12 @@ theorem getElem_concat (x : BitVec w) (b : Bool) (i : Nat) (h : i < w + 1) :
· simp [Nat.mod_eq_of_lt b.toNat_lt]
· simp [Nat.div_eq_of_lt b.toNat_lt, Nat.testBit_add_one]
@[simp] theorem getLsbD_concat_zero : (concat x b).getLsbD 0 = b := by
simp [getElem_concat]
@[simp] theorem getElem_concat_zero : (concat x b)[0] = b := by
simp [getElem_concat]
theorem getLsbD_concat_zero : (concat x b).getLsbD 0 = b := by
simp
@[simp] theorem getLsbD_concat_succ : (concat x b).getLsbD (i + 1) = x.getLsbD i := by
simp [getLsbD_concat]
@@ -3323,11 +3323,19 @@ Definition of bitvector addition as a nat.
theorem ofNat_add {n} (x y : Nat) : BitVec.ofNat n (x + y) = BitVec.ofNat n x + BitVec.ofNat n y := by
apply eq_of_toNat_eq
simp [BitVec.ofNat, Fin.ofNat'_add]
simp [BitVec.ofNat, Fin.ofNat_add]
theorem ofNat_add_ofNat {n} (x y : Nat) : BitVec.ofNat n x + BitVec.ofNat n y = BitVec.ofNat n (x + y) :=
(ofNat_add x y).symm
@[simp]
theorem toNat_add_of_not_uaddOverflow {x y : BitVec w} (h : ¬ uaddOverflow x y) :
(x + y).toNat = x.toNat + y.toNat := by
rcases w with _|w
· simp [of_length_zero]
· simp only [uaddOverflow, ge_iff_le, decide_eq_true_eq, Nat.not_le] at h
rw [toNat_add, Nat.mod_eq_of_lt h]
protected theorem add_assoc (x y z : BitVec n) : x + y + z = x + (y + z) := by
apply eq_of_toNat_eq ; simp [Nat.add_assoc]
instance : Std.Associative (α := BitVec n) (· + ·) := BitVec.add_assoc
@@ -3357,6 +3365,15 @@ theorem ofInt_add {n} (x y : Int) : BitVec.ofInt n (x + y) =
apply eq_of_toInt_eq
simp
@[simp]
theorem toInt_add_of_not_saddOverflow {x y : BitVec w} (h : ¬ saddOverflow x y) :
(x + y).toInt = x.toInt + y.toInt := by
rcases w with _|w
· simp [of_length_zero]
· simp only [saddOverflow, Nat.add_one_sub_one, ge_iff_le, Bool.or_eq_true, decide_eq_true_eq,
_root_.not_or, Int.not_le, Int.not_lt] at h
rw [toInt_add, Int.bmod_eq_of_le (by push_cast; omega) (by push_cast; omega)]
@[simp]
theorem shiftLeft_add_distrib {x y : BitVec w} {n : Nat} :
(x + y) <<< n = x <<< n + y <<< n := by
@@ -3382,6 +3399,24 @@ theorem sub_def {n} (x y : BitVec n) : x - y = .ofNat n ((2^n - y.toNat) + x.toN
(x - y).toInt = (x.toInt - y.toInt).bmod (2 ^ w) := by
simp [toInt_eq_toNat_bmod, @Int.ofNat_sub y.toNat (2 ^ w) (by omega), -Int.natCast_pow]
@[simp]
theorem toNat_sub_of_not_usubOverflow {x y : BitVec w} (h : ¬ usubOverflow x y) :
(x - y).toNat = x.toNat - y.toNat := by
rcases w with _|w
· simp [of_length_zero]
· simp only [usubOverflow, decide_eq_true_eq, Nat.not_lt] at h
rw [toNat_sub, Nat.sub_add_comm (by omega), Nat.add_sub_assoc h, Nat.add_mod_left,
Nat.mod_eq_of_lt (by omega)]
@[simp]
theorem toInt_sub_of_not_ssubOverflow {x y : BitVec w} (h : ¬ ssubOverflow x y) :
(x - y).toInt = x.toInt - y.toInt := by
rcases w with _|w
· simp [of_length_zero]
· simp only [ssubOverflow, Nat.add_one_sub_one, ge_iff_le, Bool.or_eq_true, decide_eq_true_eq,
_root_.not_or, Int.not_le, Int.not_lt] at h
rw [toInt_sub, Int.bmod_eq_of_le (by push_cast; omega) (by push_cast; omega)]
theorem toInt_sub_toInt_lt_twoPow_iff {x y : BitVec w} :
(x.toInt - y.toInt < - 2 ^ (w - 1))
(x.toInt < 0 0 y.toInt 0 (x.toInt - y.toInt).bmod (2 ^ w)) := by
@@ -3433,7 +3468,7 @@ theorem sub_ofFin (x : BitVec n) (y : Fin (2^n)) : x - .ofFin y = .ofFin (x.toFi
-- If `x` and `n` are not literals, applying this theorem eagerly may not be a good idea.
theorem ofNat_sub_ofNat {n} (x y : Nat) : BitVec.ofNat n x - BitVec.ofNat n y = .ofNat n ((2^n - y % 2^n) + x) := by
apply eq_of_toNat_eq
simp [BitVec.ofNat, Fin.ofNat'_sub]
simp [BitVec.ofNat, Fin.ofNat_sub]
@[simp] protected theorem sub_zero (x : BitVec n) : x - 0#n = x := by apply eq_of_toNat_eq ; simp
@@ -3460,11 +3495,21 @@ theorem toInt_neg {x : BitVec w} :
rw [ BitVec.zero_sub, toInt_sub]
simp [BitVec.toInt_ofNat]
@[simp]
theorem toInt_neg_of_not_negOverflow {x : BitVec w} (h : ¬ negOverflow x):
(-x).toInt = -x.toInt := by
rcases w with _|w
· simp [of_length_zero]
· have := toInt_lt (x := x); simp only [Nat.add_one_sub_one] at this
have := le_toInt (x := x); simp only [Nat.add_one_sub_one] at this
simp only [negOverflow, Nat.add_one_sub_one, beq_iff_eq] at h
rw [toInt_neg, Int.bmod_eq_of_le (by push_cast; omega) (by push_cast; omega)]
theorem ofInt_neg {w : Nat} {n : Int} : BitVec.ofInt w (-n) = -BitVec.ofInt w n :=
eq_of_toInt_eq (by simp [toInt_neg])
@[simp] theorem toFin_neg (x : BitVec n) :
(-x).toFin = Fin.ofNat' (2^n) (2^n - x.toNat) :=
(-x).toFin = Fin.ofNat (2^n) (2^n - x.toNat) :=
rfl
theorem sub_eq_add_neg {n} (x y : BitVec n) : x - y = x + - y := by
@@ -3679,7 +3724,7 @@ theorem fill_false {w : Nat} : fill w false = 0#w := by
by_cases h : v <;> simp [h]
@[simp] theorem fill_toFin {w : Nat} {v : Bool} :
(fill w v).toFin = if v = true then (allOnes w).toFin else Fin.ofNat' (2 ^ w) 0 := by
(fill w v).toFin = if v = true then (allOnes w).toFin else Fin.ofNat (2 ^ w) 0 := by
by_cases h : v <;> simp [h]
/-! ### mul -/
@@ -3691,7 +3736,7 @@ theorem mul_def {n} {x y : BitVec n} : x * y = (ofFin <| x.toFin * y.toFin) := r
theorem ofNat_mul {n} (x y : Nat) : BitVec.ofNat n (x * y) = BitVec.ofNat n x * BitVec.ofNat n y := by
apply eq_of_toNat_eq
simp [BitVec.ofNat, Fin.ofNat'_mul]
simp [BitVec.ofNat, Fin.ofNat_mul]
theorem ofNat_mul_ofNat {n} (x y : Nat) : BitVec.ofNat n x * BitVec.ofNat n y = BitVec.ofNat n (x * y) :=
(ofNat_mul x y).symm
@@ -3749,6 +3794,23 @@ theorem two_mul {x : BitVec w} : 2#w * x = x + x := by rw [BitVec.mul_comm, mul_
(x * y).toInt = (x.toInt * y.toInt).bmod (2^w) := by
simp [toInt_eq_toNat_bmod, -Int.natCast_pow]
@[simp]
theorem toNat_mul_of_not_umulOverflow {x y : BitVec w} (h : ¬ umulOverflow x y) :
(x * y).toNat = x.toNat * y.toNat := by
rcases w with _|w
· simp [of_length_zero]
· simp only [umulOverflow, ge_iff_le, decide_eq_true_eq, Nat.not_le] at h
rw [toNat_mul, Nat.mod_eq_of_lt h]
@[simp]
theorem toInt_mul_of_not_smulOverflow {x y : BitVec w} (h : ¬ smulOverflow x y) :
(x * y).toInt = x.toInt * y.toInt := by
rcases w with _|w
· simp [of_length_zero]
· simp only [smulOverflow, Nat.add_one_sub_one, ge_iff_le, Bool.or_eq_true, decide_eq_true_eq,
_root_.not_or, Int.not_le, Int.not_lt] at h
rw [toInt_mul, Int.bmod_eq_of_le (by push_cast; omega) (by push_cast; omega)]
theorem ofInt_mul {n} (x y : Int) : BitVec.ofInt n (x * y) =
BitVec.ofInt n x * BitVec.ofInt n y := by
apply eq_of_toInt_eq
@@ -4562,7 +4624,7 @@ theorem toInt_rotateLeft {x : BitVec w} {r : Nat} :
theorem toFin_rotateLeft {x : BitVec w} {r : Nat} :
(x.rotateLeft r).toFin =
Fin.ofNat' (2 ^ w) (x.toNat <<< (r % w)) ||| x.toFin / Fin.ofNat' (2 ^ w) (2 ^ (w - r % w)) := by
Fin.ofNat (2 ^ w) (x.toNat <<< (r % w)) ||| x.toFin / Fin.ofNat (2 ^ w) (2 ^ (w - r % w)) := by
simp [rotateLeft_def, toFin_shiftLeft, toFin_ushiftRight, toFin_or]
/-! ## Rotate Right -/
@@ -4724,7 +4786,7 @@ theorem toInt_rotateRight {x : BitVec w} {r : Nat} :
simp [rotateRight_def, toInt_shiftLeft, toInt_ushiftRight, toInt_or]
theorem toFin_rotateRight {x : BitVec w} {r : Nat} :
(x.rotateRight r).toFin = x.toFin / Fin.ofNat' (2 ^ w) (2 ^ (r % w)) ||| Fin.ofNat' (2 ^ w) (x.toNat <<< (w - r % w)) := by
(x.rotateRight r).toFin = x.toFin / Fin.ofNat (2 ^ w) (2 ^ (r % w)) ||| Fin.ofNat (2 ^ w) (x.toNat <<< (w - r % w)) := by
simp [rotateRight_def, toFin_shiftLeft, toFin_ushiftRight, toFin_or]
/- ## twoPow -/
@@ -4796,7 +4858,7 @@ theorem toInt_twoPow {w i : Nat} :
· simp [h, h', show i < w + 1 by omega, Int.natCast_pow]
theorem toFin_twoPow {w i : Nat} :
(BitVec.twoPow w i).toFin = Fin.ofNat' (2^w) (2^i) := by
(BitVec.twoPow w i).toFin = Fin.ofNat (2^w) (2^i) := by
rcases w with rfl | w
· simp [BitVec.twoPow, BitVec.toFin, toFin_shiftLeft, Fin.fin_one_eq_zero]
· simp [BitVec.twoPow, BitVec.toFin, toFin_shiftLeft, Nat.shiftLeft_eq]
@@ -5440,7 +5502,7 @@ theorem toInt_abs_eq_natAbs_of_ne_intMin {x : BitVec w} (hx : x ≠ intMin w) :
simp [toInt_abs_eq_natAbs, hx]
theorem toFin_abs {x : BitVec w} :
x.abs.toFin = if x.msb then Fin.ofNat' (2 ^ w) (2 ^ w - x.toNat) else x.toFin := by
x.abs.toFin = if x.msb then Fin.ofNat (2 ^ w) (2 ^ w - x.toNat) else x.toFin := by
by_cases h : x.msb <;> simp [BitVec.abs, h]
/-! ### Reverse -/

View File

@@ -455,7 +455,7 @@ theorem toNat_lt (b : Bool) : b.toNat < 2 :=
/--
Converts `true` to `1` and `false` to `0`.
-/
def toInt (b : Bool) : Int := cond b 1 0
@[expose] def toInt (b : Bool) : Int := cond b 1 0
@[simp] theorem toInt_false : false.toInt = 0 := rfl

View File

@@ -205,7 +205,7 @@ def foldlM {β : Type v} {m : Type v → Type w} [Monad m] (f : β → UInt8 →
@[inline]
def foldl {β : Type v} (f : β UInt8 β) (init : β) (as : ByteArray) (start := 0) (stop := as.size) : β :=
Id.run <| as.foldlM f init start stop
Id.run <| as.foldlM (pure <| f · ·) init start stop
/-- Iterator over the bytes (`UInt8`) of a `ByteArray`.

View File

@@ -46,15 +46,12 @@ Returns `a` modulo `n` as a `Fin n`.
The assumption `NeZero n` ensures that `Fin n` is nonempty.
-/
@[expose] protected def ofNat' (n : Nat) [NeZero n] (a : Nat) : Fin n :=
@[expose] protected def ofNat (n : Nat) [NeZero n] (a : Nat) : Fin n :=
a % n, Nat.mod_lt _ (pos_of_neZero n)
/--
Returns `a` modulo `n + 1` as a `Fin n.succ`.
-/
@[deprecated Fin.ofNat' (since := "2024-11-27")]
protected def ofNat {n : Nat} (a : Nat) : Fin (n + 1) :=
a % (n+1), Nat.mod_lt _ (Nat.zero_lt_succ _)
@[deprecated Fin.ofNat (since := "2025-05-28")]
protected def ofNat' (n : Nat) [NeZero n] (a : Nat) : Fin n :=
Fin.ofNat n a
-- We provide this because other similar types have a `toNat` function, but `simp` rewrites
-- `i.toNat` to `i.val`.
@@ -230,7 +227,7 @@ instance : ShiftRight (Fin n) where
shiftRight := Fin.shiftRight
instance instOfNat {n : Nat} [NeZero n] {i : Nat} : OfNat (Fin n) i where
ofNat := Fin.ofNat' n i
ofNat := Fin.ofNat n i
/-- If you actually have an element of `Fin n`, then the `n` is always positive -/
protected theorem pos (i : Fin n) : 0 < n :=

View File

@@ -266,7 +266,7 @@ theorem foldl_add (f : α → Fin (n + m) → α) (x) :
| succ m ih => simp [foldl_succ_last, ih, Nat.add_assoc]
theorem foldl_eq_foldlM (f : α Fin n α) (x) :
foldl n f x = foldlM (m:=Id) n f x := by
foldl n f x = (foldlM (m := Id) n (pure <| f · ·) x).run := by
induction n generalizing x <;> simp [foldl_succ, foldlM_succ, *]
-- This is not marked `@[simp]` as it would match on every occurrence of `foldlM`.
@@ -319,7 +319,7 @@ theorem foldr_add (f : Fin (n + m) → αα) (x) :
| succ m ih => simp [foldr_succ_last, ih, Nat.add_assoc]
theorem foldr_eq_foldrM (f : Fin n α α) (x) :
foldr n f x = foldrM (m:=Id) n f x := by
foldr n f x = (foldrM (m := Id) n (pure <| f · ·) x).run := by
induction n <;> simp [foldr_succ, foldrM_succ, *]
theorem foldl_rev (f : Fin n α α) (x) :

View File

@@ -15,10 +15,9 @@ import Init.Omega
namespace Fin
@[simp] theorem ofNat'_zero (n : Nat) [NeZero n] : Fin.ofNat' n 0 = 0 := rfl
@[simp] theorem ofNat_zero (n : Nat) [NeZero n] : Fin.ofNat n 0 = 0 := rfl
@[deprecated Fin.pos (since := "2024-11-11")]
theorem size_pos (i : Fin n) : 0 < n := i.pos
@[deprecated ofNat_zero (since := "2025-05-28")] abbrev ofNat'_zero := @ofNat_zero
theorem mod_def (a m : Fin n) : a % m = Fin.mk (a % m) (Nat.lt_of_le_of_lt (Nat.mod_le _ _) a.2) :=
rfl
@@ -29,8 +28,6 @@ theorem sub_def (a b : Fin n) : a - b = Fin.mk (((n - b) + a) % n) (Nat.mod_lt _
theorem pos' : [Nonempty (Fin n)], 0 < n | i => i.pos
@[deprecated pos' (since := "2024-11-11")] abbrev size_pos' := @pos'
@[simp] theorem is_lt (a : Fin n) : (a : Nat) < n := a.2
theorem pos_iff_nonempty {n : Nat} : 0 < n Nonempty (Fin n) :=
@@ -66,19 +63,25 @@ theorem mk_val (i : Fin n) : (⟨i, i.isLt⟩ : Fin n) = i := Fin.eta ..
0 = (a, ha : Fin n) a = 0 := by
simp [eq_comm]
@[simp] theorem val_ofNat' (n : Nat) [NeZero n] (a : Nat) :
(Fin.ofNat' n a).val = a % n := rfl
@[simp] theorem val_ofNat (n : Nat) [NeZero n] (a : Nat) :
(Fin.ofNat n a).val = a % n := rfl
@[simp] theorem ofNat'_self {n : Nat} [NeZero n] : Fin.ofNat' n n = 0 := by
@[deprecated val_ofNat (since := "2025-05-28")] abbrev val_ofNat' := @val_ofNat
@[simp] theorem ofNat_self {n : Nat} [NeZero n] : Fin.ofNat n n = 0 := by
ext
simp
congr
@[simp] theorem ofNat'_val_eq_self [NeZero n] (x : Fin n) : (Fin.ofNat' n x) = x := by
@[deprecated ofNat_self (since := "2025-05-28")] abbrev ofNat'_self := @ofNat_self
@[simp] theorem ofNat_val_eq_self [NeZero n] (x : Fin n) : (Fin.ofNat n x) = x := by
ext
rw [val_ofNat', Nat.mod_eq_of_lt]
rw [val_ofNat, Nat.mod_eq_of_lt]
exact x.2
@[deprecated ofNat_val_eq_self (since := "2025-05-28")] abbrev ofNat'_val_eq_self := @ofNat_val_eq_self
@[simp] theorem mod_val (a b : Fin n) : (a % b).val = a.val % b.val :=
rfl
@@ -100,19 +103,20 @@ theorem dite_val {n : Nat} {c : Prop} [Decidable c] {x y : Fin n} :
by_cases c <;> simp [*]
instance (n : Nat) [NeZero n] : NatCast (Fin n) where
natCast a := Fin.ofNat' n a
natCast a := Fin.ofNat n a
@[expose]
def intCast [NeZero n] (a : Int) : Fin n :=
if 0 a then
Fin.ofNat' n a.natAbs
Fin.ofNat n a.natAbs
else
- Fin.ofNat' n a.natAbs
- Fin.ofNat n a.natAbs
instance (n : Nat) [NeZero n] : IntCast (Fin n) where
intCast := Fin.intCast
theorem intCast_def {n : Nat} [NeZero n] (x : Int) :
(x : Fin n) = if 0 x then Fin.ofNat' n x.natAbs else -Fin.ofNat' n x.natAbs := rfl
(x : Fin n) = if 0 x then Fin.ofNat n x.natAbs else -Fin.ofNat n x.natAbs := rfl
/-! ### order -/
@@ -797,7 +801,7 @@ parameter, `Fin.cases` is the corresponding case analysis operator, and `Fin.rev
version that starts at the greatest value instead of `0`.
-/
-- FIXME: Performance review
@[elab_as_elim] def induction {motive : Fin (n + 1) Sort _} (zero : motive 0)
@[elab_as_elim, expose] def induction {motive : Fin (n + 1) Sort _} (zero : motive 0)
(succ : i : Fin n, motive (castSucc i) motive i.succ) :
i : Fin (n + 1), motive i
| i, hi => go i hi
@@ -839,7 +843,7 @@ The two cases are:
The corresponding induction principle is `Fin.induction`.
-/
@[elab_as_elim] def cases {motive : Fin (n + 1) Sort _}
@[elab_as_elim, expose] def cases {motive : Fin (n + 1) Sort _}
(zero : motive 0) (succ : i : Fin n, motive i.succ) :
i : Fin (n + 1), motive i := induction zero fun i _ => succ i
@@ -965,30 +969,38 @@ theorem val_ne_zero_iff [NeZero n] {a : Fin n} : a.val ≠ 0 ↔ a ≠ 0 :=
/-! ### add -/
theorem ofNat'_add [NeZero n] (x : Nat) (y : Fin n) :
Fin.ofNat' n x + y = Fin.ofNat' n (x + y.val) := by
theorem ofNat_add [NeZero n] (x : Nat) (y : Fin n) :
Fin.ofNat n x + y = Fin.ofNat n (x + y.val) := by
apply Fin.eq_of_val_eq
simp [Fin.ofNat', Fin.add_def]
simp [Fin.ofNat, Fin.add_def]
theorem add_ofNat' [NeZero n] (x : Fin n) (y : Nat) :
x + Fin.ofNat' n y = Fin.ofNat' n (x.val + y) := by
@[deprecated ofNat_add (since := "2025-05-28")] abbrev ofNat_add' := @ofNat_add
theorem add_ofNat [NeZero n] (x : Fin n) (y : Nat) :
x + Fin.ofNat n y = Fin.ofNat n (x.val + y) := by
apply Fin.eq_of_val_eq
simp [Fin.ofNat', Fin.add_def]
simp [Fin.ofNat, Fin.add_def]
@[deprecated add_ofNat (since := "2025-05-28")] abbrev add_ofNat' := @add_ofNat
/-! ### sub -/
protected theorem coe_sub (a b : Fin n) : ((a - b : Fin n) : Nat) = ((n - b) + a) % n := by
cases a; cases b; rfl
theorem ofNat'_sub [NeZero n] (x : Nat) (y : Fin n) :
Fin.ofNat' n x - y = Fin.ofNat' n ((n - y.val) + x) := by
theorem ofNat_sub [NeZero n] (x : Nat) (y : Fin n) :
Fin.ofNat n x - y = Fin.ofNat n ((n - y.val) + x) := by
apply Fin.eq_of_val_eq
simp [Fin.ofNat', Fin.sub_def]
simp [Fin.ofNat, Fin.sub_def]
theorem sub_ofNat' [NeZero n] (x : Fin n) (y : Nat) :
x - Fin.ofNat' n y = Fin.ofNat' n ((n - y % n) + x.val) := by
@[deprecated ofNat_sub (since := "2025-05-28")] abbrev ofNat_sub' := @ofNat_sub
theorem sub_ofNat [NeZero n] (x : Fin n) (y : Nat) :
x - Fin.ofNat n y = Fin.ofNat n ((n - y % n) + x.val) := by
apply Fin.eq_of_val_eq
simp [Fin.ofNat', Fin.sub_def]
simp [Fin.ofNat, Fin.sub_def]
@[deprecated sub_ofNat (since := "2025-05-28")] abbrev sub_ofNat' := @sub_ofNat
@[simp] protected theorem sub_self [NeZero n] {x : Fin n} : x - x = 0 := by
ext
@@ -1035,15 +1047,19 @@ theorem val_neg {n : Nat} [NeZero n] (x : Fin n) :
/-! ### mul -/
theorem ofNat'_mul [NeZero n] (x : Nat) (y : Fin n) :
Fin.ofNat' n x * y = Fin.ofNat' n (x * y.val) := by
theorem ofNat_mul [NeZero n] (x : Nat) (y : Fin n) :
Fin.ofNat n x * y = Fin.ofNat n (x * y.val) := by
apply Fin.eq_of_val_eq
simp [Fin.ofNat', Fin.mul_def]
simp [Fin.ofNat, Fin.mul_def]
theorem mul_ofNat' [NeZero n] (x : Fin n) (y : Nat) :
x * Fin.ofNat' n y = Fin.ofNat' n (x.val * y) := by
@[deprecated ofNat_mul (since := "2025-05-28")] abbrev ofNat_mul' := @ofNat_mul
theorem mul_ofNat [NeZero n] (x : Fin n) (y : Nat) :
x * Fin.ofNat n y = Fin.ofNat n (x.val * y) := by
apply Fin.eq_of_val_eq
simp [Fin.ofNat', Fin.mul_def]
simp [Fin.ofNat, Fin.mul_def]
@[deprecated mul_ofNat (since := "2025-05-28")] abbrev mul_ofNat' := @mul_ofNat
theorem val_mul {n : Nat} : a b : Fin n, (a * b).val = a.val * b.val % n
| _, _, _, _ => rfl

View File

@@ -165,7 +165,7 @@ def foldlM {β : Type v} {m : Type v → Type w} [Monad m] (f : β → Float →
@[inline]
def foldl {β : Type v} (f : β Float β) (init : β) (as : FloatArray) (start := 0) (stop := as.size) : β :=
Id.run <| as.foldlM f init start stop
Id.run <| as.foldlM (pure <| f · ·) init start stop
end FloatArray

View File

@@ -142,17 +142,36 @@ private structure WorkItem where
indent : Int
activeTags : Nat
/--
A directive indicating whether a given work group is able to be flattened.
- `allow` indicates that the group is allowed to be flattened; its argument is `true` if
there is sufficient space for it to be flattened (and so it should be), or `false` if not.
- `disallow` means that this group should not be flattened irrespective of space concerns.
This is used at levels of a `Format` outside of any flattening groups. It is necessary to track
this so that, after a hard line break, we know whether to try to flatten the next line.
-/
inductive FlattenAllowability where
| allow (fits : Bool)
| disallow
deriving BEq
/-- Whether the given directive indicates that flattening should occur. -/
def FlattenAllowability.shouldFlatten : FlattenAllowability Bool
| allow true => true
| _ => false
private structure WorkGroup where
flatten : Bool
flb : FlattenBehavior
items : List WorkItem
fla : FlattenAllowability
flb : FlattenBehavior
items : List WorkItem
private partial def spaceUptoLine' : List WorkGroup Nat Nat SpaceResult
| [], _, _ => {}
| { items := [], .. }::gs, col, w => spaceUptoLine' gs col w
| g@{ items := i::is, .. }::gs, col, w =>
merge w
(spaceUptoLine i.f g.flatten (w + col - i.indent) w)
(spaceUptoLine i.f g.fla.shouldFlatten (w + col - i.indent) w)
(spaceUptoLine' ({ g with items := is }::gs) col)
/-- A monad in which we can pretty-print `Format` objects. -/
@@ -169,11 +188,11 @@ open MonadPrettyFormat
private def pushGroup (flb : FlattenBehavior) (items : List WorkItem) (gs : List WorkGroup) (w : Nat) [Monad m] [MonadPrettyFormat m] : m (List WorkGroup) := do
let k currColumn
-- Flatten group if it + the remainder (gs) fits in the remaining space. For `fill`, measure only up to the next (ungrouped) line break.
let g := { flatten := flb == FlattenBehavior.allOrNone, flb := flb, items := items : WorkGroup }
let g := { fla := .allow (flb == FlattenBehavior.allOrNone), flb := flb, items := items : WorkGroup }
let r := spaceUptoLine' [g] k (w-k)
let r' := merge (w-k) r (spaceUptoLine' gs k)
-- Prevent flattening if any item contains a hard line break, except within `fill` if it is ungrouped (=> unflattened)
return { g with flatten := !r.foundFlattenedHardLine && r'.space <= w-k }::gs
return { g with fla := .allow (!r.foundFlattenedHardLine && r'.space <= w-k) }::gs
private partial def be (w : Nat) [Monad m] [MonadPrettyFormat m] : List WorkGroup m Unit
| [] => pure ()
@@ -200,11 +219,15 @@ private partial def be (w : Nat) [Monad m] [MonadPrettyFormat m] : List WorkGrou
pushNewline i.indent.toNat
let is := { i with f := text (s.extract (s.next p) s.endPos) }::is
-- after a hard line break, re-evaluate whether to flatten the remaining group
pushGroup g.flb is gs w >>= be w
-- note that we shouldn't start flattening after a hard break outside a group
if g.fla == .disallow then
be w (gs' is)
else
pushGroup g.flb is gs w >>= be w
| line =>
match g.flb with
| FlattenBehavior.allOrNone =>
if g.flatten then
if g.fla.shouldFlatten then
-- flatten line = text " "
pushOutput " "
endTags i.activeTags
@@ -220,10 +243,10 @@ private partial def be (w : Nat) [Monad m] [MonadPrettyFormat m] : List WorkGrou
endTags i.activeTags
pushGroup FlattenBehavior.fill is gs w >>= be w
-- if preceding fill item fit in a single line, try to fit next one too
if g.flatten then
if g.fla.shouldFlatten then
let gs'@(g'::_) pushGroup FlattenBehavior.fill is gs (w - " ".length)
| panic "unreachable"
if g'.flatten then
if g'.fla.shouldFlatten then
pushOutput " "
endTags i.activeTags
be w gs' -- TODO: use `return`
@@ -232,7 +255,7 @@ private partial def be (w : Nat) [Monad m] [MonadPrettyFormat m] : List WorkGrou
else
breakHere
| align force =>
if g.flatten && !force then
if g.fla.shouldFlatten && !force then
-- flatten (align false) = nil
endTags i.activeTags
be w (gs' is)
@@ -247,7 +270,7 @@ private partial def be (w : Nat) [Monad m] [MonadPrettyFormat m] : List WorkGrou
endTags i.activeTags
be w (gs' is)
| group f flb =>
if g.flatten then
if g.fla.shouldFlatten then
-- flatten (group f) = flatten f
be w (gs' ({ i with f }::is))
else
@@ -256,7 +279,7 @@ private partial def be (w : Nat) [Monad m] [MonadPrettyFormat m] : List WorkGrou
/-- Render the given `f : Format` with a line width of `w`.
`indent` is the starting amount to indent each line by. -/
def prettyM (f : Format) (w : Nat) (indent : Nat := 0) [Monad m] [MonadPrettyFormat m] : m Unit :=
be w [{ flb := FlattenBehavior.allOrNone, flatten := false, items := [{ f := f, indent, activeTags := 0 }]}]
be w [{ flb := FlattenBehavior.allOrNone, fla := .disallow, items := [{ f := f, indent, activeTags := 0 }]}]
/-- Create a format `l ++ f ++ r` with a flatten group.
FlattenBehaviour is `allOrNone`; for `fill` use `bracketFill`. -/

View File

@@ -41,6 +41,7 @@ Examples:
* `(-0b1000 : Int) >>> 1 = -0b0100`
* `(-0b0111 : Int) >>> 1 = -0b0100`
-/
@[expose]
protected def shiftRight : Int Nat Int
| Int.ofNat n, s => Int.ofNat (n >>> s)
| Int.negSucc n, s => Int.negSucc (n >>> s)

View File

@@ -264,8 +264,8 @@ theorem mul_emod (a b n : Int) : (a * b) % n = (a % n) * (b % n) % n := by
match k, h with
| _, t, rfl => rw [Int.mul_assoc, add_mul_emod_self_left]
@[simp] theorem emod_emod (a b : Int) : (a % b) % b = a % b := by
conv => rhs; rw [ emod_add_ediv a b, add_mul_emod_self_left]
theorem emod_emod (a b : Int) : (a % b) % b = a % b := by
simp
theorem sub_emod (a b n : Int) : (a - b) % n = (a % n - b % n) % n := by
apply (emod_add_cancel_right b).mp

View File

@@ -1410,8 +1410,7 @@ theorem mul_tmod (a b n : Int) : (a * b).tmod n = (a.tmod n * b.tmod n).tmod n :
norm_cast at h
rw [Nat.mod_mod_of_dvd _ h]
@[simp] theorem tmod_tmod (a b : Int) : (a.tmod b).tmod b = a.tmod b :=
tmod_tmod_of_dvd a (Int.dvd_refl b)
theorem tmod_tmod (a b : Int) : (a.tmod b).tmod b = a.tmod b := by simp
theorem tmod_eq_zero_of_dvd : {a b : Int}, a b tmod b a = 0
| _, _, _, rfl => mul_tmod_right ..
@@ -1469,9 +1468,8 @@ protected theorem tdiv_mul_cancel {a b : Int} (H : b a) : a.tdiv b * b = a :
protected theorem mul_tdiv_cancel' {a b : Int} (H : a b) : a * b.tdiv a = b := by
rw [Int.mul_comm, Int.tdiv_mul_cancel H]
@[simp] theorem neg_tmod_self (a : Int) : (-a).tmod a = 0 := by
rw [ dvd_iff_tmod_eq_zero, Int.dvd_neg]
exact Int.dvd_refl a
theorem neg_tmod_self (a : Int) : (-a).tmod a = 0 := by
simp
theorem lt_tdiv_add_one_mul_self (a : Int) {b : Int} (H : 0 < b) : a < (a.tdiv b + 1) * b := by
rw [Int.add_mul, Int.one_mul, Int.mul_comm]
@@ -1568,13 +1566,11 @@ theorem dvd_tmod_sub_self {x m : Int} : m x.tmod m - x := by
theorem dvd_self_sub_tmod {x m : Int} : m x - x.tmod m :=
Int.dvd_neg.1 (by simpa only [Int.neg_sub] using dvd_tmod_sub_self)
@[simp] theorem neg_mul_tmod_right (a b : Int) : (-(a * b)).tmod a = 0 := by
rw [ dvd_iff_tmod_eq_zero, Int.dvd_neg]
exact Int.dvd_mul_right a b
theorem neg_mul_tmod_right (a b : Int) : (-(a * b)).tmod a = 0 := by
simp
@[simp] theorem neg_mul_tmod_left (a b : Int) : (-(a * b)).tmod b = 0 := by
rw [ dvd_iff_tmod_eq_zero, Int.dvd_neg]
exact Int.dvd_mul_left a b
theorem neg_mul_tmod_left (a b : Int) : (-(a * b)).tmod b = 0 := by
simp
@[simp] protected theorem tdiv_one : a : Int, a.tdiv 1 = a
| (n:Nat) => congrArg ofNat (Nat.div_one _)
@@ -2193,8 +2189,8 @@ theorem mul_fmod (a b n : Int) : (a * b).fmod n = (a.fmod n * b.fmod n).fmod n :
match k, h with
| _, t, rfl => rw [Int.mul_assoc, add_mul_fmod_self_left]
@[simp] theorem fmod_fmod (a b : Int) : (a.fmod b).fmod b = a.fmod b :=
fmod_fmod_of_dvd _ (Int.dvd_refl b)
theorem fmod_fmod (a b : Int) : (a.fmod b).fmod b = a.fmod b := by
simp
theorem sub_fmod (a b n : Int) : (a - b).fmod n = (a.fmod n - b.fmod n).fmod n := by
apply (fmod_add_cancel_right b).mp

View File

@@ -35,6 +35,7 @@ Examples:
* `Int.gcd 0 5 = 5`
* `Int.gcd (-7) 0 = 7`
-/
@[expose]
def gcd (m n : Int) : Nat := m.natAbs.gcd n.natAbs
theorem gcd_eq_natAbs_gcd_natAbs (m n : Int) : gcd m n = Nat.gcd m.natAbs n.natAbs := rfl
@@ -428,6 +429,7 @@ Examples:
* `Int.lcm 0 3 = 0`
* `Int.lcm (-3) 0 = 0`
-/
@[expose]
def lcm (m n : Int) : Nat := m.natAbs.lcm n.natAbs
theorem lcm_eq_natAbs_lcm_natAbs (m n : Int) : lcm m n = Nat.lcm m.natAbs n.natAbs := rfl

View File

@@ -638,7 +638,7 @@ theorem toNat_of_nonneg {a : Int} (h : 0 ≤ a) : (toNat a : Int) = a := by
@[simp] theorem toNat_natCast (n : Nat) : toNat n = n := rfl
@[deprecated toNat_natCast (since := "2025-04-16")]
theorem toNat_ofNat (n : Nat) : toNat n = n := toNat_natCast n
theorem toNat_ofNat (n : Nat) : toNat n = n := rfl
@[simp] theorem toNat_negSucc (n : Nat) : (Int.negSucc n).toNat = 0 := by
simp [toNat]

View File

@@ -23,6 +23,7 @@ a list `l : List α`, given a proof that every element of `l` in fact satisfies
`O(|l|)`. `List.pmap`, named for “partial map,” is the equivalent of `List.map` for such partial
functions.
-/
@[expose]
def pmap {P : α Prop} (f : a, P a β) : l : List α, (H : a l, P a) List β
| [], _ => []
| a :: l, H => f a (forall_mem_cons.1 H).1 :: pmap f l (forall_mem_cons.1 H).2
@@ -40,7 +41,7 @@ elements in the corresponding subtype `{ x // P x }`.
`O(1)`.
-/
@[implemented_by attachWithImpl] def attachWith
@[implemented_by attachWithImpl, expose] def attachWith
(l : List α) (P : α Prop) (H : x l, P x) : List {x // P x} := pmap Subtype.mk l H
/--
@@ -54,7 +55,7 @@ recursion](lean-manual://section/well-founded-recursion) that use higher-order f
`List.map`) to prove that an value taken from a list is smaller than the list. This allows the
well-founded recursion mechanism to prove that the function terminates.
-/
@[inline] def attach (l : List α) : List {x // x l} := attachWith l _ fun _ => id
@[inline, expose] def attach (l : List α) : List {x // x l} := attachWith l _ fun _ => id
/-- Implementation of `pmap` using the zero-copy version of `attach`. -/
@[inline] private def pmapImpl {P : α Prop} (f : a, P a β) (l : List α) (H : a l, P a) :
@@ -675,6 +676,7 @@ the elaboration of definitions by [well-founded
recursion](lean-manual://section/well-founded-recursion). If this function is encountered in a proof
state, the right approach is usually the tactic `simp [List.unattach, -List.map_subtype]`.
-/
@[expose]
def unattach {α : Type _} {p : α Prop} (l : List { x // p x }) : List α := l.map (·.val)
@[simp] theorem unattach_nil {p : α Prop} : ([] : List { x // p x }).unattach = [] := rfl

View File

@@ -586,7 +586,7 @@ Examples:
* `[1, 2, 3, 4].reverse = [4, 3, 2, 1]`
* `[].reverse = []`
-/
def reverse (as : List α) : List α :=
@[expose] def reverse (as : List α) : List α :=
reverseAux as []
@[simp, grind] theorem reverse_nil : reverse ([] : List α) = [] := rfl
@@ -715,7 +715,7 @@ Examples:
* `List.singleton "green" = ["green"]`.
* `List.singleton [1, 2, 3] = [[1, 2, 3]]`
-/
@[inline] protected def singleton {α : Type u} (a : α) : List α := [a]
@[inline, expose] protected def singleton {α : Type u} (a : α) : List α := [a]
/-! ### flatMap -/
@@ -1190,10 +1190,10 @@ def isPrefixOf [BEq α] : List α → List α → Bool
| _, [] => false
| a::as, b::bs => a == b && isPrefixOf as bs
@[simp] theorem isPrefixOf_nil_left [BEq α] : isPrefixOf ([] : List α) l = true := by
@[simp, grind =] theorem isPrefixOf_nil_left [BEq α] : isPrefixOf ([] : List α) l = true := by
simp [isPrefixOf]
@[simp] theorem isPrefixOf_cons_nil [BEq α] : isPrefixOf (a::as) ([] : List α) = false := rfl
theorem isPrefixOf_cons₂ [BEq α] {a : α} :
@[simp, grind =] theorem isPrefixOf_cons_nil [BEq α] : isPrefixOf (a::as) ([] : List α) = false := rfl
@[grind =] theorem isPrefixOf_cons₂ [BEq α] {a : α} :
isPrefixOf (a::as) (b::bs) = (a == b && isPrefixOf as bs) := rfl
/--
@@ -1229,7 +1229,7 @@ Examples:
def isSuffixOf [BEq α] (l₁ l₂ : List α) : Bool :=
isPrefixOf l₁.reverse l₂.reverse
@[simp] theorem isSuffixOf_nil_left [BEq α] : isSuffixOf ([] : List α) l = true := by
@[simp, grind =] theorem isSuffixOf_nil_left [BEq α] : isSuffixOf ([] : List α) l = true := by
simp [isSuffixOf]
/--
@@ -1564,8 +1564,8 @@ protected def erase {α} [BEq α] : List αα → List α
| true => as
| false => a :: List.erase as b
@[simp] theorem erase_nil [BEq α] (a : α) : [].erase a = [] := rfl
theorem erase_cons [BEq α] {a b : α} {l : List α} :
@[simp, grind =] theorem erase_nil [BEq α] (a : α) : [].erase a = [] := rfl
@[grind =] theorem erase_cons [BEq α] {a b : α} {l : List α} :
(b :: l).erase a = if b == a then l else b :: l.erase a := by
simp only [List.erase]; split <;> simp_all
@@ -2096,7 +2096,7 @@ where
| 0, acc => acc
| n+1, acc => loop n (n::acc)
@[simp] theorem range_zero : range 0 = [] := rfl
@[simp, grind =] theorem range_zero : range 0 = [] := rfl
/-! ### range' -/

View File

@@ -27,7 +27,7 @@ Returns the `i`-th element in the list (zero-based).
If the index is out of bounds (`i ≥ as.length`), this function returns `none`.
Also see `get`, `getD` and `get!`.
-/
@[deprecated "Use `a[i]?` instead." (since := "2025-02-12")]
@[deprecated "Use `a[i]?` instead." (since := "2025-02-12"), expose]
def get? : (as : List α) (i : Nat) Option α
| a::_, 0 => some a
| _::as, n+1 => get? as n
@@ -61,7 +61,7 @@ Returns the `i`-th element in the list (zero-based).
If the index is out of bounds (`i ≥ as.length`), this function panics when executed, and returns
`default`. See `get?` and `getD` for safer alternatives.
-/
@[deprecated "Use `a[i]!` instead." (since := "2025-02-12")]
@[deprecated "Use `a[i]!` instead." (since := "2025-02-12"), expose]
def get! [Inhabited α] : (as : List α) (i : Nat) α
| a::_, 0 => a
| _::as, n+1 => get! as n
@@ -92,7 +92,7 @@ Examples:
* `["spring", "summer", "fall", "winter"].getD 0 "never" = "spring"`
* `["spring", "summer", "fall", "winter"].getD 4 "never" = "never"`
-/
def getD (as : List α) (i : Nat) (fallback : α) : α :=
@[expose] def getD (as : List α) (i : Nat) (fallback : α) : α :=
as[i]?.getD fallback
@[simp] theorem getD_nil : getD [] n d = d := rfl
@@ -111,6 +111,7 @@ Examples:
* `["circle", "rectangle"].getLast! = "rectangle"`
* `["circle"].getLast! = "circle"`
-/
@[expose]
def getLast! [Inhabited α] : List α α
| [] => panic! "empty list"
| a::as => getLast (a::as) (fun h => List.noConfusion h)
@@ -146,7 +147,7 @@ Examples:
* `["apple", "banana", "grape"].tail! = ["banana", "grape"]`
* `["banana", "grape"].tail! = ["grape"]`
-/
def tail! : List α List α
@[expose] def tail! : List α List α
| [] => panic! "empty list"
| _::as => as
@@ -254,7 +255,7 @@ pointer-equal to its argument.
For verification purposes, `List.mapMono = List.map`.
-/
def mapMono (as : List α) (f : α α) : List α :=
Id.run <| as.mapMonoM f
Id.run <| as.mapMonoM (pure <| f ·)
/-! ## Additional lemmas required for bootstrapping `Array`. -/

View File

@@ -54,7 +54,7 @@ This implementation is tail recursive. `List.mapM'` is a a non-tail-recursive va
more convenient to reason about. `List.forM` is the variant that discards the results and
`List.mapA` is the variant that works with `Applicative`.
-/
@[inline]
@[inline, expose]
def mapM {m : Type u Type v} [Monad m] {α : Type w} {β : Type u} (f : α m β) (as : List α) : m (List β) :=
let rec @[specialize] loop
| [], bs => pure bs.reverse
@@ -83,7 +83,7 @@ Applies the monadic action `f` to every element in the list, in order.
`List.mapM` is a variant that collects results. `List.forA` is a variant that works on any
`Applicative`.
-/
@[specialize]
@[specialize, expose]
protected def forM {m : Type u Type v} [Monad m] {α : Type w} (as : List α) (f : α m PUnit) : m PUnit :=
match as with
| [] => pure
@@ -191,7 +191,7 @@ Examining 7
[10, 14, 14]
```
-/
@[inline]
@[inline, expose]
def filterMapM {m : Type u Type v} [Monad m] {α : Type w} {β : Type u} (f : α m (Option β)) (as : List α) : m (List β) :=
let rec @[specialize] loop
| [], bs => pure bs.reverse
@@ -205,7 +205,7 @@ def filterMapM {m : Type u → Type v} [Monad m] {α : Type w} {β : Type u} (f
Applies a monadic function that returns a list to each element of a list, from left to right, and
concatenates the resulting lists.
-/
@[inline]
@[inline, expose]
def flatMapM {m : Type u Type v} [Monad m] {α : Type w} {β : Type u} (f : α m (List β)) (as : List α) : m (List β) :=
let rec @[specialize] loop
| [], bs => pure bs.reverse.flatten
@@ -230,7 +230,7 @@ example [Monad m] (f : α → β → m α) :
:= by rfl
```
-/
@[specialize]
@[specialize, expose]
def foldlM {m : Type u Type v} [Monad m] {s : Type u} {α : Type w} : (f : s α m s) (init : s) List α m s
| _, s, [] => pure s
| f, s, a :: as => do
@@ -257,7 +257,7 @@ example [Monad m] (f : α → β → m β) :
:= by rfl
```
-/
@[inline]
@[inline, expose]
def foldrM {m : Type u Type v} [Monad m] {s : Type u} {α : Type w} (f : α s m s) (init : s) (l : List α) : m s :=
l.reverse.foldlM (fun s a => f a s) init
@@ -348,9 +348,16 @@ theorem findM?_pure {m} [Monad m] [LawfulMonad m] (p : α → Bool) (as : List
| false => simp [ih]
@[simp]
theorem findM?_id (p : α Bool) (as : List α) : findM? (m := Id) p as = as.find? p :=
theorem idRun_findM? (p : α Id Bool) (as : List α) :
(findM? p as).run = as.find? (p · |>.run) :=
findM?_pure _ _
@[deprecated idRun_findM? (since := "2025-05-21")]
theorem findM?_id (p : α Id Bool) (as : List α) :
findM? (m := Id) p as = as.find? p :=
findM?_pure _ _
/--
Returns the first non-`none` result of applying the monadic function `f` to each element of the
list, in order. Returns `none` if `f` returns `none` for all elements.
@@ -394,7 +401,13 @@ theorem findSomeM?_pure [Monad m] [LawfulMonad m] {f : α → Option β} {as : L
| none => simp [ih]
@[simp]
theorem findSomeM?_id {f : α Option β} {as : List α} : findSomeM? (m := Id) f as = as.findSome? f :=
theorem idRun_findSomeM? (f : α Id (Option β)) (as : List α) :
(findSomeM? f as).run = as.findSome? (f · |>.run) :=
findSomeM?_pure
@[deprecated idRun_findSomeM? (since := "2025-05-21")]
theorem findSomeM?_id (f : α Id (Option β)) (as : List α) :
findSomeM? (m := Id) f as = as.findSome? f :=
findSomeM?_pure
theorem findM?_eq_findSomeM? [Monad m] [LawfulMonad m] {p : α m Bool} {as : List α} :
@@ -409,7 +422,7 @@ theorem findM?_eq_findSomeM? [Monad m] [LawfulMonad m] {p : α → m Bool} {as :
intro b
cases b <;> simp
@[inline] protected def forIn' {α : Type u} {β : Type v} {m : Type v Type w} [Monad m] (as : List α) (init : β) (f : (a : α) a as β m (ForInStep β)) : m β :=
@[inline, expose] protected def forIn' {α : Type u} {β : Type v} {m : Type v Type w} [Monad m] (as : List α) (init : β) (f : (a : α) a as β m (ForInStep β)) : m β :=
let rec @[specialize] loop : (as' : List α) (b : β) Exists (fun bs => bs ++ as' = as) m β
| [], b, _ => pure b
| a::as', b, h => do

View File

@@ -10,6 +10,9 @@ import Init.Data.List.Sublist
/-!
# Lemmas about `List.countP` and `List.count`.
Because we mark `countP_eq_length_filter` and `count_eq_countP` with `@[grind _=_]`,
we don't need many other `@[grind]` annotations here.
-/
set_option linter.listVariables true -- Enforce naming conventions for `List`/`Array`/`Vector` variables.
@@ -61,6 +64,7 @@ theorem length_eq_countP_add_countP (p : α → Bool) {l : List α} : length l =
· rfl
· simp [h]
@[grind =]
theorem countP_eq_length_filter {l : List α} : countP p l = length (filter p l) := by
induction l with
| nil => rfl
@@ -69,6 +73,7 @@ theorem countP_eq_length_filter {l : List α} : countP p l = length (filter p l)
then rw [countP_cons_of_pos h, ih, filter_cons_of_pos h, length]
else rw [countP_cons_of_neg h, ih, filter_cons_of_neg h]
@[grind =]
theorem countP_eq_length_filter' : countP p = length filter p := by
funext l
apply countP_eq_length_filter
@@ -97,6 +102,7 @@ theorem countP_replicate {p : α → Bool} {a : α} {n : Nat} :
simp only [countP_eq_length_filter, filter_replicate]
split <;> simp
@[grind]
theorem boole_getElem_le_countP {p : α Bool} {l : List α} {i : Nat} (h : i < l.length) :
(if p l[i] then 1 else 0) l.countP p := by
induction l generalizing i with
@@ -120,6 +126,7 @@ theorem IsInfix.countP_le (s : l₁ <:+: l₂) : countP p l₁ ≤ countP p l₂
-- See `Init.Data.List.Nat.Count` for `Sublist.le_countP : countP p l₂ - (l₂.length - l₁.length) ≤ countP p l₁`.
@[grind]
theorem countP_tail_le (l) : countP p l.tail countP p l :=
(tail_sublist l).countP_le
@@ -198,18 +205,21 @@ variable [BEq α]
@[simp] theorem count_nil {a : α} : count a [] = 0 := rfl
@[grind]
theorem count_cons {a b : α} {l : List α} :
count a (b :: l) = count a l + if b == a then 1 else 0 := by
simp [count, countP_cons]
theorem count_eq_countP {a : α} {l : List α} : count a l = countP (· == a) l := rfl
@[grind =] theorem count_eq_countP {a : α} {l : List α} : count a l = countP (· == a) l := rfl
theorem count_eq_countP' {a : α} : count a = countP (· == a) := by
funext l
apply count_eq_countP
theorem count_tail : {l : List α} (h : l []) (a : α),
l.tail.count a = l.count a - if l.head h == a then 1 else 0
| _ :: _, a, _ => by simp [count_cons]
@[grind]
theorem count_tail : {l : List α} {a : α},
l.tail.count a = l.count a - if l.head? == some a then 1 else 0
| [], a => by simp
| _ :: _, a => by simp [count_cons]
theorem count_le_length {a : α} {l : List α} : count a l l.length := countP_le_length
@@ -232,7 +242,7 @@ theorem count_le_count_cons {a b : α} {l : List α} : count a l ≤ count a (b
theorem count_singleton {a b : α} : count a [b] = if b == a then 1 else 0 := by
simp [count_cons]
@[simp] theorem count_append {a : α} {l₁ l₂ : List α} : count a (l₁ ++ l₂) = count a l₁ + count a l₂ :=
@[simp, grind =] theorem count_append {a : α} {l₁ l₂ : List α} : count a (l₁ ++ l₂) = count a l₁ + count a l₂ :=
countP_append
theorem count_flatten {a : α} {l : List (List α)} : count a l.flatten = (l.map (count a)).sum := by
@@ -241,6 +251,7 @@ theorem count_flatten {a : α} {l : List (List α)} : count a l.flatten = (l.map
@[simp] theorem count_reverse {a : α} {l : List α} : count a l.reverse = count a l := by
simp only [count_eq_countP, countP_eq_length_filter, filter_reverse, length_reverse]
@[grind]
theorem boole_getElem_le_count {a : α} {l : List α} {i : Nat} (h : i < l.length) :
(if l[i] == a then 1 else 0) l.count a := by
rw [count_eq_countP]
@@ -283,7 +294,7 @@ theorem count_eq_length {l : List α} : count a l = l.length ↔ ∀ b ∈ l, a
@[simp] theorem count_replicate_self {a : α} {n : Nat} : count a (replicate n a) = n :=
(count_eq_length.2 <| fun _ h => (eq_of_mem_replicate h).symm).trans (length_replicate ..)
theorem count_replicate {a b : α} {n : Nat} : count a (replicate n b) = if b == a then n else 0 := by
@[grind =] theorem count_replicate {a b : α} {n : Nat} : count a (replicate n b) = if b == a then n else 0 := by
split <;> (rename_i h; simp only [beq_iff_eq] at h)
· exact b = a count_replicate_self ..
· exact count_eq_zero.2 <| mt eq_of_mem_replicate (Ne.symm h)
@@ -295,14 +306,18 @@ theorem filter_beq {l : List α} (a : α) : l.filter (· == a) = replicate (coun
theorem filter_eq [DecidableEq α] {l : List α} (a : α) : l.filter (· = a) = replicate (count a l) a :=
funext (Bool.beq_eq_decide_eq · a) filter_beq a
theorem le_count_iff_replicate_sublist {l : List α} : n count a l replicate n a <+ l := by
@[grind =] theorem replicate_sublist_iff {l : List α} : replicate n a <+ l n count a l := by
refine fun h => ?_, fun h => ?_
· exact ((replicate_sublist_replicate a).2 h).trans <| filter_beq a filter_sublist
· simpa only [count_replicate_self] using h.count_le a
· exact ((replicate_sublist_replicate a).2 h).trans <| filter_beq a filter_sublist
@[deprecated replicate_sublist_iff (since := "2025-05-26")]
theorem le_count_iff_replicate_sublist {l : List α} : n count a l replicate n a <+ l :=
replicate_sublist_iff.symm
theorem replicate_count_eq_of_count_eq_length {l : List α} (h : count a l = length l) :
replicate (count a l) a = l :=
(le_count_iff_replicate_sublist.mp (Nat.le_refl _)).eq_of_length <| length_replicate.trans h
(replicate_sublist_iff.mpr (Nat.le_refl _)).eq_of_length <| length_replicate.trans h
@[simp] theorem count_filter {l : List α} (h : p a) : count a (filter p l) = count a l := by
rw [count, countP_filter]; congr; funext b
@@ -325,6 +340,7 @@ theorem count_filterMap {α} [BEq β] {b : β} {f : α → Option β} {l : List
theorem count_flatMap {α} [BEq β] {l : List α} {f : α List β} {x : β} :
count x (l.flatMap f) = sum (map (count x f) l) := countP_flatMap
@[grind]
theorem count_erase {a b : α} :
{l : List α}, count a (l.erase b) = count a l - if b == a then 1 else 0
| [] => by simp

View File

@@ -61,7 +61,7 @@ end List
namespace Fin
theorem foldlM_eq_finRange_foldlM [Monad m] (f : α Fin n m α) (x : α) :
theorem foldlM_eq_foldlM_finRange [Monad m] (f : α Fin n m α) (x : α) :
foldlM n f x = (List.finRange n).foldlM f x := by
induction n generalizing x with
| zero => simp
@@ -71,7 +71,7 @@ theorem foldlM_eq_finRange_foldlM [Monad m] (f : α → Fin n → m α) (x : α)
funext y
simp [ih, List.foldlM_map]
theorem foldrM_eq_finRange_foldrM [Monad m] [LawfulMonad m] (f : Fin n α m α) (x : α) :
theorem foldrM_eq_foldrM_finRange [Monad m] [LawfulMonad m] (f : Fin n α m α) (x : α) :
foldrM n f x = (List.finRange n).foldrM f x := by
induction n generalizing x with
| zero => simp
@@ -101,7 +101,7 @@ theorem ofFnM_succ {n} [Monad m] [LawfulMonad m] {f : Fin (n + 1) → m α} :
let a f 0
let as ofFnM fun i => f i.succ
pure (a :: as)) := by
simp [ofFnM, Fin.foldlM_eq_finRange_foldlM, List.finRange_succ, List.foldlM_cons_eq_append,
simp [ofFnM, Fin.foldlM_eq_foldlM_finRange, List.finRange_succ, List.foldlM_cons_eq_append,
List.foldlM_map]
end List

View File

@@ -243,9 +243,6 @@ theorem find?_eq_some_iff_append :
cases h₁
simp
@[deprecated find?_eq_some_iff_append (since := "2024-11-06")]
abbrev find?_eq_some := @find?_eq_some_iff_append
@[simp]
theorem find?_cons_eq_some : (a :: xs).find? p = some b (p a a = b) (!p a xs.find? p = some b) := by
rw [find?_cons]
@@ -1108,14 +1105,9 @@ theorem isSome_finIdxOf? [BEq α] [LawfulBEq α] {l : List α} {a : α} :
simp only [finIdxOf?_cons]
split <;> simp_all [@eq_comm _ x a]
@[simp]
theorem isNone_finIdxOf? [BEq α] [LawfulBEq α] {l : List α} {a : α} :
(l.finIdxOf? a).isNone = ¬ a l := by
induction l with
| nil => simp
| cons x xs ih =>
simp only [finIdxOf?_cons]
split <;> simp_all [@eq_comm _ x a]
simp
/-! ### idxOf?
@@ -1154,15 +1146,9 @@ theorem isSome_idxOf? [BEq α] [LawfulBEq α] {l : List α} {a : α} :
simp only [idxOf?_cons]
split <;> simp_all [@eq_comm _ x a]
@[simp]
theorem isNone_idxOf? [BEq α] [LawfulBEq α] {l : List α} {a : α} :
(l.idxOf? a).isNone = ¬ a l := by
induction l with
| nil => simp
| cons x xs ih =>
simp only [idxOf?_cons]
split <;> simp_all [@eq_comm _ x a]
simp
/-! ### lookup -/

View File

@@ -109,7 +109,7 @@ Example:
let rec go : as acc, filterMapTR.go f as acc = acc.toList ++ as.filterMap f
| [], acc => by simp [filterMapTR.go, filterMap]
| a::as, acc => by
simp only [filterMapTR.go, go as, Array.push_toList, append_assoc, singleton_append,
simp only [filterMapTR.go, go as, Array.toList_push, append_assoc, singleton_append,
filterMap]
split <;> simp [*]
exact (go l #[]).symm
@@ -550,7 +550,7 @@ def zipIdxTR (l : List α) (n : Nat := 0) : List (α × Nat) :=
(as.foldr (fun a (n, acc) => (n-1, (a, n-1) :: acc)) (n + as.size, [])).2
@[csimp] theorem zipIdx_eq_zipIdxTR : @zipIdx = @zipIdxTR := by
funext α l n; simp only [zipIdxTR, size_toArray]
funext α l n; simp only [zipIdxTR]
let f := fun (a : α) (n, acc) => (n-1, (a, n-1) :: acc)
let rec go : l i, l.foldr f (i + l.length, []) = (i, zipIdx l i)
| [], n => rfl
@@ -571,7 +571,7 @@ def enumFromTR (n : Nat) (l : List α) : List (Nat × α) :=
set_option linter.deprecated false in
@[deprecated zipIdx_eq_zipIdxTR (since := "2025-01-21"), csimp]
theorem enumFrom_eq_enumFromTR : @enumFrom = @enumFromTR := by
funext α n l; simp only [enumFromTR, size_toArray]
funext α n l; simp only [enumFromTR]
let f := fun (a : α) (n, acc) => (n-1, (n-1, a) :: acc)
let rec go : l n, l.foldr f (n + l.length, []) = (n, enumFrom n l)
| [], n => rfl

View File

@@ -272,13 +272,13 @@ theorem getElem_of_getElem? {l : List α} : l[i]? = some a → ∃ h : i < l.len
theorem some_eq_getElem?_iff {l : List α} : some a = l[i]? h : i < l.length, l[i] = a := by
rw [eq_comm, getElem?_eq_some_iff]
@[simp] theorem some_getElem_eq_getElem?_iff {xs : List α} {i : Nat} (h : i < xs.length) :
theorem some_getElem_eq_getElem?_iff {xs : List α} {i : Nat} (h : i < xs.length) :
(some xs[i] = xs[i]?) True := by
simp [h]
simp
@[simp] theorem getElem?_eq_some_getElem_iff {xs : List α} {i : Nat} (h : i < xs.length) :
theorem getElem?_eq_some_getElem_iff {xs : List α} {i : Nat} (h : i < xs.length) :
(xs[i]? = some xs[i]) True := by
simp [h]
simp
theorem getElem_eq_iff {l : List α} {i : Nat} (h : i < l.length) : l[i] = x l[i]? = some x := by
simp only [getElem?_eq_some_iff]
@@ -296,7 +296,7 @@ theorem getD_getElem? {l : List α} {i : Nat} {d : α} :
have p : i l.length := Nat.le_of_not_gt h
simp [getElem?_eq_none p, h]
@[simp] theorem getElem_singleton {a : α} {i : Nat} (h : i < 1) : [a][i] = a :=
@[simp] theorem getElem_singleton {a : α} {i : Nat} (h : i < 1) : [a][i] = a := by
match i, h with
| 0, _ => rfl
@@ -434,8 +434,8 @@ theorem eq_nil_iff_forall_not_mem {l : List α} : l = [] ↔ ∀ a, a ∉ l := b
theorem eq_of_mem_singleton : a [b] a = b
| .head .. => rfl
@[simp] theorem mem_singleton {a b : α} : a [b] a = b :=
eq_of_mem_singleton, (by simp [·])
theorem mem_singleton {a b : α} : a [b] a = b := by
simp
theorem forall_mem_cons {p : α Prop} {a : α} {l : List α} :
( x, x a :: l p x) p a x, x l p x :=
@@ -834,7 +834,7 @@ theorem getElem_length_sub_one_eq_getLast {l : List α} (h : l.length - 1 < l.le
rw [ getLast_eq_getElem]
@[simp, grind] theorem getLast_cons_cons {a : α} {l : List α} :
getLast (a :: b :: l) (by simp) = getLast (b :: l) (by simp) := by
getLast (a :: b :: l) (by simp) = getLast (b :: l) (by simp) :=
rfl
theorem getLast_cons {a : α} {l : List α} : (h : l nil),
@@ -1252,7 +1252,7 @@ theorem tailD_map {f : α → β} {l l' : List α} :
theorem getLastD_map {f : α β} {l : List α} {a : α} : (map f l).getLastD (f a) = f (l.getLastD a) := by
simp
@[simp] theorem map_map {g : β γ} {f : α β} {l : List α} :
@[simp, grind _=_] theorem map_map {g : β γ} {f : α β} {l : List α} :
map g (map f l) = map (g f) l := by induction l <;> simp_all
/-! ### filter -/
@@ -1337,7 +1337,7 @@ theorem foldr_filter {p : α → Bool} {f : α → β → β} {l : List α} {ini
simp only [filter_cons, foldr_cons]
split <;> simp [ih]
theorem filter_map {f : β α} {p : α Bool} {l : List β} :
@[grind _=_] theorem filter_map {f : β α} {p : α Bool} {l : List β} :
filter p (map f l) = map f (filter (p f) l) := by
induction l with
| nil => rfl
@@ -1572,9 +1572,6 @@ theorem not_mem_append {a : α} {s t : List α} (h₁ : a ∉ s) (h₂ : a ∉ t
theorem mem_append_eq {a : α} {s t : List α} : (a s ++ t) = (a s a t) :=
propext mem_append
@[deprecated mem_append_left (since := "2024-11-20")] abbrev mem_append_of_mem_left := @mem_append_left
@[deprecated mem_append_right (since := "2024-11-20")] abbrev mem_append_of_mem_right := @mem_append_right
/--
See also `eq_append_cons_of_mem`, which proves a stronger version
in which the initial list must not contain the element.
@@ -1685,8 +1682,8 @@ theorem getLast_concat {a : α} : ∀ {l : List α}, getLast (l ++ [a]) (by simp
@[deprecated append_eq_nil_iff (since := "2025-01-13")] abbrev append_eq_nil := @append_eq_nil_iff
@[simp] theorem nil_eq_append_iff : [] = a ++ b a = [] b = [] := by
rw [eq_comm, append_eq_nil_iff]
theorem nil_eq_append_iff : [] = a ++ b a = [] b = [] := by
simp
@[grind ]
theorem eq_nil_of_append_eq_nil {l₁ l₂ : List α} (h : l₁ ++ l₂ = []) : l₁ = [] l₂ = [] :=
@@ -1882,7 +1879,7 @@ theorem eq_nil_or_concat : ∀ l : List α, l = [] ∃ l' b, l = concat l' b
/-! ### flatten -/
@[simp] theorem length_flatten {L : List (List α)} : L.flatten.length = (L.map length).sum := by
@[simp, grind _=_] theorem length_flatten {L : List (List α)} : L.flatten.length = (L.map length).sum := by
induction L with
| nil => rfl
| cons =>
@@ -1897,8 +1894,8 @@ theorem eq_nil_or_concat : ∀ l : List α, l = [] ∃ l' b, l = concat l' b
@[simp] theorem flatten_eq_nil_iff {L : List (List α)} : L.flatten = [] l L, l = [] := by
induction L <;> simp_all
@[simp] theorem nil_eq_flatten_iff {L : List (List α)} : [] = L.flatten l L, l = [] := by
rw [eq_comm, flatten_eq_nil_iff]
theorem nil_eq_flatten_iff {L : List (List α)} : [] = L.flatten l L, l = [] := by
simp
theorem flatten_ne_nil_iff {xss : List (List α)} : xss.flatten [] xs, xs xss xs [] := by
simp
@@ -2052,7 +2049,7 @@ theorem eq_iff_flatten_eq : ∀ {L L' : List (List α)},
/-! ### flatMap -/
theorem flatMap_def {l : List α} {f : α List β} : l.flatMap f = flatten (map f l) := rfl
@[grind _=_] theorem flatMap_def {l : List α} {f : α List β} : l.flatMap f = flatten (map f l) := rfl
@[simp] theorem flatMap_id {L : List (List α)} : L.flatMap id = L.flatten := by simp [flatMap_def]
@@ -2541,17 +2538,25 @@ theorem flatten_reverse {L : List (List α)} :
induction l generalizing b <;> simp [*]
theorem foldl_eq_foldlM {f : β α β} {b : β} {l : List α} :
l.foldl f b = l.foldlM (m := Id) f b := by
induction l generalizing b <;> simp [*, foldl]
l.foldl f b = (l.foldlM (m := Id) (pure <| f · ·) b).run := by
simp
theorem foldr_eq_foldrM {f : α β β} {b : β} {l : List α} :
l.foldr f b = l.foldrM (m := Id) f b := by
induction l <;> simp [*, foldr]
l.foldr f b = (l.foldrM (m := Id) (pure <| f · ·) b).run := by
simp
@[simp] theorem id_run_foldlM {f : β α Id β} {b : β} {l : List α} :
theorem idRun_foldlM {f : β α Id β} {b : β} {l : List α} :
Id.run (l.foldlM f b) = l.foldl (f · · |>.run) b := foldl_eq_foldlM.symm
@[deprecated idRun_foldlM (since := "2025-05-21")]
theorem id_run_foldlM {f : β α Id β} {b : β} {l : List α} :
Id.run (l.foldlM f b) = l.foldl f b := foldl_eq_foldlM.symm
@[simp] theorem id_run_foldrM {f : α β Id β} {b : β} {l : List α} :
theorem idRun_foldrM {f : α β Id β} {b : β} {l : List α} :
Id.run (l.foldrM f b) = l.foldr (f · · |>.run) b := foldr_eq_foldrM.symm
@[deprecated idRun_foldrM (since := "2025-05-21")]
theorem id_run_foldrM {f : α β Id β} {b : β} {l : List α} :
Id.run (l.foldrM f b) = l.foldr f b := foldr_eq_foldrM.symm
@[simp] theorem foldlM_reverse [Monad m] {l : List α} {f : β α m β} {b : β} :
@@ -2577,9 +2582,9 @@ theorem foldr_eq_foldrM {f : α → β → β} {b : β} {l : List α} :
induction l generalizing l' <;> simp [*]
/-- Variant of `foldl_flip_cons_eq_append` specalized to `f = id`. -/
@[simp, grind] theorem foldl_flip_cons_eq_append' {l l' : List α} :
@[grind] theorem foldl_flip_cons_eq_append' {l l' : List α} :
l.foldl (fun xs y => y :: xs) l' = l.reverse ++ l' := by
induction l generalizing l' <;> simp [*]
simp
@[simp, grind] theorem foldr_append_eq_append {l : List α} {f : α List β} {l' : List β} :
l.foldr (f · ++ ·) l' = (l.map f).flatten ++ l' := by
@@ -2646,10 +2651,10 @@ theorem foldr_map_hom {g : α → β} {f : ααα} {f' : β → β →
induction l <;> simp [*]
@[simp, grind _=_] theorem foldl_append {β : Type _} {f : β α β} {b : β} {l l' : List α} :
(l ++ l').foldl f b = l'.foldl f (l.foldl f b) := by simp [foldl_eq_foldlM]
(l ++ l').foldl f b = l'.foldl f (l.foldl f b) := by simp [foldl_eq_foldlM, -foldlM_pure]
@[simp, grind _=_] theorem foldr_append {f : α β β} {b : β} {l l' : List α} :
(l ++ l').foldr f b = l.foldr f (l'.foldr f b) := by simp [foldr_eq_foldrM]
(l ++ l').foldr f b = l.foldr f (l'.foldr f b) := by simp [foldr_eq_foldrM, -foldrM_pure]
@[grind] theorem foldl_flatten {f : β α β} {b : β} {L : List (List α)} :
(flatten L).foldl f b = L.foldl (fun b l => l.foldl f b) b := by
@@ -2660,7 +2665,8 @@ theorem foldr_map_hom {g : α → β} {f : ααα} {f' : β → β →
induction L <;> simp_all
@[simp, grind] theorem foldl_reverse {l : List α} {f : β α β} {b : β} :
l.reverse.foldl f b = l.foldr (fun x y => f y x) b := by simp [foldl_eq_foldlM, foldr_eq_foldrM]
l.reverse.foldl f b = l.foldr (fun x y => f y x) b := by
simp [foldl_eq_foldlM, foldr_eq_foldrM, -foldrM_pure]
@[simp, grind] theorem foldr_reverse {l : List α} {f : α β β} {b : β} :
l.reverse.foldr f b = l.foldl (fun x y => f y x) b :=
@@ -2712,6 +2718,7 @@ example {xs : List Nat} : xs.foldl (· + ·) 1 > 0 := by
intros; omega
```
-/
@[expose]
def foldlRecOn {motive : β Sort _} : (l : List α) (op : β α β) {b : β} (_ : motive b)
(_ : (b : β) (_ : motive b) (a : α) (_ : a l), motive (op b a)), motive (List.foldl op b l)
| [], _, _, hb, _ => hb
@@ -2746,6 +2753,7 @@ example {xs : List Nat} : xs.foldr (· + ·) 1 > 0 := by
intros; omega
```
-/
@[expose]
def foldrRecOn {motive : β Sort _} : (l : List α) (op : α β β) {b : β} (_ : motive b)
(_ : (b : β) (_ : motive b) (a : α) (_ : a l), motive (op a b)), motive (List.foldr op b l)
| nil, _, _, hb, _ => hb
@@ -2943,7 +2951,7 @@ theorem contains_iff_exists_mem_beq [BEq α] {l : List α} {a : α} :
l.contains a a' l, a == a' := by
induction l <;> simp_all
@[grind]
@[grind _=_]
theorem contains_iff_mem [BEq α] [LawfulBEq α] {l : List α} {a : α} :
l.contains a a l := by
simp
@@ -3418,8 +3426,8 @@ variable [LawfulBEq α]
| Or.inr h' => exact h'
else rw [insert_of_not_mem h, mem_cons]
@[simp] theorem mem_insert_self {a : α} {l : List α} : a l.insert a :=
mem_insert_iff.2 (Or.inl rfl)
theorem mem_insert_self {a : α} {l : List α} : a l.insert a := by
simp
theorem mem_insert_of_mem {l : List α} (h : a l) : a l.insert b :=
mem_insert_iff.2 (Or.inr h)
@@ -3695,17 +3703,6 @@ theorem mem_iff_get? {a} {l : List α} : a ∈ l ↔ ∃ n, l.get? n = some a :=
/-! ### Deprecations -/
@[deprecated get?_eq_none (since := "2024-11-29")] abbrev get?_len_le := @getElem?_eq_none
@[deprecated getElem?_eq_some_iff (since := "2024-11-29")]
abbrev getElem?_eq_some := @getElem?_eq_some_iff
@[deprecated get?_eq_some_iff (since := "2024-11-29")]
abbrev get?_eq_some := @getElem?_eq_some_iff
@[deprecated LawfulGetElem.getElem?_def (since := "2024-11-29")]
theorem getElem?_eq (l : List α) (i : Nat) :
l[i]? = if h : i < l.length then some l[i] else none :=
getElem?_def _ _
@[deprecated getElem?_eq_none (since := "2024-11-29")] abbrev getElem?_len_le := @getElem?_eq_none
@[deprecated _root_.isSome_getElem? (since := "2024-12-09")]
theorem isSome_getElem? {l : List α} {i : Nat} : l[i]?.isSome i < l.length := by
simp

View File

@@ -27,7 +27,7 @@ that the index is valid.
`List.mapIdx` is a variant that does not provide the function with evidence that the index is valid.
-/
@[inline] def mapFinIdx (as : List α) (f : (i : Nat) α (h : i < as.length) β) : List β :=
@[inline, expose] def mapFinIdx (as : List α) (f : (i : Nat) α (h : i < as.length) β) : List β :=
go as #[] (by simp)
where
/-- Auxiliary for `mapFinIdx`:
@@ -44,7 +44,7 @@ returning the list of results.
`List.mapFinIdx` is a variant that additionally provides the function with a proof that the index
is valid.
-/
@[inline] def mapIdx (f : Nat α β) (as : List α) : List β := go as #[] where
@[inline, expose] def mapIdx (f : Nat α β) (as : List α) : List β := go as #[] where
/-- Auxiliary for `mapIdx`:
`mapIdx.go [a₀, a₁, ...] acc = acc.toList ++ [f acc.size a₀, f (acc.size + 1) a₁, ...]` -/
@[specialize] go : List α Array β List β
@@ -320,7 +320,7 @@ theorem mapIdx_nil {f : Nat → α → β} : mapIdx f [] = [] :=
theorem mapIdx_go_length {acc : Array β} :
length (mapIdx.go f l acc) = length l + acc.size := by
induction l generalizing acc with
| nil => simp only [mapIdx.go, length_nil, Nat.zero_add]
| nil => simp [mapIdx.go]
| cons _ _ ih =>
simp only [mapIdx.go, ih, Array.size_push, Nat.add_succ, length_cons, Nat.add_comm]
@@ -348,7 +348,7 @@ theorem getElem?_mapIdx_go : ∀ {l : List α} {acc : Array β} {i : Nat},
split <;> split
· simp only [Option.some.injEq]
rw [ Array.getElem_toList]
simp only [Array.push_toList]
simp only [Array.toList_push]
rw [getElem_append_left, Array.getElem_toList]
· have : i = acc.size := by omega
simp_all

View File

@@ -44,6 +44,7 @@ This is a non-tail-recursive variant of `List.mapM` that's easier to reason abou
as the main definition and replaced by the tail-recursive version because they can only be proved
equal when `m` is a `LawfulMonad`.
-/
@[expose]
def mapM' [Monad m] (f : α m β) : List α m (List β)
| [] => pure []
| a :: l => return ( f a) :: ( l.mapM' f)
@@ -68,7 +69,11 @@ theorem mapM'_eq_mapM [Monad m] [LawfulMonad m] {f : α → m β} {l : List α}
l.mapM (m := m) (pure <| f ·) = pure (l.map f) := by
induction l <;> simp_all
@[simp] theorem mapM_id {l : List α} {f : α Id β} : l.mapM f = l.map f :=
@[simp] theorem idRun_mapM {l : List α} {f : α Id β} : (l.mapM f).run = l.map (f · |>.run) :=
mapM_pure
@[deprecated idRun_mapM (since := "2025-05-21")]
theorem mapM_id {l : List α} {f : α Id β} : (l.mapM f).run = l.map (f · |>.run) :=
mapM_pure
@[simp] theorem mapM_map [Monad m] [LawfulMonad m] {f : α β} {g : β m γ} {l : List α} :
@@ -345,12 +350,18 @@ theorem forIn'_eq_foldlM [Monad m] [LawfulMonad m]
simp only [forIn'_eq_foldlM]
induction l.attach generalizing init <;> simp_all
@[simp] theorem forIn'_yield_eq_foldl
@[simp] theorem idRun_forIn'_yield_eq_foldl
(l : List α) (f : (a : α) a l β Id β) (init : β) :
(forIn' l init (fun a m b => .yield <$> f a m b)).run =
l.attach.foldl (fun b a, h => f a h b |>.run) init :=
forIn'_pure_yield_eq_foldl _ _
@[deprecated idRun_forIn'_yield_eq_foldl (since := "2025-05-21")]
theorem forIn'_yield_eq_foldl
{l : List α} (f : (a : α) a l β β) (init : β) :
forIn' (m := Id) l init (fun a m b => .yield (f a m b)) =
l.attach.foldl (fun b a, h => f a h b) init := by
simp only [forIn'_eq_foldlM]
induction l.attach generalizing init <;> simp_all
l.attach.foldl (fun b a, h => f a h b) init :=
forIn'_pure_yield_eq_foldl _ _
@[simp] theorem forIn'_map [Monad m] [LawfulMonad m]
{l : List α} (g : α β) (f : (b : β) b l.map g γ m (ForInStep γ)) :
@@ -398,12 +409,18 @@ theorem forIn_eq_foldlM [Monad m] [LawfulMonad m]
simp only [forIn_eq_foldlM]
induction l generalizing init <;> simp_all
@[simp] theorem forIn_yield_eq_foldl
@[simp] theorem idRun_forIn_yield_eq_foldl
(l : List α) (f : α β Id β) (init : β) :
(forIn l init (fun a b => .yield <$> f a b)).run =
l.foldl (fun b a => f a b |>.run) init :=
forIn_pure_yield_eq_foldl _ _
@[deprecated idRun_forIn_yield_eq_foldl (since := "2025-05-21")]
theorem forIn_yield_eq_foldl
{l : List α} (f : α β β) (init : β) :
forIn (m := Id) l init (fun a b => .yield (f a b)) =
l.foldl (fun b a => f a b) init := by
simp only [forIn_eq_foldlM]
induction l generalizing init <;> simp_all
l.foldl (fun b a => f a b) init :=
forIn_pure_yield_eq_foldl _ _
@[simp] theorem forIn_map [Monad m] [LawfulMonad m]
{l : List α} {g : α β} {f : β γ m (ForInStep γ)} :

View File

@@ -617,9 +617,6 @@ set_option linter.deprecated false
@[deprecated zipIdx_eq_nil_iff (since := "2025-01-21"), simp]
theorem enum_eq_nil_iff {l : List α} : List.enum l = [] l = [] := enumFrom_eq_nil
@[deprecated zipIdx_eq_nil_iff (since := "2024-11-04")]
theorem enum_eq_nil {l : List α} : List.enum l = [] l = [] := enum_eq_nil_iff
@[deprecated zipIdx_singleton (since := "2025-01-21"), simp]
theorem enum_singleton (x : α) : enum [x] = [(0, x)] := rfl

View File

@@ -30,7 +30,7 @@ theorem IsSuffix.getElem {xs ys : List α} (h : xs <:+ ys) {i} (hn : i < xs.leng
have := h.length_le
omega
theorem isSuffix_iff : l₁ <:+ l₂
theorem suffix_iff_getElem? : l₁ <:+ l₂
l₁.length l₂.length i (h : i < l₁.length), l₂[i + l₂.length - l₁.length]? = some l₁[i] := by
suffices l₁.length l₂.length l₁ <:+ l₂
l₁.length l₂.length i (h : i < l₁.length), l₂[i + l₂.length - l₁.length]? = some l₁[i] by
@@ -41,7 +41,7 @@ theorem isSuffix_iff : l₁ <:+ l₂ ↔
exact (this.mpr h).2
simp only [and_congr_right_iff]
intro le
rw [ reverse_prefix, isPrefix_iff]
rw [ reverse_prefix, prefix_iff_getElem?]
simp only [length_reverse]
constructor
· intro w i h
@@ -60,15 +60,33 @@ theorem isSuffix_iff : l₁ <:+ l₂ ↔
rw [w, getElem_reverse]
exact Nat.lt_of_lt_of_le h le
theorem isInfix_iff : l₁ <:+: l₂
@[deprecated suffix_iff_getElem? (since := "2025-05-27")]
abbrev isSuffix_iff := @suffix_iff_getElem?
theorem suffix_iff_getElem {l₁ l₂ : List α} :
l₁ <:+ l₂ (_ : l₁.length l₂.length), i (_ : i < l₁.length), l₂[i + l₂.length - l₁.length] = l₁[i] := by
rw [suffix_iff_getElem?]
constructor
· rintro h, w
refine h, fun i h => ?_
specialize w i h
rw [getElem?_eq_getElem] at w
simpa using w
· rintro h, w
refine h, fun i h => ?_
specialize w i h
rw [getElem?_eq_getElem]
simpa using w
theorem infix_iff_getElem? : l₁ <:+: l₂
k, l₁.length + k l₂.length i (h : i < l₁.length), l₂[i + k]? = some l₁[i] := by
constructor
· intro h
obtain t, p, s := infix_iff_suffix_prefix.mp h
refine t.length - l₁.length, by have := p.length_le; have := s.length_le; omega, ?_
rw [isSuffix_iff] at p
rw [suffix_iff_getElem?] at p
obtain p', p := p
rw [isPrefix_iff] at s
rw [prefix_iff_getElem?] at s
intro i h
rw [s _ (by omega)]
specialize p i (by omega)
@@ -93,6 +111,9 @@ theorem isInfix_iff : l₁ <:+: l₂ ↔
simp_all
omega
@[deprecated infix_iff_getElem? (since := "2025-05-27")]
abbrev isInfix_iff := @infix_iff_getElem?
theorem suffix_iff_eq_append : l₁ <:+ l₂ take (length l₂ - length l₁) l₂ ++ l₁ = l₂ :=
by rintro r, rfl; simp only [length_append, Nat.add_sub_cancel_right, take_left], fun e =>
_, e
@@ -115,7 +136,7 @@ theorem suffix_iff_eq_drop : l₁ <:+ l₂ ↔ l₁ = drop (length l₂ - length
fun h => append_cancel_left <| (suffix_iff_eq_append.1 h).trans (take_append_drop _ _).symm,
fun e => e.symm drop_suffix _ _
theorem prefix_take_le_iff {xs : List α} (hm : i < xs.length) :
@[grind =] theorem prefix_take_le_iff {xs : List α} (hm : i < xs.length) :
xs.take i <+: xs.take j i j := by
simp only [prefix_iff_eq_take, length_take]
induction i generalizing xs j with

View File

@@ -56,7 +56,7 @@ theorem getElem?_take_eq_none {l : List α} {i j : Nat} (h : i ≤ j) :
(l.take i)[j]? = none :=
getElem?_eq_none <| Nat.le_trans (length_take_le _ _) h
@[grind =]theorem getElem?_take {l : List α} {i j : Nat} :
@[grind =] theorem getElem?_take {l : List α} {i j : Nat} :
(l.take i)[j]? = if j < i then l[j]? else none := by
split
· next h => exact getElem?_take_of_lt h
@@ -199,7 +199,7 @@ theorem take_eq_dropLast {l : List α} {i : Nat} (h : i + 1 = l.length) :
simpa using h
theorem take_prefix_take_left {l : List α} {i j : Nat} (h : i j) : take i l <+: take j l := by
rw [isPrefix_iff]
rw [prefix_iff_getElem?]
intro i w
rw [getElem?_take_of_lt, getElem_take, getElem?_eq_getElem]
simp only [length_take] at w

View File

@@ -71,6 +71,7 @@ protected theorem getElem?_ofFn {f : Fin n → α} :
theorem ofFn_zero {f : Fin 0 α} : ofFn f = [] := by
rw [ofFn, Fin.foldr_zero]
@[simp]
theorem ofFn_succ {n} {f : Fin (n + 1) α} : ofFn f = f 0 :: ofFn fun i => f i.succ :=
ext_get (by simp) (fun i hi₁ hi₂ => by
cases i
@@ -91,7 +92,7 @@ theorem ofFn_add {n m} {f : Fin (n + m) → α} :
ofFn f = (ofFn fun i => f (i.castLE (Nat.le_add_right n m))) ++ (ofFn fun i => f (i.natAdd n)) := by
induction m with
| zero => simp
| succ m ih => simp [ofFn_succ_last, ih]
| succ m ih => simp [-ofFn_succ, ofFn_succ_last, ih]
@[simp]
theorem ofFn_eq_nil_iff {f : Fin n α} : ofFn f = [] n = 0 := by
@@ -172,9 +173,8 @@ theorem ofFnM_pure [Monad m] [LawfulMonad m] {n} {f : Fin n → α} :
@[simp, grind =] theorem idRun_ofFnM {f : Fin n Id α} :
Id.run (ofFnM f) = ofFn (fun i => Id.run (f i)) := by
unfold Id.run
induction n with
| zero => simp
| succ n ih => simp [ofFnM_succ_last, ofFn_succ_last, ih]
| succ n ih => simp [-ofFn_succ, ofFnM_succ_last, ofFn_succ_last, ih]
end List

View File

@@ -24,7 +24,7 @@ open Nat
/-! ### Pairwise -/
theorem Pairwise.sublist : l₁ <+ l₂ l₂.Pairwise R l₁.Pairwise R
@[grind ] theorem Pairwise.sublist : l₁ <+ l₂ l₂.Pairwise R l₁.Pairwise R
| .slnil, h => h
| .cons _ s, .cons _ h₂ => h₂.sublist s
| .cons₂ _ s, .cons h₁ h₂ => (h₂.sublist s).cons fun _ h => h₁ _ (s.subset h)
@@ -37,11 +37,11 @@ theorem Pairwise.imp {α R S} (H : ∀ {a b}, R a b → S a b) :
theorem rel_of_pairwise_cons (p : (a :: l).Pairwise R) : {a'}, a' l R a a' :=
(pairwise_cons.1 p).1 _
theorem Pairwise.of_cons (p : (a :: l).Pairwise R) : Pairwise R l :=
@[grind ] theorem Pairwise.of_cons (p : (a :: l).Pairwise R) : Pairwise R l :=
(pairwise_cons.1 p).2
set_option linter.unusedVariables false in
theorem Pairwise.tail : {l : List α} (h : Pairwise R l), Pairwise R l.tail
@[grind] theorem Pairwise.tail : {l : List α} (h : Pairwise R l), Pairwise R l.tail
| [], h => h
| _ :: _, h => h.of_cons
@@ -101,11 +101,11 @@ theorem Pairwise.forall_of_forall_of_flip (h₁ : ∀ x ∈ l, R x x) (h₂ : Pa
· exact h₃.1 _ hx
· exact ih (fun x hx => h₁ _ <| mem_cons_of_mem _ hx) h₂.2 h₃.2 hx hy
theorem pairwise_singleton (R) (a : α) : Pairwise R [a] := by simp
@[grind] theorem pairwise_singleton (R) (a : α) : Pairwise R [a] := by simp
theorem pairwise_pair {a b : α} : Pairwise R [a, b] R a b := by simp
@[grind =] theorem pairwise_pair {a b : α} : Pairwise R [a, b] R a b := by simp
theorem pairwise_map {l : List α} :
@[grind =] theorem pairwise_map {l : List α} :
(l.map f).Pairwise R l.Pairwise fun a b => R (f a) (f b) := by
induction l
· simp
@@ -115,11 +115,11 @@ theorem Pairwise.of_map {S : β → β → Prop} (f : α → β) (H : ∀ a b :
(p : Pairwise S (map f l)) : Pairwise R l :=
(pairwise_map.1 p).imp (H _ _)
theorem Pairwise.map {S : β β Prop} (f : α β) (H : a b : α, R a b S (f a) (f b))
@[grind] theorem Pairwise.map {S : β β Prop} (f : α β) (H : a b : α, R a b S (f a) (f b))
(p : Pairwise R l) : Pairwise S (map f l) :=
pairwise_map.2 <| p.imp (H _ _)
theorem pairwise_filterMap {f : β Option α} {l : List β} :
@[grind =] theorem pairwise_filterMap {f : β Option α} {l : List β} :
Pairwise R (filterMap f l) Pairwise (fun a a' : β => b, f a = some b b', f a' = some b' R b b') l := by
let _S (a a' : β) := b, f a = some b b', f a' = some b' R b b'
induction l with
@@ -134,20 +134,20 @@ theorem pairwise_filterMap {f : β → Option α} {l : List β} :
simpa [IH, e] using fun _ =>
fun h a ha b hab => h _ _ ha hab, fun h a b ha hab => h _ ha _ hab
theorem Pairwise.filterMap {S : β β Prop} (f : α Option β)
@[grind] theorem Pairwise.filterMap {S : β β Prop} (f : α Option β)
(H : a a' : α, R a a' b, f a = some b b', f a' = some b' S b b') {l : List α} (p : Pairwise R l) :
Pairwise S (filterMap f l) :=
pairwise_filterMap.2 <| p.imp (H _ _)
theorem pairwise_filter {p : α Prop} [DecidablePred p] {l : List α} :
@[grind =] theorem pairwise_filter {p : α Bool} {l : List α} :
Pairwise R (filter p l) Pairwise (fun x y => p x p y R x y) l := by
rw [ filterMap_eq_filter, pairwise_filterMap]
simp
theorem Pairwise.filter (p : α Bool) : Pairwise R l Pairwise R (filter p l) :=
@[grind] theorem Pairwise.filter (p : α Bool) : Pairwise R l Pairwise R (filter p l) :=
Pairwise.sublist filter_sublist
theorem pairwise_append {l₁ l₂ : List α} :
@[grind =] theorem pairwise_append {l₁ l₂ : List α} :
(l₁ ++ l₂).Pairwise R l₁.Pairwise R l₂.Pairwise R a l₁, b l₂, R a b := by
induction l₁ <;> simp [*, or_imp, forall_and, and_assoc, and_left_comm]
@@ -157,13 +157,13 @@ theorem pairwise_append_comm {R : αα → Prop} (s : ∀ {x y}, R x y →
(x : α) (xm : x l₂) (y : α) (ym : y l₁) : R x y := s (H y ym x xm)
simp only [pairwise_append, and_left_comm]; rw [Iff.intro (this l₁ l₂) (this l₂ l₁)]
theorem pairwise_middle {R : α α Prop} (s : {x y}, R x y R y x) {a : α} {l₁ l₂ : List α} :
@[grind =] theorem pairwise_middle {R : α α Prop} (s : {x y}, R x y R y x) {a : α} {l₁ l₂ : List α} :
Pairwise R (l₁ ++ a :: l₂) Pairwise R (a :: (l₁ ++ l₂)) := by
show Pairwise R (l₁ ++ ([a] ++ l₂)) Pairwise R ([a] ++ l₁ ++ l₂)
rw [ append_assoc, pairwise_append, @pairwise_append _ _ ([a] ++ l₁), pairwise_append_comm s]
simp only [mem_append, or_comm]
theorem pairwise_flatten {L : List (List α)} :
@[grind =] theorem pairwise_flatten {L : List (List α)} :
Pairwise R (flatten L)
( l L, Pairwise R l) Pairwise (fun l₁ l₂ => x l₁, y l₂, R x y) L := by
induction L with
@@ -174,16 +174,16 @@ theorem pairwise_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
theorem pairwise_flatMap {R : β β Prop} {l : List α} {f : α List β} :
@[grind =] 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]
theorem pairwise_reverse {l : List α} :
@[grind =] theorem pairwise_reverse {l : List α} :
l.reverse.Pairwise R l.Pairwise (fun a b => R b a) := by
induction l <;> simp [*, pairwise_append, and_comm]
@[simp] theorem pairwise_replicate {n : Nat} {a : α} :
@[simp, grind =] theorem pairwise_replicate {n : Nat} {a : α} :
(replicate n a).Pairwise R n 1 R a a := by
induction n with
| zero => simp
@@ -205,10 +205,10 @@ theorem pairwise_reverse {l : List α} :
simp
· exact fun _ => h, Or.inr h
theorem Pairwise.drop {l : List α} {i : Nat} (h : List.Pairwise R l) : List.Pairwise R (l.drop i) :=
@[grind] theorem Pairwise.drop {l : List α} {i : Nat} (h : List.Pairwise R l) : List.Pairwise R (l.drop i) :=
h.sublist (drop_sublist _ _)
theorem Pairwise.take {l : List α} {i : Nat} (h : List.Pairwise R l) : List.Pairwise R (l.take i) :=
@[grind] theorem Pairwise.take {l : List α} {i : Nat} (h : List.Pairwise R l) : List.Pairwise R (l.take i) :=
h.sublist (take_sublist _ _)
theorem pairwise_iff_forall_sublist : l.Pairwise R ( {a b}, [a,b] <+ l R a b) := by
@@ -247,7 +247,7 @@ theorem pairwise_of_forall_mem_list {l : List α} {r : αα → Prop} (h :
intro a b hab
apply h <;> (apply hab.subset; simp)
theorem pairwise_pmap {p : β Prop} {f : b, p b α} {l : List β} (h : x l, p x) :
@[grind =] theorem pairwise_pmap {p : β Prop} {f : b, p b α} {l : List β} (h : x l, p x) :
Pairwise R (l.pmap f h)
Pairwise (fun b₁ b₂ => (h₁ : p b₁) (h₂ : p b₂), R (f b₁ h₁) (f b₂ h₂)) l := by
induction l with
@@ -259,7 +259,7 @@ theorem pairwise_pmap {p : β → Prop} {f : ∀ b, p b → α} {l : List β} (h
rintro H _ b hb rfl
exact H b hb _ _
theorem Pairwise.pmap {l : List α} (hl : Pairwise R l) {p : α Prop} {f : a, p a β}
@[grind] theorem Pairwise.pmap {l : List α} (hl : Pairwise R l) {p : α Prop} {f : a, p a β}
(h : x l, p x) {S : β β Prop}
(hS : x (hx : p x) y (hy : p y), R x y S (f x hx) (f y hy)) :
Pairwise S (l.pmap f h) := by
@@ -268,17 +268,20 @@ theorem Pairwise.pmap {l : List α} (hl : Pairwise R l) {p : α → Prop} {f :
/-! ### Nodup -/
@[simp]
@[simp, grind]
theorem nodup_nil : @Nodup α [] :=
Pairwise.nil
@[simp]
@[simp, grind =]
theorem nodup_cons {a : α} {l : List α} : Nodup (a :: l) a l Nodup l := by
simp only [Nodup, pairwise_cons, forall_mem_ne]
theorem Nodup.sublist : l₁ <+ l₂ Nodup l₂ Nodup l₁ :=
Pairwise.sublist
grind_pattern Nodup.sublist => l₁ <+ l₂, Nodup l₁
grind_pattern Nodup.sublist => l₁ <+ l₂, Nodup l₂
theorem Sublist.nodup : l₁ <+ l₂ Nodup l₂ Nodup l₁ :=
Nodup.sublist
@@ -303,7 +306,7 @@ theorem getElem?_inj {xs : List α}
rw [mem_iff_getElem?]
exact _, h₂; exact _ , h₂.symm
@[simp] theorem nodup_replicate {n : Nat} {a : α} :
@[simp, grind =] theorem nodup_replicate {n : Nat} {a : α} :
(replicate n a).Nodup n 1 := by simp [Nodup]
end List

View File

@@ -142,6 +142,8 @@ theorem range'_eq_cons_iff : range' s n = a :: xs ↔ s = a ∧ 0 < n ∧ xs = r
/-! ### range -/
@[simp, grind =] theorem range_one : range 1 = [0] := rfl
theorem range_loop_range' : s n, range.loop s (range' s n) = range' 0 (n + s)
| 0, _ => rfl
| s + 1, n => by rw [ Nat.add_assoc, Nat.add_right_comm n s 1]; exact range_loop_range' s (n + 1)

View File

@@ -24,14 +24,14 @@ open Nat
section isPrefixOf
variable [BEq α]
@[simp] theorem isPrefixOf_cons₂_self [LawfulBEq α] {a : α} :
@[simp, grind =] theorem isPrefixOf_cons₂_self [LawfulBEq α] {a : α} :
isPrefixOf (a::as) (a::bs) = isPrefixOf as bs := by simp [isPrefixOf_cons₂]
@[simp] theorem isPrefixOf_length_pos_nil {l : List α} (h : 0 < l.length) : isPrefixOf l [] = false := by
cases l <;> simp_all [isPrefixOf]
@[simp] theorem isPrefixOf_replicate {a : α} :
isPrefixOf l (replicate n a) = (decide (l.length n) && l.all (· == a)) := by
@[simp, grind =] theorem isPrefixOf_replicate {a : α} :
isPrefixOf l (replicate n a) = ((l.length n) && l.all (· == a)) := by
induction l generalizing n with
| nil => simp
| cons _ _ ih =>
@@ -45,10 +45,10 @@ end isPrefixOf
section isSuffixOf
variable [BEq α]
@[simp] theorem isSuffixOf_cons_nil : isSuffixOf (a::as) ([] : List α) = false := by
@[simp, grind =] theorem isSuffixOf_cons_nil : isSuffixOf (a::as) ([] : List α) = false := by
simp [isSuffixOf]
@[simp] theorem isSuffixOf_replicate {a : α} :
@[simp, grind =] theorem isSuffixOf_replicate {a : α} :
isSuffixOf l (replicate n a) = (decide (l.length n) && l.all (· == a)) := by
simp [isSuffixOf, all_eq]
@@ -58,7 +58,8 @@ end isSuffixOf
/-! ### List subset -/
theorem subset_def {l₁ l₂ : List α} : l₁ l₂ {a : α}, a l₁ a l₂ := .rfl
-- For now we don't annotate lemmas about `Subset` for `grind`, but instead just unfold the definition.
@[grind =] theorem subset_def {l₁ l₂ : List α} : l₁ l₂ {a : α}, a l₁ a l₂ := .rfl
@[simp] theorem nil_subset (l : List α) : [] l := nofun
@@ -95,9 +96,15 @@ theorem eq_nil_of_subset_nil {l : List α} : l ⊆ [] → l = [] := subset_nil.m
theorem map_subset {l₁ l₂ : List α} (f : α β) (h : l₁ l₂) : map f l₁ map f l₂ :=
fun x => by simp only [mem_map]; exact .imp fun a => .imp_left (@h _)
grind_pattern map_subset => l₁ l₂, map f l₁
grind_pattern map_subset => l₁ l₂, map f l₂
theorem filter_subset {l₁ l₂ : List α} (p : α Bool) (H : l₁ l₂) : filter p l₁ filter p l₂ :=
fun x => by simp_all [mem_filter, subset_def.1 H]
grind_pattern filter_subset => l₁ l₂, filter p l₁
grind_pattern filter_subset => l₁ l₂, filter p l₂
theorem filterMap_subset {l₁ l₂ : List α} (f : α Option β) (H : l₁ l₂) :
filterMap f l₁ filterMap f l₂ := by
intro x
@@ -105,6 +112,9 @@ theorem filterMap_subset {l₁ l₂ : List α} (f : α → Option β) (H : l₁
rintro a, h, w
exact a, H h, w
grind_pattern filterMap_subset => l₁ l₂, filterMap f l₁
grind_pattern filterMap_subset => l₁ l₂, filterMap f l₂
theorem subset_append_left (l₁ l₂ : List α) : l₁ l₁ ++ l₂ := fun _ => mem_append_left _
theorem subset_append_right (l₁ l₂ : List α) : l₂ l₁ ++ l₂ := fun _ => mem_append_right _
@@ -139,11 +149,11 @@ theorem subset_replicate {n : Nat} {a : α} {l : List α} (h : n ≠ 0) : l ⊆
/-! ### Sublist and isSublist -/
@[simp] theorem nil_sublist : l : List α, [] <+ l
@[simp, grind] theorem nil_sublist : l : List α, [] <+ l
| [] => .slnil
| a :: l => (nil_sublist l).cons a
@[simp] theorem Sublist.refl : l : List α, l <+ l
@[simp, grind] theorem Sublist.refl : l : List α, l <+ l
| [] => .slnil
| a :: l => (Sublist.refl l).cons₂ a
@@ -160,14 +170,14 @@ theorem Sublist.trans {l₁ l₂ l₃ : List α} (h₁ : l₁ <+ l₂) (h₂ : l
instance : Trans (@Sublist α) Sublist Sublist := Sublist.trans
attribute [simp] Sublist.cons
attribute [simp, grind] Sublist.cons
theorem sublist_cons_self (a : α) (l : List α) : l <+ a :: l := (Sublist.refl l).cons _
theorem sublist_of_cons_sublist : a :: l₁ <+ l₂ l₁ <+ l₂ :=
(sublist_cons_self a l₁).trans
@[simp]
@[simp, grind =]
theorem cons_sublist_cons : a :: l₁ <+ a :: l₂ l₁ <+ l₂ :=
fun | .cons _ s => sublist_of_cons_sublist s | .cons₂ _ s => s, .cons₂ _
@@ -181,7 +191,7 @@ theorem sublist_or_mem_of_sublist (h : l <+ l₁ ++ a :: l₂) : l <+ l₁ ++ l
| .cons _ h => exact (IH h).imp_left (Sublist.cons _)
| .cons₂ _ h => exact (IH h).imp (Sublist.cons₂ _) (.tail _)
theorem Sublist.subset : l₁ <+ l₂ l₁ l₂
@[grind ] theorem Sublist.subset : l₁ <+ l₂ l₁ l₂
| .slnil, _, h => h
| .cons _ s, _, h => .tail _ (s.subset h)
| .cons₂ .., _, .head .. => .head ..
@@ -190,10 +200,10 @@ theorem Sublist.subset : l₁ <+ l₂ → l₁ ⊆ l₂
protected theorem Sublist.mem (hx : a l₁) (hl : l₁ <+ l₂) : a l₂ :=
hl.subset hx
theorem Sublist.head_mem (s : ys <+ xs) (h) : ys.head h xs :=
@[grind] theorem Sublist.head_mem (s : ys <+ xs) (h) : ys.head h xs :=
s.mem (List.head_mem h)
theorem Sublist.getLast_mem (s : ys <+ xs) (h) : ys.getLast h xs :=
@[grind] theorem Sublist.getLast_mem (s : ys <+ xs) (h) : ys.getLast h xs :=
s.mem (List.getLast_mem h)
instance : Trans (@Sublist α) Subset Subset :=
@@ -208,7 +218,7 @@ instance : Trans (fun l₁ l₂ => Sublist l₂ l₁) (Membership.mem : List α
theorem mem_of_cons_sublist {a : α} {l₁ l₂ : List α} (s : a :: l₁ <+ l₂) : a l₂ :=
(cons_subset.1 s.subset).1
@[simp] theorem sublist_nil {l : List α} : l <+ [] l = [] :=
@[simp, grind =] theorem sublist_nil {l : List α} : l <+ [] l = [] :=
fun s => subset_nil.1 s.subset, fun H => H Sublist.refl _
theorem eq_nil_of_sublist_nil {l : List α} (s : l <+ []) : l = [] :=
@@ -219,29 +229,39 @@ theorem Sublist.length_le : l₁ <+ l₂ → length l₁ ≤ length l₂
| .cons _l s => le_succ_of_le (length_le s)
| .cons₂ _ s => succ_le_succ (length_le s)
grind_pattern Sublist.length_le => l₁ <+ l₂, length l₁
grind_pattern Sublist.length_le => l₁ <+ l₂, length l₂
theorem Sublist.eq_of_length : l₁ <+ l₂ length l₁ = length l₂ l₁ = l₂
| .slnil, _ => rfl
| .cons a s, h => nomatch Nat.not_lt.2 s.length_le (h lt_succ_self _)
| .cons₂ a s, h => by rw [s.eq_of_length (succ.inj h)]
-- Only activative `eq_of_length` if we're already thinking about lengths.
grind_pattern Sublist.eq_of_length => l₁ <+ l₂, length l₁, length l₂
theorem Sublist.eq_of_length_le (s : l₁ <+ l₂) (h : length l₂ length l₁) : l₁ = l₂ :=
s.eq_of_length <| Nat.le_antisymm s.length_le h
theorem Sublist.length_eq (s : l₁ <+ l₂) : length l₁ = length l₂ l₁ = l₂ :=
s.eq_of_length, congrArg _
@[grind]
theorem tail_sublist : l : List α, tail l <+ l
| [] => .slnil
| a::l => sublist_cons_self a l
@[grind]
protected theorem Sublist.tail : {l₁ l₂ : List α}, l₁ <+ l₂ tail l₁ <+ tail l₂
| _, _, slnil => .slnil
| _, _, Sublist.cons _ h => (tail_sublist _).trans h
| _, _, Sublist.cons₂ _ h => h
@[grind ]
theorem Sublist.of_cons_cons {l₁ l₂ : List α} {a b : α} (h : a :: l₁ <+ b :: l₂) : l₁ <+ l₂ :=
h.tail
@[grind]
protected theorem Sublist.map (f : α β) {l₁ l₂} (s : l₁ <+ l₂) : map f l₁ <+ map f l₂ := by
induction s with
| slnil => simp
@@ -250,19 +270,31 @@ protected theorem Sublist.map (f : α → β) {l₁ l₂} (s : l₁ <+ l₂) : m
| cons₂ a s ih =>
simpa using cons₂ (f a) ih
grind_pattern Sublist.map => l₁ <+ l₂, map f l₁
grind_pattern Sublist.map => l₁ <+ l₂, map f l₂
@[grind]
protected theorem Sublist.filterMap (f : α Option β) (s : l₁ <+ l₂) :
filterMap f l₁ <+ filterMap f l₂ := by
induction s <;> simp [filterMap_cons] <;> split <;> simp [*, cons, cons₂]
grind_pattern Sublist.filterMap => l₁ <+ l₂, filterMap f l₁
grind_pattern Sublist.filterMap => l₁ <+ l₂, filterMap f l₂
@[grind]
protected theorem Sublist.filter (p : α Bool) {l₁ l₂} (s : l₁ <+ l₂) : filter p l₁ <+ filter p l₂ := by
rw [ filterMap_eq_filter]; apply s.filterMap
grind_pattern Sublist.filter => l₁ <+ l₂, l₁.filter p
grind_pattern Sublist.filter => l₁ <+ l₂, l₂.filter p
theorem head_filter_mem (xs : List α) (p : α Bool) (h) : (xs.filter p).head h xs :=
filter_sublist.head_mem h
theorem getLast_filter_mem (xs : List α) (p : α Bool) (h) : (xs.filter p).getLast h xs :=
filter_sublist.getLast_mem h
@[grind =]
theorem sublist_filterMap_iff {l₁ : List β} {f : α Option β} :
l₁ <+ l₂.filterMap f l', l' <+ l₂ l₁ = l'.filterMap f := by
induction l₂ generalizing l₁ with
@@ -297,10 +329,12 @@ theorem sublist_filterMap_iff {l₁ : List β} {f : α → Option β} :
rwa [filterMap_cons_some] at h
assumption
@[grind =]
theorem sublist_map_iff {l₁ : List β} {f : α β} :
l₁ <+ l₂.map f l', l' <+ l₂ l₁ = l'.map f := by
simp only [ filterMap_eq_map, sublist_filterMap_iff]
@[grind =]
theorem sublist_filter_iff {l₁ : List α} {p : α Bool} :
l₁ <+ l₂.filter p l', l' <+ l₂ l₁ = l'.filter p := by
simp only [ filterMap_eq_filter, sublist_filterMap_iff]
@@ -309,11 +343,15 @@ theorem sublist_append_left : ∀ l₁ l₂ : List α, l₁ <+ l₁ ++ l₂
| [], _ => nil_sublist _
| _ :: l₁, l₂ => (sublist_append_left l₁ l₂).cons₂ _
grind_pattern sublist_append_left => Sublist, l₁ ++ l₂
theorem sublist_append_right : l₁ l₂ : List α, l₂ <+ l₁ ++ l₂
| [], _ => Sublist.refl _
| _ :: l₁, l₂ => (sublist_append_right l₁ l₂).cons _
@[simp] theorem singleton_sublist {a : α} {l} : [a] <+ l a l := by
grind_pattern sublist_append_right => Sublist, l₁ ++ l
@[simp, grind =] theorem singleton_sublist {a : α} {l} : [a] <+ l a l := by
refine fun h => h.subset (mem_singleton_self _), fun h => ?_
obtain _, _, rfl := append_of_mem h
exact ((nil_sublist _).cons₂ _).trans (sublist_append_right ..)
@@ -321,10 +359,14 @@ theorem sublist_append_right : ∀ l₁ l₂ : List α, l₂ <+ l₁ ++ l₂
@[simp] theorem sublist_append_of_sublist_left (s : l <+ l₁) : l <+ l₁ ++ l₂ :=
s.trans <| sublist_append_left ..
grind_pattern sublist_append_of_sublist_left => l <+ l₁, l₁ ++ l₂
@[simp] theorem sublist_append_of_sublist_right (s : l <+ l₂) : l <+ l₁ ++ l₂ :=
s.trans <| sublist_append_right ..
@[simp] theorem append_sublist_append_left : l, l ++ l <+ l ++ l₂ l₁ <+ l₂
grind_pattern sublist_append_of_sublist_right => l <+ l, l₁ ++ l₂
@[simp, grind =] theorem append_sublist_append_left : l, l ++ l₁ <+ l ++ l₂ l₁ <+ l₂
| [] => Iff.rfl
| _ :: l => cons_sublist_cons.trans (append_sublist_append_left l)
@@ -339,6 +381,9 @@ theorem Sublist.append_right : l₁ <+ l₂ → ∀ l, l₁ ++ l <+ l₂ ++ l
theorem Sublist.append (hl : l₁ <+ l₂) (hr : r₁ <+ r₂) : l₁ ++ r₁ <+ l₂ ++ r₂ :=
(hl.append_right _).trans ((append_sublist_append_left _).2 hr)
grind_pattern Sublist.append => l₁ <+ l₂, r₁ <+ r₂, l₁ ++ r₁, l₂ ++ r₂
@[grind =]
theorem sublist_cons_iff {a : α} {l l'} :
l <+ a :: l' l <+ l' r, l = a :: r r <+ l' := by
constructor
@@ -350,6 +395,7 @@ theorem sublist_cons_iff {a : α} {l l'} :
· exact h.cons _
· exact h.cons₂ _
@[grind =]
theorem cons_sublist_iff {a : α} {l l'} :
a :: l <+ l' r₁ r₂, l' = r₁ ++ r₂ a r₁ l <+ r₂ := by
induction l' with
@@ -433,6 +479,7 @@ theorem Sublist.of_sublist_append_right (w : ∀ a, a ∈ l → a ∉ l₁) (h :
exact fun x m => w x (mem_append_left l₂' m) (h₁.mem m)
simp_all
@[grind]
theorem Sublist.middle {l : List α} (h : l <+ l₁ ++ l₂) (a : α) : l <+ l₁ ++ a :: l₂ := by
rw [sublist_append_iff] at h
obtain l₁', l₂', rfl, h₁, h₂ := h
@@ -443,13 +490,14 @@ theorem Sublist.reverse : l₁ <+ l₂ → l₁.reverse <+ l₂.reverse
| .cons _ h => by rw [reverse_cons]; exact sublist_append_of_sublist_left h.reverse
| .cons₂ _ h => by rw [reverse_cons, reverse_cons]; exact h.reverse.append_right _
@[simp] theorem reverse_sublist : l₁.reverse <+ l₂.reverse l₁ <+ l₂ :=
@[simp, grind =] theorem reverse_sublist : l₁.reverse <+ l₂.reverse l₁ <+ l₂ :=
fun h => l₁.reverse_reverse l₂.reverse_reverse h.reverse, Sublist.reverse
@[grind _=_]
theorem sublist_reverse_iff : l₁ <+ l₂.reverse l₁.reverse <+ l₂ :=
by rw [ reverse_sublist, reverse_reverse]
@[simp] theorem append_sublist_append_right (l) : l₁ ++ l <+ l₂ ++ l l₁ <+ l₂ :=
@[simp, grind =] theorem append_sublist_append_right (l) : l₁ ++ l <+ l₂ ++ l l₁ <+ l₂ :=
fun h => by
have := h.reverse
simp only [reverse_append, append_sublist_append_left, reverse_sublist] at this
@@ -464,6 +512,7 @@ theorem sublist_reverse_iff : l₁ <+ l₂.reverse ↔ l₁.reverse <+ l₂ :=
| refl => apply Sublist.refl
| step => simp [*, replicate, Sublist.cons]
@[grind =]
theorem sublist_replicate_iff : l <+ replicate m a n, n m l = replicate n a := by
induction l generalizing m with
| nil =>
@@ -551,7 +600,7 @@ theorem flatten_sublist_iff {L : List (List α)} {l} :
exact l₁, L'.flatten, by simp, by simpa using h 0 (by simp), L', rfl,
fun i lt => by simpa using h (i+1) (Nat.add_lt_add_right lt 1)
@[simp] theorem isSublist_iff_sublist [BEq α] [LawfulBEq α] {l₁ l₂ : List α} :
@[simp, grind =] theorem isSublist_iff_sublist [BEq α] [LawfulBEq α] {l₁ l₂ : List α} :
l₁.isSublist l₂ l₁ <+ l₂ := by
cases l₁ <;> cases l₂ <;> simp [isSublist]
case cons.cons hd₁ tl₁ hd₂ tl₂ =>
@@ -573,41 +622,49 @@ theorem flatten_sublist_iff {L : List (List α)} {l} :
instance [DecidableEq α] (l₁ l₂ : List α) : Decidable (l₁ <+ l₂) :=
decidable_of_iff (l₁.isSublist l₂) isSublist_iff_sublist
@[grind]
protected theorem Sublist.drop : {l₁ l₂ : List α}, l₁ <+ l₂ i, l₁.drop i <+ l₂.drop i
| _, _, h, 0 => h
| _, _, h, i + 1 => by rw [ drop_tail, drop_tail]; exact h.tail.drop i
/-! ### IsPrefix / IsSuffix / IsInfix -/
@[simp] theorem prefix_append (l₁ l₂ : List α) : l₁ <+: l₁ ++ l₂ := l₂, rfl
@[simp, grind] theorem prefix_append (l₁ l₂ : List α) : l₁ <+: l₁ ++ l₂ := l₂, rfl
@[simp] theorem suffix_append (l₁ l₂ : List α) : l₂ <:+ l₁ ++ l₂ := l₁, rfl
@[simp, grind] theorem suffix_append (l₁ l₂ : List α) : l₂ <:+ l₁ ++ l₂ := l₁, rfl
theorem infix_append (l₁ l₂ l₃ : List α) : l₂ <:+: l₁ ++ l₂ ++ l₃ := l₁, l₃, rfl
@[simp] theorem infix_append' (l₁ l₂ l₃ : List α) : l₂ <:+: l₁ ++ (l₂ ++ l₃) := by
@[simp, grind] theorem infix_append' (l₁ l₂ l₃ : List α) : l₂ <:+: l₁ ++ (l₂ ++ l₃) := by
rw [ List.append_assoc]; apply infix_append
theorem infix_append_left : l₁ <:+: l₁ ++ l₂ := [], l₂, rfl
theorem infix_append_right : l₂ <:+: l₁ ++ l₂ := l₁, [], by simp
theorem IsPrefix.isInfix : l₁ <+: l₂ l₁ <:+: l₂ := fun t, h => [], t, h
grind_pattern IsPrefix.isInfix => l₁ <+: l₂, IsInfix
theorem IsSuffix.isInfix : l₁ <:+ l₂ l₁ <:+: l₂ := fun t, h => t, [], by rw [h, append_nil]
@[simp] theorem nil_prefix {l : List α} : [] <+: l := l, rfl
grind_pattern IsSuffix.isInfix => l <:+ l, IsInfix
@[simp] theorem nil_suffix {l : List α} : [] <:+ l := l, append_nil _
@[simp, grind] theorem nil_prefix {l : List α} : [] <+: l := l, rfl
@[simp] theorem nil_infix {l : List α} : [] <:+: l := nil_prefix.isInfix
@[simp, grind] theorem nil_suffix {l : List α} : [] <:+ l := l, append_nil _
@[simp, grind] theorem nil_infix {l : List α} : [] <:+: l := nil_prefix.isInfix
theorem prefix_refl (l : List α) : l <+: l := [], append_nil _
@[simp] theorem prefix_rfl {l : List α} : l <+: l := prefix_refl l
@[simp, grind] theorem prefix_rfl {l : List α} : l <+: l := prefix_refl l
theorem suffix_refl (l : List α) : l <:+ l := [], rfl
@[simp] theorem suffix_rfl {l : List α} : l <:+ l := suffix_refl l
@[simp, grind] theorem suffix_rfl {l : List α} : l <:+ l := suffix_refl l
theorem infix_refl (l : List α) : l <:+: l := prefix_rfl.isInfix
@[simp] theorem infix_rfl {l : List α} : l <:+: l := infix_refl l
@[simp, grind] theorem infix_rfl {l : List α} : l <:+: l := infix_refl l
@[simp] theorem suffix_cons (a : α) : l, l <:+ a :: l := suffix_append [a]
@[simp, grind] theorem suffix_cons (a : α) : l, l <:+ a :: l := suffix_append [a]
theorem infix_cons : l₁ <:+: l₂ l₁ <:+: a :: l₂ := fun l₁', l₂', h => a :: l₁', l₂', h rfl
@@ -617,12 +674,38 @@ theorem infix_concat : l₁ <:+: l₂ → l₁ <:+: concat l₂ a := fun ⟨l₁
theorem IsPrefix.trans : {l₁ l₂ l₃ : List α}, l₁ <+: l₂ l₂ <+: l₃ l₁ <+: l₃
| _, _, _, r₁, rfl, r₂, rfl => r₁ ++ r₂, (append_assoc _ _ _).symm
grind_pattern IsPrefix.trans => l₁ <+: l₂, l₂ <+: l₃
theorem IsSuffix.trans : {l₁ l₂ l₃ : List α}, l₁ <:+ l₂ l₂ <:+ l₃ l₁ <:+ l₃
| _, _, _, l₁, rfl, l₂, rfl => l₂ ++ l₁, append_assoc _ _ _
grind_pattern IsSuffix.trans => l₁ <:+ l₂, l₂ <:+ l₃
theorem IsInfix.trans : {l₁ l₂ l₃ : List α}, l₁ <:+: l₂ l₂ <:+: l₃ l₁ <:+: l₃
| l, _, _, l₁, r₁, rfl, l₂, r₂, rfl => l₂ ++ l₁, r₁ ++ r₂, by simp only [append_assoc]
grind_pattern IsInfix.trans => l₁ <:+: l₂, l₂ <:+: l₃
theorem prefix_append_of_prefix (h : l₁ <+: l₂) : l₁ <+: l₂ ++ l₃ :=
h.trans (prefix_append l₂ l₃)
grind_pattern prefix_append_of_prefix => l₁ <+: l₂, l₂ ++ l₃
theorem suffix_append_of_suffix (h : l₁ <:+ l₃) : l₁ <:+ l₂ ++ l₃ :=
h.trans (suffix_append l₂ l₃)
grind_pattern suffix_append_of_suffix => l₁ <:+ l₃, l₂ ++ l₃
theorem infix_append_of_infix_left (h : l₁ <:+: l₂) : l₁ <:+: l₂ ++ l₃ :=
h.trans infix_append_left
grind_pattern infix_append_of_infix_left => l₁ <:+: l₂, l₂ ++ l₃
theorem infix_append_of_infix_right (h : l₁ <:+: l₃) : l₁ <:+: l₂ ++ l₃ :=
h.trans infix_append_right
grind_pattern infix_append_of_infix_right => l₁ <:+: l₃, l₂ ++ l₃
protected theorem IsInfix.sublist : l₁ <:+: l₂ l₁ <+ l₂
| _, _, h => h (sublist_append_right ..).trans (sublist_append_left ..)
@@ -641,11 +724,11 @@ protected theorem IsSuffix.sublist (h : l₁ <:+ l₂) : l₁ <+ l₂ :=
protected theorem IsSuffix.subset (hl : l₁ <:+ l₂) : l₁ l₂ :=
hl.sublist.subset
@[simp] theorem infix_nil : l <:+: [] l = [] := (sublist_nil.1 ·.sublist), (· infix_rfl)
@[simp, grind =] theorem infix_nil : l <:+: [] l = [] := (sublist_nil.1 ·.sublist), (· infix_rfl)
@[simp] theorem prefix_nil : l <+: [] l = [] := (sublist_nil.1 ·.sublist), (· prefix_rfl)
@[simp, grind =] theorem prefix_nil : l <+: [] l = [] := (sublist_nil.1 ·.sublist), (· prefix_rfl)
@[simp] theorem suffix_nil : l <:+ [] l = [] := (sublist_nil.1 ·.sublist), (· suffix_rfl)
@[simp, grind =] theorem suffix_nil : l <:+ [] l = [] := (sublist_nil.1 ·.sublist), (· suffix_rfl)
theorem eq_nil_of_infix_nil (h : l <:+: []) : l = [] := infix_nil.mp h
theorem eq_nil_of_prefix_nil (h : l <+: []) : l = [] := prefix_nil.mp h
@@ -663,12 +746,21 @@ theorem IsInfix.ne_nil {xs ys : List α} (h : xs <:+: ys) (hx : xs ≠ []) : ys
theorem IsInfix.length_le (h : l₁ <:+: l₂) : l₁.length l₂.length :=
h.sublist.length_le
grind_pattern IsInfix.length_le => l₁ <:+: l₂, l₁.length
grind_pattern IsInfix.length_le => l₁ <:+: l₂, l₂.length
theorem IsPrefix.length_le (h : l₁ <+: l₂) : l₁.length l₂.length :=
h.sublist.length_le
grind_pattern IsPrefix.length_le => l₁ <+: l₂, l₁.length
grind_pattern IsPrefix.length_le => l₁ <+: l₂, l₂.length
theorem IsSuffix.length_le (h : l₁ <:+ l₂) : l₁.length l₂.length :=
h.sublist.length_le
grind_pattern IsSuffix.length_le => l₁ <:+ l₂, l₁.length
grind_pattern IsSuffix.length_le => l₁ <:+ l₂, l₂.length
theorem IsPrefix.getElem {xs ys : List α} (h : xs <+: ys) {i} (hi : i < xs.length) :
xs[i] = ys[i]'(Nat.le_trans hi h.length_le) := by
obtain _, rfl := h
@@ -676,23 +768,23 @@ theorem IsPrefix.getElem {xs ys : List α} (h : xs <+: ys) {i} (hi : i < xs.leng
-- See `Init.Data.List.Nat.Sublist` for `IsSuffix.getElem`.
theorem IsPrefix.mem (hx : a l₁) (hl : l₁ <+: l₂) : a l₂ :=
@[grind ] theorem IsPrefix.mem (hx : a l₁) (hl : l₁ <+: l₂) : a l₂ :=
hl.subset hx
theorem IsSuffix.mem (hx : a l₁) (hl : l₁ <:+ l₂) : a l₂ :=
@[grind ] theorem IsSuffix.mem (hx : a l₁) (hl : l₁ <:+ l₂) : a l₂ :=
hl.subset hx
theorem IsInfix.mem (hx : a l₁) (hl : l₁ <:+: l₂) : a l₂ :=
@[grind ] theorem IsInfix.mem (hx : a l₁) (hl : l₁ <:+: l₂) : a l₂ :=
hl.subset hx
@[simp] theorem reverse_suffix : reverse l₁ <:+ reverse l₂ l₁ <+: l₂ :=
@[simp, grind =] theorem reverse_suffix : reverse l₁ <:+ reverse l₂ l₁ <+: l₂ :=
fun r, e => reverse r, by rw [ reverse_reverse l₁, reverse_append, e, reverse_reverse],
fun r, e => reverse r, by rw [ reverse_append, e]
@[simp] theorem reverse_prefix : reverse l₁ <+: reverse l₂ l₁ <:+ l₂ := by
@[simp, grind =] theorem reverse_prefix : reverse l₁ <+: reverse l₂ l₁ <:+ l₂ := by
rw [ reverse_suffix]; simp only [reverse_reverse]
@[simp] theorem reverse_infix : reverse l₁ <:+: reverse l₂ l₁ <:+: l₂ := by
@[simp, grind =] theorem reverse_infix : reverse l₁ <:+: reverse l₂ l₁ <:+: l₂ := by
refine fun s, t, e => reverse t, reverse s, ?_, fun s, t, e => reverse t, reverse s, ?_
· rw [ reverse_reverse l₁, append_assoc, reverse_append, reverse_append, e,
reverse_reverse]
@@ -701,12 +793,21 @@ theorem IsInfix.mem (hx : a ∈ l₁) (hl : l₁ <:+: l₂) : a ∈ l₂ :=
theorem IsInfix.reverse : l₁ <:+: l₂ reverse l₁ <:+: reverse l₂ :=
reverse_infix.2
grind_pattern IsInfix.reverse => l₁ <:+: l₂, l₁.reverse
grind_pattern IsInfix.reverse => l₁ <:+: l₂, l₂.reverse
theorem IsSuffix.reverse : l₁ <:+ l₂ reverse l₁ <+: reverse l₂ :=
reverse_prefix.2
grind_pattern IsSuffix.reverse => l₁ <:+ l₂, l₁.reverse
grind_pattern IsSuffix.reverse => l₁ <:+ l₂, l₂.reverse
theorem IsPrefix.reverse : l₁ <+: l₂ reverse l₁ <:+ reverse l₂ :=
reverse_suffix.2
grind_pattern IsPrefix.reverse => l₁ <+: l₂, l₁.reverse
grind_pattern IsPrefix.reverse => l₁ <+: l₂, l₂.reverse
theorem IsPrefix.head {l₁ l₂ : List α} (h : l₁ <+: l₂) (hx : l₁ []) :
l₁.head hx = l₂.head (h.ne_nil hx) := by
cases l₁ <;> cases l₂ <;> simp only [head_cons, ne_eq, not_true_eq_false] at hx
@@ -780,7 +881,7 @@ theorem prefix_cons_iff : l₁ <+: a :: l₂ ↔ l₁ = [] ∃ t, l₁ = a :
· simp only [w]
refine s, by simp [h']
@[simp] theorem cons_prefix_cons : a :: l₁ <+: b :: l₂ a = b l₁ <+: l₂ := by
@[simp, grind =] theorem cons_prefix_cons : a :: l₁ <+: b :: l₂ a = b l₁ <+: l₂ := by
simp only [prefix_cons_iff, cons.injEq, false_or, List.cons_ne_nil]
constructor
· rintro t, rfl, rfl, h
@@ -831,7 +932,7 @@ theorem infix_concat_iff {l₁ l₂ : List α} {a : α} :
rw [ reverse_infix, reverse_concat, infix_cons_iff, reverse_infix,
reverse_prefix, reverse_concat]
theorem isPrefix_iff : l₁ <+: l₂ i (h : i < l₁.length), l₂[i]? = some l₁[i] := by
theorem prefix_iff_getElem? : l₁ <+: l₂ i (h : i < l₁.length), l₂[i]? = some l₁[i] := by
induction l₁ generalizing l₂ with
| nil => simp
| cons a l₁ ih =>
@@ -843,7 +944,12 @@ theorem isPrefix_iff : l₁ <+: l₂ ↔ ∀ i (h : i < l₁.length), l₂[i]? =
rw (occs := [2]) [ Nat.and_forall_add_one]
simp [Nat.succ_lt_succ_iff, eq_comm]
theorem isPrefix_iff_getElem {l₁ l₂ : List α} :
-- See `Init.Data.List.Nat.Sublist` for `isSuffix_iff` and `ifInfix_iff`.
@[deprecated prefix_iff_getElem? (since := "2025-05-27")]
abbrev isPrefix_iff := @prefix_iff_getElem?
theorem prefix_iff_getElem {l₁ l₂ : List α} :
l₁ <+: l₂ (h : l₁.length l₂.length), i (hx : i < l₁.length),
l₁[i] = l₂[i]'(Nat.lt_of_lt_of_le hx h) where
mp h := h.length_le, fun _ h' h.getElem h'
@@ -861,9 +967,16 @@ theorem isPrefix_iff_getElem {l₁ l₂ : List α} :
simp only [cons_prefix_cons]
exact h 0 (zero_lt_succ _), tail_ih hl fun a ha h a.succ (succ_lt_succ ha)
-- See `Init.Data.List.Nat.Sublist` for `isSuffix_iff` and `ifInfix_iff`.
@[deprecated prefix_iff_getElem (since := "2025-05-27")]
abbrev isPrefix_iff_getElem := @prefix_iff_getElem
theorem isPrefix_filterMap_iff {β} {f : α Option β} {l₁ : List α} {l₂ : List β} :
theorem cons_prefix_iff {a : α} {l₁ l₂ : List α} :
a :: l₁ <+: l₂ l', l₂ = a :: l' l₁ <+: l' := by
match l₂ with
| nil => simp
| cons b l₂ => simp [and_assoc, eq_comm]
theorem prefix_filterMap_iff {β} {f : α Option β} {l₁ : List α} {l₂ : List β} :
l₂ <+: filterMap f l₁ l, l <+: l₁ l₂ = filterMap f l := by
simp only [IsPrefix, append_eq_filterMap_iff]
constructor
@@ -872,7 +985,10 @@ theorem isPrefix_filterMap_iff {β} {f : α → Option β} {l₁ : List α} {l
· rintro l₁, l₂, rfl, rfl
exact _, l₁, l₂, rfl, rfl, rfl
theorem isSuffix_filterMap_iff {β} {f : α Option β} {l₁ : List α} {l₂ : List β} :
@[deprecated prefix_filterMap_iff (since := "2025-05-27")]
abbrev isPrefix_filterMap_iff := @prefix_filterMap_iff
theorem suffix_filterMap_iff {β} {f : α Option β} {l₁ : List α} {l₂ : List β} :
l₂ <:+ filterMap f l₁ l, l <:+ l₁ l₂ = filterMap f l := by
simp only [IsSuffix, append_eq_filterMap_iff]
constructor
@@ -881,7 +997,10 @@ theorem isSuffix_filterMap_iff {β} {f : α → Option β} {l₁ : List α} {l
· rintro l₁, l₂, rfl, rfl
exact _, l₂, l₁, rfl, rfl, rfl
theorem isInfix_filterMap_iff {β} {f : α Option β} {l₁ : List α} {l₂ : List β} :
@[deprecated suffix_filterMap_iff (since := "2025-05-27")]
abbrev isSuffix_filterMap_iff := @suffix_filterMap_iff
theorem infix_filterMap_iff {β} {f : α Option β} {l₁ : List α} {l₂ : List β} :
l₂ <:+: filterMap f l₁ l, l <:+: l₁ l₂ = filterMap f l := by
simp only [IsInfix, append_eq_filterMap_iff, filterMap_eq_append_iff]
constructor
@@ -890,31 +1009,52 @@ theorem isInfix_filterMap_iff {β} {f : α → Option β} {l₁ : List α} {l₂
· rintro l₃, l₂, l₁, rfl, rfl
exact _, _, _, l₁, rfl, l₂, l₃, rfl, rfl, rfl, rfl
theorem isPrefix_filter_iff {p : α Bool} {l₁ l₂ : List α} :
@[deprecated infix_filterMap_iff (since := "2025-05-27")]
abbrev isInfix_filterMap_iff := @infix_filterMap_iff
theorem prefix_filter_iff {p : α Bool} {l₁ l₂ : List α} :
l₂ <+: l₁.filter p l, l <+: l₁ l₂ = l.filter p := by
rw [ filterMap_eq_filter, isPrefix_filterMap_iff]
rw [ filterMap_eq_filter, prefix_filterMap_iff]
theorem isSuffix_filter_iff {p : α Bool} {l₁ l₂ : List α} :
@[deprecated prefix_filter_iff (since := "2025-05-27")]
abbrev isPrefix_filter_iff := @prefix_filter_iff
theorem suffix_filter_iff {p : α Bool} {l₁ l₂ : List α} :
l₂ <:+ l₁.filter p l, l <:+ l₁ l₂ = l.filter p := by
rw [ filterMap_eq_filter, isSuffix_filterMap_iff]
rw [ filterMap_eq_filter, suffix_filterMap_iff]
theorem isInfix_filter_iff {p : α Bool} {l₁ l₂ : List α} :
@[deprecated suffix_filter_iff (since := "2025-05-27")]
abbrev isSuffix_filter_iff := @suffix_filter_iff
theorem infix_filter_iff {p : α Bool} {l₁ l₂ : List α} :
l₂ <:+: l₁.filter p l, l <:+: l₁ l₂ = l.filter p := by
rw [ filterMap_eq_filter, isInfix_filterMap_iff]
rw [ filterMap_eq_filter, infix_filterMap_iff]
theorem isPrefix_map_iff {β} {f : α β} {l₁ : List α} {l₂ : List β} :
@[deprecated infix_filter_iff (since := "2025-05-27")]
abbrev isInfix_filter_iff := @infix_filter_iff
theorem prefix_map_iff {β} {f : α β} {l₁ : List α} {l₂ : List β} :
l₂ <+: l₁.map f l, l <+: l₁ l₂ = l.map f := by
rw [ filterMap_eq_map, isPrefix_filterMap_iff]
rw [ filterMap_eq_map, prefix_filterMap_iff]
theorem isSuffix_map_iff {β} {f : α β} {l₁ : List α} {l₂ : List β} :
@[deprecated prefix_map_iff (since := "2025-05-27")]
abbrev isPrefix_map_iff := @prefix_map_iff
theorem suffix_map_iff {β} {f : α β} {l₁ : List α} {l₂ : List β} :
l₂ <:+ l₁.map f l, l <:+ l₁ l₂ = l.map f := by
rw [ filterMap_eq_map, isSuffix_filterMap_iff]
rw [ filterMap_eq_map, suffix_filterMap_iff]
theorem isInfix_map_iff {β} {f : α β} {l₁ : List α} {l₂ : List β} :
@[deprecated suffix_map_iff (since := "2025-05-27")]
abbrev isSuffix_map_iff := @suffix_map_iff
theorem infix_map_iff {β} {f : α β} {l₁ : List α} {l₂ : List β} :
l₂ <:+: l₁.map f l, l <:+: l₁ l₂ = l.map f := by
rw [ filterMap_eq_map, isInfix_filterMap_iff]
rw [ filterMap_eq_map, infix_filterMap_iff]
theorem isPrefix_replicate_iff {n} {a : α} {l : List α} :
@[deprecated infix_map_iff (since := "2025-05-27")]
abbrev isInfix_map_iff := @infix_map_iff
@[grind =] theorem prefix_replicate_iff {n} {a : α} {l : List α} :
l <+: List.replicate n a l.length n l = List.replicate l.length a := by
rw [IsPrefix]
simp only [append_eq_replicate_iff]
@@ -926,12 +1066,18 @@ theorem isPrefix_replicate_iff {n} {a : α} {l : List α} :
· simpa using add_sub_of_le h
· simpa using w
theorem isSuffix_replicate_iff {n} {a : α} {l : List α} :
@[deprecated prefix_replicate_iff (since := "2025-05-27")]
abbrev isPrefix_replicate_iff := @prefix_replicate_iff
@[grind =] theorem suffix_replicate_iff {n} {a : α} {l : List α} :
l <:+ List.replicate n a l.length n l = List.replicate l.length a := by
rw [ reverse_prefix, reverse_replicate, isPrefix_replicate_iff]
rw [ reverse_prefix, reverse_replicate, prefix_replicate_iff]
simp [reverse_eq_iff]
theorem isInfix_replicate_iff {n} {a : α} {l : List α} :
@[deprecated suffix_replicate_iff (since := "2025-05-27")]
abbrev isSuffix_replicate_iff := @suffix_replicate_iff
@[grind =] theorem infix_replicate_iff {n} {a : α} {l : List α} :
l <:+: List.replicate n a l.length n l = List.replicate l.length a := by
rw [IsInfix]
simp only [append_eq_replicate_iff, length_append]
@@ -943,6 +1089,9 @@ theorem isInfix_replicate_iff {n} {a : α} {l : List α} :
· simpa using Nat.sub_add_cancel h
· simpa using w
@[deprecated infix_replicate_iff (since := "2025-05-27")]
abbrev isInfix_replicate_iff := @infix_replicate_iff
theorem infix_of_mem_flatten : {L : List (List α)}, l L l <:+: flatten L
| l' :: _, h =>
match h with
@@ -956,16 +1105,16 @@ theorem infix_of_mem_flatten : ∀ {L : List (List α)}, l ∈ L → l <:+: flat
theorem prefix_cons_inj (a) : a :: l₁ <+: a :: l₂ l₁ <+: l₂ :=
prefix_append_right_inj [a]
theorem take_prefix (i) (l : List α) : take i l <+: l :=
@[grind] theorem take_prefix (i) (l : List α) : take i l <+: l :=
_, take_append_drop _ _
theorem drop_suffix (i) (l : List α) : drop i l <:+ l :=
@[grind] theorem drop_suffix (i) (l : List α) : drop i l <:+ l :=
_, take_append_drop _ _
theorem take_sublist (i) (l : List α) : take i l <+ l :=
@[grind] theorem take_sublist (i) (l : List α) : take i l <+ l :=
(take_prefix i l).sublist
theorem drop_sublist (i) (l : List α) : drop i l <+ l :=
@[grind] theorem drop_sublist (i) (l : List α) : drop i l <+ l :=
(drop_suffix i l).sublist
theorem take_subset (i) (l : List α) : take i l l :=
@@ -986,22 +1135,22 @@ theorem drop_suffix_drop_left (l : List α) {i j : Nat} (h : i ≤ j) : drop j l
-- See `Init.Data.List.Nat.TakeDrop` for `take_prefix_take_left`.
theorem drop_sublist_drop_left (l : List α) {i j : Nat} (h : i j) : drop j l <+ drop i l :=
@[grind] theorem drop_sublist_drop_left (l : List α) {i j : Nat} (h : i j) : drop j l <+ drop i l :=
(drop_suffix_drop_left l h).sublist
theorem drop_subset_drop_left (l : List α) {i j : Nat} (h : i j) : drop j l drop i l :=
@[grind] theorem drop_subset_drop_left (l : List α) {i j : Nat} (h : i j) : drop j l drop i l :=
(drop_sublist_drop_left l h).subset
theorem takeWhile_prefix (p : α Bool) : l.takeWhile p <+: l :=
@[grind] theorem takeWhile_prefix (p : α Bool) : l.takeWhile p <+: l :=
l.dropWhile p, takeWhile_append_dropWhile
theorem dropWhile_suffix (p : α Bool) : l.dropWhile p <:+ l :=
@[grind] theorem dropWhile_suffix (p : α Bool) : l.dropWhile p <:+ l :=
l.takeWhile p, takeWhile_append_dropWhile
theorem takeWhile_sublist (p : α Bool) : l.takeWhile p <+ l :=
@[grind] theorem takeWhile_sublist (p : α Bool) : l.takeWhile p <+ l :=
(takeWhile_prefix p).sublist
theorem dropWhile_sublist (p : α Bool) : l.dropWhile p <+ l :=
@[grind] theorem dropWhile_sublist (p : α Bool) : l.dropWhile p <+ l :=
(dropWhile_suffix p).sublist
theorem takeWhile_subset {l : List α} (p : α Bool) : l.takeWhile p l :=
@@ -1010,61 +1159,88 @@ theorem takeWhile_subset {l : List α} (p : α → Bool) : l.takeWhile p ⊆ l :
theorem dropWhile_subset {l : List α} (p : α Bool) : l.dropWhile p l :=
(dropWhile_sublist p).subset
theorem dropLast_prefix : l : List α, l.dropLast <+: l
@[grind] theorem dropLast_prefix : l : List α, l.dropLast <+: l
| [] => nil, by rw [dropLast, List.append_nil]
| a :: l => _, dropLast_concat_getLast (cons_ne_nil a l)
theorem dropLast_sublist (l : List α) : l.dropLast <+ l :=
@[grind] theorem dropLast_sublist (l : List α) : l.dropLast <+ l :=
(dropLast_prefix l).sublist
theorem dropLast_subset (l : List α) : l.dropLast l :=
(dropLast_sublist l).subset
theorem tail_suffix (l : List α) : tail l <:+ l := by rw [ drop_one]; apply drop_suffix
@[grind] theorem tail_suffix (l : List α) : tail l <:+ l := by rw [ drop_one]; apply drop_suffix
theorem IsPrefix.map {β} (f : α β) l₁ l₂ : List α (h : l₁ <+: l₂) : l₁.map f <+: l₂.map f := by
@[grind] theorem IsPrefix.map {β} (f : α β) l₁ l₂ : List α (h : l₁ <+: l₂) : l₁.map f <+: l₂.map f := by
obtain r, rfl := h
rw [map_append]; apply prefix_append
theorem IsSuffix.map {β} (f : α β) l₁ l₂ : List α (h : l₁ <:+ l₂) : l₁.map f <:+ l.map f := by
grind_pattern IsPrefix.map => l₁ <+: l₂, l.map f
grind_pattern IsPrefix.map => l₁ <+: l₂, l₂.map f
@[grind] theorem IsSuffix.map {β} (f : α β) l₁ l₂ : List α (h : l₁ <:+ l₂) : l₁.map f <:+ l₂.map f := by
obtain r, rfl := h
rw [map_append]; apply suffix_append
theorem IsInfix.map {β} (f : α β) l₁ l₂ : List α (h : l₁ <:+: l₂) : l₁.map f <:+: l₂.map f := by
grind_pattern IsSuffix.map => l₁ <:+ l₂, l₁.map f
grind_pattern IsSuffix.map => l₁ <:+ l₂, l₂.map f
@[grind] theorem IsInfix.map {β} (f : α β) l₁ l₂ : List α (h : l₁ <:+: l₂) : l₁.map f <:+: l₂.map f := by
obtain r₁, r₂, rfl := h
rw [map_append, map_append]; apply infix_append
theorem IsPrefix.filter (p : α Bool) l₁ l₂ : List α (h : l₁ <+: l₂) :
grind_pattern IsInfix.map => l₁ <:+: l₂, l₁.map f
grind_pattern IsInfix.map => l₁ <:+: l₂, l₂.map f
@[grind] theorem IsPrefix.filter (p : α Bool) l₁ l₂ : List α (h : l₁ <+: l₂) :
l₁.filter p <+: l₂.filter p := by
obtain xs, rfl := h
rw [filter_append]; apply prefix_append
theorem IsSuffix.filter (p : α Bool) l₁ l₂ : List α (h : l₁ <:+ l₂) :
grind_pattern IsPrefix.filter => l₁ <+: l₂, l₁.filter p
grind_pattern IsPrefix.filter => l₁ <+: l₂, l₂.filter p
@[grind] theorem IsSuffix.filter (p : α Bool) l₁ l₂ : List α (h : l₁ <:+ l₂) :
l₁.filter p <:+ l₂.filter p := by
obtain xs, rfl := h
rw [filter_append]; apply suffix_append
theorem IsInfix.filter (p : α Bool) l₁ l₂ : List α (h : l₁ <:+: l₂) :
grind_pattern IsSuffix.filter => l₁ <:+ l₂, l₁.filter p
grind_pattern IsSuffix.filter => l₁ <:+ l₂, l₂.filter p
@[grind] theorem IsInfix.filter (p : α Bool) l₁ l₂ : List α (h : l₁ <:+: l₂) :
l₁.filter p <:+: l₂.filter p := by
obtain xs, ys, rfl := h
rw [filter_append, filter_append]; apply infix_append _
theorem IsPrefix.filterMap {β} (f : α Option β) l₁ l₂ : List α (h : l₁ <+: l₂) :
grind_pattern IsInfix.filter => l₁ <:+: l₂, l₁.filter p
grind_pattern IsInfix.filter => l₁ <:+: l₂, l₂.filter p
@[grind] theorem IsPrefix.filterMap {β} (f : α Option β) l₁ l₂ : List α (h : l₁ <+: l₂) :
filterMap f l₁ <+: filterMap f l₂ := by
obtain xs, rfl := h
rw [filterMap_append]; apply prefix_append
theorem IsSuffix.filterMap {β} (f : α Option β) l₁ l₂ : List α (h : l₁ <:+ l₂) :
grind_pattern IsPrefix.filterMap => l₁ <+: l₂, filterMap f l₁
grind_pattern IsPrefix.filterMap => l₁ <+: l₂, filterMap f l₂
@[grind] theorem IsSuffix.filterMap {β} (f : α Option β) l₁ l₂ : List α (h : l₁ <:+ l₂) :
filterMap f l₁ <:+ filterMap f l₂ := by
obtain xs, rfl := h
rw [filterMap_append]; apply suffix_append
theorem IsInfix.filterMap {β} (f : α Option β) l₁ l₂ : List α (h : l₁ <:+: l₂) :
grind_pattern IsSuffix.filterMap => l₁ <:+ l₂, filterMap f l₁
grind_pattern IsSuffix.filterMap => l₁ <:+ l₂, filterMap f l₂
@[grind] theorem IsInfix.filterMap {β} (f : α Option β) l₁ l₂ : List α (h : l₁ <:+: l₂) :
filterMap f l₁ <:+: filterMap f l₂ := by
obtain xs, ys, rfl := h
rw [filterMap_append, filterMap_append]; apply infix_append
@[simp] theorem isPrefixOf_iff_prefix [BEq α] [LawfulBEq α] {l₁ l₂ : List α} :
grind_pattern IsInfix.filterMap => l₁ <:+: l₂, filterMap f l₁
grind_pattern IsInfix.filterMap => l₁ <:+: l₂, filterMap f l₂
@[simp, grind =] theorem isPrefixOf_iff_prefix [BEq α] [LawfulBEq α] {l₁ l₂ : List α} :
l₁.isPrefixOf l₂ l₁ <+: l₂ := by
induction l₁ generalizing l₂ with
| nil => simp
@@ -1076,7 +1252,7 @@ theorem IsInfix.filterMap {β} (f : α → Option β) ⦃l₁ l₂ : List α⦄
instance [DecidableEq α] (l₁ l₂ : List α) : Decidable (l₁ <+: l₂) :=
decidable_of_iff (l₁.isPrefixOf l₂) isPrefixOf_iff_prefix
@[simp] theorem isSuffixOf_iff_suffix [BEq α] [LawfulBEq α] {l₁ l₂ : List α} :
@[simp, grind =] theorem isSuffixOf_iff_suffix [BEq α] [LawfulBEq α] {l₁ l₂ : List α} :
l₁.isSuffixOf l₂ l₁ <:+ l₂ := by
simp [isSuffixOf]

View File

@@ -31,6 +31,11 @@ theorem take_cons {l : List α} (h : 0 < i) : (a :: l).take i = a :: l.take (i -
| zero => exact absurd h (Nat.lt_irrefl _)
| succ i => rfl
theorem drop_cons {l : List α} (h : 0 < i) : (a :: l).drop i = l.drop (i - 1) := by
cases i with
| zero => exact absurd h (Nat.lt_irrefl _)
| succ i => rfl
@[simp]
theorem drop_one : {l : List α}, l.drop 1 = l.tail
| [] | _ :: _ => rfl

View File

@@ -256,16 +256,16 @@ theorem findRevM?_toArray [Monad m] [LawfulMonad m] (f : α → m Bool) (l : Lis
@[simp, grind =] theorem findSome?_toArray (f : α Option β) (l : List α) :
l.toArray.findSome? f = l.findSome? f := by
rw [Array.findSome?, findSomeM?_id, findSomeM?_toArray, Id.run]
rw [Array.findSome?, findSomeM?_toArray, findSomeM?_pure, Id.run_pure]
@[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]
simp only [forIn_toArray]
induction l with
| nil => simp
| cons a l ih =>
simp only [forIn_cons, Id.pure_eq, Id.bind_eq, find?]
simp only [forIn_cons, find?]
by_cases f a <;> simp_all
private theorem findFinIdx?_loop_toArray (w : l' = l.drop j) :
@@ -302,7 +302,7 @@ termination_by l.length - j
@[simp, grind =] theorem findIdx?_toArray (p : α Bool) (l : List α) :
l.toArray.findIdx? p = l.findIdx? p := by
rw [Array.findIdx?_eq_map_findFinIdx?_val, findIdx?_eq_map_findFinIdx?_val]
simp
simp [Array.size]
private theorem idxAuxOf_toArray [BEq α] (a : α) (l : List α) (j : Nat) (w : l' = l.drop j) (h) :
l.toArray.idxOfAux a j = findFinIdx?.go (fun x => x == a) l l' j h := by
@@ -339,11 +339,11 @@ termination_by l.length - j
@[simp, grind =] theorem idxOf?_toArray [BEq α] (a : α) (l : List α) :
l.toArray.idxOf? a = l.idxOf? a := by
rw [Array.idxOf?, idxOf?]
simp [finIdxOf?, findIdx?_eq_map_findFinIdx?_val]
simp [finIdxOf?, findIdx?_eq_map_findFinIdx?_val, Array.size]
@[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?]
rw [Array.findIdx, findIdx?_toArray, findIdx_eq_getD_findIdx?, Array.size]
@[simp, grind =] theorem idxOf_toArray [BEq α] {as : List α} {a : α} :
as.toArray.idxOf a = as.idxOf a := by
@@ -670,9 +670,9 @@ theorem replace_toArray [BEq α] [LawfulBEq α] (l : List α) (a b : α) :
split <;> rename_i i h
· simp only [finIdxOf?_toArray, finIdxOf?_eq_none_iff] at h
rw [replace_of_not_mem]
simpa
exact finIdxOf?_eq_none_iff.mp h
· simp_all only [finIdxOf?_toArray, finIdxOf?_eq_some_iff, Fin.getElem_fin, set_toArray,
mk.injEq]
mk.injEq, Array.size]
apply List.ext_getElem
· simp
· intro j h₁ h₂

View File

@@ -150,7 +150,7 @@ theorem add_one (n : Nat) : n + 1 = succ n :=
@[simp] theorem succ_eq_add_one (n : Nat) : succ n = n + 1 :=
rfl
@[simp] theorem add_one_ne_zero (n : Nat) : n + 1 0 := nofun
theorem add_one_ne_zero (n : Nat) : n + 1 0 := nofun
theorem zero_ne_add_one (n : Nat) : 0 n + 1 := by simp
protected theorem add_comm : (n m : Nat), n + m = m + n
@@ -731,13 +731,12 @@ theorem exists_eq_add_one_of_ne_zero : ∀ {n}, n ≠ 0 → Exists fun k => n =
theorem ctor_eq_zero : Nat.zero = 0 :=
rfl
@[simp] protected theorem one_ne_zero : 1 (0 : Nat) :=
fun h => Nat.noConfusion h
protected theorem one_ne_zero : 1 (0 : Nat) := by simp
@[simp] protected theorem zero_ne_one : 0 (1 : Nat) :=
fun h => Nat.noConfusion h
@[simp] theorem succ_ne_zero (n : Nat) : succ n 0 := by simp
theorem succ_ne_zero (n : Nat) : succ n 0 := by simp
instance instNeZeroSucc {n : Nat} : NeZero (n + 1) := succ_ne_zero n

View File

@@ -72,7 +72,7 @@ Examples:
* `0 <<< 3 = 0`
* `0xf1 <<< 4 = 0xf10`
-/
@[extern "lean_nat_shiftl"]
@[extern "lean_nat_shiftl", expose]
def shiftLeft : @& Nat @& Nat Nat
| n, 0 => n
| n, succ m => shiftLeft (2*n) m
@@ -88,7 +88,7 @@ Examples:
* `0 >>> 3 = 0`
* `0xf13a >>> 8 = 0xf1`
-/
@[extern "lean_nat_shiftr"]
@[extern "lean_nat_shiftr", expose]
def shiftRight : @& Nat @& Nat Nat
| n, 0 => n
| n, succ m => shiftRight n m / 2

View File

@@ -26,6 +26,7 @@ Examples:
* `Nat.lcm 0 3 = 0`
* `Nat.lcm 3 0 = 0`
-/
@[expose]
def lcm (m n : Nat) : Nat := m * n / gcd m n
theorem lcm_eq_mul_div (m n : Nat) : lcm m n = m * n / gcd m n := rfl

View File

@@ -415,7 +415,7 @@ theorem succ_min_succ (x y) : min (succ x) (succ y) = succ (min x y) := by
| inl h => rw [Nat.min_eq_left h, Nat.min_eq_left (Nat.succ_le_succ h)]
| inr h => rw [Nat.min_eq_right h, Nat.min_eq_right (Nat.succ_le_succ h)]
@[simp] protected theorem min_self (a : Nat) : min a a = a := Nat.min_eq_left (Nat.le_refl _)
protected theorem min_self (a : Nat) : min a a = a := by simp
instance : Std.IdempotentOp (α := Nat) min := Nat.min_self
@[simp] protected theorem min_assoc : (a b c : Nat), min (min a b) c = min a (min b c)
@@ -431,16 +431,14 @@ instance : Std.Associative (α := Nat) min := ⟨Nat.min_assoc⟩
@[simp] protected theorem min_self_assoc' {m n : Nat} : min n (min m n) = min n m := by
rw [Nat.min_comm m n, Nat.min_assoc, Nat.min_self]
@[simp] theorem min_add_left_self {a b : Nat} : min a (b + a) = a := by
rw [Nat.min_def]
theorem min_add_left_self {a b : Nat} : min a (b + a) = a := by
simp
@[simp] theorem min_add_right_self {a b : Nat} : min a (a + b) = a := by
rw [Nat.min_def]
theorem min_add_right_self {a b : Nat} : min a (a + b) = a := by
simp
theorem add_left_min_self {a b : Nat} : min (b + a) a = a := by
simp
theorem add_right_min_self {a b : Nat} : min (a + b) a = a := by
simp
@[simp] theorem add_left_min_self {a b : Nat} : min (b + a) a = a := by
rw [Nat.min_comm, min_add_left_self]
@[simp] theorem add_right_min_self {a b : Nat} : min (a + b) a = a := by
rw [Nat.min_comm, min_add_right_self]
protected theorem sub_sub_eq_min : (a b : Nat), a - (a - b) = min a b
| 0, _ => by rw [Nat.zero_sub, Nat.zero_min]
@@ -462,7 +460,7 @@ protected theorem succ_max_succ (x y) : max (succ x) (succ y) = succ (max x y) :
| inl h => rw [Nat.max_eq_right h, Nat.max_eq_right (Nat.succ_le_succ h)]
| inr h => rw [Nat.max_eq_left h, Nat.max_eq_left (Nat.succ_le_succ h)]
@[simp] protected theorem max_self (a : Nat) : max a a = a := Nat.max_eq_right (Nat.le_refl _)
protected theorem max_self (a : Nat) : max a a = a := by simp
instance : Std.IdempotentOp (α := Nat) max := Nat.max_self
instance : Std.LawfulIdentity (α := Nat) max 0 where
@@ -476,16 +474,14 @@ instance : Std.LawfulIdentity (α := Nat) max 0 where
| _+1, _+1, _+1 => by simp only [Nat.succ_max_succ]; exact congrArg succ <| Nat.max_assoc ..
instance : Std.Associative (α := Nat) max := Nat.max_assoc
@[simp] theorem max_add_left_self {a b : Nat} : max a (b + a) = b + a := by
rw [Nat.max_def]
theorem max_add_left_self {a b : Nat} : max a (b + a) = b + a := by
simp
@[simp] theorem max_add_right_self {a b : Nat} : max a (a + b) = a + b := by
rw [Nat.max_def]
theorem max_add_right_self {a b : Nat} : max a (a + b) = a + b := by
simp
theorem add_left_max_self {a b : Nat} : max (b + a) a = b + a := by
simp
theorem add_right_max_self {a b : Nat} : max (a + b) a = a + b := by
simp
@[simp] theorem add_left_max_self {a b : Nat} : max (b + a) a = b + a := by
rw [Nat.max_comm, max_add_left_self]
@[simp] theorem add_right_max_self {a b : Nat} : max (a + b) a = a + b := by
rw [Nat.max_comm, max_add_right_self]
protected theorem sub_add_eq_max (a b : Nat) : a - b + b = max a b := by
match Nat.le_total a b with
@@ -814,10 +810,8 @@ theorem sub_mul_mod {x k n : Nat} (h₁ : n*k ≤ x) : (x - n*k) % n = x % n :=
simp [mul_succ, Nat.add_comm] at h₁; simp [h₁]
rw [mul_succ, Nat.sub_sub, mod_eq_sub_mod h₄, sub_mul_mod h₂]
@[simp] theorem mod_mod (a n : Nat) : (a % n) % n = a % n :=
match eq_zero_or_pos n with
| .inl n0 => by simp [n0, mod_zero]
| .inr npos => Nat.mod_eq_of_lt (mod_lt _ npos)
theorem mod_mod (a n : Nat) : (a % n) % n = a % n := by
simp
theorem mul_mod (a b n : Nat) : a * b % n = (a % n) * (b % n) % n := by
rw (occs := [1]) [ mod_add_div a n]

View File

@@ -39,11 +39,11 @@ namespace Option
o.toArray.foldr f a = o.elim a (fun b => f b a) := by
cases o <;> simp
@[simp]
@[simp, grind =]
theorem toList_toArray {o : Option α} : o.toArray.toList = o.toList := by
cases o <;> simp
@[simp]
@[simp, grind =]
theorem toArray_toList {o : Option α} : o.toList.toArray = o.toArray := by
cases o <;> simp
@@ -69,7 +69,8 @@ theorem toArray_min [Min α] {o o' : Option α} :
theorem size_toArray_le {o : Option α} : o.toArray.size 1 := by
cases o <;> simp
theorem size_toArray_eq_ite {o : Option α} :
@[grind =]
theorem size_toArray {o : Option α} :
o.toArray.size = if o.isSome then 1 else 0 := by
cases o <;> simp
@@ -81,10 +82,9 @@ theorem toArray_eq_empty_iff {o : Option α} : o.toArray = #[] ↔ o = none := b
theorem toArray_eq_singleton_iff {o : Option α} : o.toArray = #[a] o = some a := by
cases o <;> simp
@[simp]
theorem size_toArray_eq_zero_iff {o : Option α} :
o.toArray.size = 0 o = none := by
cases o <;> simp
simp [Array.size]
@[simp]
theorem size_toArray_eq_one_iff {o : Option α} :

View File

@@ -34,7 +34,7 @@ well-founded recursion that use iteration operators (such as `Option.map`) to pr
value drawn from a parameter is smaller than the parameter. This allows the well-founded recursion
mechanism to prove that the function terminates.
-/
@[implemented_by attachWithImpl] def attachWith
@[implemented_by attachWithImpl, expose] def attachWith
(xs : Option α) (P : α Prop) (H : x, xs = some x P x) : Option {x // P x} :=
match xs with
| none => none
@@ -49,14 +49,14 @@ operators (such as `Option.map`) to prove that an optional value drawn from a pa
than the parameter. This allows the well-founded recursion mechanism to prove that the function
terminates.
-/
@[inline] def attach (xs : Option α) : Option {x // xs = some x} := xs.attachWith _ fun _ => id
@[inline, expose] def attach (xs : Option α) : Option {x // xs = some x} := xs.attachWith _ fun _ => id
@[simp] theorem attach_none : (none : Option α).attach = none := rfl
@[simp] theorem attachWith_none : (none : Option α).attachWith P H = none := rfl
@[simp, grind =] theorem attach_none : (none : Option α).attach = none := rfl
@[simp, grind =] theorem attachWith_none : (none : Option α).attachWith P H = none := rfl
@[simp] theorem attach_some {x : α} :
@[simp, grind =] theorem attach_some {x : α} :
(some x).attach = some x, rfl := rfl
@[simp] theorem attachWith_some {x : α} {P : α Prop} (h : (b : α), some x = some b P b) :
@[simp, grind =] theorem attachWith_some {x : α} {P : α Prop} (h : (b : α), some x = some b P b) :
(some x).attachWith P h = some x, by simpa using h := rfl
theorem attach_congr {o₁ o₂ : Option α} (h : o₁ = o₂) :
@@ -76,7 +76,7 @@ theorem attach_map_val (o : Option α) (f : α → β) :
@[deprecated attach_map_val (since := "2025-02-17")]
abbrev attach_map_coe := @attach_map_val
theorem attach_map_subtype_val (o : Option α) :
@[simp, grind =]theorem attach_map_subtype_val (o : Option α) :
o.attach.map Subtype.val = o :=
(attach_map_val _ _).trans (congrFun Option.map_id _)
@@ -87,7 +87,7 @@ theorem attachWith_map_val {p : α → Prop} (f : α → β) (o : Option α) (H
@[deprecated attachWith_map_val (since := "2025-02-17")]
abbrev attachWith_map_coe := @attachWith_map_val
theorem attachWith_map_subtype_val {p : α Prop} (o : Option α) (H : a, o = some a p a) :
@[simp, grind =] theorem attachWith_map_subtype_val {p : α Prop} (o : Option α) (H : a, o = some a p a) :
(o.attachWith p H).map Subtype.val = o :=
(attachWith_map_val _ _ _).trans (congrFun Option.map_id _)
@@ -98,17 +98,17 @@ theorem attach_eq_some : ∀ (o : Option α) (x : {x // o = some x}), o.attach =
theorem mem_attach : (o : Option α) (x : {x // o = some x}), x o.attach :=
attach_eq_some
@[simp] theorem isNone_attach (o : Option α) : o.attach.isNone = o.isNone := by
@[simp, grind =] theorem isNone_attach (o : Option α) : o.attach.isNone = o.isNone := by
cases o <;> simp
@[simp] theorem isNone_attachWith {p : α Prop} (o : Option α) (H : a, o = some a p a) :
@[simp, grind =] theorem isNone_attachWith {p : α Prop} (o : Option α) (H : a, o = some a p a) :
(o.attachWith p H).isNone = o.isNone := by
cases o <;> simp
@[simp] theorem isSome_attach (o : Option α) : o.attach.isSome = o.isSome := by
@[simp, grind =] theorem isSome_attach (o : Option α) : o.attach.isSome = o.isSome := by
cases o <;> simp
@[simp] theorem isSome_attachWith {p : α Prop} (o : Option α) (H : a, o = some a p a) :
@[simp, grind =] theorem isSome_attachWith {p : α Prop} (o : Option α) (H : a, o = some a p a) :
(o.attachWith p H).isSome = o.isSome := by
cases o <;> simp
@@ -127,25 +127,28 @@ theorem mem_attach : ∀ (o : Option α) (x : {x // o = some x}), x ∈ o.attach
o.attachWith p H = some x o = some x.val := by
cases o <;> cases x <;> simp
@[simp] theorem get_attach {o : Option α} (h : o.attach.isSome = true) :
@[simp, grind =] theorem get_attach {o : Option α} (h : o.attach.isSome = true) :
o.attach.get h = o.get (by simpa using h), by simp :=
Subsingleton.elim _ _
@[simp] theorem getD_attach {o : Option α} {fallback} :
@[simp, grind =] theorem getD_attach {o : Option α} {fallback} :
o.attach.getD fallback = fallback :=
Subsingleton.elim _ _
@[simp] theorem get!_attach {o : Option α} [Inhabited { x // o = some x }] :
@[simp, grind =] theorem get!_attach {o : Option α} [Inhabited { x // o = some x }] :
o.attach.get! = default :=
Subsingleton.elim _ _
@[simp] theorem get_attachWith {p : α Prop} {o : Option α} (H : a, o = some a p a) (h : (o.attachWith p H).isSome) :
@[simp, grind =] theorem get_attachWith {p : α Prop} {o : Option α} (H : a, o = some a p a) (h : (o.attachWith p H).isSome) :
(o.attachWith p H).get h = o.get (by simpa using h), H _ (by simp) := by
cases o <;> simp
@[simp] theorem getD_attachWith {p : α Prop} {o : Option α} {h} {fallback} :
@[simp, grind =] theorem getD_attachWith {p : α Prop} {o : Option α} {h} {fallback} :
(o.attachWith p h).getD fallback =
o.getD fallback.1, by cases o <;> (try exact fallback.2) <;> exact h _ (by simp) := by
o.getD fallback.val, by
cases o
· exact fallback.property
· exact h _ (by simp) := by
cases o <;> simp
theorem toList_attach (o : Option α) :
@@ -168,23 +171,23 @@ theorem toArray_attachWith {p : α → Prop} {o : Option α} {h} :
o.toList.attach = (o.attach.map fun a, h => a, by simpa using h).toList := by
cases o <;> simp [toList]
theorem attach_map {o : Option α} (f : α β) :
@[grind =] theorem attach_map {o : Option α} (f : α β) :
(o.map f).attach = o.attach.map (fun x, h => f x, map_eq_some_iff.2 _, h, rfl) := by
cases o <;> simp
theorem attachWith_map {o : Option α} (f : α β) {P : β Prop} {H : (b : β), o.map f = some b P b} :
@[grind =] theorem attachWith_map {o : Option α} (f : α β) {P : β Prop} {H : (b : β), o.map f = some b P b} :
(o.map f).attachWith P H = (o.attachWith (P f) (fun _ h => H _ (map_eq_some_iff.2 _, h, rfl))).map
fun x, h => f x, h := by
cases o <;> simp
theorem map_attach_eq_pmap {o : Option α} (f : { x // o = some x } β) :
@[grind =] theorem map_attach_eq_pmap {o : Option α} (f : { x // o = some x } β) :
o.attach.map f = o.pmap (fun a (h : o = some a) => f a, h) (fun _ h => h) := by
cases o <;> simp
@[deprecated map_attach_eq_pmap (since := "2025-02-09")]
abbrev map_attach := @map_attach_eq_pmap
@[simp] theorem map_attachWith {l : Option α} {P : α Prop} {H : (a : α), l = some a P a}
@[simp, grind =] theorem map_attachWith {l : Option α} {P : α Prop} {H : (a : α), l = some a P a}
(f : { x // P x } β) :
(l.attachWith P H).map f = l.attach.map fun x, h => f x, H _ h := by
cases l <;> simp_all
@@ -200,12 +203,12 @@ theorem map_attach_eq_attachWith {o : Option α} {p : α → Prop} (f : ∀ a, o
o.attach.map (fun x => x.1, f x.1 x.2) = o.attachWith p f := by
cases o <;> simp_all [Function.comp_def]
theorem attach_bind {o : Option α} {f : α Option β} :
@[grind =] theorem attach_bind {o : Option α} {f : α Option β} :
(o.bind f).attach =
o.attach.bind fun x, h => (f x).attach.map fun y, h' => y, bind_eq_some_iff.2 _, h, h' := by
cases o <;> simp
theorem bind_attach {o : Option α} {f : {x // o = some x} Option β} :
@[grind =] theorem bind_attach {o : Option α} {f : {x // o = some x} Option β} :
o.attach.bind f = o.pbind fun a h => f a, h := by
cases o <;> simp
@@ -213,7 +216,7 @@ theorem pbind_eq_bind_attach {o : Option α} {f : (a : α) → o = some a → Op
o.pbind f = o.attach.bind fun x, h => f x h := by
cases o <;> simp
theorem attach_filter {o : Option α} {p : α Bool} :
@[grind =] theorem attach_filter {o : Option α} {p : α Bool} :
(o.filter p).attach =
o.attach.bind fun x, h => if h' : p x then some x, by simp_all else none := by
cases o with
@@ -229,12 +232,12 @@ theorem attach_filter {o : Option α} {p : α → Bool} :
· rintro h, rfl
simp [h]
theorem filter_attachWith {P : α Prop} {o : Option α} {h : x, o = some x P x} {q : α Bool} :
@[grind =] theorem filter_attachWith {P : α Prop} {o : Option α} {h : x, o = some x P x} {q : α Bool} :
(o.attachWith P h).filter q =
(o.filter q).attachWith P (fun _ h' => h _ (eq_some_of_filter_eq_some h')) := by
cases o <;> simp [filter_some] <;> split <;> simp
theorem filter_attach {o : Option α} {p : {x // o = some x} Bool} :
@[grind =] 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]
@@ -278,7 +281,7 @@ theorem toArray_pmap {p : α → Prop} {o : Option α} {f : (a : α) → p a →
(o.pmap f h).toArray = o.attach.toArray.map (fun x => f x.1 (h _ x.2)) := by
cases o <;> simp
theorem attach_pfilter {o : Option α} {p : (a : α) o = some a Bool} :
@[grind =] theorem attach_pfilter {o : Option α} {p : (a : α) o = some a Bool} :
(o.pfilter p).attach =
o.attach.pbind fun x h => if h' : p x (by simp_all) then
some x.1, by simpa [pfilter_eq_some_iff] using _, h' else none := by
@@ -322,6 +325,7 @@ If this function is encountered in a proof state, the right approach is usually
It is a synonym for `Option.map Subtype.val`.
-/
@[expose]
def unattach {α : Type _} {p : α Prop} (o : Option { x // p x }) := o.map (·.val)
@[simp] theorem unattach_none {p : α Prop} : (none : Option { x // p x }).unattach = none := rfl

View File

@@ -16,7 +16,7 @@ namespace Option
/--
Extracts the value from an `Option`, panicking on `none`.
-/
@[inline] def get! {α : Type u} [Inhabited α] : Option α α
@[inline, expose] def get! {α : Type u} [Inhabited α] : Option α α
| some x => x
| none => panic! "value is none"

View File

@@ -87,7 +87,7 @@ some ⟨3, ⋯⟩
none
```
-/
@[inline]
@[inline, expose]
def pbind : (o : Option α) (f : (a : α) o = some a Option β) Option β
| none, _ => none
| some a, f => f a rfl
@@ -114,7 +114,7 @@ some ⟨3, ⋯⟩
none
```
-/
@[inline] def pmap {p : α Prop}
@[inline, expose] def pmap {p : α Prop}
(f : a : α, p a β) :
(o : Option α) ( a, o = some a p a) Option β
| none, _ => none
@@ -147,14 +147,14 @@ some ⟨3, ⋯⟩
none
```
-/
@[inline] def pelim (o : Option α) (b : β) (f : (a : α) o = some a β) : β :=
@[inline, expose] def pelim (o : Option α) (b : β) (f : (a : α) o = some a β) : β :=
match o with
| none => b
| some a => f a rfl
/-- Partial filter. If `o : Option α`, `p : (a : α) → o = some a → Bool`, then `o.pfilter p` is
the same as `o.filter p` but `p` is passed the proof that `o = some a`. -/
@[inline] def pfilter (o : Option α) (p : (a : α) o = some a Bool) : Option α :=
@[inline, expose] def pfilter (o : Option α) (p : (a : α) o = some a Bool) : Option α :=
match o with
| none => none
| some a => bif p a rfl then o else none
@@ -177,7 +177,7 @@ Examples:
((), 0)
```
-/
@[inline] protected def forM [Pure m] : Option α (α m PUnit) m PUnit
@[inline, expose] protected def forM [Pure m] : Option α (α m PUnit) m PUnit
| none , _ => pure
| some a, f => f a

View File

@@ -14,7 +14,7 @@ import Init.Ext
namespace Option
theorem default_eq_none : (default : Option α) = none := rfl
@[grind =] theorem default_eq_none : (default : Option α) = none := rfl
@[deprecated mem_def (since := "2025-04-07")]
theorem mem_iff {a : α} {b : Option α} : a b b = some a := .rfl
@@ -70,8 +70,6 @@ theorem some_get! [Inhabited α] : (o : Option α) → o.isSome → some (o.get!
theorem get!_eq_getD [Inhabited α] (o : Option α) : o.get! = o.getD default := rfl
@[deprecated get!_eq_getD (since := "2024-11-18")] abbrev get!_eq_getD_default := @get!_eq_getD
theorem get_congr {o o' : Option α} {ho : o.isSome} (h : o = o') :
o.get ho = o'.get (h ho) := by
cases h; rfl
@@ -254,11 +252,11 @@ theorem isSome_apply_of_isSome_bind {α β : Type _} {x : Option α} {f : α
(isSome_apply_of_isSome_bind h) := by
cases x <;> trivial
theorem any_bind {p : β Bool} {f : α Option β} {o : Option α} :
@[grind =] theorem any_bind {p : β Bool} {f : α Option β} {o : Option α} :
(o.bind f).any p = o.any (Option.any p f) := by
cases o <;> simp
theorem all_bind {p : β Bool} {f : α Option β} {o : Option α} :
@[grind =] theorem all_bind {p : β Bool} {f : α Option β} {o : Option α} :
(o.bind f).all p = o.all (Option.all p f) := by
cases o <;> simp
@@ -431,7 +429,7 @@ theorem filter_eq_bind (x : Option α) (p : α → Bool) :
x.filter p = x.bind (Option.guard p) :=
(bind_guard x p).symm
@[simp] theorem any_filter : (o : Option α)
@[simp, grind =] theorem any_filter : (o : Option α)
(Option.filter p o).any q = Option.any (fun a => p a && q a) o
| none => rfl
| some a =>
@@ -439,7 +437,7 @@ theorem filter_eq_bind (x : Option α) (p : α → Bool) :
| false => by simp [filter_some_neg h, h]
| true => by simp [filter_some_pos h, h]
@[simp] theorem all_filter : (o : Option α)
@[simp, grind =] theorem all_filter : (o : Option α)
(Option.filter p o).all q = Option.all (fun a => !p a || q a) o
| none => rfl
| some a =>
@@ -447,7 +445,7 @@ theorem filter_eq_bind (x : Option α) (p : α → Bool) :
| false => by simp [filter_some_neg h, h]
| true => by simp [filter_some_pos h, h]
@[simp] theorem isNone_filter :
@[simp, grind =] theorem isNone_filter :
Option.isNone (Option.filter p o) = Option.all (fun a => !p a) o :=
match o with
| none => rfl
@@ -468,7 +466,7 @@ theorem filter_eq_bind (x : Option α) (p : α → Bool) :
Option.filter q (Option.filter p o) = Option.filter (fun x => p x && q x) o := by
cases o <;> repeat (simp_all [filter_some]; try split)
theorem filter_bind {f : α Option β} :
@[grind =] 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
@@ -483,16 +481,16 @@ theorem filter_bind {f : α → Option β} :
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} :
@[grind =] 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 : α) :
@[simp] theorem all_guard (a : α) :
Option.all q (guard p a) = (!p a || q a) := by
simp only [guard]
split <;> simp_all
@[simp, grind] theorem any_guard (a : α) : Option.any q (guard p a) = (p a && q a) := by
@[simp] theorem any_guard (a : α) : Option.any q (guard p a) = (p a && q a) := by
simp only [guard]
split <;> simp_all
@@ -563,21 +561,21 @@ theorem bind_map_comm {α β} {x : Option (Option α)} {f : α → β} :
theorem mem_of_mem_join {a : α} {x : Option (Option α)} (h : a x.join) : some a x :=
h.symm join_eq_some_iff.1 h
theorem any_join {p : α Bool} {x : Option (Option α)} :
@[grind _=_] theorem any_join {p : α Bool} {x : Option (Option α)} :
x.join.any p = x.any (Option.any p) := by
cases x <;> simp
theorem all_join {p : α Bool} {x : Option (Option α)} :
@[grind _=_] theorem all_join {p : α Bool} {x : Option (Option α)} :
x.join.all p = x.all (Option.all p) := by
cases x <;> simp
theorem isNone_join {x : Option (Option α)} : x.join.isNone = x.all Option.isNone := by
@[grind =] theorem isNone_join {x : Option (Option α)} : x.join.isNone = x.all Option.isNone := by
cases x <;> simp
theorem isSome_join {x : Option (Option α)} : x.join.isSome = x.any Option.isSome := by
@[grind =]theorem isSome_join {x : Option (Option α)} : x.join.isSome = x.any Option.isSome := by
cases x <;> simp
theorem get_join {x : Option (Option α)} {h} : x.join.get h =
@[grind =] theorem get_join {x : Option (Option α)} {h} : x.join.get h =
(x.get (Option.isSome_of_any (Option.isSome_join h))).get (get_of_any_eq_true _ _ (Option.isSome_join h)) := by
cases x with
| none => simp at h
@@ -588,11 +586,11 @@ theorem join_eq_get {x : Option (Option α)} {h} : x.join = x.get h := by
| none => simp at h
| some _ => simp
theorem getD_join {x : Option (Option α)} {default : α} :
@[grind =] theorem getD_join {x : Option (Option α)} {default : α} :
x.join.getD default = (x.getD (some default)).getD default := by
cases x <;> simp
theorem get!_join [Inhabited α] {x : Option (Option α)} :
@[grind =] theorem get!_join [Inhabited α] {x : Option (Option α)} :
x.join.get! = x.get!.get! := by
cases x <;> simp [default_eq_none]
@@ -602,13 +600,13 @@ theorem get!_join [Inhabited α] {x : Option (Option α)} :
@[deprecated guard_eq_some_iff (since := "2025-04-10")]
abbrev guard_eq_some := @guard_eq_some_iff
@[simp] theorem isSome_guard : (Option.guard p a).isSome = p a :=
@[simp, grind =] theorem isSome_guard : (Option.guard p a).isSome = p a :=
if h : p a then by simp [Option.guard, h] else by simp [Option.guard, h]
@[deprecated isSome_guard (since := "2025-03-18")]
abbrev guard_isSome := @isSome_guard
@[simp] theorem isNone_guard : (Option.guard p a).isNone = !p a := by
@[simp, grind =] theorem isNone_guard : (Option.guard p a).isNone = !p a := by
rw [ not_isSome, isSome_guard]
@[simp] theorem guard_eq_none_iff : Option.guard p a = none p a = false :=
@@ -643,7 +641,7 @@ theorem get_none (a : α) {h} : none.get h = a := by
theorem get_none_eq_iff_true {h} : (none : Option α).get h = a True := by
simp at h
theorem get_guard : (guard p a).get h = a := by
@[simp, grind =] theorem get_guard : (guard p a).get h = a := by
simp only [guard]
split <;> simp
@@ -672,7 +670,7 @@ theorem map_guard {p : α → Bool} {f : α → β} {x : α} :
(Option.guard p x).map f = if p x then some (f x) else none := by
simp [guard_eq_ite]
theorem join_filter {p : Option α Bool} : {o : Option (Option α)}
@[grind =] 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
@@ -682,7 +680,7 @@ theorem join_filter {p : Option α → Bool} : {o : Option (Option α)} →
simp only [join_some, filter_some]
split <;> simp
theorem filter_join {p : α Bool} : {o : Option (Option α)}
@[grind =] theorem filter_join {p : α Bool} : {o : Option (Option α)}
o.join.filter p = (o.filter (Option.any p)).join
| none => by simp
| some none => by
@@ -754,22 +752,22 @@ theorem merge_eq_some_iff {o o' : Option α} {f : ααα} {a : α} :
theorem merge_eq_none_iff {o o' : Option α} : o.merge f o' = none o = none o' = none := by
cases o <;> cases o' <;> simp
@[simp]
@[simp, grind =]
theorem any_merge {p : α Bool} {f : α α α} (hpf : a b, p (f a b) = (p a || p b))
{o o' : Option α} : (o.merge f o').any p = (o.any p || o'.any p) := by
cases o <;> cases o' <;> simp [*]
@[simp]
@[simp, grind =]
theorem all_merge {p : α Bool} {f : α α α} (hpf : a b, p (f a b) = (p a && p b))
{o o' : Option α} : (o.merge f o').all p = (o.all p && o'.all p) := by
cases o <;> cases o' <;> simp [*]
@[simp]
@[simp, grind =]
theorem isSome_merge {o o' : Option α} {f : α α α} :
(o.merge f o').isSome = (o.isSome || o'.isSome) := by
simp [ any_true]
@[simp]
@[simp, grind =]
theorem isNone_merge {o o' : Option α} {f : α α α} :
(o.merge f o').isNone = (o.isNone && o'.isNone) := by
simp [ all_false]
@@ -783,7 +781,7 @@ theorem get_merge {o o' : Option α} {f : ααα} {i : α} [Std.Lawful
@[simp, grind] theorem elim_some (x : β) (f : α β) (a : α) : (some a).elim x f = f a := rfl
theorem elim_filter {o : Option α} {b : β} :
@[grind =] 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
@@ -792,7 +790,7 @@ theorem elim_filter {o : Option α} {b : β} :
| false => by simp [filter_some_neg h, h]
| true => by simp [filter_some_pos, h]
theorem elim_join {o : Option (Option α)} {b : β} {f : α β} :
@[grind =] theorem elim_join {o : Option (Option α)} {b : β} {f : α β} :
o.join.elim b f = o.elim b (·.elim b f) := by
cases o <;> simp
@@ -830,9 +828,16 @@ theorem choice_eq_default [Subsingleton α] [Inhabited α] : choice α = some de
theorem choice_eq_none_iff_not_nonempty : choice α = none ¬Nonempty α := by
simp [choice]
theorem isNone_choice_iff_not_nonempty : (choice α).isNone ¬Nonempty α := by
rw [isNone_iff_eq_none, choice_eq_none_iff_not_nonempty]
grind_pattern isNone_choice_iff_not_nonempty => (choice α).isNone
theorem isSome_choice_iff_nonempty : (choice α).isSome Nonempty α :=
fun h => (choice α).get h, fun h => by simp only [choice, dif_pos h, isSome_some]
grind_pattern isSome_choice_iff_nonempty => (choice α).isSome
@[simp]
theorem isSome_choice [Nonempty α] : (choice α).isSome :=
isSome_choice_iff_nonempty.2 inferInstance
@@ -840,19 +845,16 @@ theorem isSome_choice [Nonempty α] : (choice α).isSome :=
@[deprecated isSome_choice_iff_nonempty (since := "2025-03-18")]
abbrev choice_isSome_iff_nonempty := @isSome_choice_iff_nonempty
theorem isNone_choice_iff_not_nonempty : (choice α).isNone ¬Nonempty α := by
rw [isNone_iff_eq_none, choice_eq_none_iff_not_nonempty]
@[simp]
theorem isNone_choice_eq_false [Nonempty α] : (choice α).isNone = false := by
simp [ not_isSome]
@[simp]
@[simp, grind =]
theorem getD_choice {a} :
(choice α).getD a = (choice α).get (isSome_choice_iff_nonempty.2 a) := by
rw [get_eq_getD]
@[simp]
@[simp, grind =]
theorem get!_choice [Inhabited α] : (choice α).get! = (choice α).get isSome_choice := by
rw [get_eq_get!]
@@ -933,16 +935,16 @@ theorem or_of_isNone {o o' : Option α} (h : o.isNone) : o.or o' = o' := by
match o, h with
| none, _ => simp
@[simp, grind]
@[simp, grind =]
theorem getD_or {o o' : Option α} {fallback : α} :
(o.or o').getD fallback = o.getD (o'.getD fallback) := by
cases o <;> simp
@[simp]
@[simp, grind =]
theorem get!_or {o o' : Option α} [Inhabited α] : (o.or o').get! = o.getD o'.get! := by
cases o <;> simp
@[simp] theorem filter_or_filter {o o' : Option α} {f : α Bool} :
@[simp, grind =] 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
@@ -1026,16 +1028,16 @@ variable [BEq α]
@[simp] theorem beq_none {o : Option α} : (o == none) = o.isNone := by cases o <;> simp
@[simp]
theorem filter_beq_self [ReflBEq α] {p : α Bool} {o : Option α} : (o.filter p == o) = (o.all p) := by
@[simp, grind =]
theorem filter_beq_self [ReflBEq α] {p : α Bool} {o : Option α} : (o.filter p == o) = o.all p := by
cases o with
| none => simp
| some _ =>
simp only [filter_some]
split <;> simp [*]
@[simp]
theorem self_beq_filter [ReflBEq α] {p : α Bool} {o : Option α} : (o == o.filter p) = (o.all p) := by
@[simp, grind =]
theorem self_beq_filter [ReflBEq α] {p : α Bool} {o : Option α} : (o == o.filter p) = o.all p := by
cases o with
| none => simp
| some _ =>
@@ -1204,7 +1206,7 @@ theorem pbind_eq_some_iff {o : Option α} {f : (a : α) → o = some a → Optio
o.pbind f = some b a h, f a h = some b := by
cases o <;> simp
theorem pbind_join {o : Option (Option α)} {f : (a : α) o.join = some a Option β} :
@[grind =] theorem pbind_join {o : Option (Option α)} {f : (a : α) o.join = some a Option β} :
o.join.pbind f = o.pbind (fun o' ho' => o'.pbind (fun a ha => f a (by simp_all))) := by
cases o <;> simp <;> congr
@@ -1218,7 +1220,7 @@ theorem isSome_get_of_isSome_pbind {o : Option α} {f : (a : α) → o = some a
| none => simp at h
| some a => simp [ h]
@[simp]
@[simp, grind =]
theorem get_pbind {o : Option α} {f : (a : α) o = some a Option β} {h} :
(o.pbind f).get h = (f (o.get (isSome_of_isSome_pbind h)) (by simp)).get (isSome_get_of_isSome_pbind h) := by
cases o <;> simp
@@ -1256,7 +1258,7 @@ theorem get_pbind {o : Option α} {f : (a : α) → o = some a → Option β} {h
· rintro h, rfl
rfl
@[simp, grind]
@[simp]
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
@@ -1305,7 +1307,7 @@ theorem pmap_guard {q : α → Bool} {p : α → Prop} (f : (x : α) → p x →
simp only [guard_eq_ite]
split <;> simp_all
@[simp]
@[simp, grind =]
theorem get_pmap {p : α Bool} {f : (x : α) p x β} {o : Option α}
{h : a, o = some a p a} {h'} :
(o.pmap f h).get h' = f (o.get (by simpa using h')) (h _ (by simp)) := by
@@ -1316,7 +1318,7 @@ theorem get_pmap {p : α → Bool} {f : (x : α) → p x → β} {o : Option α}
@[simp, grind] theorem pelim_none : pelim none b f = b := rfl
@[simp, grind] theorem pelim_some : pelim (some a) b f = f a rfl := rfl
@[simp, grind] theorem pelim_eq_elim : pelim o b (fun a _ => f a) = o.elim b f := by
@[simp] theorem pelim_eq_elim : pelim o b (fun a _ => f a) = o.elim b f := by
cases o <;> simp
@[simp, grind] theorem elim_pmap {p : α Prop} (f : (a : α) p a β) (o : Option α)
@@ -1329,7 +1331,7 @@ theorem pelim_congr_left {o o' : Option α } {b : β} {f : (a : α) → (a ∈ o
pelim o b f = pelim o' b (fun a ha => f a (h ha)) := by
cases h; rfl
theorem pelim_filter {o : Option α} {b : β} {f : (a : α) a o.filter p β} :
@[grind =] 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
@@ -1339,7 +1341,7 @@ theorem pelim_filter {o : Option α} {b : β} {f : (a : α) → a ∈ o.filter p
| false => by simp [pelim_congr_left (filter_some_neg h), h]
| true => by simp [pelim_congr_left (filter_some_pos h), h]
theorem pelim_join {o : Option (Option α)} {b : β} {f : (a : α) a o.join β} :
@[grind =] theorem pelim_join {o : Option (Option α)} {b : β} {f : (a : α) a o.join β} :
o.join.pelim b f = o.pelim b (fun o' ho' => o'.pelim b (fun a ha => f a (by simp_all))) := by
cases o <;> simp <;> congr
@@ -1417,7 +1419,7 @@ theorem eq_some_of_pfilter_eq_some {o : Option α} {p : (a : α) → o = some a
{a : α} (h : o.pfilter p = some a) : o = some a :=
pfilter_eq_some_iff.1 h |>.1
theorem filter_pbind {f : (a : α) o = some a Option β} :
@[grind =] 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
@@ -1429,7 +1431,7 @@ theorem filter_pbind {f : (a : α) → o = some a → Option β} :
· simp only [h, filter_some, any_some]
split <;> simp [h]
@[simp, grind] theorem pfilter_eq_filter {α : Type _} {o : Option α} {p : α Bool} :
@[simp] theorem pfilter_eq_filter {α : Type _} {o : Option α} {p : α Bool} :
o.pfilter (fun a _ => p a) = o.filter p := by
cases o with
| none => rfl
@@ -1468,7 +1470,7 @@ theorem pfilter_eq_pbind_ite {α : Type _} {o : Option α}
· rfl
· simp only [Option.pfilter, Bool.cond_eq_ite, Option.pbind_some]
theorem filter_pmap {p : α Prop} {f : (a : α) p a β} {h : (a : α), o = some a p a}
@[grind =] theorem filter_pmap {p : α Prop} {f : (a : α) p a β} {h : (a : α), o = some a p a}
{q : β Bool} : (o.pmap f h).filter q = (o.pfilter (fun a h' => q (f a (h _ h')))).pmap f
(fun _ h' => h _ (eq_some_of_pfilter_eq_some h')) := by
cases o with
@@ -1477,7 +1479,7 @@ theorem filter_pmap {p : α → Prop} {f : (a : α) → p a → β} {h : ∀ (a
simp only [pmap_some, filter_some, pfilter_some]
split <;> simp
theorem pfilter_join {o : Option (Option α)} {p : (a : α) o.join = some a Bool} :
@[grind =] theorem pfilter_join {o : Option (Option α)} {p : (a : α) o.join = some a Bool} :
o.join.pfilter p = (o.pfilter (fun o' h => o'.pelim false (fun a ha => p a (by simp_all)))).join := by
cases o with
| none => simp
@@ -1488,11 +1490,11 @@ theorem pfilter_join {o : Option (Option α)} {p : (a : α) → o.join = some a
simp only [join_some, pfilter_some, pelim_some]
split <;> simp
theorem join_pfilter {o : Option (Option α)} {p : (o' : Option α) o = some o' Bool} :
@[grind =] theorem join_pfilter {o : Option (Option α)} {p : (o' : Option α) o = some o' Bool} :
(o.pfilter p).join = o.pbind (fun o' ho' => if p o' ho' then o' else none) := by
cases o <;> simp <;> split <;> simp
theorem elim_pfilter {o : Option α} {b : β} {f : α β} {p : (a : α) o = some a Bool} :
@[grind =] theorem elim_pfilter {o : Option α} {b : β} {f : α β} {p : (a : α) o = some a Bool} :
(o.pfilter p).elim b f = o.pelim b (fun a ha => if p a ha then f a else b) := by
cases o with
| none => simp
@@ -1500,7 +1502,7 @@ theorem elim_pfilter {o : Option α} {b : β} {f : α → β} {p : (a : α) →
simp only [pfilter_some, pelim_some]
split <;> simp
theorem pelim_pfilter {o : Option α} {b : β} {p : (a : α) o = some a Bool}
@[grind =] theorem pelim_pfilter {o : Option α} {b : β} {p : (a : α) o = some a Bool}
{f : (a : α) o.pfilter p = some a β} :
(o.pfilter p).pelim b f = o.pelim b
(fun a ha => if hp : p a ha then f a (pfilter_eq_some_iff.2 _, hp) else b) := by
@@ -1518,13 +1520,13 @@ theorem pfilter_guard {a : α} {p : α → Bool} {q : (a' : α) → guard p a =
/-! ### LT and LE -/
@[simp, grind] theorem not_lt_none [LT α] {a : Option α} : ¬ a < none := by cases a <;> simp [LT.lt, Option.lt]
@[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
@[grind] theorem none_lt_some [LT α] {a : α} : none < some a := by simp [LT.lt, Option.lt]
@[simp] theorem none_lt [LT α] {a : Option α} : none < a a.isSome := by cases a <;> simp [none_lt_some]
@[simp, grind] theorem some_lt_some [LT α] {a b : α} : some a < some b a < b := by simp [LT.lt, Option.lt]
@[simp, grind] theorem none_le [LE α] {a : Option α} : none a := by cases a <;> simp [LE.le, Option.le]
@[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
@[grind] theorem not_some_le_none [LE α] {a : α} : ¬ some a none := by simp [LE.le, Option.le]
@[simp] theorem le_none [LE α] {a : Option α} : a none a = none := by cases a <;> simp [not_some_le_none]
@[simp, grind] theorem some_le_some [LE α] {a b : α} : some a some b a b := by simp [LE.le, Option.le]
@[simp]
@@ -1789,19 +1791,19 @@ theorem min_pfilter_right [Min α] [Std.IdempotentOp (α := α) min] {o : Option
simp only [pfilter_some]
split <;> simp [Std.IdempotentOp.idempotent]
@[simp]
@[simp, grind =]
theorem isSome_max [Max α] {o o' : Option α} : (max o o').isSome = (o.isSome || o'.isSome) := by
cases o <;> cases o' <;> simp
@[simp]
@[simp, grind =]
theorem isNone_max [Max α] {o o' : Option α} : (max o o').isNone = (o.isNone && o'.isNone) := by
cases o <;> cases o' <;> simp
@[simp]
@[simp, grind =]
theorem isSome_min [Min α] {o o' : Option α} : (min o o').isSome = (o.isSome && o'.isSome) := by
cases o <;> cases o' <;> simp
@[simp]
@[simp, grind =]
theorem isNone_min [Min α] {o o' : Option α} : (min o o').isNone = (o.isNone || o'.isNone) := by
cases o <;> cases o' <;> simp
@@ -1813,7 +1815,7 @@ theorem max_join_right [Max α] {o : Option α} {o' : Option (Option α)} :
max o o'.join = (max (some o) o').get (by simp) := by
cases o' <;> simp
theorem join_max [Max α] {o o' : Option (Option α)} :
@[grind _=_] theorem join_max [Max α] {o o' : Option (Option α)} :
(max o o').join = max o.join o'.join := by
cases o <;> cases o' <;> simp
@@ -1825,7 +1827,7 @@ theorem min_join_right [Min α] {o : Option α} {o' : Option (Option α)} :
min o o'.join = (min (some o) o').join := by
cases o' <;> simp
theorem join_min [Min α] {o o' : Option (Option α)} :
@[grind _=_] theorem join_min [Min α] {o o' : Option (Option α)} :
(min o o').join = min o.join o'.join := by
cases o <;> cases o' <;> simp
@@ -1873,12 +1875,12 @@ theorem min_eq_none_iff [Min α] {o o' : Option α} :
min o o' = none o = none o' = none := by
cases o <;> cases o' <;> simp
@[simp]
@[simp, grind =]
theorem any_max [Max α] {o o' : Option α} {p : α Bool} (hp : a b, p (max a b) = (p a || p b)) :
(max o o').any p = (o.any p || o'.any p) := by
cases o <;> cases o' <;> simp [hp]
@[simp]
@[simp, grind =]
theorem all_min [Min α] {o o' : Option α} {p : α Bool} (hp : a b, p (min a b) = (p a || p b)) :
(min o o').all p = (o.all p || o'.all p) := by
cases o <;> cases o' <;> simp [hp]
@@ -1889,7 +1891,7 @@ theorem isSome_left_of_isSome_min [Min α] {o o' : Option α} : (min o o').isSom
theorem isSome_right_of_isSome_min [Min α] {o o' : Option α} : (min o o').isSome o'.isSome := by
cases o' <;> simp
@[simp]
@[simp, grind =]
theorem get_min [Min α] {o o' : Option α} {h} :
(min o o').get h = min (o.get (isSome_left_of_isSome_min h)) (o'.get (isSome_right_of_isSome_min h)) := by
cases o <;> cases o' <;> simp

View File

@@ -73,7 +73,8 @@ theorem toList_min [Min α] {o o' : Option α} :
theorem length_toList_le {o : Option α} : o.toList.length 1 := by
cases o <;> simp
theorem length_toList_eq_ite {o : Option α} :
@[grind =]
theorem length_toList {o : Option α} :
o.toList.length = if o.isSome then 1 else 0 := by
cases o <;> simp
@@ -85,10 +86,9 @@ theorem toList_eq_nil_iff {o : Option α} : o.toList = [] ↔ o = none := by
theorem toList_eq_singleton_iff {o : Option α} : o.toList = [a] o = some a := by
cases o <;> simp
@[simp]
theorem length_toList_eq_zero_iff {o : Option α} :
o.toList.length = 0 o = none := by
cases o <;> simp
simp
@[simp]
theorem length_toList_eq_one_iff {o : Option α} :

View File

@@ -90,11 +90,18 @@ theorem forIn'_eq_pelim [Monad m] [LawfulMonad m]
pure (f := m) (o.pelim b (fun a h => f a h b)) := by
cases o <;> simp
@[simp] theorem forIn'_id_yield_eq_pelim
@[simp] theorem idRun_forIn'_yield_eq_pelim
(o : Option α) (f : (a : α) a o β Id β) (b : β) :
(forIn' o b (fun a m b => .yield <$> f a m b)).run =
o.pelim b (fun a h => f a h b |>.run) :=
forIn'_pure_yield_eq_pelim _ _ _
@[deprecated idRun_forIn'_yield_eq_pelim (since := "2025-05-21")]
theorem forIn'_id_yield_eq_pelim
(o : Option α) (f : (a : α) a o β β) (b : β) :
forIn' (m := Id) o b (fun a m b => .yield (f a m b)) =
o.pelim b (fun a h => f a h b) := by
cases o <;> simp
o.pelim b (fun a h => f a h b) :=
forIn'_pure_yield_eq_pelim _ _ _
@[simp, grind] theorem forIn'_map [Monad m] [LawfulMonad m]
(o : Option α) (g : α β) (f : (b : β) b o.map g γ m (ForInStep γ)) :
@@ -126,11 +133,18 @@ theorem forIn_eq_elim [Monad m] [LawfulMonad m]
pure (f := m) (o.elim b (fun a => f a b)) := by
cases o <;> simp
@[simp] theorem forIn_id_yield_eq_elim
@[simp] theorem idRun_forIn_yield_eq_elim
(o : Option α) (f : (a : α) β Id β) (b : β) :
(forIn o b (fun a b => .yield <$> f a b)).run =
o.elim b (fun a => f a b |>.run) :=
forIn_pure_yield_eq_elim _ _ _
@[deprecated idRun_forIn_yield_eq_elim (since := "2025-05-21")]
theorem forIn_id_yield_eq_elim
(o : Option α) (f : (a : α) β β) (b : β) :
forIn (m := Id) o b (fun a b => .yield (f a b)) =
o.elim b (fun a => f a b) := by
cases o <;> simp
o.elim b (fun a => f a b) :=
forIn_pure_yield_eq_elim _ _ _
@[simp, grind] theorem forIn_map [Monad m] [LawfulMonad m]
(o : Option α) (g : α β) (f : β γ m (ForInStep γ)) :
@@ -142,26 +156,26 @@ theorem forIn_join [Monad m] [LawfulMonad m]
forIn o.join init f = forIn o init (fun o' b => ForInStep.yield <$> forIn o' b f) := by
cases o <;> simp
@[simp] theorem elimM_pure [Monad m] [LawfulMonad m] (x : Option α) (y : m β) (z : α m β) :
@[simp, grind =] 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 β))
@[simp, grind =] 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 β)
@[simp, grind =] 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_eq_or (o : Option α) (alternative : Unit Option α) :
@[simp, grind =] theorem tryCatch_eq_or (o : Option α) (alternative : Unit Option α) :
tryCatch o alternative = o.or (alternative ()) := by cases o <;> rfl
@[simp] theorem throw_eq_none : throw () = (none : Option α) := rfl
@[simp, grind =] theorem throw_eq_none : throw () = (none : Option α) := rfl
@[simp, grind] theorem filterM_none [Applicative m] (p : α m Bool) :
@[simp, grind =] theorem filterM_none [Applicative m] (p : α m Bool) :
none.filterM p = pure none := rfl
theorem filterM_some [Applicative m] (p : α m Bool) (a : α) :
@[grind =] theorem filterM_some [Applicative m] (p : α m Bool) (a : α) :
(some a).filterM p = (fun b => if b then some a else none) <$> p a := rfl
theorem sequence_join [Applicative m] [LawfulApplicative m] {o : Option (Option (m α))} :

View File

@@ -3,7 +3,6 @@ Copyright (c) 2021 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Dany Fabian, Sebastian Ullrich
-/
module
prelude
@@ -21,13 +20,13 @@ The relationship between the compared items may be:
* `Ordering.gt`: greater than
-/
inductive Ordering where
| /-- Less than. -/
lt
| /-- Equal. -/
eq
| /-- Greater than. -/
gt
deriving Inhabited, DecidableEq
/-- Less than. -/
| lt
/-- Equal. -/
| eq
/-- Greater than. -/
| gt
deriving Inhabited, DecidableEq, Repr
namespace Ordering
@@ -39,6 +38,7 @@ Examples:
* `Ordering.eq.swap = Ordering.eq`
* `Ordering.gt.swap = Ordering.lt`
-/
@[inline, expose]
def swap : Ordering Ordering
| .lt => .gt
| .eq => .eq
@@ -96,6 +96,7 @@ Ordering.lt
/--
Checks whether the ordering is `eq`.
-/
@[inline, expose]
def isEq : Ordering Bool
| eq => true
| _ => false
@@ -103,6 +104,7 @@ def isEq : Ordering → Bool
/--
Checks whether the ordering is not `eq`.
-/
@[inline, expose]
def isNe : Ordering Bool
| eq => false
| _ => true
@@ -110,6 +112,7 @@ def isNe : Ordering → Bool
/--
Checks whether the ordering is `lt` or `eq`.
-/
@[inline, expose]
def isLE : Ordering Bool
| gt => false
| _ => true
@@ -117,6 +120,7 @@ def isLE : Ordering → Bool
/--
Checks whether the ordering is `lt`.
-/
@[inline, expose]
def isLT : Ordering Bool
| lt => true
| _ => false
@@ -124,6 +128,7 @@ def isLT : Ordering → Bool
/--
Checks whether the ordering is `gt`.
-/
@[inline, expose]
def isGT : Ordering Bool
| gt => true
| _ => false
@@ -131,203 +136,158 @@ def isGT : Ordering → Bool
/--
Checks whether the ordering is `gt` or `eq`.
-/
@[inline, expose]
def isGE : Ordering Bool
| lt => false
| _ => true
section Lemmas
@[simp]
theorem isLT_lt : lt.isLT := rfl
protected theorem «forall» {p : Ordering Prop} : ( o, p o) p .lt p .eq p .gt := by
constructor
· intro h
exact h _, h _, h _
· rintro h₁, h₂, h₃ (_ | _ | _) <;> assumption
@[simp]
theorem isLE_lt : lt.isLE := rfl
protected theorem «exists» {p : Ordering Prop} : ( o, p o) p .lt p .eq p .gt := by
constructor
· rintro (_ | _ | _), h
· exact .inl h
· exact .inr (.inl h)
· exact .inr (.inr h)
· rintro (h | h | h) <;> exact _, h
@[simp]
theorem isEq_lt : lt.isEq = false := rfl
instance [DecidablePred p] : Decidable ( o : Ordering, p o) :=
decidable_of_decidable_of_iff Ordering.«forall».symm
@[simp]
theorem isNe_lt : lt.isNe = true := rfl
instance [DecidablePred p] : Decidable ( o : Ordering, p o) :=
decidable_of_decidable_of_iff Ordering.«exists».symm
@[simp]
theorem isGE_lt : lt.isGE = false := rfl
@[simp] theorem isLT_lt : lt.isLT := rfl
@[simp] theorem isLE_lt : lt.isLE := rfl
@[simp] theorem isEq_lt : lt.isEq = false := rfl
@[simp] theorem isNe_lt : lt.isNe = true := rfl
@[simp] theorem isGE_lt : lt.isGE = false := rfl
@[simp] theorem isGT_lt : lt.isGT = false := rfl
@[simp]
theorem isGT_lt : lt.isGT = false := rfl
@[simp] theorem isLT_eq : eq.isLT = false := rfl
@[simp] theorem isLE_eq : eq.isLE := rfl
@[simp] theorem isEq_eq : eq.isEq := rfl
@[simp] theorem isNe_eq : eq.isNe = false := rfl
@[simp] theorem isGE_eq : eq.isGE := rfl
@[simp] theorem isGT_eq : eq.isGT = false := rfl
@[simp]
theorem isLT_eq : eq.isLT = false := rfl
@[simp] theorem isLT_gt : gt.isLT = false := rfl
@[simp] theorem isLE_gt : gt.isLE = false := rfl
@[simp] theorem isEq_gt : gt.isEq = false := rfl
@[simp] theorem isNe_gt : gt.isNe = true := rfl
@[simp] theorem isGE_gt : gt.isGE := rfl
@[simp] theorem isGT_gt : gt.isGT := rfl
@[simp]
theorem isLE_eq : eq.isLE := rfl
@[simp] theorem lt_beq_eq : (lt == eq) = false := rfl
@[simp] theorem lt_beq_gt : (lt == gt) = false := rfl
@[simp] theorem eq_beq_lt : (eq == lt) = false := rfl
@[simp] theorem eq_beq_gt : (eq == gt) = false := rfl
@[simp] theorem gt_beq_lt : (gt == lt) = false := rfl
@[simp] theorem gt_beq_eq : (gt == eq) = false := rfl
@[simp]
theorem isEq_eq : eq.isEq := rfl
@[simp] theorem swap_lt : lt.swap = .gt := rfl
@[simp] theorem swap_eq : eq.swap = .eq := rfl
@[simp] theorem swap_gt : gt.swap = .lt := rfl
@[simp]
theorem isNe_eq : eq.isNe = false := rfl
theorem eq_eq_of_isLE_of_isLE_swap : {o : Ordering}, o.isLE o.swap.isLE o = .eq := by decide
theorem eq_eq_of_isGE_of_isGE_swap : {o : Ordering}, o.isGE o.swap.isGE o = .eq := by decide
theorem eq_eq_of_isLE_of_isGE : {o : Ordering}, o.isLE o.isGE o = .eq := by decide
theorem eq_swap_iff_eq_eq : {o : Ordering}, o = o.swap o = .eq := by decide
theorem eq_eq_of_eq_swap : {o : Ordering}, o = o.swap o = .eq := eq_swap_iff_eq_eq.mp
@[simp]
theorem isGE_eq : eq.isGE := rfl
@[simp] theorem isLE_eq_false : {o : Ordering}, o.isLE = false o = .gt := by decide
@[simp] theorem isGE_eq_false : {o : Ordering}, o.isGE = false o = .lt := by decide
@[simp] theorem isNe_eq_false : {o : Ordering}, o.isNe = false o = .eq := by decide
@[simp] theorem isEq_eq_false : {o : Ordering}, o.isEq = false ¬o = .eq := by decide
@[simp]
theorem isGT_eq : eq.isGT = false := rfl
@[simp] theorem swap_eq_gt : {o : Ordering}, o.swap = .gt o = .lt := by decide
@[simp] theorem swap_eq_lt : {o : Ordering}, o.swap = .lt o = .gt := by decide
@[simp] theorem swap_eq_eq : {o : Ordering}, o.swap = .eq o = .eq := by decide
@[simp]
theorem isLT_gt : gt.isLT = false := rfl
@[simp] theorem isLT_swap : {o : Ordering}, o.swap.isLT = o.isGT := by decide
@[simp] theorem isLE_swap : {o : Ordering}, o.swap.isLE = o.isGE := by decide
@[simp] theorem isEq_swap : {o : Ordering}, o.swap.isEq = o.isEq := by decide
@[simp] theorem isNe_swap : {o : Ordering}, o.swap.isNe = o.isNe := by decide
@[simp] theorem isGE_swap : {o : Ordering}, o.swap.isGE = o.isLE := by decide
@[simp] theorem isGT_swap : {o : Ordering}, o.swap.isGT = o.isLT := by decide
@[simp]
theorem isLE_gt : gt.isLE = false := rfl
theorem isLE_of_eq_lt : {o : Ordering}, o = .lt o.isLE := by decide
theorem isLE_of_eq_eq : {o : Ordering}, o = .eq o.isLE := by decide
theorem isGE_of_eq_gt : {o : Ordering}, o = .gt o.isGE := by decide
theorem isGE_of_eq_eq : {o : Ordering}, o = .eq o.isGE := by decide
@[simp]
theorem isEq_gt : gt.isEq = false := rfl
theorem ne_eq_of_eq_lt : {o : Ordering}, o = .lt o .eq := by decide
theorem ne_eq_of_eq_gt : {o : Ordering}, o = .gt o .eq := by decide
@[simp]
theorem isNe_gt : gt.isNe = true := rfl
@[simp] theorem isLT_iff_eq_lt : {o : Ordering}, o.isLT o = .lt := by decide
@[simp] theorem isGT_iff_eq_gt : {o : Ordering}, o.isGT o = .gt := by decide
@[simp] theorem isEq_iff_eq_eq : {o : Ordering}, o.isEq o = .eq := by decide
@[simp] theorem isNe_iff_ne_eq : {o : Ordering}, o.isNe ¬o = .eq := by decide
@[simp]
theorem isGE_gt : gt.isGE := rfl
theorem isLE_iff_ne_gt : {o : Ordering}, o.isLE ¬o = .gt := by decide
theorem isGE_iff_ne_lt : {o : Ordering}, o.isGE ¬o = .lt := by decide
theorem isLE_iff_eq_lt_or_eq_eq : {o : Ordering}, o.isLE o = .lt o = .eq := by decide
theorem isGE_iff_eq_gt_or_eq_eq : {o : Ordering}, o.isGE o = .gt o = .eq := by decide
@[simp]
theorem isGT_gt : gt.isGT := rfl
theorem isLT_eq_beq_lt : {o : Ordering}, o.isLT = (o == .lt) := by decide
theorem isLE_eq_not_beq_gt : {o : Ordering}, o.isLE = (!o == .gt) := by decide
theorem isLE_eq_isLT_or_isEq : {o : Ordering}, o.isLE = (o.isLT || o.isEq) := by decide
theorem isGT_eq_beq_gt : {o : Ordering}, o.isGT = (o == .gt) := by decide
theorem isGE_eq_not_beq_lt : {o : Ordering}, o.isGE = (!o == .lt) := by decide
theorem isGE_eq_isGT_or_isEq : {o : Ordering}, o.isGE = (o.isGT || o.isEq) := by decide
theorem isEq_eq_beq_eq : {o : Ordering}, o.isEq = (o == .eq) := by decide
theorem isNe_eq_not_beq_eq : {o : Ordering}, o.isNe = (!o == .eq) := by decide
theorem isNe_eq_isLT_or_isGT : {o : Ordering}, o.isNe = (o.isLT || o.isGT) := by decide
@[simp]
theorem swap_lt : lt.swap = .gt := rfl
@[simp] theorem not_isLT_eq_isGE : {o : Ordering}, !o.isLT = o.isGE := by decide
@[simp] theorem not_isLE_eq_isGT : {o : Ordering}, !o.isLE = o.isGT := by decide
@[simp] theorem not_isGT_eq_isLE : {o : Ordering}, !o.isGT = o.isLE := by decide
@[simp] theorem not_isGE_eq_isLT : {o : Ordering}, !o.isGE = o.isLT := by decide
@[simp] theorem not_isNe_eq_isEq : {o : Ordering}, !o.isNe = o.isEq := by decide
theorem not_isEq_eq_isNe : {o : Ordering}, !o.isEq = o.isNe := by decide
@[simp]
theorem swap_eq : eq.swap = .eq := rfl
theorem ne_lt_iff_isGE : {o : Ordering}, ¬o = .lt o.isGE := by decide
theorem ne_gt_iff_isLE : {o : Ordering}, ¬o = .gt o.isLE := by decide
@[simp]
theorem swap_gt : gt.swap = .lt := rfl
@[simp] theorem swap_swap : {o : Ordering}, o.swap.swap = o := by decide
@[simp] theorem swap_inj : {o₁ o₂ : Ordering}, o₁.swap = o₂.swap o₁ = o₂ := by decide
theorem eq_eq_of_isLE_of_isLE_swap {o : Ordering} : o.isLE o.swap.isLE o = .eq := by
cases o <;> simp
theorem swap_then : (o₁ o₂ : Ordering), (o₁.then o).swap = o.swap.then o₂.swap := by decide
theorem eq_eq_of_isGE_of_isGE_swap {o : Ordering} : o.isGE o.swap.isGE o = .eq := by
cases o <;> simp
theorem then_eq_lt : {o o₂ : Ordering}, o₁.then o₂ = lt o = lt o₁ = eq o = lt := by decide
theorem then_eq_gt : {o₁ o₂ : Ordering}, o₁.then o₂ = gt o₁ = gt o = eq o₂ = gt := by decide
@[simp] theorem then_eq_eq : {o₁ o₂ : Ordering}, o₁.then o₂ = eq o₁ = eq o₂ = eq := by decide
theorem eq_eq_of_isLE_of_isGE {o : Ordering} : o.isLE o.isGE o = .eq := by
cases o <;> simp
theorem isLT_then : {o o₂ : Ordering}, (o₁.then o).isLT = (o.isLT || o.isEq && o₂.isLT) := by decide
theorem isEq_then : {o₁ o₂ : Ordering}, (o₁.then o₂).isEq = (o₁.isEq && o₂.isEq) := by decide
theorem isNe_then : {o₁ o₂ : Ordering}, (o₁.then o₂).isNe = (o₁.isNe || o₂.isNe) := by decide
theorem isGT_then : {o₁ o₂ : Ordering}, (o₁.then o₂).isGT = (o₁.isGT || o₁.isEq && o₂.isGT) := by decide
theorem eq_swap_iff_eq_eq {o : Ordering} : o = o.swap o = .eq := by
cases o <;> simp
@[simp] theorem lt_then {o : Ordering} : lt.then o = lt := rfl
@[simp] theorem gt_then {o : Ordering} : gt.then o = gt := rfl
@[simp] theorem eq_then {o : Ordering} : eq.then o = o := rfl
theorem eq_eq_of_eq_swap {o : Ordering} : o = o.swap o = .eq :=
eq_swap_iff_eq_eq.mp
@[simp] theorem then_eq : {o : Ordering}, o.then eq = o := by decide
@[simp] theorem then_self : {o : Ordering}, o.then o = o := by decide
theorem then_assoc : (o₁ o₂ o₃ : Ordering), (o₁.then o₂).then o₃ = o₁.then (o₂.then o₃) := by decide
@[simp]
theorem isLE_eq_false {o : Ordering} : o.isLE = false o = .gt := by
cases o <;> simp
theorem isLE_then_iff_or : {o₁ o₂ : Ordering}, (o₁.then o₂).isLE o₁ = lt (o₁ = eq o₂.isLE) := by decide
theorem isLE_then_iff_and : {o o₂ : Ordering}, (o₁.then o).isLE o₁.isLE (o = lt o₂.isLE) := by decide
theorem isLE_left_of_isLE_then : {o o₂ : Ordering}, (o₁.then o₂).isLE o₁.isLE := by decide
theorem isGE_left_of_isGE_then : {o₁ o₂ : Ordering}, (o₁.then o₂).isGE o₁.isGE := by decide
@[simp]
theorem isGE_eq_false {o : Ordering} : o.isGE = false o = .lt := by
cases o <;> simp
instance : Std.Associative Ordering.then := then_assoc
instance : Std.IdempotentOp Ordering.then := fun _ => then_self
@[simp]
theorem swap_eq_gt {o : Ordering} : o.swap = .gt o = .lt := by
cases o <;> simp
@[simp]
theorem swap_eq_lt {o : Ordering} : o.swap = .lt o = .gt := by
cases o <;> simp
@[simp]
theorem swap_eq_eq {o : Ordering} : o.swap = .eq o = .eq := by
cases o <;> simp
@[simp]
theorem isLT_swap {o : Ordering} : o.swap.isLT = o.isGT := by
cases o <;> simp
@[simp]
theorem isLE_swap {o : Ordering} : o.swap.isLE = o.isGE := by
cases o <;> simp
@[simp]
theorem isEq_swap {o : Ordering} : o.swap.isEq = o.isEq := by
cases o <;> simp
@[simp]
theorem isNe_swap {o : Ordering} : o.swap.isNe = o.isNe := by
cases o <;> simp
@[simp]
theorem isGE_swap {o : Ordering} : o.swap.isGE = o.isLE := by
cases o <;> simp
@[simp]
theorem isGT_swap {o : Ordering} : o.swap.isGT = o.isLT := by
cases o <;> simp
theorem isLT_iff_eq_lt {o : Ordering} : o.isLT o = .lt := by
cases o <;> simp
theorem isLE_iff_eq_lt_or_eq_eq {o : Ordering} : o.isLE o = .lt o = .eq := by
cases o <;> simp
theorem isLE_of_eq_lt {o : Ordering} : o = .lt o.isLE := by
rintro rfl; rfl
theorem isLE_of_eq_eq {o : Ordering} : o = .eq o.isLE := by
rintro rfl; rfl
theorem isEq_iff_eq_eq {o : Ordering} : o.isEq o = .eq := by
cases o <;> simp
theorem isNe_iff_ne_eq {o : Ordering} : o.isNe o .eq := by
cases o <;> simp
theorem isGE_iff_eq_gt_or_eq_eq {o : Ordering} : o.isGE o = .gt o = .eq := by
cases o <;> simp
theorem isGE_of_eq_gt {o : Ordering} : o = .gt o.isGE := by
rintro rfl; rfl
theorem isGE_of_eq_eq {o : Ordering} : o = .eq o.isGE := by
rintro rfl; rfl
theorem isGT_iff_eq_gt {o : Ordering} : o.isGT o = .gt := by
cases o <;> simp
@[simp]
theorem swap_swap {o : Ordering} : o.swap.swap = o := by
cases o <;> simp
@[simp] theorem swap_inj {o₁ o₂ : Ordering} : o₁.swap = o₂.swap o₁ = o₂ :=
fun h => by simpa using congrArg swap h, congrArg _
theorem swap_then (o₁ o₂ : Ordering) : (o₁.then o₂).swap = o₁.swap.then o₂.swap := by
cases o₁ <;> rfl
theorem then_eq_lt {o₁ o₂ : Ordering} : o₁.then o₂ = lt o₁ = lt o₁ = eq o₂ = lt := by
cases o₁ <;> cases o₂ <;> decide
theorem then_eq_eq {o₁ o₂ : Ordering} : o₁.then o₂ = eq o₁ = eq o₂ = eq := by
cases o₁ <;> simp [«then»]
theorem then_eq_gt {o₁ o₂ : Ordering} : o₁.then o₂ = gt o₁ = gt o₁ = eq o₂ = gt := by
cases o₁ <;> cases o₂ <;> decide
@[simp]
theorem lt_then {o : Ordering} : lt.then o = lt := rfl
@[simp]
theorem gt_then {o : Ordering} : gt.then o = gt := rfl
@[simp]
theorem eq_then {o : Ordering} : eq.then o = o := rfl
theorem isLE_then_iff_or {o₁ o₂ : Ordering} : (o₁.then o₂).isLE o₁ = lt (o₁ = eq o₂.isLE) := by
cases o₁ <;> simp
theorem isLE_then_iff_and {o₁ o₂ : Ordering} : (o₁.then o₂).isLE o₁.isLE (o₁ = lt o₂.isLE) := by
cases o₁ <;> simp
theorem isLE_left_of_isLE_then {o₁ o₂ : Ordering} (h : (o₁.then o₂).isLE) : o₁.isLE := by
cases o₁ <;> simp_all
theorem isGE_left_of_isGE_then {o₁ o₂ : Ordering} (h : (o₁.then o₂).isGE) : o₁.isGE := by
cases o₁ <;> simp_all
instance : Std.LawfulIdentity Ordering.then eq where
left_id _ := eq_then
right_id _ := then_eq
end Lemmas
@@ -375,7 +335,7 @@ section Lemmas
@[simp]
theorem compareLex_eq_eq {α} {cmp₁ cmp₂} {a b : α} :
compareLex cmp₁ cmp₂ a b = .eq cmp₁ a b = .eq cmp₂ a b = .eq := by
simp [compareLex, Ordering.then_eq_eq]
simp [compareLex]
theorem compareOfLessAndEq_eq_swap_of_lt_iff_not_gt_and_ne {α : Type u} [LT α] [DecidableLT α] [DecidableEq α]
(h : x y : α, x < y ¬ y < x x y) {x y : α} :
@@ -384,14 +344,14 @@ theorem compareOfLessAndEq_eq_swap_of_lt_iff_not_gt_and_ne {α : Type u} [LT α]
split
· rename_i h'
rw [h] at h'
simp only [h'.1, h'.2.symm, reduceIte, Ordering.swap_gt]
simp only [h'.1, h'.2.symm, reduceIte, Ordering.swap_gt]
· split
· rename_i h'
have : ¬ y < y := Not.imp (·.2 rfl) <| (h y y).mp
simp only [h', this, reduceIte, Ordering.swap_eq]
simp only [h', this, reduceIte, Ordering.swap_eq]
· rename_i h' h''
replace h' := (h y x).mpr h', Ne.symm h''
simp only [h', Ne.symm h'', reduceIte, Ordering.swap_lt]
simp only [h', Ne.symm h'', reduceIte, Ordering.swap_lt]
theorem lt_iff_not_gt_and_ne_of_antisymm_of_total_of_not_le
{α : Type u} [LT α] [LE α] [DecidableLT α] [DecidableEq α]
@@ -478,13 +438,13 @@ but this is not enforced by the typeclass.
There is a derive handler, so appending `deriving Ord` to an inductive type or structure
will attempt to create an `Ord` instance.
-/
@[ext]
class Ord (α : Type u) where
/-- Compare two elements in `α` using the comparator contained in an `[Ord α]` instance. -/
compare : α α Ordering
export Ord (compare)
set_option linter.unusedVariables false in -- allow specifying `ord` explicitly
/--
Compares two values by comparing the results of applying a function.
@@ -564,7 +524,7 @@ instance : Ord Ordering where
namespace List
@[specialize]
@[specialize, expose]
protected def compareLex {α} (cmp : α α Ordering) :
List α List α Ordering
| [], [] => .eq
@@ -736,6 +696,7 @@ end Array
namespace Vector
@[expose]
protected def compareLex {α n} (cmp : α α Ordering) (a b : Vector α n) : Ordering :=
Array.compareLex cmp a.toArray b.toArray
@@ -764,6 +725,13 @@ end Vector
def lexOrd [Ord α] [Ord β] : Ord (α × β) where
compare := compareLex (compareOn (·.1)) (compareOn (·.2))
/--
Constructs an `BEq` instance from an `Ord` instance that asserts that the result of `compare` is
`Ordering.eq`.
-/
@[expose] def beqOfOrd [Ord α] : BEq α where
beq a b := (compare a b).isEq
/--
Constructs an `LT` instance from an `Ord` instance that asserts that the result of `compare` is
`Ordering.lt`.
@@ -771,8 +739,9 @@ Constructs an `LT` instance from an `Ord` instance that asserts that the result
@[expose] def ltOfOrd [Ord α] : LT α where
lt a b := compare a b = Ordering.lt
instance [Ord α] : DecidableRel (@LT.lt α ltOfOrd) :=
inferInstanceAs (DecidableRel (fun a b => compare a b = Ordering.lt))
@[inline]
instance [Ord α] : DecidableRel (@LT.lt α ltOfOrd) := fun a b =>
decidable_of_bool (compare a b).isLT Ordering.isLT_iff_eq_lt
/--
Constructs an `LT` instance from an `Ord` instance that asserts that the result of `compare`
@@ -781,35 +750,29 @@ satisfies `Ordering.isLE`.
@[expose] def leOfOrd [Ord α] : LE α where
le a b := (compare a b).isLE
instance [Ord α] : DecidableRel (@LE.le α leOfOrd) :=
inferInstanceAs (DecidableRel (fun a b => (compare a b).isLE))
@[inline]
instance [Ord α] : DecidableRel (@LE.le α leOfOrd) := fun _ _ => instDecidableEqBool ..
namespace Ord
/--
Constructs a `BEq` instance from an `Ord` instance.
-/
protected def toBEq (ord : Ord α) : BEq α where
beq x y := ord.compare x y == .eq
@[expose] protected abbrev toBEq (ord : Ord α) : BEq α :=
beqOfOrd
/--
Constructs an `LT` instance from an `Ord` instance.
-/
@[expose] protected def toLT (ord : Ord α) : LT α :=
@[expose] protected abbrev toLT (ord : Ord α) : LT α :=
ltOfOrd
instance [i : Ord α] : DecidableRel (@LT.lt _ (Ord.toLT i)) :=
inferInstanceAs (DecidableRel (fun a b => compare a b = Ordering.lt))
/--
Constructs an `LE` instance from an `Ord` instance.
-/
@[expose] protected def toLE (ord : Ord α) : LE α :=
@[expose] protected abbrev toLE (ord : Ord α) : LE α :=
leOfOrd
instance [i : Ord α] : DecidableRel (@LE.le _ (Ord.toLE i)) :=
inferInstanceAs (DecidableRel (fun a b => (compare a b).isLE))
/--
Inverts the order of an `Ord` instance.
@@ -833,7 +796,7 @@ protected def on (_ : Ord β) (f : α → β) : Ord α where
/--
Constructs the lexicographic order on products `α × β` from orders for `α` and `β`.
-/
protected def lex (_ : Ord α) (_ : Ord β) : Ord (α × β) :=
protected abbrev lex (_ : Ord α) (_ : Ord β) : Ord (α × β) :=
lexOrd
/--

View File

@@ -54,7 +54,7 @@ Examples:
* `(1, 2).swap = (2, 1)`
* `("orange", -87).swap = (-87, "orange")`
-/
def swap : α × β β × α := fun p => (p.2, p.1)
@[expose] def swap : α × β β × α := fun p => (p.2, p.1)
@[simp]
theorem swap_swap : x : α × β, swap (swap x) = x

View File

@@ -25,7 +25,7 @@ namespace Range
universe u v
/-- The number of elements in the range. -/
@[simp] def size (r : Range) : Nat := (r.stop - r.start + r.step - 1) / r.step
@[simp, expose] def size (r : Range) : Nat := (r.stop - r.start + r.step - 1) / r.step
@[inline] protected def forIn' [Monad m] (range : Range) (init : β)
(f : (i : Nat) i range β m (ForInStep β)) : m β :=

View File

@@ -18,13 +18,13 @@ macro "declare_bitwise_int_theorems" typeName:ident bits:term:arg : command =>
`(
namespace $typeName
@[simp, int_toBitVec] protected theorem toBitVec_not {a : $typeName} : (~~~a).toBitVec = ~~~a.toBitVec := rfl
@[simp, int_toBitVec] protected theorem toBitVec_and (a b : $typeName) : (a &&& b).toBitVec = a.toBitVec &&& b.toBitVec := rfl
@[simp, int_toBitVec] protected theorem toBitVec_or (a b : $typeName) : (a ||| b).toBitVec = a.toBitVec ||| b.toBitVec := rfl
@[simp, int_toBitVec] protected theorem toBitVec_xor (a b : $typeName) : (a ^^^ b).toBitVec = a.toBitVec ^^^ b.toBitVec := rfl
@[simp, int_toBitVec] protected theorem toBitVec_shiftLeft (a b : $typeName) : (a <<< b).toBitVec = a.toBitVec <<< (b.toBitVec.smod $bits) := rfl
@[simp, int_toBitVec] protected theorem toBitVec_shiftRight (a b : $typeName) : (a >>> b).toBitVec = a.toBitVec.sshiftRight' (b.toBitVec.smod $bits) := rfl
@[simp, int_toBitVec] protected theorem toBitVec_abs (a : $typeName) : a.abs.toBitVec = a.toBitVec.abs := rfl
@[simp, int_toBitVec] protected theorem toBitVec_not {a : $typeName} : (~~~a).toBitVec = ~~~a.toBitVec := (rfl)
@[simp, int_toBitVec] protected theorem toBitVec_and (a b : $typeName) : (a &&& b).toBitVec = a.toBitVec &&& b.toBitVec := (rfl)
@[simp, int_toBitVec] protected theorem toBitVec_or (a b : $typeName) : (a ||| b).toBitVec = a.toBitVec ||| b.toBitVec := (rfl)
@[simp, int_toBitVec] protected theorem toBitVec_xor (a b : $typeName) : (a ^^^ b).toBitVec = a.toBitVec ^^^ b.toBitVec := (rfl)
@[simp, int_toBitVec] protected theorem toBitVec_shiftLeft (a b : $typeName) : (a <<< b).toBitVec = a.toBitVec <<< (b.toBitVec.smod $bits) := (rfl)
@[simp, int_toBitVec] protected theorem toBitVec_shiftRight (a b : $typeName) : (a >>> b).toBitVec = a.toBitVec.sshiftRight' (b.toBitVec.smod $bits) := (rfl)
@[simp, int_toBitVec] protected theorem toBitVec_abs (a : $typeName) : a.abs.toBitVec = a.toBitVec.abs := (rfl)
end $typeName
)
@@ -58,53 +58,53 @@ theorem Bool.toBitVec_toISize {b : Bool} :
· apply BitVec.eq_of_toNat_eq
simp [toISize]
@[simp] theorem UInt8.toInt8_and (a b : UInt8) : (a &&& b).toInt8 = a.toInt8 &&& b.toInt8 := rfl
@[simp] theorem UInt16.toInt16_and (a b : UInt16) : (a &&& b).toInt16 = a.toInt16 &&& b.toInt16 := rfl
@[simp] theorem UInt32.toInt32_and (a b : UInt32) : (a &&& b).toInt32 = a.toInt32 &&& b.toInt32 := rfl
@[simp] theorem UInt64.toInt64_and (a b : UInt64) : (a &&& b).toInt64 = a.toInt64 &&& b.toInt64 := rfl
@[simp] theorem USize.toISize_and (a b : USize) : (a &&& b).toISize = a.toISize &&& b.toISize := rfl
@[simp] theorem UInt8.toInt8_and (a b : UInt8) : (a &&& b).toInt8 = a.toInt8 &&& b.toInt8 := (rfl)
@[simp] theorem UInt16.toInt16_and (a b : UInt16) : (a &&& b).toInt16 = a.toInt16 &&& b.toInt16 := (rfl)
@[simp] theorem UInt32.toInt32_and (a b : UInt32) : (a &&& b).toInt32 = a.toInt32 &&& b.toInt32 := (rfl)
@[simp] theorem UInt64.toInt64_and (a b : UInt64) : (a &&& b).toInt64 = a.toInt64 &&& b.toInt64 := (rfl)
@[simp] theorem USize.toISize_and (a b : USize) : (a &&& b).toISize = a.toISize &&& b.toISize := (rfl)
@[simp] theorem UInt8.toInt8_or (a b : UInt8) : (a ||| b).toInt8 = a.toInt8 ||| b.toInt8 := rfl
@[simp] theorem UInt16.toInt16_or (a b : UInt16) : (a ||| b).toInt16 = a.toInt16 ||| b.toInt16 := rfl
@[simp] theorem UInt32.toInt32_or (a b : UInt32) : (a ||| b).toInt32 = a.toInt32 ||| b.toInt32 := rfl
@[simp] theorem UInt64.toInt64_or (a b : UInt64) : (a ||| b).toInt64 = a.toInt64 ||| b.toInt64 := rfl
@[simp] theorem USize.toISize_or (a b : USize) : (a ||| b).toISize = a.toISize ||| b.toISize := rfl
@[simp] theorem UInt8.toInt8_or (a b : UInt8) : (a ||| b).toInt8 = a.toInt8 ||| b.toInt8 := (rfl)
@[simp] theorem UInt16.toInt16_or (a b : UInt16) : (a ||| b).toInt16 = a.toInt16 ||| b.toInt16 := (rfl)
@[simp] theorem UInt32.toInt32_or (a b : UInt32) : (a ||| b).toInt32 = a.toInt32 ||| b.toInt32 := (rfl)
@[simp] theorem UInt64.toInt64_or (a b : UInt64) : (a ||| b).toInt64 = a.toInt64 ||| b.toInt64 := (rfl)
@[simp] theorem USize.toISize_or (a b : USize) : (a ||| b).toISize = a.toISize ||| b.toISize := (rfl)
@[simp] theorem UInt8.toInt8_xor (a b : UInt8) : (a ^^^ b).toInt8 = a.toInt8 ^^^ b.toInt8 := rfl
@[simp] theorem UInt16.toInt16_xor (a b : UInt16) : (a ^^^ b).toInt16 = a.toInt16 ^^^ b.toInt16 := rfl
@[simp] theorem UInt32.toInt32_xor (a b : UInt32) : (a ^^^ b).toInt32 = a.toInt32 ^^^ b.toInt32 := rfl
@[simp] theorem UInt64.toInt64_xor (a b : UInt64) : (a ^^^ b).toInt64 = a.toInt64 ^^^ b.toInt64 := rfl
@[simp] theorem USize.toISize_xor (a b : USize) : (a ^^^ b).toISize = a.toISize ^^^ b.toISize := rfl
@[simp] theorem UInt8.toInt8_xor (a b : UInt8) : (a ^^^ b).toInt8 = a.toInt8 ^^^ b.toInt8 := (rfl)
@[simp] theorem UInt16.toInt16_xor (a b : UInt16) : (a ^^^ b).toInt16 = a.toInt16 ^^^ b.toInt16 := (rfl)
@[simp] theorem UInt32.toInt32_xor (a b : UInt32) : (a ^^^ b).toInt32 = a.toInt32 ^^^ b.toInt32 := (rfl)
@[simp] theorem UInt64.toInt64_xor (a b : UInt64) : (a ^^^ b).toInt64 = a.toInt64 ^^^ b.toInt64 := (rfl)
@[simp] theorem USize.toISize_xor (a b : USize) : (a ^^^ b).toISize = a.toISize ^^^ b.toISize := (rfl)
@[simp] theorem UInt8.toInt8_not (a : UInt8) : (~~~a).toInt8 = ~~~a.toInt8 := rfl
@[simp] theorem UInt16.toInt16_not (a : UInt16) : (~~~a).toInt16 = ~~~a.toInt16 := rfl
@[simp] theorem UInt32.toInt32_not (a : UInt32) : (~~~a).toInt32 = ~~~a.toInt32 := rfl
@[simp] theorem UInt64.toInt64_not (a : UInt64) : (~~~a).toInt64 = ~~~a.toInt64 := rfl
@[simp] theorem USize.toISize_not (a : USize) : (~~~a).toISize = ~~~a.toISize := rfl
@[simp] theorem UInt8.toInt8_not (a : UInt8) : (~~~a).toInt8 = ~~~a.toInt8 := (rfl)
@[simp] theorem UInt16.toInt16_not (a : UInt16) : (~~~a).toInt16 = ~~~a.toInt16 := (rfl)
@[simp] theorem UInt32.toInt32_not (a : UInt32) : (~~~a).toInt32 = ~~~a.toInt32 := (rfl)
@[simp] theorem UInt64.toInt64_not (a : UInt64) : (~~~a).toInt64 = ~~~a.toInt64 := (rfl)
@[simp] theorem USize.toISize_not (a : USize) : (~~~a).toISize = ~~~a.toISize := (rfl)
@[simp] theorem Int8.toUInt8_and (a b : Int8) : (a &&& b).toUInt8 = a.toUInt8 &&& b.toUInt8 := rfl
@[simp] theorem Int16.toUInt16_and (a b : Int16) : (a &&& b).toUInt16 = a.toUInt16 &&& b.toUInt16 := rfl
@[simp] theorem Int32.toUInt32_and (a b : Int32) : (a &&& b).toUInt32 = a.toUInt32 &&& b.toUInt32 := rfl
@[simp] theorem Int64.toUInt64_and (a b : Int64) : (a &&& b).toUInt64 = a.toUInt64 &&& b.toUInt64 := rfl
@[simp] theorem ISize.toUSize_and (a b : ISize) : (a &&& b).toUSize = a.toUSize &&& b.toUSize := rfl
@[simp] theorem Int8.toUInt8_and (a b : Int8) : (a &&& b).toUInt8 = a.toUInt8 &&& b.toUInt8 := (rfl)
@[simp] theorem Int16.toUInt16_and (a b : Int16) : (a &&& b).toUInt16 = a.toUInt16 &&& b.toUInt16 := (rfl)
@[simp] theorem Int32.toUInt32_and (a b : Int32) : (a &&& b).toUInt32 = a.toUInt32 &&& b.toUInt32 := (rfl)
@[simp] theorem Int64.toUInt64_and (a b : Int64) : (a &&& b).toUInt64 = a.toUInt64 &&& b.toUInt64 := (rfl)
@[simp] theorem ISize.toUSize_and (a b : ISize) : (a &&& b).toUSize = a.toUSize &&& b.toUSize := (rfl)
@[simp] theorem Int8.toUInt8_or (a b : Int8) : (a ||| b).toUInt8 = a.toUInt8 ||| b.toUInt8 := rfl
@[simp] theorem Int16.toUInt16_or (a b : Int16) : (a ||| b).toUInt16 = a.toUInt16 ||| b.toUInt16 := rfl
@[simp] theorem Int32.toUInt32_or (a b : Int32) : (a ||| b).toUInt32 = a.toUInt32 ||| b.toUInt32 := rfl
@[simp] theorem Int64.toUInt64_or (a b : Int64) : (a ||| b).toUInt64 = a.toUInt64 ||| b.toUInt64 := rfl
@[simp] theorem ISize.toUSize_or (a b : ISize) : (a ||| b).toUSize = a.toUSize ||| b.toUSize := rfl
@[simp] theorem Int8.toUInt8_or (a b : Int8) : (a ||| b).toUInt8 = a.toUInt8 ||| b.toUInt8 := (rfl)
@[simp] theorem Int16.toUInt16_or (a b : Int16) : (a ||| b).toUInt16 = a.toUInt16 ||| b.toUInt16 := (rfl)
@[simp] theorem Int32.toUInt32_or (a b : Int32) : (a ||| b).toUInt32 = a.toUInt32 ||| b.toUInt32 := (rfl)
@[simp] theorem Int64.toUInt64_or (a b : Int64) : (a ||| b).toUInt64 = a.toUInt64 ||| b.toUInt64 := (rfl)
@[simp] theorem ISize.toUSize_or (a b : ISize) : (a ||| b).toUSize = a.toUSize ||| b.toUSize := (rfl)
@[simp] theorem Int8.toUInt8_xor (a b : Int8) : (a ^^^ b).toUInt8 = a.toUInt8 ^^^ b.toUInt8 := rfl
@[simp] theorem Int16.toUInt16_xor (a b : Int16) : (a ^^^ b).toUInt16 = a.toUInt16 ^^^ b.toUInt16 := rfl
@[simp] theorem Int32.toUInt32_xor (a b : Int32) : (a ^^^ b).toUInt32 = a.toUInt32 ^^^ b.toUInt32 := rfl
@[simp] theorem Int64.toUInt64_xor (a b : Int64) : (a ^^^ b).toUInt64 = a.toUInt64 ^^^ b.toUInt64 := rfl
@[simp] theorem ISize.toUSize_xor (a b : ISize) : (a ^^^ b).toUSize = a.toUSize ^^^ b.toUSize := rfl
@[simp] theorem Int8.toUInt8_xor (a b : Int8) : (a ^^^ b).toUInt8 = a.toUInt8 ^^^ b.toUInt8 := (rfl)
@[simp] theorem Int16.toUInt16_xor (a b : Int16) : (a ^^^ b).toUInt16 = a.toUInt16 ^^^ b.toUInt16 := (rfl)
@[simp] theorem Int32.toUInt32_xor (a b : Int32) : (a ^^^ b).toUInt32 = a.toUInt32 ^^^ b.toUInt32 := (rfl)
@[simp] theorem Int64.toUInt64_xor (a b : Int64) : (a ^^^ b).toUInt64 = a.toUInt64 ^^^ b.toUInt64 := (rfl)
@[simp] theorem ISize.toUSize_xor (a b : ISize) : (a ^^^ b).toUSize = a.toUSize ^^^ b.toUSize := (rfl)
@[simp] theorem Int8.toUInt8_not (a : Int8) : (~~~a).toUInt8 = ~~~a.toUInt8 := rfl
@[simp] theorem Int16.toUInt16_not (a : Int16) : (~~~a).toUInt16 = ~~~a.toUInt16 := rfl
@[simp] theorem Int32.toUInt32_not (a : Int32) : (~~~a).toUInt32 = ~~~a.toUInt32 := rfl
@[simp] theorem Int64.toUInt64_not (a : Int64) : (~~~a).toUInt64 = ~~~a.toUInt64 := rfl
@[simp] theorem ISize.toUSize_not (a : ISize) : (~~~a).toUSize = ~~~a.toUSize := rfl
@[simp] theorem Int8.toUInt8_not (a : Int8) : (~~~a).toUInt8 = ~~~a.toUInt8 := (rfl)
@[simp] theorem Int16.toUInt16_not (a : Int16) : (~~~a).toUInt16 = ~~~a.toUInt16 := (rfl)
@[simp] theorem Int32.toUInt32_not (a : Int32) : (~~~a).toUInt32 = ~~~a.toUInt32 := (rfl)
@[simp] theorem Int64.toUInt64_not (a : Int64) : (~~~a).toUInt64 = ~~~a.toUInt64 := (rfl)
@[simp] theorem ISize.toUSize_not (a : ISize) : (~~~a).toUSize = ~~~a.toUSize := (rfl)
@[simp] theorem Int8.toInt16_and (a b : Int8) : (a &&& b).toInt16 = a.toInt16 &&& b.toInt16 := Int16.toBitVec_inj.1 (by simp)
@[simp] theorem Int8.toInt32_and (a b : Int8) : (a &&& b).toInt32 = a.toInt32 &&& b.toInt32 := Int32.toBitVec_inj.1 (by simp)
@@ -208,41 +208,41 @@ theorem ISize.not_eq_neg_add (a : ISize) : ~~~a = -a - 1 := ISize.toBitVec_inj.1
@[simp] theorem Int64.toISize_not (a : Int64) : (~~~a).toISize = ~~~a.toISize := ISize.toBitVec_inj.1 (by simp)
@[simp] theorem Int8.ofBitVec_and (a b : BitVec 8) : Int8.ofBitVec (a &&& b) = Int8.ofBitVec a &&& Int8.ofBitVec b := rfl
@[simp] theorem Int16.ofBitVec_and (a b : BitVec 16) : Int16.ofBitVec (a &&& b) = Int16.ofBitVec a &&& Int16.ofBitVec b := rfl
@[simp] theorem Int32.ofBitVec_and (a b : BitVec 32) : Int32.ofBitVec (a &&& b) = Int32.ofBitVec a &&& Int32.ofBitVec b := rfl
@[simp] theorem Int64.ofBitVec_and (a b : BitVec 64) : Int64.ofBitVec (a &&& b) = Int64.ofBitVec a &&& Int64.ofBitVec b := rfl
@[simp] theorem ISize.ofBitVec_and (a b : BitVec System.Platform.numBits) : ISize.ofBitVec (a &&& b) = ISize.ofBitVec a &&& ISize.ofBitVec b := rfl
@[simp] theorem Int8.ofBitVec_and (a b : BitVec 8) : Int8.ofBitVec (a &&& b) = Int8.ofBitVec a &&& Int8.ofBitVec b := (rfl)
@[simp] theorem Int16.ofBitVec_and (a b : BitVec 16) : Int16.ofBitVec (a &&& b) = Int16.ofBitVec a &&& Int16.ofBitVec b := (rfl)
@[simp] theorem Int32.ofBitVec_and (a b : BitVec 32) : Int32.ofBitVec (a &&& b) = Int32.ofBitVec a &&& Int32.ofBitVec b := (rfl)
@[simp] theorem Int64.ofBitVec_and (a b : BitVec 64) : Int64.ofBitVec (a &&& b) = Int64.ofBitVec a &&& Int64.ofBitVec b := (rfl)
@[simp] theorem ISize.ofBitVec_and (a b : BitVec System.Platform.numBits) : ISize.ofBitVec (a &&& b) = ISize.ofBitVec a &&& ISize.ofBitVec b := (rfl)
@[simp] theorem Int8.ofBitVec_or (a b : BitVec 8) : Int8.ofBitVec (a ||| b) = Int8.ofBitVec a ||| Int8.ofBitVec b := rfl
@[simp] theorem Int16.ofBitVec_or (a b : BitVec 16) : Int16.ofBitVec (a ||| b) = Int16.ofBitVec a ||| Int16.ofBitVec b := rfl
@[simp] theorem Int32.ofBitVec_or (a b : BitVec 32) : Int32.ofBitVec (a ||| b) = Int32.ofBitVec a ||| Int32.ofBitVec b := rfl
@[simp] theorem Int64.ofBitVec_or (a b : BitVec 64) : Int64.ofBitVec (a ||| b) = Int64.ofBitVec a ||| Int64.ofBitVec b := rfl
@[simp] theorem ISize.ofBitVec_or (a b : BitVec System.Platform.numBits) : ISize.ofBitVec (a ||| b) = ISize.ofBitVec a ||| ISize.ofBitVec b := rfl
@[simp] theorem Int8.ofBitVec_or (a b : BitVec 8) : Int8.ofBitVec (a ||| b) = Int8.ofBitVec a ||| Int8.ofBitVec b := (rfl)
@[simp] theorem Int16.ofBitVec_or (a b : BitVec 16) : Int16.ofBitVec (a ||| b) = Int16.ofBitVec a ||| Int16.ofBitVec b := (rfl)
@[simp] theorem Int32.ofBitVec_or (a b : BitVec 32) : Int32.ofBitVec (a ||| b) = Int32.ofBitVec a ||| Int32.ofBitVec b := (rfl)
@[simp] theorem Int64.ofBitVec_or (a b : BitVec 64) : Int64.ofBitVec (a ||| b) = Int64.ofBitVec a ||| Int64.ofBitVec b := (rfl)
@[simp] theorem ISize.ofBitVec_or (a b : BitVec System.Platform.numBits) : ISize.ofBitVec (a ||| b) = ISize.ofBitVec a ||| ISize.ofBitVec b := (rfl)
@[simp] theorem Int8.ofBitVec_xor (a b : BitVec 8) : Int8.ofBitVec (a ^^^ b) = Int8.ofBitVec a ^^^ Int8.ofBitVec b := rfl
@[simp] theorem Int16.ofBitVec_xor (a b : BitVec 16) : Int16.ofBitVec (a ^^^ b) = Int16.ofBitVec a ^^^ Int16.ofBitVec b := rfl
@[simp] theorem Int32.ofBitVec_xor (a b : BitVec 32) : Int32.ofBitVec (a ^^^ b) = Int32.ofBitVec a ^^^ Int32.ofBitVec b := rfl
@[simp] theorem Int64.ofBitVec_xor (a b : BitVec 64) : Int64.ofBitVec (a ^^^ b) = Int64.ofBitVec a ^^^ Int64.ofBitVec b := rfl
@[simp] theorem ISize.ofBitVec_xor (a b : BitVec System.Platform.numBits) : ISize.ofBitVec (a ^^^ b) = ISize.ofBitVec a ^^^ ISize.ofBitVec b := rfl
@[simp] theorem Int8.ofBitVec_xor (a b : BitVec 8) : Int8.ofBitVec (a ^^^ b) = Int8.ofBitVec a ^^^ Int8.ofBitVec b := (rfl)
@[simp] theorem Int16.ofBitVec_xor (a b : BitVec 16) : Int16.ofBitVec (a ^^^ b) = Int16.ofBitVec a ^^^ Int16.ofBitVec b := (rfl)
@[simp] theorem Int32.ofBitVec_xor (a b : BitVec 32) : Int32.ofBitVec (a ^^^ b) = Int32.ofBitVec a ^^^ Int32.ofBitVec b := (rfl)
@[simp] theorem Int64.ofBitVec_xor (a b : BitVec 64) : Int64.ofBitVec (a ^^^ b) = Int64.ofBitVec a ^^^ Int64.ofBitVec b := (rfl)
@[simp] theorem ISize.ofBitVec_xor (a b : BitVec System.Platform.numBits) : ISize.ofBitVec (a ^^^ b) = ISize.ofBitVec a ^^^ ISize.ofBitVec b := (rfl)
@[simp] theorem Int8.ofBitVec_not (a : BitVec 8) : Int8.ofBitVec (~~~a) = ~~~Int8.ofBitVec a := rfl
@[simp] theorem Int16.ofBitVec_not (a : BitVec 16) : Int16.ofBitVec (~~~a) = ~~~Int16.ofBitVec a := rfl
@[simp] theorem Int32.ofBitVec_not (a : BitVec 32) : Int32.ofBitVec (~~~a) = ~~~Int32.ofBitVec a := rfl
@[simp] theorem Int64.ofBitVec_not (a : BitVec 64) : Int64.ofBitVec (~~~a) = ~~~Int64.ofBitVec a := rfl
@[simp] theorem ISize.ofBitVec_not (a : BitVec System.Platform.numBits) : ISize.ofBitVec (~~~a) = ~~~ISize.ofBitVec a := rfl
@[simp] theorem Int8.ofBitVec_not (a : BitVec 8) : Int8.ofBitVec (~~~a) = ~~~Int8.ofBitVec a := (rfl)
@[simp] theorem Int16.ofBitVec_not (a : BitVec 16) : Int16.ofBitVec (~~~a) = ~~~Int16.ofBitVec a := (rfl)
@[simp] theorem Int32.ofBitVec_not (a : BitVec 32) : Int32.ofBitVec (~~~a) = ~~~Int32.ofBitVec a := (rfl)
@[simp] theorem Int64.ofBitVec_not (a : BitVec 64) : Int64.ofBitVec (~~~a) = ~~~Int64.ofBitVec a := (rfl)
@[simp] theorem ISize.ofBitVec_not (a : BitVec System.Platform.numBits) : ISize.ofBitVec (~~~a) = ~~~ISize.ofBitVec a := (rfl)
@[simp] theorem Int8.ofBitVec_intMin : Int8.ofBitVec (BitVec.intMin 8) = Int8.minValue := rfl
@[simp] theorem Int16.ofBitVec_intMin : Int16.ofBitVec (BitVec.intMin 16) = Int16.minValue := rfl
@[simp] theorem Int32.ofBitVec_intMin : Int32.ofBitVec (BitVec.intMin 32) = Int32.minValue := rfl
@[simp] theorem Int64.ofBitVec_intMin : Int64.ofBitVec (BitVec.intMin 64) = Int64.minValue := rfl
@[simp] theorem Int8.ofBitVec_intMin : Int8.ofBitVec (BitVec.intMin 8) = Int8.minValue := (rfl)
@[simp] theorem Int16.ofBitVec_intMin : Int16.ofBitVec (BitVec.intMin 16) = Int16.minValue := (rfl)
@[simp] theorem Int32.ofBitVec_intMin : Int32.ofBitVec (BitVec.intMin 32) = Int32.minValue := (rfl)
@[simp] theorem Int64.ofBitVec_intMin : Int64.ofBitVec (BitVec.intMin 64) = Int64.minValue := (rfl)
@[simp] theorem ISize.ofBitVec_intMin : ISize.ofBitVec (BitVec.intMin System.Platform.numBits) = ISize.minValue :=
ISize.toBitVec_inj.1 (by simp [BitVec.intMin_eq_neg_two_pow])
@[simp] theorem Int8.ofBitVec_intMax : Int8.ofBitVec (BitVec.intMax 8) = Int8.maxValue := rfl
@[simp] theorem Int16.ofBitVec_intMax : Int16.ofBitVec (BitVec.intMax 16) = Int16.maxValue := rfl
@[simp] theorem Int32.ofBitVec_intMax : Int32.ofBitVec (BitVec.intMax 32) = Int32.maxValue := rfl
@[simp] theorem Int64.ofBitVec_intMax : Int64.ofBitVec (BitVec.intMax 64) = Int64.maxValue := rfl
@[simp] theorem Int8.ofBitVec_intMax : Int8.ofBitVec (BitVec.intMax 8) = Int8.maxValue := (rfl)
@[simp] theorem Int16.ofBitVec_intMax : Int16.ofBitVec (BitVec.intMax 16) = Int16.maxValue := (rfl)
@[simp] theorem Int32.ofBitVec_intMax : Int32.ofBitVec (BitVec.intMax 32) = Int32.maxValue := (rfl)
@[simp] theorem Int64.ofBitVec_intMax : Int64.ofBitVec (BitVec.intMax 64) = Int64.maxValue := (rfl)
@[simp] theorem ISize.ofBitVec_intMax : ISize.ofBitVec (BitVec.intMax System.Platform.numBits) = ISize.maxValue :=
ISize.toInt_inj.1 (by rw [toInt_ofBitVec, BitVec.toInt_intMax, toInt_maxValue])
@@ -550,16 +550,16 @@ instance : Std.LawfulCommIdentity (α := ISize) (· ^^^ ·) 0 where
@[simp] theorem ISize.xor_right_inj {a b : ISize} (c : ISize) : (c ^^^ a = c ^^^ b) a = b := by
simp [ ISize.toBitVec_inj]
@[simp] theorem Int8.not_zero : ~~~(0 : Int8) = -1 := rfl
@[simp] theorem Int16.not_zero : ~~~(0 : Int16) = -1 := rfl
@[simp] theorem Int32.not_zero : ~~~(0 : Int32) = -1 := rfl
@[simp] theorem Int64.not_zero : ~~~(0 : Int64) = -1 := rfl
@[simp] theorem Int8.not_zero : ~~~(0 : Int8) = -1 := (rfl)
@[simp] theorem Int16.not_zero : ~~~(0 : Int16) = -1 := (rfl)
@[simp] theorem Int32.not_zero : ~~~(0 : Int32) = -1 := (rfl)
@[simp] theorem Int64.not_zero : ~~~(0 : Int64) = -1 := (rfl)
@[simp] theorem ISize.not_zero : ~~~(0 : ISize) = -1 := by simp [ISize.not_eq_neg_sub]
@[simp] theorem Int8.not_neg_one : ~~~(-1 : Int8) = 0 := rfl
@[simp] theorem Int16.not_neg_one : ~~~(-1 : Int16) = 0 := rfl
@[simp] theorem Int32.not_neg_one : ~~~(-1 : Int32) = 0 := rfl
@[simp] theorem Int64.not_neg_one : ~~~(-1 : Int64) = 0 := rfl
@[simp] theorem Int8.not_neg_one : ~~~(-1 : Int8) = 0 := (rfl)
@[simp] theorem Int16.not_neg_one : ~~~(-1 : Int16) = 0 := (rfl)
@[simp] theorem Int32.not_neg_one : ~~~(-1 : Int32) = 0 := (rfl)
@[simp] theorem Int64.not_neg_one : ~~~(-1 : Int64) = 0 := (rfl)
@[simp] theorem ISize.not_neg_one : ~~~(-1 : ISize) = 0 := by simp [ISize.not_eq_neg_sub]
@[simp] theorem Int8.not_not {a : Int8} : ~~~(~~~a) = a := by simp [ Int8.toBitVec_inj]

View File

@@ -31,14 +31,14 @@ macro "declare_int_theorems" typeName:ident _bits:term:arg : command => do
toBitVec_inj.symm
@[int_toBitVec] theorem ne_iff_toBitVec_ne {a b : $typeName} : a b a.toBitVec b.toBitVec :=
Decidable.not_iff_not.2 eq_iff_toBitVec_eq
@[simp] theorem toBitVec_ofNat' {n : Nat} : toBitVec (ofNat n) = BitVec.ofNat _ n := rfl
@[simp, int_toBitVec] theorem toBitVec_ofNat {n : Nat} : toBitVec (no_index (OfNat.ofNat n)) = OfNat.ofNat n := rfl
@[simp] theorem toBitVec_ofNat' {n : Nat} : toBitVec (ofNat n) = BitVec.ofNat _ n := (rfl)
@[simp, int_toBitVec] theorem toBitVec_ofNat {n : Nat} : toBitVec (no_index (OfNat.ofNat n)) = OfNat.ofNat n := (rfl)
@[simp, int_toBitVec] protected theorem toBitVec_add {a b : $typeName} : (a + b).toBitVec = a.toBitVec + b.toBitVec := rfl
@[simp, int_toBitVec] protected theorem toBitVec_sub {a b : $typeName} : (a - b).toBitVec = a.toBitVec - b.toBitVec := rfl
@[simp, int_toBitVec] protected theorem toBitVec_mul {a b : $typeName} : (a * b).toBitVec = a.toBitVec * b.toBitVec := rfl
@[simp, int_toBitVec] protected theorem toBitVec_div {a b : $typeName} : (a / b).toBitVec = a.toBitVec.sdiv b.toBitVec := rfl
@[simp, int_toBitVec] protected theorem toBitVec_mod {a b : $typeName} : (a % b).toBitVec = a.toBitVec.srem b.toBitVec := rfl
@[simp, int_toBitVec] protected theorem toBitVec_add {a b : $typeName} : (a + b).toBitVec = a.toBitVec + b.toBitVec := (rfl)
@[simp, int_toBitVec] protected theorem toBitVec_sub {a b : $typeName} : (a - b).toBitVec = a.toBitVec - b.toBitVec := (rfl)
@[simp, int_toBitVec] protected theorem toBitVec_mul {a b : $typeName} : (a * b).toBitVec = a.toBitVec * b.toBitVec := (rfl)
@[simp, int_toBitVec] protected theorem toBitVec_div {a b : $typeName} : (a / b).toBitVec = a.toBitVec.sdiv b.toBitVec := (rfl)
@[simp, int_toBitVec] protected theorem toBitVec_mod {a b : $typeName} : (a % b).toBitVec = a.toBitVec.srem b.toBitVec := (rfl)
end $typeName
)
@@ -83,34 +83,34 @@ theorem Int64.toInt_inj {x y : Int64} : x.toInt = y.toInt ↔ x = y := ⟨Int64.
theorem ISize.toInt.inj {x y : ISize} (h : x.toInt = y.toInt) : x = y := ISize.toBitVec.inj (BitVec.eq_of_toInt_eq h)
theorem ISize.toInt_inj {x y : ISize} : x.toInt = y.toInt x = y := ISize.toInt.inj, fun h => h rfl
@[simp] theorem Int8.toBitVec_neg (x : Int8) : (-x).toBitVec = -x.toBitVec := rfl
@[simp] theorem Int16.toBitVec_neg (x : Int16) : (-x).toBitVec = -x.toBitVec := rfl
@[simp] theorem Int32.toBitVec_neg (x : Int32) : (-x).toBitVec = -x.toBitVec := rfl
@[simp] theorem Int64.toBitVec_neg (x : Int64) : (-x).toBitVec = -x.toBitVec := rfl
@[simp] theorem ISize.toBitVec_neg (x : ISize) : (-x).toBitVec = -x.toBitVec := rfl
@[simp] theorem Int8.toBitVec_neg (x : Int8) : (-x).toBitVec = -x.toBitVec := (rfl)
@[simp] theorem Int16.toBitVec_neg (x : Int16) : (-x).toBitVec = -x.toBitVec := (rfl)
@[simp] theorem Int32.toBitVec_neg (x : Int32) : (-x).toBitVec = -x.toBitVec := (rfl)
@[simp] theorem Int64.toBitVec_neg (x : Int64) : (-x).toBitVec = -x.toBitVec := (rfl)
@[simp] theorem ISize.toBitVec_neg (x : ISize) : (-x).toBitVec = -x.toBitVec := (rfl)
@[simp] theorem Int8.toBitVec_zero : toBitVec 0 = 0#8 := rfl
@[simp] theorem Int16.toBitVec_zero : toBitVec 0 = 0#16 := rfl
@[simp] theorem Int32.toBitVec_zero : toBitVec 0 = 0#32 := rfl
@[simp] theorem Int64.toBitVec_zero : toBitVec 0 = 0#64 := rfl
@[simp] theorem ISize.toBitVec_zero : toBitVec 0 = 0#System.Platform.numBits := rfl
@[simp] theorem Int8.toBitVec_zero : toBitVec 0 = 0#8 := (rfl)
@[simp] theorem Int16.toBitVec_zero : toBitVec 0 = 0#16 := (rfl)
@[simp] theorem Int32.toBitVec_zero : toBitVec 0 = 0#32 := (rfl)
@[simp] theorem Int64.toBitVec_zero : toBitVec 0 = 0#64 := (rfl)
@[simp] theorem ISize.toBitVec_zero : toBitVec 0 = 0#System.Platform.numBits := (rfl)
theorem Int8.toBitVec_one : (1 : Int8).toBitVec = 1#8 := rfl
theorem Int16.toBitVec_one : (1 : Int16).toBitVec = 1#16 := rfl
theorem Int32.toBitVec_one : (1 : Int32).toBitVec = 1#32 := rfl
theorem Int64.toBitVec_one : (1 : Int64).toBitVec = 1#64 := rfl
theorem ISize.toBitVec_one : (1 : ISize).toBitVec = 1#System.Platform.numBits := rfl
theorem Int8.toBitVec_one : (1 : Int8).toBitVec = 1#8 := (rfl)
theorem Int16.toBitVec_one : (1 : Int16).toBitVec = 1#16 := (rfl)
theorem Int32.toBitVec_one : (1 : Int32).toBitVec = 1#32 := (rfl)
theorem Int64.toBitVec_one : (1 : Int64).toBitVec = 1#64 := (rfl)
theorem ISize.toBitVec_one : (1 : ISize).toBitVec = 1#System.Platform.numBits := (rfl)
@[simp] theorem Int8.toBitVec_ofInt (i : Int) : (ofInt i).toBitVec = BitVec.ofInt _ i := rfl
@[simp] theorem Int16.toBitVec_ofInt (i : Int) : (ofInt i).toBitVec = BitVec.ofInt _ i := rfl
@[simp] theorem Int32.toBitVec_ofInt (i : Int) : (ofInt i).toBitVec = BitVec.ofInt _ i := rfl
@[simp] theorem Int64.toBitVec_ofInt (i : Int) : (ofInt i).toBitVec = BitVec.ofInt _ i := rfl
@[simp] theorem ISize.toBitVec_ofInt (i : Int) : (ofInt i).toBitVec = BitVec.ofInt _ i := rfl
@[simp] theorem Int8.toBitVec_ofInt (i : Int) : (ofInt i).toBitVec = BitVec.ofInt _ i := (rfl)
@[simp] theorem Int16.toBitVec_ofInt (i : Int) : (ofInt i).toBitVec = BitVec.ofInt _ i := (rfl)
@[simp] theorem Int32.toBitVec_ofInt (i : Int) : (ofInt i).toBitVec = BitVec.ofInt _ i := (rfl)
@[simp] theorem Int64.toBitVec_ofInt (i : Int) : (ofInt i).toBitVec = BitVec.ofInt _ i := (rfl)
@[simp] theorem ISize.toBitVec_ofInt (i : Int) : (ofInt i).toBitVec = BitVec.ofInt _ i := (rfl)
@[simp] protected theorem Int8.neg_zero : -(0 : Int8) = 0 := rfl
@[simp] protected theorem Int16.neg_zero : -(0 : Int16) = 0 := rfl
@[simp] protected theorem Int32.neg_zero : -(0 : Int32) = 0 := rfl
@[simp] protected theorem Int64.neg_zero : -(0 : Int64) = 0 := rfl
@[simp] protected theorem Int8.neg_zero : -(0 : Int8) = 0 := (rfl)
@[simp] protected theorem Int16.neg_zero : -(0 : Int16) = 0 := (rfl)
@[simp] protected theorem Int32.neg_zero : -(0 : Int32) = 0 := (rfl)
@[simp] protected theorem Int64.neg_zero : -(0 : Int64) = 0 := (rfl)
@[simp] protected theorem ISize.neg_zero : -(0 : ISize) = 0 := ISize.toBitVec.inj (by simp)
theorem ISize.toNat_toBitVec_ofNat_of_lt {n : Nat} (h : n < 2^32) :
@@ -234,84 +234,84 @@ theorem Int32.toInt_zero : toInt 0 = 0 := by simp
theorem Int64.toInt_zero : toInt 0 = 0 := by simp
theorem ISize.toInt_zero : toInt 0 = 0 := by simp
theorem Int8.toInt_minValue : Int8.minValue.toInt = -2^7 := rfl
theorem Int16.toInt_minValue : Int16.minValue.toInt = -2^15 := rfl
theorem Int32.toInt_minValue : Int32.minValue.toInt = -2^31 := rfl
theorem Int64.toInt_minValue : Int64.minValue.toInt = -2^63 := rfl
theorem Int8.toInt_minValue : Int8.minValue.toInt = -2^7 := (rfl)
theorem Int16.toInt_minValue : Int16.minValue.toInt = -2^15 := (rfl)
theorem Int32.toInt_minValue : Int32.minValue.toInt = -2^31 := (rfl)
theorem Int64.toInt_minValue : Int64.minValue.toInt = -2^63 := (rfl)
theorem ISize.toInt_minValue : ISize.minValue.toInt = -2 ^ (System.Platform.numBits - 1) := by
rw [minValue, toInt_ofInt_of_two_pow_numBits_le] <;> cases System.Platform.numBits_eq
<;> simp_all
theorem Int8.toInt_maxValue : Int8.maxValue.toInt = 2 ^ 7 - 1 := rfl
theorem Int16.toInt_maxValue : Int16.maxValue.toInt = 2 ^ 15 - 1 := rfl
theorem Int32.toInt_maxValue : Int32.maxValue.toInt = 2 ^ 31 - 1 := rfl
theorem Int64.toInt_maxValue : Int64.maxValue.toInt = 2 ^ 63 - 1 := rfl
theorem Int8.toInt_maxValue : Int8.maxValue.toInt = 2 ^ 7 - 1 := (rfl)
theorem Int16.toInt_maxValue : Int16.maxValue.toInt = 2 ^ 15 - 1 := (rfl)
theorem Int32.toInt_maxValue : Int32.maxValue.toInt = 2 ^ 31 - 1 := (rfl)
theorem Int64.toInt_maxValue : Int64.maxValue.toInt = 2 ^ 63 - 1 := (rfl)
theorem ISize.toInt_maxValue : ISize.maxValue.toInt = 2 ^ (System.Platform.numBits - 1) - 1:= by
rw [maxValue, toInt_ofInt_of_two_pow_numBits_le] <;> cases System.Platform.numBits_eq
<;> simp_all
@[simp] theorem Int8.toNatClampNeg_minValue : Int8.minValue.toNatClampNeg = 0 := rfl
@[simp] theorem Int16.toNatClampNeg_minValue : Int16.minValue.toNatClampNeg = 0 := rfl
@[simp] theorem Int32.toNatClampNeg_minValue : Int32.minValue.toNatClampNeg = 0 := rfl
@[simp] theorem Int64.toNatClampNeg_minValue : Int64.minValue.toNatClampNeg = 0 := rfl
@[simp] theorem Int8.toNatClampNeg_minValue : Int8.minValue.toNatClampNeg = 0 := (rfl)
@[simp] theorem Int16.toNatClampNeg_minValue : Int16.minValue.toNatClampNeg = 0 := (rfl)
@[simp] theorem Int32.toNatClampNeg_minValue : Int32.minValue.toNatClampNeg = 0 := (rfl)
@[simp] theorem Int64.toNatClampNeg_minValue : Int64.minValue.toNatClampNeg = 0 := (rfl)
@[simp] theorem ISize.toNatClampNeg_minValue : ISize.minValue.toNatClampNeg = 0 := by
rw [toNatClampNeg, toInt_minValue]
cases System.Platform.numBits_eq <;> simp_all
@[simp] theorem UInt8.toBitVec_toInt8 (x : UInt8) : x.toInt8.toBitVec = x.toBitVec := rfl
@[simp] theorem UInt16.toBitVec_toInt16 (x : UInt16) : x.toInt16.toBitVec = x.toBitVec := rfl
@[simp] theorem UInt32.toBitVec_toInt32 (x : UInt32) : x.toInt32.toBitVec = x.toBitVec := rfl
@[simp] theorem UInt64.toBitVec_toInt64 (x : UInt64) : x.toInt64.toBitVec = x.toBitVec := rfl
@[simp] theorem USize.toBitVec_toISize (x : USize) : x.toISize.toBitVec = x.toBitVec := rfl
@[simp] theorem UInt8.toBitVec_toInt8 (x : UInt8) : x.toInt8.toBitVec = x.toBitVec := (rfl)
@[simp] theorem UInt16.toBitVec_toInt16 (x : UInt16) : x.toInt16.toBitVec = x.toBitVec := (rfl)
@[simp] theorem UInt32.toBitVec_toInt32 (x : UInt32) : x.toInt32.toBitVec = x.toBitVec := (rfl)
@[simp] theorem UInt64.toBitVec_toInt64 (x : UInt64) : x.toInt64.toBitVec = x.toBitVec := (rfl)
@[simp] theorem USize.toBitVec_toISize (x : USize) : x.toISize.toBitVec = x.toBitVec := (rfl)
@[simp] theorem Int8.ofBitVec_uInt8ToBitVec (x : UInt8) : Int8.ofBitVec x.toBitVec = x.toInt8 := rfl
@[simp] theorem Int16.ofBitVec_uInt16ToBitVec (x : UInt16) : Int16.ofBitVec x.toBitVec = x.toInt16 := rfl
@[simp] theorem Int32.ofBitVec_uInt32ToBitVec (x : UInt32) : Int32.ofBitVec x.toBitVec = x.toInt32 := rfl
@[simp] theorem Int64.ofBitVec_uInt64ToBitVec (x : UInt64) : Int64.ofBitVec x.toBitVec = x.toInt64 := rfl
@[simp] theorem ISize.ofBitVec_uSizeToBitVec (x : USize) : ISize.ofBitVec x.toBitVec = x.toISize := rfl
@[simp] theorem Int8.ofBitVec_uInt8ToBitVec (x : UInt8) : Int8.ofBitVec x.toBitVec = x.toInt8 := (rfl)
@[simp] theorem Int16.ofBitVec_uInt16ToBitVec (x : UInt16) : Int16.ofBitVec x.toBitVec = x.toInt16 := (rfl)
@[simp] theorem Int32.ofBitVec_uInt32ToBitVec (x : UInt32) : Int32.ofBitVec x.toBitVec = x.toInt32 := (rfl)
@[simp] theorem Int64.ofBitVec_uInt64ToBitVec (x : UInt64) : Int64.ofBitVec x.toBitVec = x.toInt64 := (rfl)
@[simp] theorem ISize.ofBitVec_uSizeToBitVec (x : USize) : ISize.ofBitVec x.toBitVec = x.toISize := (rfl)
@[simp] theorem UInt8.toUInt8_toInt8 (x : UInt8) : x.toInt8.toUInt8 = x := rfl
@[simp] theorem UInt16.toUInt16_toInt16 (x : UInt16) : x.toInt16.toUInt16 = x := rfl
@[simp] theorem UInt32.toUInt32_toInt32 (x : UInt32) : x.toInt32.toUInt32 = x := rfl
@[simp] theorem UInt64.toUInt64_toInt64 (x : UInt64) : x.toInt64.toUInt64 = x := rfl
@[simp] theorem USize.toUSize_toISize (x : USize) : x.toISize.toUSize = x := rfl
@[simp] theorem UInt8.toUInt8_toInt8 (x : UInt8) : x.toInt8.toUInt8 = x := (rfl)
@[simp] theorem UInt16.toUInt16_toInt16 (x : UInt16) : x.toInt16.toUInt16 = x := (rfl)
@[simp] theorem UInt32.toUInt32_toInt32 (x : UInt32) : x.toInt32.toUInt32 = x := (rfl)
@[simp] theorem UInt64.toUInt64_toInt64 (x : UInt64) : x.toInt64.toUInt64 = x := (rfl)
@[simp] theorem USize.toUSize_toISize (x : USize) : x.toISize.toUSize = x := (rfl)
@[simp] theorem Int8.toNat_toInt (x : Int8) : x.toInt.toNat = x.toNatClampNeg := rfl
@[simp] theorem Int16.toNat_toInt (x : Int16) : x.toInt.toNat = x.toNatClampNeg := rfl
@[simp] theorem Int32.toNat_toInt (x : Int32) : x.toInt.toNat = x.toNatClampNeg := rfl
@[simp] theorem Int64.toNat_toInt (x : Int64) : x.toInt.toNat = x.toNatClampNeg := rfl
@[simp] theorem ISize.toNat_toInt (x : ISize) : x.toInt.toNat = x.toNatClampNeg := rfl
@[simp] theorem Int8.toNat_toInt (x : Int8) : x.toInt.toNat = x.toNatClampNeg := (rfl)
@[simp] theorem Int16.toNat_toInt (x : Int16) : x.toInt.toNat = x.toNatClampNeg := (rfl)
@[simp] theorem Int32.toNat_toInt (x : Int32) : x.toInt.toNat = x.toNatClampNeg := (rfl)
@[simp] theorem Int64.toNat_toInt (x : Int64) : x.toInt.toNat = x.toNatClampNeg := (rfl)
@[simp] theorem ISize.toNat_toInt (x : ISize) : x.toInt.toNat = x.toNatClampNeg := (rfl)
@[simp] theorem Int8.toInt_toBitVec (x : Int8) : x.toBitVec.toInt = x.toInt := rfl
@[simp] theorem Int16.toInt_toBitVec (x : Int16) : x.toBitVec.toInt = x.toInt := rfl
@[simp] theorem Int32.toInt_toBitVec (x : Int32) : x.toBitVec.toInt = x.toInt := rfl
@[simp] theorem Int64.toInt_toBitVec (x : Int64) : x.toBitVec.toInt = x.toInt := rfl
@[simp] theorem ISize.toInt_toBitVec (x : ISize) : x.toBitVec.toInt = x.toInt := rfl
@[simp] theorem Int8.toInt_toBitVec (x : Int8) : x.toBitVec.toInt = x.toInt := (rfl)
@[simp] theorem Int16.toInt_toBitVec (x : Int16) : x.toBitVec.toInt = x.toInt := (rfl)
@[simp] theorem Int32.toInt_toBitVec (x : Int32) : x.toBitVec.toInt = x.toInt := (rfl)
@[simp] theorem Int64.toInt_toBitVec (x : Int64) : x.toBitVec.toInt = x.toInt := (rfl)
@[simp] theorem ISize.toInt_toBitVec (x : ISize) : x.toBitVec.toInt = x.toInt := (rfl)
@[simp] theorem Int8.toBitVec_toInt16 (x : Int8) : x.toInt16.toBitVec = x.toBitVec.signExtend 16 := rfl
@[simp] theorem Int8.toBitVec_toInt32 (x : Int8) : x.toInt32.toBitVec = x.toBitVec.signExtend 32 := rfl
@[simp] theorem Int8.toBitVec_toInt64 (x : Int8) : x.toInt64.toBitVec = x.toBitVec.signExtend 64 := rfl
@[simp] theorem Int8.toBitVec_toISize (x : Int8) : x.toISize.toBitVec = x.toBitVec.signExtend System.Platform.numBits := rfl
@[simp] theorem Int8.toBitVec_toInt16 (x : Int8) : x.toInt16.toBitVec = x.toBitVec.signExtend 16 := (rfl)
@[simp] theorem Int8.toBitVec_toInt32 (x : Int8) : x.toInt32.toBitVec = x.toBitVec.signExtend 32 := (rfl)
@[simp] theorem Int8.toBitVec_toInt64 (x : Int8) : x.toInt64.toBitVec = x.toBitVec.signExtend 64 := (rfl)
@[simp] theorem Int8.toBitVec_toISize (x : Int8) : x.toISize.toBitVec = x.toBitVec.signExtend System.Platform.numBits := (rfl)
@[simp] theorem Int16.toBitVec_toInt8 (x : Int16) : x.toInt8.toBitVec = x.toBitVec.signExtend 8 := rfl
@[simp] theorem Int16.toBitVec_toInt32 (x : Int16) : x.toInt32.toBitVec = x.toBitVec.signExtend 32 := rfl
@[simp] theorem Int16.toBitVec_toInt64 (x : Int16) : x.toInt64.toBitVec = x.toBitVec.signExtend 64 := rfl
@[simp] theorem Int16.toBitVec_toISize (x : Int16) : x.toISize.toBitVec = x.toBitVec.signExtend System.Platform.numBits := rfl
@[simp] theorem Int16.toBitVec_toInt8 (x : Int16) : x.toInt8.toBitVec = x.toBitVec.signExtend 8 := (rfl)
@[simp] theorem Int16.toBitVec_toInt32 (x : Int16) : x.toInt32.toBitVec = x.toBitVec.signExtend 32 := (rfl)
@[simp] theorem Int16.toBitVec_toInt64 (x : Int16) : x.toInt64.toBitVec = x.toBitVec.signExtend 64 := (rfl)
@[simp] theorem Int16.toBitVec_toISize (x : Int16) : x.toISize.toBitVec = x.toBitVec.signExtend System.Platform.numBits := (rfl)
@[simp] theorem Int32.toBitVec_toInt8 (x : Int32) : x.toInt8.toBitVec = x.toBitVec.signExtend 8 := rfl
@[simp] theorem Int32.toBitVec_toInt16 (x : Int32) : x.toInt16.toBitVec = x.toBitVec.signExtend 16 := rfl
@[simp] theorem Int32.toBitVec_toInt64 (x : Int32) : x.toInt64.toBitVec = x.toBitVec.signExtend 64 := rfl
@[simp] theorem Int32.toBitVec_toISize (x : Int32) : x.toISize.toBitVec = x.toBitVec.signExtend System.Platform.numBits := rfl
@[simp] theorem Int32.toBitVec_toInt8 (x : Int32) : x.toInt8.toBitVec = x.toBitVec.signExtend 8 := (rfl)
@[simp] theorem Int32.toBitVec_toInt16 (x : Int32) : x.toInt16.toBitVec = x.toBitVec.signExtend 16 := (rfl)
@[simp] theorem Int32.toBitVec_toInt64 (x : Int32) : x.toInt64.toBitVec = x.toBitVec.signExtend 64 := (rfl)
@[simp] theorem Int32.toBitVec_toISize (x : Int32) : x.toISize.toBitVec = x.toBitVec.signExtend System.Platform.numBits := (rfl)
@[simp] theorem Int64.toBitVec_toInt8 (x : Int64) : x.toInt8.toBitVec = x.toBitVec.signExtend 8 := rfl
@[simp] theorem Int64.toBitVec_toInt16 (x : Int64) : x.toInt16.toBitVec = x.toBitVec.signExtend 16 := rfl
@[simp] theorem Int64.toBitVec_toInt32 (x : Int64) : x.toInt32.toBitVec = x.toBitVec.signExtend 32 := rfl
@[simp] theorem Int64.toBitVec_toISize (x : Int64) : x.toISize.toBitVec = x.toBitVec.signExtend System.Platform.numBits := rfl
@[simp] theorem Int64.toBitVec_toInt8 (x : Int64) : x.toInt8.toBitVec = x.toBitVec.signExtend 8 := (rfl)
@[simp] theorem Int64.toBitVec_toInt16 (x : Int64) : x.toInt16.toBitVec = x.toBitVec.signExtend 16 := (rfl)
@[simp] theorem Int64.toBitVec_toInt32 (x : Int64) : x.toInt32.toBitVec = x.toBitVec.signExtend 32 := (rfl)
@[simp] theorem Int64.toBitVec_toISize (x : Int64) : x.toISize.toBitVec = x.toBitVec.signExtend System.Platform.numBits := (rfl)
@[simp] theorem ISize.toBitVec_toInt8 (x : ISize) : x.toInt8.toBitVec = x.toBitVec.signExtend 8 := rfl
@[simp] theorem ISize.toBitVec_toInt16 (x : ISize) : x.toInt16.toBitVec = x.toBitVec.signExtend 16 := rfl
@[simp] theorem ISize.toBitVec_toInt32 (x : ISize) : x.toInt32.toBitVec = x.toBitVec.signExtend 32 := rfl
@[simp] theorem ISize.toBitVec_toInt64 (x : ISize) : x.toInt64.toBitVec = x.toBitVec.signExtend 64 := rfl
@[simp] theorem ISize.toBitVec_toInt8 (x : ISize) : x.toInt8.toBitVec = x.toBitVec.signExtend 8 := (rfl)
@[simp] theorem ISize.toBitVec_toInt16 (x : ISize) : x.toInt16.toBitVec = x.toBitVec.signExtend 16 := (rfl)
@[simp] theorem ISize.toBitVec_toInt32 (x : ISize) : x.toInt32.toBitVec = x.toBitVec.signExtend 32 := (rfl)
@[simp] theorem ISize.toBitVec_toInt64 (x : ISize) : x.toInt64.toBitVec = x.toBitVec.signExtend 64 := (rfl)
theorem Int8.toInt_lt (x : Int8) : x.toInt < 2 ^ 7 := Int.lt_of_mul_lt_mul_left BitVec.two_mul_toInt_lt (by decide)
theorem Int8.le_toInt (x : Int8) : -2 ^ 7 x.toInt := Int.le_of_mul_le_mul_left BitVec.le_two_mul_toInt (by decide)
@@ -454,17 +454,17 @@ theorem ISize.toNatClampNeg_lt (x : ISize) : x.toNatClampNeg < 2 ^ 63 := (Int.to
@[simp] theorem ISize.toNatClampNeg_toInt64 (x : ISize) : x.toInt64.toNatClampNeg = x.toNatClampNeg :=
congrArg Int.toNat x.toInt_toInt64
@[simp] theorem Int8.toInt8_toUInt8 (x : Int8) : x.toUInt8.toInt8 = x := rfl
@[simp] theorem Int16.toInt16_toUInt16 (x : Int16) : x.toUInt16.toInt16 = x := rfl
@[simp] theorem Int32.toInt32_toUInt32 (x : Int32) : x.toUInt32.toInt32 = x := rfl
@[simp] theorem Int64.toInt64_toUInt64 (x : Int64) : x.toUInt64.toInt64 = x := rfl
@[simp] theorem ISize.toISize_toUSize (x : ISize) : x.toUSize.toISize = x := rfl
@[simp] theorem Int8.toInt8_toUInt8 (x : Int8) : x.toUInt8.toInt8 = x := (rfl)
@[simp] theorem Int16.toInt16_toUInt16 (x : Int16) : x.toUInt16.toInt16 = x := (rfl)
@[simp] theorem Int32.toInt32_toUInt32 (x : Int32) : x.toUInt32.toInt32 = x := (rfl)
@[simp] theorem Int64.toInt64_toUInt64 (x : Int64) : x.toUInt64.toInt64 = x := (rfl)
@[simp] theorem ISize.toISize_toUSize (x : ISize) : x.toUSize.toISize = x := (rfl)
theorem Int8.toNat_toBitVec (x : Int8) : x.toBitVec.toNat = x.toUInt8.toNat := rfl
theorem Int16.toNat_toBitVec (x : Int16) : x.toBitVec.toNat = x.toUInt16.toNat := rfl
theorem Int32.toNat_toBitVec (x : Int32) : x.toBitVec.toNat = x.toUInt32.toNat := rfl
theorem Int64.toNat_toBitVec (x : Int64) : x.toBitVec.toNat = x.toUInt64.toNat := rfl
theorem ISize.toNat_toBitVec (x : ISize) : x.toBitVec.toNat = x.toUSize.toNat := rfl
theorem Int8.toNat_toBitVec (x : Int8) : x.toBitVec.toNat = x.toUInt8.toNat := (rfl)
theorem Int16.toNat_toBitVec (x : Int16) : x.toBitVec.toNat = x.toUInt16.toNat := (rfl)
theorem Int32.toNat_toBitVec (x : Int32) : x.toBitVec.toNat = x.toUInt32.toNat := (rfl)
theorem Int64.toNat_toBitVec (x : Int64) : x.toBitVec.toNat = x.toUInt64.toNat := (rfl)
theorem ISize.toNat_toBitVec (x : ISize) : x.toBitVec.toNat = x.toUSize.toNat := (rfl)
theorem Int8.toNat_toBitVec_of_le {x : Int8} (hx : 0 x) : x.toBitVec.toNat = x.toNatClampNeg :=
(x.toBitVec.toNat_toInt_of_sle hx).symm
@@ -488,60 +488,60 @@ theorem Int64.toNat_toUInt64_of_le {x : Int64} (hx : 0 ≤ x) : x.toUInt64.toNat
theorem ISize.toNat_toUSize_of_le {x : ISize} (hx : 0 x) : x.toUSize.toNat = x.toNatClampNeg := by
rw [ toNat_toBitVec, toNat_toBitVec_of_le hx]
theorem Int8.toFin_toBitVec (x : Int8) : x.toBitVec.toFin = x.toUInt8.toFin := rfl
theorem Int16.toFin_toBitVec (x : Int16) : x.toBitVec.toFin = x.toUInt16.toFin := rfl
theorem Int32.toFin_toBitVec (x : Int32) : x.toBitVec.toFin = x.toUInt32.toFin := rfl
theorem Int64.toFin_toBitVec (x : Int64) : x.toBitVec.toFin = x.toUInt64.toFin := rfl
theorem ISize.toFin_toBitVec (x : ISize) : x.toBitVec.toFin = x.toUSize.toFin := rfl
theorem Int8.toFin_toBitVec (x : Int8) : x.toBitVec.toFin = x.toUInt8.toFin := (rfl)
theorem Int16.toFin_toBitVec (x : Int16) : x.toBitVec.toFin = x.toUInt16.toFin := (rfl)
theorem Int32.toFin_toBitVec (x : Int32) : x.toBitVec.toFin = x.toUInt32.toFin := (rfl)
theorem Int64.toFin_toBitVec (x : Int64) : x.toBitVec.toFin = x.toUInt64.toFin := (rfl)
theorem ISize.toFin_toBitVec (x : ISize) : x.toBitVec.toFin = x.toUSize.toFin := (rfl)
@[simp] theorem Int8.toBitVec_toUInt8 (x : Int8) : x.toUInt8.toBitVec = x.toBitVec := rfl
@[simp] theorem Int16.toBitVec_toUInt16 (x : Int16) : x.toUInt16.toBitVec = x.toBitVec := rfl
@[simp] theorem Int32.toBitVec_toUInt32 (x : Int32) : x.toUInt32.toBitVec = x.toBitVec := rfl
@[simp] theorem Int64.toBitVec_toUInt64 (x : Int64) : x.toUInt64.toBitVec = x.toBitVec := rfl
@[simp] theorem ISize.toBitVec_toUSize (x : ISize) : x.toUSize.toBitVec = x.toBitVec := rfl
@[simp] theorem Int8.toBitVec_toUInt8 (x : Int8) : x.toUInt8.toBitVec = x.toBitVec := (rfl)
@[simp] theorem Int16.toBitVec_toUInt16 (x : Int16) : x.toUInt16.toBitVec = x.toBitVec := (rfl)
@[simp] theorem Int32.toBitVec_toUInt32 (x : Int32) : x.toUInt32.toBitVec = x.toBitVec := (rfl)
@[simp] theorem Int64.toBitVec_toUInt64 (x : Int64) : x.toUInt64.toBitVec = x.toBitVec := (rfl)
@[simp] theorem ISize.toBitVec_toUSize (x : ISize) : x.toUSize.toBitVec = x.toBitVec := (rfl)
@[simp] theorem UInt8.ofBitVec_int8ToBitVec (x : Int8) : UInt8.ofBitVec x.toBitVec = x.toUInt8 := rfl
@[simp] theorem UInt16.ofBitVec_int16ToBitVec (x : Int16) : UInt16.ofBitVec x.toBitVec = x.toUInt16 := rfl
@[simp] theorem UInt32.ofBitVec_int32ToBitVec (x : Int32) : UInt32.ofBitVec x.toBitVec = x.toUInt32 := rfl
@[simp] theorem UInt64.ofBitVec_int64ToBitVec (x : Int64) : UInt64.ofBitVec x.toBitVec = x.toUInt64 := rfl
@[simp] theorem USize.ofBitVec_iSizeToBitVec (x : ISize) : USize.ofBitVec x.toBitVec = x.toUSize := rfl
@[simp] theorem UInt8.ofBitVec_int8ToBitVec (x : Int8) : UInt8.ofBitVec x.toBitVec = x.toUInt8 := (rfl)
@[simp] theorem UInt16.ofBitVec_int16ToBitVec (x : Int16) : UInt16.ofBitVec x.toBitVec = x.toUInt16 := (rfl)
@[simp] theorem UInt32.ofBitVec_int32ToBitVec (x : Int32) : UInt32.ofBitVec x.toBitVec = x.toUInt32 := (rfl)
@[simp] theorem UInt64.ofBitVec_int64ToBitVec (x : Int64) : UInt64.ofBitVec x.toBitVec = x.toUInt64 := (rfl)
@[simp] theorem USize.ofBitVec_iSizeToBitVec (x : ISize) : USize.ofBitVec x.toBitVec = x.toUSize := (rfl)
@[simp] theorem Int8.ofBitVec_toBitVec (x : Int8) : Int8.ofBitVec x.toBitVec = x := rfl
@[simp] theorem Int16.ofBitVec_toBitVec (x : Int16) : Int16.ofBitVec x.toBitVec = x := rfl
@[simp] theorem Int32.ofBitVec_toBitVec (x : Int32) : Int32.ofBitVec x.toBitVec = x := rfl
@[simp] theorem Int64.ofBitVec_toBitVec (x : Int64) : Int64.ofBitVec x.toBitVec = x := rfl
@[simp] theorem ISize.ofBitVec_toBitVec (x : ISize) : ISize.ofBitVec x.toBitVec = x := rfl
@[simp] theorem Int8.ofBitVec_toBitVec (x : Int8) : Int8.ofBitVec x.toBitVec = x := (rfl)
@[simp] theorem Int16.ofBitVec_toBitVec (x : Int16) : Int16.ofBitVec x.toBitVec = x := (rfl)
@[simp] theorem Int32.ofBitVec_toBitVec (x : Int32) : Int32.ofBitVec x.toBitVec = x := (rfl)
@[simp] theorem Int64.ofBitVec_toBitVec (x : Int64) : Int64.ofBitVec x.toBitVec = x := (rfl)
@[simp] theorem ISize.ofBitVec_toBitVec (x : ISize) : ISize.ofBitVec x.toBitVec = x := (rfl)
@[simp] theorem Int8.ofBitVec_int16ToBitVec (x : Int16) : Int8.ofBitVec (x.toBitVec.signExtend 8) = x.toInt8 := rfl
@[simp] theorem Int8.ofBitVec_int32ToBitVec (x : Int32) : Int8.ofBitVec (x.toBitVec.signExtend 8) = x.toInt8 := rfl
@[simp] theorem Int8.ofBitVec_int64ToBitVec (x : Int64) : Int8.ofBitVec (x.toBitVec.signExtend 8) = x.toInt8 := rfl
@[simp] theorem Int8.ofBitVec_iSizeToBitVec (x : ISize) : Int8.ofBitVec (x.toBitVec.signExtend 8) = x.toInt8 := rfl
@[simp] theorem Int8.ofBitVec_int16ToBitVec (x : Int16) : Int8.ofBitVec (x.toBitVec.signExtend 8) = x.toInt8 := (rfl)
@[simp] theorem Int8.ofBitVec_int32ToBitVec (x : Int32) : Int8.ofBitVec (x.toBitVec.signExtend 8) = x.toInt8 := (rfl)
@[simp] theorem Int8.ofBitVec_int64ToBitVec (x : Int64) : Int8.ofBitVec (x.toBitVec.signExtend 8) = x.toInt8 := (rfl)
@[simp] theorem Int8.ofBitVec_iSizeToBitVec (x : ISize) : Int8.ofBitVec (x.toBitVec.signExtend 8) = x.toInt8 := (rfl)
@[simp] theorem Int16.ofBitVec_int8ToBitVec (x : Int8) : Int16.ofBitVec (x.toBitVec.signExtend 16) = x.toInt16 := rfl
@[simp] theorem Int16.ofBitVec_int32ToBitVec (x : Int32) : Int16.ofBitVec (x.toBitVec.signExtend 16) = x.toInt16 := rfl
@[simp] theorem Int16.ofBitVec_int64ToBitVec (x : Int64) : Int16.ofBitVec (x.toBitVec.signExtend 16) = x.toInt16 := rfl
@[simp] theorem Int16.ofBitVec_iSizeToBitVec (x : ISize) : Int16.ofBitVec (x.toBitVec.signExtend 16) = x.toInt16 := rfl
@[simp] theorem Int16.ofBitVec_int8ToBitVec (x : Int8) : Int16.ofBitVec (x.toBitVec.signExtend 16) = x.toInt16 := (rfl)
@[simp] theorem Int16.ofBitVec_int32ToBitVec (x : Int32) : Int16.ofBitVec (x.toBitVec.signExtend 16) = x.toInt16 := (rfl)
@[simp] theorem Int16.ofBitVec_int64ToBitVec (x : Int64) : Int16.ofBitVec (x.toBitVec.signExtend 16) = x.toInt16 := (rfl)
@[simp] theorem Int16.ofBitVec_iSizeToBitVec (x : ISize) : Int16.ofBitVec (x.toBitVec.signExtend 16) = x.toInt16 := (rfl)
@[simp] theorem Int32.ofBitVec_int8ToBitVec (x : Int8) : Int32.ofBitVec (x.toBitVec.signExtend 32) = x.toInt32 := rfl
@[simp] theorem Int32.ofBitVec_int16ToBitVec (x : Int16) : Int32.ofBitVec (x.toBitVec.signExtend 32) = x.toInt32 := rfl
@[simp] theorem Int32.ofBitVec_int64ToBitVec (x : Int64) : Int32.ofBitVec (x.toBitVec.signExtend 32) = x.toInt32 := rfl
@[simp] theorem Int32.ofBitVec_iSizeToBitVec (x : ISize) : Int32.ofBitVec (x.toBitVec.signExtend 32) = x.toInt32 := rfl
@[simp] theorem Int32.ofBitVec_int8ToBitVec (x : Int8) : Int32.ofBitVec (x.toBitVec.signExtend 32) = x.toInt32 := (rfl)
@[simp] theorem Int32.ofBitVec_int16ToBitVec (x : Int16) : Int32.ofBitVec (x.toBitVec.signExtend 32) = x.toInt32 := (rfl)
@[simp] theorem Int32.ofBitVec_int64ToBitVec (x : Int64) : Int32.ofBitVec (x.toBitVec.signExtend 32) = x.toInt32 := (rfl)
@[simp] theorem Int32.ofBitVec_iSizeToBitVec (x : ISize) : Int32.ofBitVec (x.toBitVec.signExtend 32) = x.toInt32 := (rfl)
@[simp] theorem Int64.ofBitVec_int8ToBitVec (x : Int8) : Int64.ofBitVec (x.toBitVec.signExtend 64) = x.toInt64 := rfl
@[simp] theorem Int64.ofBitVec_int16ToBitVec (x : Int16) : Int64.ofBitVec (x.toBitVec.signExtend 64) = x.toInt64 := rfl
@[simp] theorem Int64.ofBitVec_int32ToBitVec (x : Int32) : Int64.ofBitVec (x.toBitVec.signExtend 64) = x.toInt64 := rfl
@[simp] theorem Int64.ofBitVec_iSizeToBitVec (x : ISize) : Int64.ofBitVec (x.toBitVec.signExtend 64) = x.toInt64 := rfl
@[simp] theorem Int64.ofBitVec_int8ToBitVec (x : Int8) : Int64.ofBitVec (x.toBitVec.signExtend 64) = x.toInt64 := (rfl)
@[simp] theorem Int64.ofBitVec_int16ToBitVec (x : Int16) : Int64.ofBitVec (x.toBitVec.signExtend 64) = x.toInt64 := (rfl)
@[simp] theorem Int64.ofBitVec_int32ToBitVec (x : Int32) : Int64.ofBitVec (x.toBitVec.signExtend 64) = x.toInt64 := (rfl)
@[simp] theorem Int64.ofBitVec_iSizeToBitVec (x : ISize) : Int64.ofBitVec (x.toBitVec.signExtend 64) = x.toInt64 := (rfl)
@[simp] theorem ISize.ofBitVec_int8ToBitVec (x : Int8) : ISize.ofBitVec (x.toBitVec.signExtend System.Platform.numBits) = x.toISize := rfl
@[simp] theorem ISize.ofBitVec_int16ToBitVec (x : Int16) : ISize.ofBitVec (x.toBitVec.signExtend System.Platform.numBits) = x.toISize := rfl
@[simp] theorem ISize.ofBitVec_int32ToBitVec (x : Int32) : ISize.ofBitVec (x.toBitVec.signExtend System.Platform.numBits) = x.toISize := rfl
@[simp] theorem ISize.ofBitVec_int64ToBitVec (x : Int64) : ISize.ofBitVec (x.toBitVec.signExtend System.Platform.numBits) = x.toISize := rfl
@[simp] theorem ISize.ofBitVec_int8ToBitVec (x : Int8) : ISize.ofBitVec (x.toBitVec.signExtend System.Platform.numBits) = x.toISize := (rfl)
@[simp] theorem ISize.ofBitVec_int16ToBitVec (x : Int16) : ISize.ofBitVec (x.toBitVec.signExtend System.Platform.numBits) = x.toISize := (rfl)
@[simp] theorem ISize.ofBitVec_int32ToBitVec (x : Int32) : ISize.ofBitVec (x.toBitVec.signExtend System.Platform.numBits) = x.toISize := (rfl)
@[simp] theorem ISize.ofBitVec_int64ToBitVec (x : Int64) : ISize.ofBitVec (x.toBitVec.signExtend System.Platform.numBits) = x.toISize := (rfl)
@[simp] theorem Int8.toBitVec_ofIntLE (x : Int) (h₁ h₂) : (Int8.ofIntLE x h₁ h₂).toBitVec = BitVec.ofInt 8 x := rfl
@[simp] theorem Int16.toBitVec_ofIntLE (x : Int) (h₁ h₂) : (Int16.ofIntLE x h₁ h₂).toBitVec = BitVec.ofInt 16 x := rfl
@[simp] theorem Int32.toBitVec_ofIntLE (x : Int) (h₁ h₂) : (Int32.ofIntLE x h₁ h₂).toBitVec = BitVec.ofInt 32 x := rfl
@[simp] theorem Int64.toBitVec_ofIntLE (x : Int) (h₁ h₂) : (Int64.ofIntLE x h₁ h₂).toBitVec = BitVec.ofInt 64 x := rfl
@[simp] theorem ISize.toBitVec_ofIntLE (x : Int) (h₁ h₂) : (ISize.ofIntLE x h₁ h₂).toBitVec = BitVec.ofInt System.Platform.numBits x := rfl
@[simp] theorem Int8.toBitVec_ofIntLE (x : Int) (h₁ h₂) : (Int8.ofIntLE x h₁ h₂).toBitVec = BitVec.ofInt 8 x := (rfl)
@[simp] theorem Int16.toBitVec_ofIntLE (x : Int) (h₁ h₂) : (Int16.ofIntLE x h₁ h₂).toBitVec = BitVec.ofInt 16 x := (rfl)
@[simp] theorem Int32.toBitVec_ofIntLE (x : Int) (h₁ h₂) : (Int32.ofIntLE x h₁ h₂).toBitVec = BitVec.ofInt 32 x := (rfl)
@[simp] theorem Int64.toBitVec_ofIntLE (x : Int) (h₁ h₂) : (Int64.ofIntLE x h₁ h₂).toBitVec = BitVec.ofInt 64 x := (rfl)
@[simp] theorem ISize.toBitVec_ofIntLE (x : Int) (h₁ h₂) : (ISize.ofIntLE x h₁ h₂).toBitVec = BitVec.ofInt System.Platform.numBits x := (rfl)
@[simp] theorem Int8.toInt_bmod (x : Int8) : x.toInt.bmod 256 = x.toInt := Int.bmod_eq_of_le x.le_toInt x.toInt_lt
@[simp] theorem Int16.toInt_bmod (x : Int16) : x.toInt.bmod 65536 = x.toInt := Int.bmod_eq_of_le x.le_toInt x.toInt_lt
@@ -594,40 +594,40 @@ theorem ISize.toFin_toBitVec (x : ISize) : x.toBitVec.toFin = x.toUSize.toFin :=
@[simp] theorem Int64.ofIntLE_toInt (x : Int64) : Int64.ofIntLE x.toInt x.minValue_le_toInt x.toInt_le = x := Int64.toBitVec.inj (by simp)
@[simp] theorem ISize.ofIntLE_toInt (x : ISize) : ISize.ofIntLE x.toInt x.minValue_le_toInt x.toInt_le = x := ISize.toBitVec.inj (by simp)
theorem Int8.ofIntLE_int16ToInt (x : Int16) {h₁ h₂} : Int8.ofIntLE x.toInt h₁ h₂ = x.toInt8 := rfl
theorem Int8.ofIntLE_int32ToInt (x : Int32) {h₁ h₂} : Int8.ofIntLE x.toInt h₁ h₂ = x.toInt8 := rfl
theorem Int8.ofIntLE_int64ToInt (x : Int64) {h₁ h₂} : Int8.ofIntLE x.toInt h₁ h₂ = x.toInt8 := rfl
theorem Int8.ofIntLE_iSizeToInt (x : ISize) {h₁ h₂} : Int8.ofIntLE x.toInt h₁ h₂ = x.toInt8 := rfl
theorem Int8.ofIntLE_int16ToInt (x : Int16) {h₁ h₂} : Int8.ofIntLE x.toInt h₁ h₂ = x.toInt8 := (rfl)
theorem Int8.ofIntLE_int32ToInt (x : Int32) {h₁ h₂} : Int8.ofIntLE x.toInt h₁ h₂ = x.toInt8 := (rfl)
theorem Int8.ofIntLE_int64ToInt (x : Int64) {h₁ h₂} : Int8.ofIntLE x.toInt h₁ h₂ = x.toInt8 := (rfl)
theorem Int8.ofIntLE_iSizeToInt (x : ISize) {h₁ h₂} : Int8.ofIntLE x.toInt h₁ h₂ = x.toInt8 := (rfl)
@[simp] theorem Int16.ofIntLE_int8ToInt (x : Int8) :
Int16.ofIntLE x.toInt (Int.le_trans (by decide) x.minValue_le_toInt) (Int.le_trans x.toInt_le (by decide)) = x.toInt16 := rfl
theorem Int16.ofIntLE_int32ToInt (x : Int32) {h₁ h₂} : Int16.ofIntLE x.toInt h₁ h₂ = x.toInt16 := rfl
theorem Int16.ofIntLE_int64ToInt (x : Int64) {h₁ h₂} : Int16.ofIntLE x.toInt h₁ h₂ = x.toInt16 := rfl
theorem Int16.ofIntLE_iSizeToInt (x : ISize) {h₁ h₂} : Int16.ofIntLE x.toInt h₁ h₂ = x.toInt16 := rfl
Int16.ofIntLE x.toInt (Int.le_trans (by decide) x.minValue_le_toInt) (Int.le_trans x.toInt_le (by decide)) = x.toInt16 := (rfl)
theorem Int16.ofIntLE_int32ToInt (x : Int32) {h₁ h₂} : Int16.ofIntLE x.toInt h₁ h₂ = x.toInt16 := (rfl)
theorem Int16.ofIntLE_int64ToInt (x : Int64) {h₁ h₂} : Int16.ofIntLE x.toInt h₁ h₂ = x.toInt16 := (rfl)
theorem Int16.ofIntLE_iSizeToInt (x : ISize) {h₁ h₂} : Int16.ofIntLE x.toInt h₁ h₂ = x.toInt16 := (rfl)
@[simp] theorem Int32.ofIntLE_int8ToInt (x : Int8) :
Int32.ofIntLE x.toInt (Int.le_trans (by decide) x.minValue_le_toInt) (Int.le_trans x.toInt_le (by decide)) = x.toInt32 := rfl
Int32.ofIntLE x.toInt (Int.le_trans (by decide) x.minValue_le_toInt) (Int.le_trans x.toInt_le (by decide)) = x.toInt32 := (rfl)
@[simp] theorem Int32.ofIntLE_int16ToInt (x : Int16) :
Int32.ofIntLE x.toInt (Int.le_trans (by decide) x.minValue_le_toInt) (Int.le_trans x.toInt_le (by decide)) = x.toInt32 := rfl
theorem Int32.ofIntLE_int64ToInt (x : Int64) {h₁ h₂} : Int32.ofIntLE x.toInt h₁ h₂ = x.toInt32 := rfl
theorem Int32.ofIntLE_iSizeToInt (x : ISize) {h₁ h₂} : Int32.ofIntLE x.toInt h₁ h₂ = x.toInt32 := rfl
Int32.ofIntLE x.toInt (Int.le_trans (by decide) x.minValue_le_toInt) (Int.le_trans x.toInt_le (by decide)) = x.toInt32 := (rfl)
theorem Int32.ofIntLE_int64ToInt (x : Int64) {h₁ h₂} : Int32.ofIntLE x.toInt h₁ h₂ = x.toInt32 := (rfl)
theorem Int32.ofIntLE_iSizeToInt (x : ISize) {h₁ h₂} : Int32.ofIntLE x.toInt h₁ h₂ = x.toInt32 := (rfl)
@[simp] theorem Int64.ofIntLE_int8ToInt (x : Int8) :
Int64.ofIntLE x.toInt (Int.le_trans (by decide) x.minValue_le_toInt) (Int.le_trans x.toInt_le (by decide)) = x.toInt64 := rfl
Int64.ofIntLE x.toInt (Int.le_trans (by decide) x.minValue_le_toInt) (Int.le_trans x.toInt_le (by decide)) = x.toInt64 := (rfl)
@[simp] theorem Int64.ofIntLE_int16ToInt (x : Int16) :
Int64.ofIntLE x.toInt (Int.le_trans (by decide) x.minValue_le_toInt) (Int.le_trans x.toInt_le (by decide)) = x.toInt64 := rfl
Int64.ofIntLE x.toInt (Int.le_trans (by decide) x.minValue_le_toInt) (Int.le_trans x.toInt_le (by decide)) = x.toInt64 := (rfl)
@[simp] theorem Int64.ofIntLE_int32ToInt (x : Int32) :
Int64.ofIntLE x.toInt (Int.le_trans (by decide) x.minValue_le_toInt) (Int.le_trans x.toInt_le (by decide)) = x.toInt64 := rfl
Int64.ofIntLE x.toInt (Int.le_trans (by decide) x.minValue_le_toInt) (Int.le_trans x.toInt_le (by decide)) = x.toInt64 := (rfl)
@[simp] theorem Int64.ofIntLE_iSizeToInt (x : ISize) :
Int64.ofIntLE x.toInt x.int64MinValue_le_toInt x.toInt_le_int64MaxValue = x.toInt64 := rfl
Int64.ofIntLE x.toInt x.int64MinValue_le_toInt x.toInt_le_int64MaxValue = x.toInt64 := (rfl)
@[simp] theorem ISize.ofIntLE_int8ToInt (x : Int8) :
ISize.ofIntLE x.toInt x.iSizeMinValue_le_toInt x.toInt_le_iSizeMaxValue = x.toISize := rfl
ISize.ofIntLE x.toInt x.iSizeMinValue_le_toInt x.toInt_le_iSizeMaxValue = x.toISize := (rfl)
@[simp] theorem ISize.ofIntLE_int16ToInt (x : Int16) :
ISize.ofIntLE x.toInt x.iSizeMinValue_le_toInt x.toInt_le_iSizeMaxValue = x.toISize := rfl
ISize.ofIntLE x.toInt x.iSizeMinValue_le_toInt x.toInt_le_iSizeMaxValue = x.toISize := (rfl)
@[simp] theorem ISize.ofIntLE_int32ToInt (x : Int32) :
ISize.ofIntLE x.toInt x.iSizeMinValue_le_toInt x.toInt_le_iSizeMaxValue = x.toISize := rfl
theorem ISize.ofIntLE_int64ToInt (x : Int64) {h₁ h₂} : ISize.ofIntLE x.toInt h₁ h₂ = x.toISize := rfl
ISize.ofIntLE x.toInt x.iSizeMinValue_le_toInt x.toInt_le_iSizeMaxValue = x.toISize := (rfl)
theorem ISize.ofIntLE_int64ToInt (x : Int64) {h₁ h₂} : ISize.ofIntLE x.toInt h₁ h₂ = x.toISize := (rfl)
@[simp] theorem Int8.ofInt_toInt (x : Int8) : Int8.ofInt x.toInt = x := Int8.toBitVec.inj (by simp)
@[simp] theorem Int16.ofInt_toInt (x : Int16) : Int16.ofInt x.toInt = x := Int16.toBitVec.inj (by simp)
@@ -635,30 +635,30 @@ theorem ISize.ofIntLE_int64ToInt (x : Int64) {h₁ h₂} : ISize.ofIntLE x.toInt
@[simp] theorem Int64.ofInt_toInt (x : Int64) : Int64.ofInt x.toInt = x := Int64.toBitVec.inj (by simp)
@[simp] theorem ISize.ofInt_toInt (x : ISize) : ISize.ofInt x.toInt = x := ISize.toBitVec.inj (by simp)
@[simp] theorem Int8.ofInt_int16ToInt (x : Int16) : Int8.ofInt x.toInt = x.toInt8 := rfl
@[simp] theorem Int8.ofInt_int32ToInt (x : Int32) : Int8.ofInt x.toInt = x.toInt8 := rfl
@[simp] theorem Int8.ofInt_int64ToInt (x : Int64) : Int8.ofInt x.toInt = x.toInt8 := rfl
@[simp] theorem Int8.ofInt_iSizeToInt (x : ISize) : Int8.ofInt x.toInt = x.toInt8 := rfl
@[simp] theorem Int8.ofInt_int16ToInt (x : Int16) : Int8.ofInt x.toInt = x.toInt8 := (rfl)
@[simp] theorem Int8.ofInt_int32ToInt (x : Int32) : Int8.ofInt x.toInt = x.toInt8 := (rfl)
@[simp] theorem Int8.ofInt_int64ToInt (x : Int64) : Int8.ofInt x.toInt = x.toInt8 := (rfl)
@[simp] theorem Int8.ofInt_iSizeToInt (x : ISize) : Int8.ofInt x.toInt = x.toInt8 := (rfl)
@[simp] theorem Int16.ofInt_int8ToInt (x : Int8) : Int16.ofInt x.toInt = x.toInt16 := rfl
@[simp] theorem Int16.ofInt_int32ToInt (x : Int32) : Int16.ofInt x.toInt = x.toInt16 := rfl
@[simp] theorem Int16.ofInt_int64ToInt (x : Int64) : Int16.ofInt x.toInt = x.toInt16 := rfl
@[simp] theorem Int16.ofInt_iSizeToInt (x : ISize) : Int16.ofInt x.toInt = x.toInt16 := rfl
@[simp] theorem Int16.ofInt_int8ToInt (x : Int8) : Int16.ofInt x.toInt = x.toInt16 := (rfl)
@[simp] theorem Int16.ofInt_int32ToInt (x : Int32) : Int16.ofInt x.toInt = x.toInt16 := (rfl)
@[simp] theorem Int16.ofInt_int64ToInt (x : Int64) : Int16.ofInt x.toInt = x.toInt16 := (rfl)
@[simp] theorem Int16.ofInt_iSizeToInt (x : ISize) : Int16.ofInt x.toInt = x.toInt16 := (rfl)
@[simp] theorem Int32.ofInt_int8ToInt (x : Int8) : Int32.ofInt x.toInt = x.toInt32 := rfl
@[simp] theorem Int32.ofInt_int16ToInt (x : Int16) : Int32.ofInt x.toInt = x.toInt32 := rfl
@[simp] theorem Int32.ofInt_int64ToInt (x : Int64) : Int32.ofInt x.toInt = x.toInt32 := rfl
@[simp] theorem Int32.ofInt_iSizeToInt (x : ISize) : Int32.ofInt x.toInt = x.toInt32 := rfl
@[simp] theorem Int32.ofInt_int8ToInt (x : Int8) : Int32.ofInt x.toInt = x.toInt32 := (rfl)
@[simp] theorem Int32.ofInt_int16ToInt (x : Int16) : Int32.ofInt x.toInt = x.toInt32 := (rfl)
@[simp] theorem Int32.ofInt_int64ToInt (x : Int64) : Int32.ofInt x.toInt = x.toInt32 := (rfl)
@[simp] theorem Int32.ofInt_iSizeToInt (x : ISize) : Int32.ofInt x.toInt = x.toInt32 := (rfl)
@[simp] theorem Int64.ofInt_int8ToInt (x : Int8) : Int64.ofInt x.toInt = x.toInt64 := rfl
@[simp] theorem Int64.ofInt_int16ToInt (x : Int16) : Int64.ofInt x.toInt = x.toInt64 := rfl
@[simp] theorem Int64.ofInt_int32ToInt (x : Int32) : Int64.ofInt x.toInt = x.toInt64 := rfl
@[simp] theorem Int64.ofInt_iSizeToInt (x : ISize) : Int64.ofInt x.toInt = x.toInt64 := rfl
@[simp] theorem Int64.ofInt_int8ToInt (x : Int8) : Int64.ofInt x.toInt = x.toInt64 := (rfl)
@[simp] theorem Int64.ofInt_int16ToInt (x : Int16) : Int64.ofInt x.toInt = x.toInt64 := (rfl)
@[simp] theorem Int64.ofInt_int32ToInt (x : Int32) : Int64.ofInt x.toInt = x.toInt64 := (rfl)
@[simp] theorem Int64.ofInt_iSizeToInt (x : ISize) : Int64.ofInt x.toInt = x.toInt64 := (rfl)
@[simp] theorem ISize.ofInt_int8ToInt (x : Int8) : ISize.ofInt x.toInt = x.toISize := rfl
@[simp] theorem ISize.ofInt_int16ToInt (x : Int16) : ISize.ofInt x.toInt = x.toISize := rfl
@[simp] theorem ISize.ofInt_int32ToInt (x : Int32) : ISize.ofInt x.toInt = x.toISize := rfl
@[simp] theorem ISize.ofInt_int64ToInt (x : Int64) : ISize.ofInt x.toInt = x.toISize := rfl
@[simp] theorem ISize.ofInt_int8ToInt (x : Int8) : ISize.ofInt x.toInt = x.toISize := (rfl)
@[simp] theorem ISize.ofInt_int16ToInt (x : Int16) : ISize.ofInt x.toInt = x.toISize := (rfl)
@[simp] theorem ISize.ofInt_int32ToInt (x : Int32) : ISize.ofInt x.toInt = x.toISize := (rfl)
@[simp] theorem ISize.ofInt_int64ToInt (x : Int64) : ISize.ofInt x.toInt = x.toISize := (rfl)
@[simp] theorem Int8.toInt_ofIntLE {x : Int} {h₁ h₂} : (ofIntLE x h₁ h₂).toInt = x := by
rw [ofIntLE, toInt_ofInt_of_le h₁ (Int.lt_of_le_sub_one h₂)]
@@ -685,11 +685,11 @@ theorem Int64.ofIntLE_eq_ofIntTruncate {x : Int} {h₁ h₂} : (ofIntLE x h₁ h
theorem ISize.ofIntLE_eq_ofIntTruncate {x : Int} {h₁ h₂} : (ofIntLE x h₁ h₂) = ofIntTruncate x := by
rw [ofIntTruncate, dif_pos h₁, dif_pos h₂]
theorem Int8.ofIntLE_eq_ofInt {n : Int} (h₁ h₂) : Int8.ofIntLE n h₁ h₂ = Int8.ofInt n := rfl
theorem Int16.ofIntLE_eq_ofInt {n : Int} (h₁ h₂) : Int16.ofIntLE n h₁ h₂ = Int16.ofInt n := rfl
theorem Int32.ofIntLE_eq_ofInt {n : Int} (h₁ h₂) : Int32.ofIntLE n h₁ h₂ = Int32.ofInt n := rfl
theorem Int64.ofIntLE_eq_ofInt {n : Int} (h₁ h₂) : Int64.ofIntLE n h₁ h₂ = Int64.ofInt n := rfl
theorem ISize.ofIntLE_eq_ofInt {n : Int} (h₁ h₂) : ISize.ofIntLE n h₁ h₂ = ISize.ofInt n := rfl
theorem Int8.ofIntLE_eq_ofInt {n : Int} (h₁ h₂) : Int8.ofIntLE n h₁ h₂ = Int8.ofInt n := (rfl)
theorem Int16.ofIntLE_eq_ofInt {n : Int} (h₁ h₂) : Int16.ofIntLE n h₁ h₂ = Int16.ofInt n := (rfl)
theorem Int32.ofIntLE_eq_ofInt {n : Int} (h₁ h₂) : Int32.ofIntLE n h₁ h₂ = Int32.ofInt n := (rfl)
theorem Int64.ofIntLE_eq_ofInt {n : Int} (h₁ h₂) : Int64.ofIntLE n h₁ h₂ = Int64.ofInt n := (rfl)
theorem ISize.ofIntLE_eq_ofInt {n : Int} (h₁ h₂) : ISize.ofIntLE n h₁ h₂ = ISize.ofInt n := (rfl)
theorem Int8.toInt_ofIntTruncate {x : Int} (h₁ : Int8.minValue.toInt x)
(h₂ : x Int8.maxValue.toInt) : (Int8.ofIntTruncate x).toInt = x := by
@@ -970,29 +970,29 @@ theorem UInt64.toInt64_ofNatLT {n : Nat} (hn) : (UInt64.ofNatLT n hn).toInt64 =
theorem USize.toISize_ofNatLT {n : Nat} (hn) : (USize.ofNatLT n hn).toISize = ISize.ofNat n :=
ISize.toBitVec.inj (by simp [BitVec.ofNatLT_eq_ofNat])
@[simp] theorem UInt8.toInt8_ofNat' {n : Nat} : (UInt8.ofNat n).toInt8 = Int8.ofNat n := rfl
@[simp] theorem UInt16.toInt16_ofNat' {n : Nat} : (UInt16.ofNat n).toInt16 = Int16.ofNat n := rfl
@[simp] theorem UInt32.toInt32_ofNat' {n : Nat} : (UInt32.ofNat n).toInt32 = Int32.ofNat n := rfl
@[simp] theorem UInt64.toInt64_ofNat' {n : Nat} : (UInt64.ofNat n).toInt64 = Int64.ofNat n := rfl
@[simp] theorem USize.toISize_ofNat' {n : Nat} : (USize.ofNat n).toISize = ISize.ofNat n := rfl
@[simp] theorem UInt8.toInt8_ofNat' {n : Nat} : (UInt8.ofNat n).toInt8 = Int8.ofNat n := (rfl)
@[simp] theorem UInt16.toInt16_ofNat' {n : Nat} : (UInt16.ofNat n).toInt16 = Int16.ofNat n := (rfl)
@[simp] theorem UInt32.toInt32_ofNat' {n : Nat} : (UInt32.ofNat n).toInt32 = Int32.ofNat n := (rfl)
@[simp] theorem UInt64.toInt64_ofNat' {n : Nat} : (UInt64.ofNat n).toInt64 = Int64.ofNat n := (rfl)
@[simp] theorem USize.toISize_ofNat' {n : Nat} : (USize.ofNat n).toISize = ISize.ofNat n := (rfl)
@[simp] theorem UInt8.toInt8_ofNat {n : Nat} : toInt8 (no_index (OfNat.ofNat n)) = OfNat.ofNat n := rfl
@[simp] theorem UInt16.toInt16_ofNat {n : Nat} : toInt16 (no_index (OfNat.ofNat n)) = OfNat.ofNat n := rfl
@[simp] theorem UInt32.toInt32_ofNat {n : Nat} : toInt32 (no_index (OfNat.ofNat n)) = OfNat.ofNat n := rfl
@[simp] theorem UInt64.toInt64_ofNat {n : Nat} : toInt64 (no_index (OfNat.ofNat n)) = OfNat.ofNat n := rfl
@[simp] theorem USize.toISize_ofNat {n : Nat} : toISize (no_index (OfNat.ofNat n)) = OfNat.ofNat n := rfl
@[simp] theorem UInt8.toInt8_ofNat {n : Nat} : toInt8 (no_index (OfNat.ofNat n)) = OfNat.ofNat n := (rfl)
@[simp] theorem UInt16.toInt16_ofNat {n : Nat} : toInt16 (no_index (OfNat.ofNat n)) = OfNat.ofNat n := (rfl)
@[simp] theorem UInt32.toInt32_ofNat {n : Nat} : toInt32 (no_index (OfNat.ofNat n)) = OfNat.ofNat n := (rfl)
@[simp] theorem UInt64.toInt64_ofNat {n : Nat} : toInt64 (no_index (OfNat.ofNat n)) = OfNat.ofNat n := (rfl)
@[simp] theorem USize.toISize_ofNat {n : Nat} : toISize (no_index (OfNat.ofNat n)) = OfNat.ofNat n := (rfl)
@[simp] theorem UInt8.toInt8_ofBitVec (b) : (UInt8.ofBitVec b).toInt8 = Int8.ofBitVec b := rfl
@[simp] theorem UInt16.toInt16_ofBitVec (b) : (UInt16.ofBitVec b).toInt16 = Int16.ofBitVec b := rfl
@[simp] theorem UInt32.toInt32_ofBitVec (b) : (UInt32.ofBitVec b).toInt32 = Int32.ofBitVec b := rfl
@[simp] theorem UInt64.toInt64_ofBitVec (b) : (UInt64.ofBitVec b).toInt64 = Int64.ofBitVec b := rfl
@[simp] theorem USize.toISize_ofBitVec (b) : (USize.ofBitVec b).toISize = ISize.ofBitVec b := rfl
@[simp] theorem UInt8.toInt8_ofBitVec (b) : (UInt8.ofBitVec b).toInt8 = Int8.ofBitVec b := (rfl)
@[simp] theorem UInt16.toInt16_ofBitVec (b) : (UInt16.ofBitVec b).toInt16 = Int16.ofBitVec b := (rfl)
@[simp] theorem UInt32.toInt32_ofBitVec (b) : (UInt32.ofBitVec b).toInt32 = Int32.ofBitVec b := (rfl)
@[simp] theorem UInt64.toInt64_ofBitVec (b) : (UInt64.ofBitVec b).toInt64 = Int64.ofBitVec b := (rfl)
@[simp] theorem USize.toISize_ofBitVec (b) : (USize.ofBitVec b).toISize = ISize.ofBitVec b := (rfl)
@[simp] theorem Int8.toBitVec_ofBitVec (b) : (Int8.ofBitVec b).toBitVec = b := rfl
@[simp] theorem Int16.toBitVec_ofBitVec (b) : (Int16.ofBitVec b).toBitVec = b := rfl
@[simp] theorem Int32.toBitVec_ofBitVec (b) : (Int32.ofBitVec b).toBitVec = b := rfl
@[simp] theorem Int64.toBitVec_ofBitVec (b) : (Int64.ofBitVec b).toBitVec = b := rfl
@[simp] theorem ISize.toBitVec_ofBitVec (b) : (ISize.ofBitVec b).toBitVec = b := rfl
@[simp] theorem Int8.toBitVec_ofBitVec (b) : (Int8.ofBitVec b).toBitVec = b := (rfl)
@[simp] theorem Int16.toBitVec_ofBitVec (b) : (Int16.ofBitVec b).toBitVec = b := (rfl)
@[simp] theorem Int32.toBitVec_ofBitVec (b) : (Int32.ofBitVec b).toBitVec = b := (rfl)
@[simp] theorem Int64.toBitVec_ofBitVec (b) : (Int64.ofBitVec b).toBitVec = b := (rfl)
@[simp] theorem ISize.toBitVec_ofBitVec (b) : (ISize.ofBitVec b).toBitVec = b := (rfl)
theorem Int8.toBitVec_ofIntTruncate {n : Int} (h₁ : Int8.minValue.toInt n) (h₂ : n Int8.maxValue.toInt) :
(Int8.ofIntTruncate n).toBitVec = BitVec.ofInt _ n := by
@@ -1010,11 +1010,11 @@ theorem ISize.toBitVec_ofIntTruncate {n : Int} (h₁ : ISize.minValue.toInt ≤
(ISize.ofIntTruncate n).toBitVec = BitVec.ofInt _ n := by
rw [ ofIntLE_eq_ofIntTruncate (h₁ := h₁) (h₂ := h₂), toBitVec_ofIntLE]
@[simp] theorem Int8.toInt_ofBitVec (b) : (Int8.ofBitVec b).toInt = b.toInt := rfl
@[simp] theorem Int16.toInt_ofBitVec (b) : (Int16.ofBitVec b).toInt = b.toInt := rfl
@[simp] theorem Int32.toInt_ofBitVec (b) : (Int32.ofBitVec b).toInt = b.toInt := rfl
@[simp] theorem Int64.toInt_ofBitVec (b) : (Int64.ofBitVec b).toInt = b.toInt := rfl
@[simp] theorem ISize.toInt_ofBitVec (b) : (ISize.ofBitVec b).toInt = b.toInt := rfl
@[simp] theorem Int8.toInt_ofBitVec (b) : (Int8.ofBitVec b).toInt = b.toInt := (rfl)
@[simp] theorem Int16.toInt_ofBitVec (b) : (Int16.ofBitVec b).toInt = b.toInt := (rfl)
@[simp] theorem Int32.toInt_ofBitVec (b) : (Int32.ofBitVec b).toInt = b.toInt := (rfl)
@[simp] theorem Int64.toInt_ofBitVec (b) : (Int64.ofBitVec b).toInt = b.toInt := (rfl)
@[simp] theorem ISize.toInt_ofBitVec (b) : (ISize.ofBitVec b).toInt = b.toInt := (rfl)
@[simp] theorem Int8.toNatClampNeg_ofIntLE {n : Int} (h₁ h₂) : (Int8.ofIntLE n h₁ h₂).toNatClampNeg = n.toNat := by
rw [ofIntLE, toNatClampNeg, toInt_ofInt_of_le h₁ (Int.lt_of_le_sub_one h₂)]
@@ -1030,11 +1030,11 @@ theorem ISize.toBitVec_ofIntTruncate {n : Int} (h₁ : ISize.minValue.toInt ≤
· apply Int.lt_of_le_sub_one
rwa [ ISize.toInt_maxValue]
@[simp] theorem Int8.toNatClampNeg_ofBitVec (b) : (Int8.ofBitVec b).toNatClampNeg = b.toInt.toNat := rfl
@[simp] theorem Int16.toNatClampNeg_ofBitVec (b) : (Int16.ofBitVec b).toNatClampNeg = b.toInt.toNat := rfl
@[simp] theorem Int32.toNatClampNeg_ofBitVec (b) : (Int32.ofBitVec b).toNatClampNeg = b.toInt.toNat := rfl
@[simp] theorem Int64.toNatClampNeg_ofBitVec (b) : (Int64.ofBitVec b).toNatClampNeg = b.toInt.toNat := rfl
@[simp] theorem ISize.toNatClampNeg_ofBitVec (b) : (ISize.ofBitVec b).toNatClampNeg = b.toInt.toNat := rfl
@[simp] theorem Int8.toNatClampNeg_ofBitVec (b) : (Int8.ofBitVec b).toNatClampNeg = b.toInt.toNat := (rfl)
@[simp] theorem Int16.toNatClampNeg_ofBitVec (b) : (Int16.ofBitVec b).toNatClampNeg = b.toInt.toNat := (rfl)
@[simp] theorem Int32.toNatClampNeg_ofBitVec (b) : (Int32.ofBitVec b).toNatClampNeg = b.toInt.toNat := (rfl)
@[simp] theorem Int64.toNatClampNeg_ofBitVec (b) : (Int64.ofBitVec b).toNatClampNeg = b.toInt.toNat := (rfl)
@[simp] theorem ISize.toNatClampNeg_ofBitVec (b) : (ISize.ofBitVec b).toNatClampNeg = b.toInt.toNat := (rfl)
theorem Int8.toNatClampNeg_ofInt_of_le {n : Int} (h₁ : -2 ^ 7 n) (h₂ : n < 2 ^ 7) :
(Int8.ofInt n).toNatClampNeg = n.toNat := by rw [toNatClampNeg, toInt_ofInt_of_le h₁ h₂]
@@ -1101,33 +1101,33 @@ theorem ISize.toNatClampNeg_ofIntTruncate_of_lt {n : Int} (h₁ : n < 2 ^ 31) :
apply ISize.toNatClampNeg_ofIntTruncate_of_lt_two_pow_numBits (Int.lt_of_lt_of_le h₁ _)
cases System.Platform.numBits_eq <;> simp_all
@[simp] theorem Int8.toUInt8_ofBitVec (b) : (Int8.ofBitVec b).toUInt8 = UInt8.ofBitVec b := rfl
@[simp] theorem Int16.toUInt16_ofBitVec (b) : (Int16.ofBitVec b).toUInt16 = UInt16.ofBitVec b := rfl
@[simp] theorem Int32.toUInt32_ofBitVec (b) : (Int32.ofBitVec b).toUInt32 = UInt32.ofBitVec b := rfl
@[simp] theorem Int64.toUInt64_ofBitVec (b) : (Int64.ofBitVec b).toUInt64 = UInt64.ofBitVec b := rfl
@[simp] theorem ISize.toUSize_ofBitVec (b) : (ISize.ofBitVec b).toUSize = USize.ofBitVec b := rfl
@[simp] theorem Int8.toUInt8_ofBitVec (b) : (Int8.ofBitVec b).toUInt8 = UInt8.ofBitVec b := (rfl)
@[simp] theorem Int16.toUInt16_ofBitVec (b) : (Int16.ofBitVec b).toUInt16 = UInt16.ofBitVec b := (rfl)
@[simp] theorem Int32.toUInt32_ofBitVec (b) : (Int32.ofBitVec b).toUInt32 = UInt32.ofBitVec b := (rfl)
@[simp] theorem Int64.toUInt64_ofBitVec (b) : (Int64.ofBitVec b).toUInt64 = UInt64.ofBitVec b := (rfl)
@[simp] theorem ISize.toUSize_ofBitVec (b) : (ISize.ofBitVec b).toUSize = USize.ofBitVec b := (rfl)
@[simp] theorem Int8.toUInt8_ofNat' {n} : (Int8.ofNat n).toUInt8 = UInt8.ofNat n := rfl
@[simp] theorem Int16.toUInt16_ofNat' {n} : (Int16.ofNat n).toUInt16 = UInt16.ofNat n := rfl
@[simp] theorem Int32.toUInt32_ofNat' {n} : (Int32.ofNat n).toUInt32 = UInt32.ofNat n := rfl
@[simp] theorem Int64.toUInt64_ofNat' {n} : (Int64.ofNat n).toUInt64 = UInt64.ofNat n := rfl
@[simp] theorem ISize.toUSize_ofNat' {n} : (ISize.ofNat n).toUSize = USize.ofNat n := rfl
@[simp] theorem Int8.toUInt8_ofNat' {n} : (Int8.ofNat n).toUInt8 = UInt8.ofNat n := (rfl)
@[simp] theorem Int16.toUInt16_ofNat' {n} : (Int16.ofNat n).toUInt16 = UInt16.ofNat n := (rfl)
@[simp] theorem Int32.toUInt32_ofNat' {n} : (Int32.ofNat n).toUInt32 = UInt32.ofNat n := (rfl)
@[simp] theorem Int64.toUInt64_ofNat' {n} : (Int64.ofNat n).toUInt64 = UInt64.ofNat n := (rfl)
@[simp] theorem ISize.toUSize_ofNat' {n} : (ISize.ofNat n).toUSize = USize.ofNat n := (rfl)
@[simp] theorem Int8.toUInt8_ofNat {n} : toUInt8 (OfNat.ofNat n) = OfNat.ofNat n := rfl
@[simp] theorem Int16.toUInt16_ofNat {n} : toUInt16 (OfNat.ofNat n) = OfNat.ofNat n := rfl
@[simp] theorem Int32.toUInt32_ofNat {n} : toUInt32 (OfNat.ofNat n) = OfNat.ofNat n := rfl
@[simp] theorem Int64.toUInt64_ofNat {n} : toUInt64 (OfNat.ofNat n) = OfNat.ofNat n := rfl
@[simp] theorem ISize.toUSize_ofNat {n} : toUSize (OfNat.ofNat n) = OfNat.ofNat n := rfl
@[simp] theorem Int8.toUInt8_ofNat {n} : toUInt8 (OfNat.ofNat n) = OfNat.ofNat n := (rfl)
@[simp] theorem Int16.toUInt16_ofNat {n} : toUInt16 (OfNat.ofNat n) = OfNat.ofNat n := (rfl)
@[simp] theorem Int32.toUInt32_ofNat {n} : toUInt32 (OfNat.ofNat n) = OfNat.ofNat n := (rfl)
@[simp] theorem Int64.toUInt64_ofNat {n} : toUInt64 (OfNat.ofNat n) = OfNat.ofNat n := (rfl)
@[simp] theorem ISize.toUSize_ofNat {n} : toUSize (OfNat.ofNat n) = OfNat.ofNat n := (rfl)
theorem Int16.toInt8_ofIntLE {n} (h₁ h₂) : (Int16.ofIntLE n h₁ h₂).toInt8 = Int8.ofInt n := Int8.toInt.inj (by simp)
theorem Int32.toInt8_ofIntLE {n} (h₁ h₂) : (Int32.ofIntLE n h₁ h₂).toInt8 = Int8.ofInt n := Int8.toInt.inj (by simp)
theorem Int64.toInt8_ofIntLE {n} (h₁ h₂) : (Int64.ofIntLE n h₁ h₂).toInt8 = Int8.ofInt n := Int8.toInt.inj (by simp)
theorem ISize.toInt8_ofIntLE {n} (h₁ h₂) : (ISize.ofIntLE n h₁ h₂).toInt8 = Int8.ofInt n := Int8.toInt.inj (by simp)
@[simp] theorem Int16.toInt8_ofBitVec (b) : (Int16.ofBitVec b).toInt8 = Int8.ofBitVec (b.signExtend _) := rfl
@[simp] theorem Int32.toInt8_ofBitVec (b) : (Int32.ofBitVec b).toInt8 = Int8.ofBitVec (b.signExtend _) := rfl
@[simp] theorem Int64.toInt8_ofBitVec (b) : (Int64.ofBitVec b).toInt8 = Int8.ofBitVec (b.signExtend _) := rfl
@[simp] theorem ISize.toInt8_ofBitVec (b) : (ISize.ofBitVec b).toInt8 = Int8.ofBitVec (b.signExtend _) := rfl
@[simp] theorem Int16.toInt8_ofBitVec (b) : (Int16.ofBitVec b).toInt8 = Int8.ofBitVec (b.signExtend _) := (rfl)
@[simp] theorem Int32.toInt8_ofBitVec (b) : (Int32.ofBitVec b).toInt8 = Int8.ofBitVec (b.signExtend _) := (rfl)
@[simp] theorem Int64.toInt8_ofBitVec (b) : (Int64.ofBitVec b).toInt8 = Int8.ofBitVec (b.signExtend _) := (rfl)
@[simp] theorem ISize.toInt8_ofBitVec (b) : (ISize.ofBitVec b).toInt8 = Int8.ofBitVec (b.signExtend _) := (rfl)
@[simp] theorem Int16.toInt8_ofNat' {n} : (Int16.ofNat n).toInt8 = Int8.ofNat n :=
Int8.toBitVec.inj (by simp [BitVec.signExtend_eq_setWidth_of_le])
@@ -1177,9 +1177,9 @@ theorem Int32.toInt16_ofIntLE {n} (h₁ h₂) : (Int32.ofIntLE n h₁ h₂).toIn
theorem Int64.toInt16_ofIntLE {n} (h₁ h₂) : (Int64.ofIntLE n h₁ h₂).toInt16 = Int16.ofInt n := Int16.toInt.inj (by simp)
theorem ISize.toInt16_ofIntLE {n} (h₁ h₂) : (ISize.ofIntLE n h₁ h₂).toInt16 = Int16.ofInt n := Int16.toInt.inj (by simp)
@[simp] theorem Int32.toInt16_ofBitVec (b) : (Int32.ofBitVec b).toInt16 = Int16.ofBitVec (b.signExtend _) := rfl
@[simp] theorem Int64.toInt16_ofBitVec (b) : (Int64.ofBitVec b).toInt16 = Int16.ofBitVec (b.signExtend _) := rfl
@[simp] theorem ISize.toInt16_ofBitVec (b) : (ISize.ofBitVec b).toInt16 = Int16.ofBitVec (b.signExtend _) := rfl
@[simp] theorem Int32.toInt16_ofBitVec (b) : (Int32.ofBitVec b).toInt16 = Int16.ofBitVec (b.signExtend _) := (rfl)
@[simp] theorem Int64.toInt16_ofBitVec (b) : (Int64.ofBitVec b).toInt16 = Int16.ofBitVec (b.signExtend _) := (rfl)
@[simp] theorem ISize.toInt16_ofBitVec (b) : (ISize.ofBitVec b).toInt16 = Int16.ofBitVec (b.signExtend _) := (rfl)
@[simp] theorem Int32.toInt16_ofNat' {n} : (Int32.ofNat n).toInt16 = Int16.ofNat n :=
Int16.toBitVec.inj (by simp [BitVec.signExtend_eq_setWidth_of_le])
@@ -1220,8 +1220,8 @@ theorem ISize.toInt16_ofIntTruncate {n : Int} (h₁ : -2 ^ (System.Platform.numB
theorem Int64.toInt32_ofIntLE {n} (h₁ h₂) : (Int64.ofIntLE n h₁ h₂).toInt32 = Int32.ofInt n := Int32.toInt.inj (by simp)
theorem ISize.toInt32_ofIntLE {n} (h₁ h₂) : (ISize.ofIntLE n h₁ h₂).toInt32 = Int32.ofInt n := Int32.toInt.inj (by simp)
@[simp] theorem Int64.toInt32_ofBitVec (b) : (Int64.ofBitVec b).toInt32 = Int32.ofBitVec (b.signExtend _) := rfl
@[simp] theorem ISize.toInt32_ofBitVec (b) : (ISize.ofBitVec b).toInt32 = Int32.ofBitVec (b.signExtend _) := rfl
@[simp] theorem Int64.toInt32_ofBitVec (b) : (Int64.ofBitVec b).toInt32 = Int32.ofBitVec (b.signExtend _) := (rfl)
@[simp] theorem ISize.toInt32_ofBitVec (b) : (ISize.ofBitVec b).toInt32 = Int32.ofBitVec (b.signExtend _) := (rfl)
@[simp] theorem Int64.toInt32_ofNat' {n} : (Int64.ofNat n).toInt32 = Int32.ofNat n :=
Int32.toBitVec.inj (by simp [BitVec.signExtend_eq_setWidth_of_le])
@@ -1254,7 +1254,7 @@ theorem ISize.toInt32_ofIntTruncate {n : Int} (h₁ : -2 ^ (System.Platform.numB
theorem Int64.toISize_ofIntLE {n} (h₁ h₂) : (Int64.ofIntLE n h₁ h₂).toISize = ISize.ofInt n :=
ISize.toInt.inj (by simp [ISize.toInt_ofInt])
@[simp] theorem Int64.toISize_ofBitVec (b) : (Int64.ofBitVec b).toISize = ISize.ofBitVec (b.signExtend _) := rfl
@[simp] theorem Int64.toISize_ofBitVec (b) : (Int64.ofBitVec b).toISize = ISize.ofBitVec (b.signExtend _) := (rfl)
@[simp] theorem Int64.toISize_ofNat' {n} : (Int64.ofNat n).toISize = ISize.ofNat n :=
ISize.toBitVec.inj (by simp [BitVec.signExtend_eq_setWidth_of_le])
@@ -1268,10 +1268,10 @@ theorem Int64.toISize_ofIntTruncate {n : Int} (h₁ : -2 ^ 63 ≤ n) (h₂ : n <
(Int64.ofIntTruncate n).toISize = ISize.ofInt n := by
rw [ ofIntLE_eq_ofIntTruncate (h₁ := h₁) (h₂ := Int.le_of_lt_add_one h₂), toISize_ofIntLE]
@[simp] theorem Int8.toBitVec_minValue : minValue.toBitVec = BitVec.intMin _ := rfl
@[simp] theorem Int16.toBitVec_minValue : minValue.toBitVec = BitVec.intMin _ := rfl
@[simp] theorem Int32.toBitVec_minValue : minValue.toBitVec = BitVec.intMin _ := rfl
@[simp] theorem Int64.toBitVec_minValue : minValue.toBitVec = BitVec.intMin _ := rfl
@[simp] theorem Int8.toBitVec_minValue : minValue.toBitVec = BitVec.intMin _ := (rfl)
@[simp] theorem Int16.toBitVec_minValue : minValue.toBitVec = BitVec.intMin _ := (rfl)
@[simp] theorem Int32.toBitVec_minValue : minValue.toBitVec = BitVec.intMin _ := (rfl)
@[simp] theorem Int64.toBitVec_minValue : minValue.toBitVec = BitVec.intMin _ := (rfl)
@[simp] theorem ISize.toBitVec_minValue : minValue.toBitVec = BitVec.intMin _ :=
BitVec.eq_of_toInt_eq (by rw [toInt_toBitVec, toInt_minValue,
BitVec.toInt_intMin_of_pos (by cases System.Platform.numBits_eq <;> simp_all)])
@@ -1335,10 +1335,10 @@ theorem Int8.toISize_ofIntLE {n : Int} (h₁ h₂) :
(Int.le_trans h₂ maxValue.toInt_le_iSizeMaxValue) :=
ISize.toInt.inj (by simp)
@[simp] theorem Int8.toInt16_ofBitVec (b) : (Int8.ofBitVec b).toInt16 = Int16.ofBitVec (b.signExtend _) := rfl
@[simp] theorem Int8.toInt32_ofBitVec (b) : (Int8.ofBitVec b).toInt32 = Int32.ofBitVec (b.signExtend _) := rfl
@[simp] theorem Int8.toInt64_ofBitVec (b) : (Int8.ofBitVec b).toInt64 = Int64.ofBitVec (b.signExtend _) := rfl
@[simp] theorem Int8.toISize_ofBitVec (b) : (Int8.ofBitVec b).toISize = ISize.ofBitVec (b.signExtend _) := rfl
@[simp] theorem Int8.toInt16_ofBitVec (b) : (Int8.ofBitVec b).toInt16 = Int16.ofBitVec (b.signExtend _) := (rfl)
@[simp] theorem Int8.toInt32_ofBitVec (b) : (Int8.ofBitVec b).toInt32 = Int32.ofBitVec (b.signExtend _) := (rfl)
@[simp] theorem Int8.toInt64_ofBitVec (b) : (Int8.ofBitVec b).toInt64 = Int64.ofBitVec (b.signExtend _) := (rfl)
@[simp] theorem Int8.toISize_ofBitVec (b) : (Int8.ofBitVec b).toISize = ISize.ofBitVec (b.signExtend _) := (rfl)
@[simp] theorem Int8.toInt16_ofInt {n : Int} (h₁ : Int8.minValue.toInt n) (h₂ : n Int8.maxValue.toInt) :
(Int8.ofInt n).toInt16 = Int16.ofInt n := by rw [ Int8.ofIntLE_eq_ofInt h₁ h₂, toInt16_ofIntLE, Int16.ofIntLE_eq_ofInt]
@@ -1382,9 +1382,9 @@ theorem Int16.toISize_ofIntLE {n : Int} (h₁ h₂) :
(Int.le_trans h₂ maxValue.toInt_le_iSizeMaxValue) :=
ISize.toInt.inj (by simp)
@[simp] theorem Int16.toInt32_ofBitVec (b) : (Int16.ofBitVec b).toInt32 = Int32.ofBitVec (b.signExtend _) := rfl
@[simp] theorem Int16.toInt64_ofBitVec (b) : (Int16.ofBitVec b).toInt64 = Int64.ofBitVec (b.signExtend _) := rfl
@[simp] theorem Int16.toISize_ofBitVec (b) : (Int16.ofBitVec b).toISize = ISize.ofBitVec (b.signExtend _) := rfl
@[simp] theorem Int16.toInt32_ofBitVec (b) : (Int16.ofBitVec b).toInt32 = Int32.ofBitVec (b.signExtend _) := (rfl)
@[simp] theorem Int16.toInt64_ofBitVec (b) : (Int16.ofBitVec b).toInt64 = Int64.ofBitVec (b.signExtend _) := (rfl)
@[simp] theorem Int16.toISize_ofBitVec (b) : (Int16.ofBitVec b).toISize = ISize.ofBitVec (b.signExtend _) := (rfl)
@[simp] theorem Int16.toInt32_ofInt {n : Int} (h₁ : Int16.minValue.toInt n) (h₂ : n Int16.maxValue.toInt) :
(Int16.ofInt n).toInt32 = Int32.ofInt n := by rw [ Int16.ofIntLE_eq_ofInt h₁ h₂, toInt32_ofIntLE, Int32.ofIntLE_eq_ofInt]
@@ -1418,8 +1418,8 @@ theorem Int32.toISize_ofIntLE {n : Int} (h₁ h₂) :
(Int.le_trans h₂ maxValue.toInt_le_iSizeMaxValue) :=
ISize.toInt.inj (by simp)
@[simp] theorem Int32.toInt64_ofBitVec (b) : (Int32.ofBitVec b).toInt64 = Int64.ofBitVec (b.signExtend _) := rfl
@[simp] theorem Int32.toISize_ofBitVec (b) : (Int32.ofBitVec b).toISize = ISize.ofBitVec (b.signExtend _) := rfl
@[simp] theorem Int32.toInt64_ofBitVec (b) : (Int32.ofBitVec b).toInt64 = Int64.ofBitVec (b.signExtend _) := (rfl)
@[simp] theorem Int32.toISize_ofBitVec (b) : (Int32.ofBitVec b).toISize = ISize.ofBitVec (b.signExtend _) := (rfl)
@[simp] theorem Int32.toInt64_ofInt {n : Int} (h₁ : Int32.minValue.toInt n) (h₂ : n Int32.maxValue.toInt) :
(Int32.ofInt n).toInt64 = Int64.ofInt n := by rw [ Int32.ofIntLE_eq_ofInt h₁ h₂, toInt64_ofIntLE, Int64.ofIntLE_eq_ofInt]
@@ -1443,7 +1443,7 @@ theorem ISize.toInt64_ofIntLE {n : Int} (h₁ h₂) :
(Int.le_trans h₂ maxValue.toInt_le_int64MaxValue) :=
Int64.toInt.inj (by simp)
@[simp] theorem ISize.toInt64_ofBitVec (b) : (ISize.ofBitVec b).toInt64 = Int64.ofBitVec (b.signExtend _) := rfl
@[simp] theorem ISize.toInt64_ofBitVec (b) : (ISize.ofBitVec b).toInt64 = Int64.ofBitVec (b.signExtend _) := (rfl)
@[simp] theorem ISize.toInt64_ofInt {n : Int} (h₁ : ISize.minValue.toInt n) (h₂ : n ISize.maxValue.toInt) :
(ISize.ofInt n).toInt64 = Int64.ofInt n := by rw [ ISize.ofIntLE_eq_ofInt h₁ h₂, toInt64_ofIntLE, Int64.ofIntLE_eq_ofInt]
@@ -1486,17 +1486,17 @@ theorem Int64.ofBitVec_ofNatLT (n : Nat) (hn) : Int64.ofBitVec (BitVec.ofNatLT n
theorem ISize.ofBitVec_ofNatLT (n : Nat) (hn) : ISize.ofBitVec (BitVec.ofNatLT n hn) = ISize.ofNat n :=
ISize.toBitVec.inj (by simp [BitVec.ofNatLT_eq_ofNat hn])
@[simp] theorem Int8.ofBitVec_ofNat (n : Nat) : Int8.ofBitVec (BitVec.ofNat 8 n) = Int8.ofNat n := rfl
@[simp] theorem Int16.ofBitVec_ofNat (n : Nat) : Int16.ofBitVec (BitVec.ofNat 16 n) = Int16.ofNat n := rfl
@[simp] theorem Int32.ofBitVec_ofNat (n : Nat) : Int32.ofBitVec (BitVec.ofNat 32 n) = Int32.ofNat n := rfl
@[simp] theorem Int64.ofBitVec_ofNat (n : Nat) : Int64.ofBitVec (BitVec.ofNat 64 n) = Int64.ofNat n := rfl
@[simp] theorem ISize.ofBitVec_ofNat (n : Nat) : ISize.ofBitVec (BitVec.ofNat System.Platform.numBits n) = ISize.ofNat n := rfl
@[simp] theorem Int8.ofBitVec_ofNat (n : Nat) : Int8.ofBitVec (BitVec.ofNat 8 n) = Int8.ofNat n := (rfl)
@[simp] theorem Int16.ofBitVec_ofNat (n : Nat) : Int16.ofBitVec (BitVec.ofNat 16 n) = Int16.ofNat n := (rfl)
@[simp] theorem Int32.ofBitVec_ofNat (n : Nat) : Int32.ofBitVec (BitVec.ofNat 32 n) = Int32.ofNat n := (rfl)
@[simp] theorem Int64.ofBitVec_ofNat (n : Nat) : Int64.ofBitVec (BitVec.ofNat 64 n) = Int64.ofNat n := (rfl)
@[simp] theorem ISize.ofBitVec_ofNat (n : Nat) : ISize.ofBitVec (BitVec.ofNat System.Platform.numBits n) = ISize.ofNat n := (rfl)
@[simp] theorem Int8.ofBitVec_ofInt (n : Int) : Int8.ofBitVec (BitVec.ofInt 8 n) = Int8.ofInt n := rfl
@[simp] theorem Int16.ofBitVec_ofInt (n : Int) : Int16.ofBitVec (BitVec.ofInt 16 n) = Int16.ofInt n := rfl
@[simp] theorem Int32.ofBitVec_ofInt (n : Int) : Int32.ofBitVec (BitVec.ofInt 32 n) = Int32.ofInt n := rfl
@[simp] theorem Int64.ofBitVec_ofInt (n : Int) : Int64.ofBitVec (BitVec.ofInt 64 n) = Int64.ofInt n := rfl
@[simp] theorem ISize.ofBitVec_ofInt (n : Int) : ISize.ofBitVec (BitVec.ofInt System.Platform.numBits n) = ISize.ofInt n := rfl
@[simp] theorem Int8.ofBitVec_ofInt (n : Int) : Int8.ofBitVec (BitVec.ofInt 8 n) = Int8.ofInt n := (rfl)
@[simp] theorem Int16.ofBitVec_ofInt (n : Int) : Int16.ofBitVec (BitVec.ofInt 16 n) = Int16.ofInt n := (rfl)
@[simp] theorem Int32.ofBitVec_ofInt (n : Int) : Int32.ofBitVec (BitVec.ofInt 32 n) = Int32.ofInt n := (rfl)
@[simp] theorem Int64.ofBitVec_ofInt (n : Int) : Int64.ofBitVec (BitVec.ofInt 64 n) = Int64.ofInt n := (rfl)
@[simp] theorem ISize.ofBitVec_ofInt (n : Int) : ISize.ofBitVec (BitVec.ofInt System.Platform.numBits n) = ISize.ofInt n := (rfl)
@[simp] theorem Int8.ofNat_bitVecToNat (n : BitVec 8) : Int8.ofNat n.toNat = Int8.ofBitVec n :=
Int8.toBitVec.inj (by simp)
@@ -1741,10 +1741,10 @@ theorem ISize.toInt64_div_of_ne_right (a b : ISize) (hb : b ≠ -1) : (a / b).to
Int64.toInt_inj.1 (by rw [toInt_toInt64, toInt_div_of_ne_right _ _ hb,
Int64.toInt_div_of_ne_right _ _ (b.toInt64_ne_neg_one hb), toInt_toInt64, toInt_toInt64])
@[simp] theorem Int8.minValue_div_neg_one : minValue / -1 = minValue := rfl
@[simp] theorem Int16.minValue_div_neg_one : minValue / -1 = minValue := rfl
@[simp] theorem Int32.minValue_div_neg_one : minValue / -1 = minValue := rfl
@[simp] theorem Int64.minValue_div_neg_one : minValue / -1 = minValue := rfl
@[simp] theorem Int8.minValue_div_neg_one : minValue / -1 = minValue := (rfl)
@[simp] theorem Int16.minValue_div_neg_one : minValue / -1 = minValue := (rfl)
@[simp] theorem Int32.minValue_div_neg_one : minValue / -1 = minValue := (rfl)
@[simp] theorem Int64.minValue_div_neg_one : minValue / -1 = minValue := (rfl)
@[simp] theorem ISize.minValue_div_neg_one : minValue / -1 = minValue :=
ISize.toBitVec_inj.1 (by simpa [BitVec.intMin_eq_neg_two_pow] using BitVec.intMin_sdiv_neg_one)
@@ -1907,11 +1907,11 @@ protected theorem ISize.sub_eq_add_neg (a b : ISize) : a - b = a + -b := ISize.t
@[simp] theorem ISize.toInt64_le {a b : ISize} : a.toInt64 b.toInt64 a b := by
simp [le_iff_toInt_le, Int64.le_iff_toInt_le]
@[simp] theorem Int8.ofBitVec_neg (a : BitVec 8) : Int8.ofBitVec (-a) = -Int8.ofBitVec a := rfl
@[simp] theorem Int16.ofBitVec_neg (a : BitVec 16) : Int16.ofBitVec (-a) = -Int16.ofBitVec a := rfl
@[simp] theorem Int32.ofBitVec_neg (a : BitVec 32) : Int32.ofBitVec (-a) = -Int32.ofBitVec a := rfl
@[simp] theorem Int64.ofBitVec_neg (a : BitVec 64) : Int64.ofBitVec (-a) = -Int64.ofBitVec a := rfl
@[simp] theorem ISize.ofBitVec_neg (a : BitVec System.Platform.numBits) : ISize.ofBitVec (-a) = -ISize.ofBitVec a := rfl
@[simp] theorem Int8.ofBitVec_neg (a : BitVec 8) : Int8.ofBitVec (-a) = -Int8.ofBitVec a := (rfl)
@[simp] theorem Int16.ofBitVec_neg (a : BitVec 16) : Int16.ofBitVec (-a) = -Int16.ofBitVec a := (rfl)
@[simp] theorem Int32.ofBitVec_neg (a : BitVec 32) : Int32.ofBitVec (-a) = -Int32.ofBitVec a := (rfl)
@[simp] theorem Int64.ofBitVec_neg (a : BitVec 64) : Int64.ofBitVec (-a) = -Int64.ofBitVec a := (rfl)
@[simp] theorem ISize.ofBitVec_neg (a : BitVec System.Platform.numBits) : ISize.ofBitVec (-a) = -ISize.ofBitVec a := (rfl)
@[simp] theorem Int8.ofInt_neg (a : Int) : Int8.ofInt (-a) = -Int8.ofInt a := Int8.toInt_inj.1 (by simp)
@[simp] theorem Int16.ofInt_neg (a : Int) : Int16.ofInt (-a) = -Int16.ofInt a := Int16.toInt_inj.1 (by simp)
@@ -1931,11 +1931,11 @@ theorem Int64.ofInt_eq_iff_bmod_eq_toInt (a : Int) (b : Int64) : Int64.ofInt a =
theorem ISize.ofInt_eq_iff_bmod_eq_toInt (a : Int) (b : ISize) : ISize.ofInt a = b a.bmod (2 ^ System.Platform.numBits) = b.toInt := by
simp [ ISize.toInt_inj, ISize.toInt_ofInt]
@[simp] theorem Int8.ofBitVec_add (a b : BitVec 8) : Int8.ofBitVec (a + b) = Int8.ofBitVec a + Int8.ofBitVec b := rfl
@[simp] theorem Int16.ofBitVec_add (a b : BitVec 16) : Int16.ofBitVec (a + b) = Int16.ofBitVec a + Int16.ofBitVec b := rfl
@[simp] theorem Int32.ofBitVec_add (a b : BitVec 32) : Int32.ofBitVec (a + b) = Int32.ofBitVec a + Int32.ofBitVec b := rfl
@[simp] theorem Int64.ofBitVec_add (a b : BitVec 64) : Int64.ofBitVec (a + b) = Int64.ofBitVec a + Int64.ofBitVec b := rfl
@[simp] theorem ISize.ofBitVec_add (a b : BitVec System.Platform.numBits) : ISize.ofBitVec (a + b) = ISize.ofBitVec a + ISize.ofBitVec b := rfl
@[simp] theorem Int8.ofBitVec_add (a b : BitVec 8) : Int8.ofBitVec (a + b) = Int8.ofBitVec a + Int8.ofBitVec b := (rfl)
@[simp] theorem Int16.ofBitVec_add (a b : BitVec 16) : Int16.ofBitVec (a + b) = Int16.ofBitVec a + Int16.ofBitVec b := (rfl)
@[simp] theorem Int32.ofBitVec_add (a b : BitVec 32) : Int32.ofBitVec (a + b) = Int32.ofBitVec a + Int32.ofBitVec b := (rfl)
@[simp] theorem Int64.ofBitVec_add (a b : BitVec 64) : Int64.ofBitVec (a + b) = Int64.ofBitVec a + Int64.ofBitVec b := (rfl)
@[simp] theorem ISize.ofBitVec_add (a b : BitVec System.Platform.numBits) : ISize.ofBitVec (a + b) = ISize.ofBitVec a + ISize.ofBitVec b := (rfl)
@[simp] theorem Int8.ofInt_add (a b : Int) : Int8.ofInt (a + b) = Int8.ofInt a + Int8.ofInt b := by
simp [Int8.ofInt_eq_iff_bmod_eq_toInt]
@@ -1970,11 +1970,11 @@ theorem Int64.ofIntLE_add {a b : Int} {hab₁ hab₂} : Int64.ofIntLE (a + b) ha
theorem ISize.ofIntLE_add {a b : Int} {hab₁ hab₂} : ISize.ofIntLE (a + b) hab₁ hab₂ = ISize.ofInt a + ISize.ofInt b := by
simp [ISize.ofIntLE_eq_ofInt]
@[simp] theorem Int8.ofBitVec_sub (a b : BitVec 8) : Int8.ofBitVec (a - b) = Int8.ofBitVec a - Int8.ofBitVec b := rfl
@[simp] theorem Int16.ofBitVec_sub (a b : BitVec 16) : Int16.ofBitVec (a - b) = Int16.ofBitVec a - Int16.ofBitVec b := rfl
@[simp] theorem Int32.ofBitVec_sub (a b : BitVec 32) : Int32.ofBitVec (a - b) = Int32.ofBitVec a - Int32.ofBitVec b := rfl
@[simp] theorem Int64.ofBitVec_sub (a b : BitVec 64) : Int64.ofBitVec (a - b) = Int64.ofBitVec a - Int64.ofBitVec b := rfl
@[simp] theorem ISize.ofBitVec_sub (a b : BitVec System.Platform.numBits) : ISize.ofBitVec (a - b) = ISize.ofBitVec a - ISize.ofBitVec b := rfl
@[simp] theorem Int8.ofBitVec_sub (a b : BitVec 8) : Int8.ofBitVec (a - b) = Int8.ofBitVec a - Int8.ofBitVec b := (rfl)
@[simp] theorem Int16.ofBitVec_sub (a b : BitVec 16) : Int16.ofBitVec (a - b) = Int16.ofBitVec a - Int16.ofBitVec b := (rfl)
@[simp] theorem Int32.ofBitVec_sub (a b : BitVec 32) : Int32.ofBitVec (a - b) = Int32.ofBitVec a - Int32.ofBitVec b := (rfl)
@[simp] theorem Int64.ofBitVec_sub (a b : BitVec 64) : Int64.ofBitVec (a - b) = Int64.ofBitVec a - Int64.ofBitVec b := (rfl)
@[simp] theorem ISize.ofBitVec_sub (a b : BitVec System.Platform.numBits) : ISize.ofBitVec (a - b) = ISize.ofBitVec a - ISize.ofBitVec b := (rfl)
@[simp] theorem Int8.ofInt_sub (a b : Int) : Int8.ofInt (a - b) = Int8.ofInt a - Int8.ofInt b := by
simp [Int8.ofInt_eq_iff_bmod_eq_toInt]
@@ -2009,11 +2009,11 @@ theorem Int64.ofIntLE_sub {a b : Int} {hab₁ hab₂} : Int64.ofIntLE (a - b) ha
theorem ISize.ofIntLE_sub {a b : Int} {hab₁ hab₂} : ISize.ofIntLE (a - b) hab₁ hab₂ = ISize.ofInt a - ISize.ofInt b := by
simp [ISize.ofIntLE_eq_ofInt]
@[simp] theorem Int8.ofBitVec_mul (a b : BitVec 8) : Int8.ofBitVec (a * b) = Int8.ofBitVec a * Int8.ofBitVec b := rfl
@[simp] theorem Int16.ofBitVec_mul (a b : BitVec 16) : Int16.ofBitVec (a * b) = Int16.ofBitVec a * Int16.ofBitVec b := rfl
@[simp] theorem Int32.ofBitVec_mul (a b : BitVec 32) : Int32.ofBitVec (a * b) = Int32.ofBitVec a * Int32.ofBitVec b := rfl
@[simp] theorem Int64.ofBitVec_mul (a b : BitVec 64) : Int64.ofBitVec (a * b) = Int64.ofBitVec a * Int64.ofBitVec b := rfl
@[simp] theorem ISize.ofBitVec_mul (a b : BitVec System.Platform.numBits) : ISize.ofBitVec (a * b) = ISize.ofBitVec a * ISize.ofBitVec b := rfl
@[simp] theorem Int8.ofBitVec_mul (a b : BitVec 8) : Int8.ofBitVec (a * b) = Int8.ofBitVec a * Int8.ofBitVec b := (rfl)
@[simp] theorem Int16.ofBitVec_mul (a b : BitVec 16) : Int16.ofBitVec (a * b) = Int16.ofBitVec a * Int16.ofBitVec b := (rfl)
@[simp] theorem Int32.ofBitVec_mul (a b : BitVec 32) : Int32.ofBitVec (a * b) = Int32.ofBitVec a * Int32.ofBitVec b := (rfl)
@[simp] theorem Int64.ofBitVec_mul (a b : BitVec 64) : Int64.ofBitVec (a * b) = Int64.ofBitVec a * Int64.ofBitVec b := (rfl)
@[simp] theorem ISize.ofBitVec_mul (a b : BitVec System.Platform.numBits) : ISize.ofBitVec (a * b) = ISize.ofBitVec a * ISize.ofBitVec b := (rfl)
@[simp] theorem Int8.ofInt_mul (a b : Int) : Int8.ofInt (a * b) = Int8.ofInt a * Int8.ofInt b := by
simp [Int8.ofInt_eq_iff_bmod_eq_toInt]
@@ -2056,18 +2056,18 @@ theorem ISize.toInt_minValue_lt_zero : minValue.toInt < 0 := by
rw [toInt_minValue, Int.neg_lt_zero_iff]
exact Int.pow_pos (by decide)
theorem Int8.toInt_maxValue_add_one : maxValue.toInt + 1 = 2 ^ 7 := rfl
theorem Int16.toInt_maxValue_add_one : maxValue.toInt + 1 = 2 ^ 15 := rfl
theorem Int32.toInt_maxValue_add_one : maxValue.toInt + 1 = 2 ^ 31 := rfl
theorem Int64.toInt_maxValue_add_one : maxValue.toInt + 1 = 2 ^ 63 := rfl
theorem Int8.toInt_maxValue_add_one : maxValue.toInt + 1 = 2 ^ 7 := (rfl)
theorem Int16.toInt_maxValue_add_one : maxValue.toInt + 1 = 2 ^ 15 := (rfl)
theorem Int32.toInt_maxValue_add_one : maxValue.toInt + 1 = 2 ^ 31 := (rfl)
theorem Int64.toInt_maxValue_add_one : maxValue.toInt + 1 = 2 ^ 63 := (rfl)
theorem ISize.toInt_maxValue_add_one : maxValue.toInt + 1 = 2 ^ (System.Platform.numBits - 1) := by
rw [toInt_maxValue, Int.sub_add_cancel]
@[simp] theorem Int8.ofBitVec_sdiv (a b : BitVec 8) : Int8.ofBitVec (a.sdiv b) = Int8.ofBitVec a / Int8.ofBitVec b := rfl
@[simp] theorem Int16.ofBitVec_sdiv (a b : BitVec 16) : Int16.ofBitVec (a.sdiv b) = Int16.ofBitVec a / Int16.ofBitVec b := rfl
@[simp] theorem Int32.ofBitVec_sdiv (a b : BitVec 32) : Int32.ofBitVec (a.sdiv b) = Int32.ofBitVec a / Int32.ofBitVec b := rfl
@[simp] theorem Int64.ofBitVec_sdiv (a b : BitVec 64) : Int64.ofBitVec (a.sdiv b) = Int64.ofBitVec a / Int64.ofBitVec b := rfl
@[simp] theorem ISize.ofBitVec_sdiv (a b : BitVec System.Platform.numBits) : ISize.ofBitVec (a.sdiv b) = ISize.ofBitVec a / ISize.ofBitVec b := rfl
@[simp] theorem Int8.ofBitVec_sdiv (a b : BitVec 8) : Int8.ofBitVec (a.sdiv b) = Int8.ofBitVec a / Int8.ofBitVec b := (rfl)
@[simp] theorem Int16.ofBitVec_sdiv (a b : BitVec 16) : Int16.ofBitVec (a.sdiv b) = Int16.ofBitVec a / Int16.ofBitVec b := (rfl)
@[simp] theorem Int32.ofBitVec_sdiv (a b : BitVec 32) : Int32.ofBitVec (a.sdiv b) = Int32.ofBitVec a / Int32.ofBitVec b := (rfl)
@[simp] theorem Int64.ofBitVec_sdiv (a b : BitVec 64) : Int64.ofBitVec (a.sdiv b) = Int64.ofBitVec a / Int64.ofBitVec b := (rfl)
@[simp] theorem ISize.ofBitVec_sdiv (a b : BitVec System.Platform.numBits) : ISize.ofBitVec (a.sdiv b) = ISize.ofBitVec a / ISize.ofBitVec b := (rfl)
theorem Int8.ofInt_tdiv {a b : Int} (ha₁ : minValue.toInt a) (ha₂ : a maxValue.toInt)
(hb₁ : minValue.toInt b) (hb₂ : b maxValue.toInt) : Int8.ofInt (a.tdiv b) = Int8.ofInt a / Int8.ofInt b := by
@@ -2162,11 +2162,11 @@ theorem ISize.ofNat_div {a b : Nat} (ha : a < 2 ^ (System.Platform.numBits - 1))
· apply Int.le_of_lt_add_one
simpa only [toInt_maxValue_add_one, Int.ofNat_lt, Int.natCast_pow] using hb
@[simp] theorem Int8.ofBitVec_srem (a b : BitVec 8) : Int8.ofBitVec (a.srem b) = Int8.ofBitVec a % Int8.ofBitVec b := rfl
@[simp] theorem Int16.ofBitVec_srem (a b : BitVec 16) : Int16.ofBitVec (a.srem b) = Int16.ofBitVec a % Int16.ofBitVec b := rfl
@[simp] theorem Int32.ofBitVec_srem (a b : BitVec 32) : Int32.ofBitVec (a.srem b) = Int32.ofBitVec a % Int32.ofBitVec b := rfl
@[simp] theorem Int64.ofBitVec_srem (a b : BitVec 64) : Int64.ofBitVec (a.srem b) = Int64.ofBitVec a % Int64.ofBitVec b := rfl
@[simp] theorem ISize.ofBitVec_srem (a b : BitVec System.Platform.numBits) : ISize.ofBitVec (a.srem b) = ISize.ofBitVec a % ISize.ofBitVec b := rfl
@[simp] theorem Int8.ofBitVec_srem (a b : BitVec 8) : Int8.ofBitVec (a.srem b) = Int8.ofBitVec a % Int8.ofBitVec b := (rfl)
@[simp] theorem Int16.ofBitVec_srem (a b : BitVec 16) : Int16.ofBitVec (a.srem b) = Int16.ofBitVec a % Int16.ofBitVec b := (rfl)
@[simp] theorem Int32.ofBitVec_srem (a b : BitVec 32) : Int32.ofBitVec (a.srem b) = Int32.ofBitVec a % Int32.ofBitVec b := (rfl)
@[simp] theorem Int64.ofBitVec_srem (a b : BitVec 64) : Int64.ofBitVec (a.srem b) = Int64.ofBitVec a % Int64.ofBitVec b := (rfl)
@[simp] theorem ISize.ofBitVec_srem (a b : BitVec System.Platform.numBits) : ISize.ofBitVec (a.srem b) = ISize.ofBitVec a % ISize.ofBitVec b := (rfl)
@[simp] theorem Int8.toInt_bmod_size (a : Int8) : a.toInt.bmod size = a.toInt := BitVec.toInt_bmod_cancel _
@[simp] theorem Int16.toInt_bmod_size (a : Int16) : a.toInt.bmod size = a.toInt := BitVec.toInt_bmod_cancel _
@@ -2300,16 +2300,16 @@ theorem Int32.ofBitVec_lt_iff_slt (a b : BitVec 32) : Int32.ofBitVec a < Int32.o
theorem Int64.ofBitVec_lt_iff_slt (a b : BitVec 64) : Int64.ofBitVec a < Int64.ofBitVec b a.slt b := Iff.rfl
theorem ISize.ofBitVec_lt_iff_slt (a b : BitVec System.Platform.numBits) : ISize.ofBitVec a < ISize.ofBitVec b a.slt b := Iff.rfl
theorem Int8.toNatClampNeg_one : (1 : Int8).toNatClampNeg = 1 := rfl
theorem Int16.toNatClampNeg_one : (1 : Int16).toNatClampNeg = 1 := rfl
theorem Int32.toNatClampNeg_one : (1 : Int32).toNatClampNeg = 1 := rfl
theorem Int64.toNatClampNeg_one : (1 : Int64).toNatClampNeg = 1 := rfl
theorem Int8.toNatClampNeg_one : (1 : Int8).toNatClampNeg = 1 := (rfl)
theorem Int16.toNatClampNeg_one : (1 : Int16).toNatClampNeg = 1 := (rfl)
theorem Int32.toNatClampNeg_one : (1 : Int32).toNatClampNeg = 1 := (rfl)
theorem Int64.toNatClampNeg_one : (1 : Int64).toNatClampNeg = 1 := (rfl)
theorem ISize.toNatClampNeg_one : (1 : ISize).toNatClampNeg = 1 := by simp
theorem Int8.toInt_one : (1 : Int8).toInt = 1 := rfl
theorem Int16.toInt_one : (1 : Int16).toInt = 1 := rfl
theorem Int32.toInt_one : (1 : Int32).toInt = 1 := rfl
theorem Int64.toInt_one : (1 : Int64).toInt = 1 := rfl
theorem Int8.toInt_one : (1 : Int8).toInt = 1 := (rfl)
theorem Int16.toInt_one : (1 : Int16).toInt = 1 := (rfl)
theorem Int32.toInt_one : (1 : Int32).toInt = 1 := (rfl)
theorem Int64.toInt_one : (1 : Int64).toInt = 1 := (rfl)
theorem ISize.toInt_one : (1 : ISize).toInt = 1 := by simp
theorem Int8.zero_lt_one : (0 : Int8) < 1 := by simp
@@ -2631,16 +2631,16 @@ instance : Std.LawfulCommIdentity (α := ISize) (· * ·) 1 where
@[simp] theorem Int64.zero_mul {a : Int64} : 0 * a = 0 := Int64.toBitVec_inj.1 BitVec.zero_mul
@[simp] theorem ISize.zero_mul {a : ISize} : 0 * a = 0 := ISize.toBitVec_inj.1 BitVec.zero_mul
@[simp] protected theorem Int8.pow_zero (x : Int8) : x ^ 0 = 1 := rfl
protected theorem Int8.pow_succ (x : Int8) (n : Nat) : x ^ (n + 1) = x ^ n * x := rfl
@[simp] protected theorem Int16.pow_zero (x : Int16) : x ^ 0 = 1 := rfl
protected theorem Int16.pow_succ (x : Int16) (n : Nat) : x ^ (n + 1) = x ^ n * x := rfl
@[simp] protected theorem Int32.pow_zero (x : Int32) : x ^ 0 = 1 := rfl
protected theorem Int32.pow_succ (x : Int32) (n : Nat) : x ^ (n + 1) = x ^ n * x := rfl
@[simp] protected theorem Int64.pow_zero (x : Int64) : x ^ 0 = 1 := rfl
protected theorem Int64.pow_succ (x : Int64) (n : Nat) : x ^ (n + 1) = x ^ n * x := rfl
@[simp] protected theorem ISize.pow_zero (x : ISize) : x ^ 0 = 1 := rfl
protected theorem ISize.pow_succ (x : ISize) (n : Nat) : x ^ (n + 1) = x ^ n * x := rfl
@[simp] protected theorem Int8.pow_zero (x : Int8) : x ^ 0 = 1 := (rfl)
protected theorem Int8.pow_succ (x : Int8) (n : Nat) : x ^ (n + 1) = x ^ n * x := (rfl)
@[simp] protected theorem Int16.pow_zero (x : Int16) : x ^ 0 = 1 := (rfl)
protected theorem Int16.pow_succ (x : Int16) (n : Nat) : x ^ (n + 1) = x ^ n * x := (rfl)
@[simp] protected theorem Int32.pow_zero (x : Int32) : x ^ 0 = 1 := (rfl)
protected theorem Int32.pow_succ (x : Int32) (n : Nat) : x ^ (n + 1) = x ^ n * x := (rfl)
@[simp] protected theorem Int64.pow_zero (x : Int64) : x ^ 0 = 1 := (rfl)
protected theorem Int64.pow_succ (x : Int64) (n : Nat) : x ^ (n + 1) = x ^ n * x := (rfl)
@[simp] protected theorem ISize.pow_zero (x : ISize) : x ^ 0 = 1 := (rfl)
protected theorem ISize.pow_succ (x : ISize) (n : Nat) : x ^ (n + 1) = x ^ n * x := (rfl)
protected theorem Int8.mul_add {a b c : Int8} : a * (b + c) = a * b + a * c :=
Int8.toBitVec_inj.1 BitVec.mul_add
@@ -3092,53 +3092,53 @@ theorem Int64.toInt_eq_toNatClampNeg {a : Int64} (ha : 0 ≤ a) : a.toInt = a.to
theorem ISize.toInt_eq_toNatClampNeg {a : ISize} (ha : 0 a) : a.toInt = a.toNatClampNeg := by
simpa only [ toNat_toInt, Int.eq_natCast_toNat, le_iff_toInt_le, toInt_zero] using ha
@[simp] theorem UInt8.toInt8_add (a b : UInt8) : (a + b).toInt8 = a.toInt8 + b.toInt8 := rfl
@[simp] theorem UInt16.toInt16_add (a b : UInt16) : (a + b).toInt16 = a.toInt16 + b.toInt16 := rfl
@[simp] theorem UInt32.toInt32_add (a b : UInt32) : (a + b).toInt32 = a.toInt32 + b.toInt32 := rfl
@[simp] theorem UInt64.toInt64_add (a b : UInt64) : (a + b).toInt64 = a.toInt64 + b.toInt64 := rfl
@[simp] theorem USize.toISize_add (a b : USize) : (a + b).toISize = a.toISize + b.toISize := rfl
@[simp] theorem UInt8.toInt8_add (a b : UInt8) : (a + b).toInt8 = a.toInt8 + b.toInt8 := (rfl)
@[simp] theorem UInt16.toInt16_add (a b : UInt16) : (a + b).toInt16 = a.toInt16 + b.toInt16 := (rfl)
@[simp] theorem UInt32.toInt32_add (a b : UInt32) : (a + b).toInt32 = a.toInt32 + b.toInt32 := (rfl)
@[simp] theorem UInt64.toInt64_add (a b : UInt64) : (a + b).toInt64 = a.toInt64 + b.toInt64 := (rfl)
@[simp] theorem USize.toISize_add (a b : USize) : (a + b).toISize = a.toISize + b.toISize := (rfl)
@[simp] theorem UInt8.toInt8_neg (a : UInt8) : (-a).toInt8 = -a.toInt8 := rfl
@[simp] theorem UInt16.toInt16_neg (a : UInt16) : (-a).toInt16 = -a.toInt16 := rfl
@[simp] theorem UInt32.toInt32_neg (a : UInt32) : (-a).toInt32 = -a.toInt32 := rfl
@[simp] theorem UInt64.toInt64_neg (a : UInt64) : (-a).toInt64 = -a.toInt64 := rfl
@[simp] theorem USize.toISize_neg (a : USize) : (-a).toISize = -a.toISize := rfl
@[simp] theorem UInt8.toInt8_neg (a : UInt8) : (-a).toInt8 = -a.toInt8 := (rfl)
@[simp] theorem UInt16.toInt16_neg (a : UInt16) : (-a).toInt16 = -a.toInt16 := (rfl)
@[simp] theorem UInt32.toInt32_neg (a : UInt32) : (-a).toInt32 = -a.toInt32 := (rfl)
@[simp] theorem UInt64.toInt64_neg (a : UInt64) : (-a).toInt64 = -a.toInt64 := (rfl)
@[simp] theorem USize.toISize_neg (a : USize) : (-a).toISize = -a.toISize := (rfl)
@[simp] theorem UInt8.toInt8_sub (a b : UInt8) : (a - b).toInt8 = a.toInt8 - b.toInt8 := rfl
@[simp] theorem UInt16.toInt16_sub (a b : UInt16) : (a - b).toInt16 = a.toInt16 - b.toInt16 := rfl
@[simp] theorem UInt32.toInt32_sub (a b : UInt32) : (a - b).toInt32 = a.toInt32 - b.toInt32 := rfl
@[simp] theorem UInt64.toInt64_sub (a b : UInt64) : (a - b).toInt64 = a.toInt64 - b.toInt64 := rfl
@[simp] theorem USize.toISize_sub (a b : USize) : (a - b).toISize = a.toISize - b.toISize := rfl
@[simp] theorem UInt8.toInt8_sub (a b : UInt8) : (a - b).toInt8 = a.toInt8 - b.toInt8 := (rfl)
@[simp] theorem UInt16.toInt16_sub (a b : UInt16) : (a - b).toInt16 = a.toInt16 - b.toInt16 := (rfl)
@[simp] theorem UInt32.toInt32_sub (a b : UInt32) : (a - b).toInt32 = a.toInt32 - b.toInt32 := (rfl)
@[simp] theorem UInt64.toInt64_sub (a b : UInt64) : (a - b).toInt64 = a.toInt64 - b.toInt64 := (rfl)
@[simp] theorem USize.toISize_sub (a b : USize) : (a - b).toISize = a.toISize - b.toISize := (rfl)
@[simp] theorem UInt8.toInt8_mul (a b : UInt8) : (a * b).toInt8 = a.toInt8 * b.toInt8 := rfl
@[simp] theorem UInt16.toInt16_mul (a b : UInt16) : (a * b).toInt16 = a.toInt16 * b.toInt16 := rfl
@[simp] theorem UInt32.toInt32_mul (a b : UInt32) : (a * b).toInt32 = a.toInt32 * b.toInt32 := rfl
@[simp] theorem UInt64.toInt64_mul (a b : UInt64) : (a * b).toInt64 = a.toInt64 * b.toInt64 := rfl
@[simp] theorem USize.toISize_mul (a b : USize) : (a * b).toISize = a.toISize * b.toISize := rfl
@[simp] theorem UInt8.toInt8_mul (a b : UInt8) : (a * b).toInt8 = a.toInt8 * b.toInt8 := (rfl)
@[simp] theorem UInt16.toInt16_mul (a b : UInt16) : (a * b).toInt16 = a.toInt16 * b.toInt16 := (rfl)
@[simp] theorem UInt32.toInt32_mul (a b : UInt32) : (a * b).toInt32 = a.toInt32 * b.toInt32 := (rfl)
@[simp] theorem UInt64.toInt64_mul (a b : UInt64) : (a * b).toInt64 = a.toInt64 * b.toInt64 := (rfl)
@[simp] theorem USize.toISize_mul (a b : USize) : (a * b).toISize = a.toISize * b.toISize := (rfl)
@[simp] theorem Int8.toUInt8_add (a b : Int8) : (a + b).toUInt8 = a.toUInt8 + b.toUInt8 := rfl
@[simp] theorem Int16.toUInt16_add (a b : Int16) : (a + b).toUInt16 = a.toUInt16 + b.toUInt16 := rfl
@[simp] theorem Int32.toUInt32_add (a b : Int32) : (a + b).toUInt32 = a.toUInt32 + b.toUInt32 := rfl
@[simp] theorem Int64.toUInt64_add (a b : Int64) : (a + b).toUInt64 = a.toUInt64 + b.toUInt64 := rfl
@[simp] theorem ISize.toUSize_add (a b : ISize) : (a + b).toUSize = a.toUSize + b.toUSize := rfl
@[simp] theorem Int8.toUInt8_add (a b : Int8) : (a + b).toUInt8 = a.toUInt8 + b.toUInt8 := (rfl)
@[simp] theorem Int16.toUInt16_add (a b : Int16) : (a + b).toUInt16 = a.toUInt16 + b.toUInt16 := (rfl)
@[simp] theorem Int32.toUInt32_add (a b : Int32) : (a + b).toUInt32 = a.toUInt32 + b.toUInt32 := (rfl)
@[simp] theorem Int64.toUInt64_add (a b : Int64) : (a + b).toUInt64 = a.toUInt64 + b.toUInt64 := (rfl)
@[simp] theorem ISize.toUSize_add (a b : ISize) : (a + b).toUSize = a.toUSize + b.toUSize := (rfl)
@[simp] theorem Int8.toUInt8_neg (a : Int8) : (-a).toUInt8 = -a.toUInt8 := rfl
@[simp] theorem Int16.toUInt16_neg (a : Int16) : (-a).toUInt16 = -a.toUInt16 := rfl
@[simp] theorem Int32.toUInt32_neg (a : Int32) : (-a).toUInt32 = -a.toUInt32 := rfl
@[simp] theorem Int64.toUInt64_neg (a : Int64) : (-a).toUInt64 = -a.toUInt64 := rfl
@[simp] theorem ISize.toUSize_neg (a : ISize) : (-a).toUSize = -a.toUSize := rfl
@[simp] theorem Int8.toUInt8_neg (a : Int8) : (-a).toUInt8 = -a.toUInt8 := (rfl)
@[simp] theorem Int16.toUInt16_neg (a : Int16) : (-a).toUInt16 = -a.toUInt16 := (rfl)
@[simp] theorem Int32.toUInt32_neg (a : Int32) : (-a).toUInt32 = -a.toUInt32 := (rfl)
@[simp] theorem Int64.toUInt64_neg (a : Int64) : (-a).toUInt64 = -a.toUInt64 := (rfl)
@[simp] theorem ISize.toUSize_neg (a : ISize) : (-a).toUSize = -a.toUSize := (rfl)
@[simp] theorem Int8.toUInt8_sub (a b : Int8) : (a - b).toUInt8 = a.toUInt8 - b.toUInt8 := rfl
@[simp] theorem Int16.toUInt16_sub (a b : Int16) : (a - b).toUInt16 = a.toUInt16 - b.toUInt16 := rfl
@[simp] theorem Int32.toUInt32_sub (a b : Int32) : (a - b).toUInt32 = a.toUInt32 - b.toUInt32 := rfl
@[simp] theorem Int64.toUInt64_sub (a b : Int64) : (a - b).toUInt64 = a.toUInt64 - b.toUInt64 := rfl
@[simp] theorem ISize.toUSize_sub (a b : ISize) : (a - b).toUSize = a.toUSize - b.toUSize := rfl
@[simp] theorem Int8.toUInt8_sub (a b : Int8) : (a - b).toUInt8 = a.toUInt8 - b.toUInt8 := (rfl)
@[simp] theorem Int16.toUInt16_sub (a b : Int16) : (a - b).toUInt16 = a.toUInt16 - b.toUInt16 := (rfl)
@[simp] theorem Int32.toUInt32_sub (a b : Int32) : (a - b).toUInt32 = a.toUInt32 - b.toUInt32 := (rfl)
@[simp] theorem Int64.toUInt64_sub (a b : Int64) : (a - b).toUInt64 = a.toUInt64 - b.toUInt64 := (rfl)
@[simp] theorem ISize.toUSize_sub (a b : ISize) : (a - b).toUSize = a.toUSize - b.toUSize := (rfl)
@[simp] theorem Int8.toUInt8_mul (a b : Int8) : (a * b).toUInt8 = a.toUInt8 * b.toUInt8 := rfl
@[simp] theorem Int16.toUInt16_mul (a b : Int16) : (a * b).toUInt16 = a.toUInt16 * b.toUInt16 := rfl
@[simp] theorem Int32.toUInt32_mul (a b : Int32) : (a * b).toUInt32 = a.toUInt32 * b.toUInt32 := rfl
@[simp] theorem Int64.toUInt64_mul (a b : Int64) : (a * b).toUInt64 = a.toUInt64 * b.toUInt64 := rfl
@[simp] theorem ISize.toUSize_mul (a b : ISize) : (a * b).toUSize = a.toUSize * b.toUSize := rfl
@[simp] theorem Int8.toUInt8_mul (a b : Int8) : (a * b).toUInt8 = a.toUInt8 * b.toUInt8 := (rfl)
@[simp] theorem Int16.toUInt16_mul (a b : Int16) : (a * b).toUInt16 = a.toUInt16 * b.toUInt16 := (rfl)
@[simp] theorem Int32.toUInt32_mul (a b : Int32) : (a * b).toUInt32 = a.toUInt32 * b.toUInt32 := (rfl)
@[simp] theorem Int64.toUInt64_mul (a b : Int64) : (a * b).toUInt64 = a.toUInt64 * b.toUInt64 := (rfl)
@[simp] theorem ISize.toUSize_mul (a b : ISize) : (a * b).toUSize = a.toUSize * b.toUSize := (rfl)
theorem Int8.toNatClampNeg_le {a b : Int8} (hab : a b) : a.toNatClampNeg b.toNatClampNeg := by
rw [ Int8.toNat_toInt, Int8.toNat_toInt]

View File

@@ -57,7 +57,7 @@ Examples:
* `"abc".length = 3`
* `"L∃∀N".length = 4`
-/
@[extern "lean_string_length"]
@[extern "lean_string_length", expose]
def length : (@& String) Nat
| s => s.length
@@ -71,7 +71,7 @@ Examples:
* `"abc".push 'd' = "abcd"`
* `"".push 'a' = "a"`
-/
@[extern "lean_string_push"]
@[extern "lean_string_push", expose]
def push : String Char String
| s, c => s ++ [c]
@@ -85,7 +85,7 @@ Examples:
* `"abc" ++ "def" = "abcdef"`
* `"" ++ "" = ""`
-/
@[extern "lean_string_append"]
@[extern "lean_string_append", expose]
def append : String (@& String) String
| a, b => a ++ b
@@ -145,7 +145,7 @@ Examples:
* `"abc".get ⟨3⟩ = (default : Char)` because byte `3` is at the end of the string.
* `"L∃∀N".get ⟨2⟩ = (default : Char)` because byte `2` is in the middle of `'∃'`.
-/
@[extern "lean_string_utf8_get"]
@[extern "lean_string_utf8_get", expose]
def get (s : @& String) (p : @& Pos) : Char :=
match s with
| s => utf8GetAux s 0 p
@@ -182,7 +182,7 @@ This function is overridden with an efficient implementation in runtime code. Se
Examples
* `"abc".get! ⟨1⟩ = 'b'`
-/
@[extern "lean_string_utf8_get_bang"]
@[extern "lean_string_utf8_get_bang", expose]
def get! (s : @& String) (p : @& Pos) : Char :=
match s with
| s => utf8GetAux s 0 p
@@ -239,7 +239,7 @@ Examples:
* `"abc".get ("abc".next 0) = 'b'`
* `"L∃∀N".get (0 |> "L∃∀N".next |> "L∃∀N".next) = '∀'`
-/
@[extern "lean_string_utf8_next"]
@[extern "lean_string_utf8_next", expose]
def next (s : @& String) (p : @& Pos) : Pos :=
let c := get s p
p + c
@@ -261,7 +261,7 @@ Examples:
* `"abc".get ("abc".endPos |> "abc".prev) = 'c'`
* `"L∃∀N".get ("L∃∀N".endPos |> "L∃∀N".prev |> "L∃∀N".prev |> "L∃∀N".prev) = '∃'`
-/
@[extern "lean_string_utf8_prev"]
@[extern "lean_string_utf8_prev", expose]
def prev : (@& String) (@& Pos) Pos
| s, p => if p = 0 then 0 else utf8PrevAux s 0 p
@@ -322,7 +322,7 @@ Examples:
* `"abc".get' 0 (by decide) = 'a'`
* `let lean := "L∃∀N"; lean.get' (0 |> lean.next |> lean.next) (by decide) = '∀'`
-/
@[extern "lean_string_utf8_get_fast"]
@[extern "lean_string_utf8_get_fast", expose]
def get' (s : @& String) (p : @& Pos) (h : ¬ s.atEnd p) : Char :=
match s with
| s => utf8GetAux s 0 p
@@ -344,7 +344,7 @@ def next? (s: String) (p : String.Pos) : Option Char :=
Example:
* `let abc := "abc"; abc.get (abc.next' 0 (by decide)) = 'b'`
-/
@[extern "lean_string_utf8_next_fast"]
@[extern "lean_string_utf8_next_fast", expose]
def next' (s : @& String) (p : @& Pos) (h : ¬ s.atEnd p) : Pos :=
let c := get s p
p + c
@@ -669,7 +669,7 @@ Examples:
* `String.singleton '"' = "\""`
* `String.singleton '𝒫' = "𝒫"`
-/
@[inline] def singleton (c : Char) : String :=
@[inline,expose] def singleton (c : Char) : String :=
"".push c
/--
@@ -1954,7 +1954,7 @@ Examples:
* `'L'.toString = "L"`
* `'"'.toString = "\""`
-/
@[inline] protected def toString (c : Char) : String :=
@[inline, expose] protected def toString (c : Char) : String :=
String.singleton c
@[simp] theorem length_toString (c : Char) : c.toString.length = 1 := rfl

View File

@@ -49,30 +49,30 @@ deriving instance BEq for Sum
section get
/-- Checks whether a sum is the left injection `inl`. -/
def isLeft : α β Bool
@[expose] def isLeft : α β Bool
| inl _ => true
| inr _ => false
/-- Checks whether a sum is the right injection `inr`. -/
def isRight : α β Bool
@[expose] def isRight : α β Bool
| inl _ => false
| inr _ => true
/-- Retrieves the contents from a sum known to be `inl`.-/
def getLeft : (ab : α β) ab.isLeft α
@[expose] def getLeft : (ab : α β) ab.isLeft α
| inl a, _ => a
/-- Retrieves the contents from a sum known to be `inr`.-/
def getRight : (ab : α β) ab.isRight β
@[expose] def getRight : (ab : α β) ab.isRight β
| inr b, _ => b
/-- Checks whether a sum is the left injection `inl` and, if so, retrieves its contents. -/
def getLeft? : α β Option α
@[expose] def getLeft? : α β Option α
| inl a => some a
| inr _ => none
/-- Checks whether a sum is the right injection `inr` and, if so, retrieves its contents. -/
def getRight? : α β Option β
@[expose] def getRight? : α β Option β
| inr b => some b
| inl _ => none
@@ -95,7 +95,7 @@ end get
Case analysis for sums that applies the appropriate function `f` or `g` after checking which
constructor is present.
-/
protected def elim {α β γ} (f : α γ) (g : β γ) : α β γ :=
@[expose] protected def elim {α β γ} (f : α γ) (g : β γ) : α β γ :=
fun x => Sum.casesOn x f g
@[simp] theorem elim_inl (f : α γ) (g : β γ) (x : α) :
@@ -109,7 +109,7 @@ Transforms a sum according to functions on each type.
This function maps `α ⊕ β` to `α' ⊕ β'`, sending `α` to `α'` and `β` to `β'`.
-/
protected def map (f : α α') (g : β β') : α β α' β' :=
@[expose] protected def map (f : α α') (g : β β') : α β α' β' :=
Sum.elim (inl f) (inr g)
@[simp] theorem map_inl (f : α α') (g : β β') (x : α) : (inl x).map f g = inl (f x) := rfl
@@ -121,7 +121,7 @@ Swaps the factors of a sum type.
The constructor `Sum.inl` is replaced with `Sum.inr`, and vice versa.
-/
def swap : α β β α := Sum.elim inr inl
@[expose] def swap : α β β α := Sum.elim inr inl
@[simp] theorem swap_inl : swap (inl x : α β) = inr x := rfl

View File

@@ -220,7 +220,7 @@ instance UInt32.instOfNat : OfNat UInt32 n := ⟨UInt32.ofNat n⟩
theorem UInt32.ofNatLT_lt_of_lt {n m : Nat} (h1 : n < UInt32.size) (h2 : m < UInt32.size) :
n < m UInt32.ofNatLT n h1 < UInt32.ofNat m := by
simp only [(· < ·), BitVec.toNat, ofNatLT, BitVec.ofNatLT, ofNat, BitVec.ofNat, Fin.ofNat',
simp only [(· < ·), BitVec.toNat, ofNatLT, BitVec.ofNatLT, ofNat, BitVec.ofNat, Fin.ofNat,
Nat.mod_eq_of_lt h2, imp_self]
@[deprecated UInt32.ofNatLT_lt_of_lt (since := "2025-02-13")]
@@ -229,7 +229,7 @@ theorem UInt32.ofNat'_lt_of_lt {n m : Nat} (h1 : n < UInt32.size) (h2 : m < UInt
theorem UInt32.lt_ofNatLT_of_lt {n m : Nat} (h1 : n < UInt32.size) (h2 : m < UInt32.size) :
m < n UInt32.ofNat m < UInt32.ofNatLT n h1 := by
simp only [(· < ·), BitVec.toNat, ofNatLT, BitVec.ofNatLT, ofNat, BitVec.ofNat, Fin.ofNat',
simp only [(· < ·), BitVec.toNat, ofNatLT, BitVec.ofNatLT, ofNat, BitVec.ofNat, Fin.ofNat,
Nat.mod_eq_of_lt h2, imp_self]
@[deprecated UInt32.lt_ofNatLT_of_lt (since := "2025-02-13")]
@@ -336,9 +336,6 @@ theorem usize_size_eq : USize.size = 4294967296 USize.size = 184467440737095
theorem usize_size_pos : 0 < USize.size :=
USize.size_pos
@[deprecated USize.size_pos (since := "2024-11-24")] theorem usize_size_gt_zero : USize.size > 0 :=
USize.size_pos
/-- Converts a `USize` into the corresponding `Fin USize.size`. -/
def USize.toFin (x : USize) : Fin USize.size := x.toBitVec.toFin
@[deprecated USize.toFin (since := "2025-02-12"), inherit_doc USize.toFin]

View File

@@ -16,12 +16,12 @@ macro "declare_bitwise_uint_theorems" typeName:ident bits:term:arg : command =>
`(
namespace $typeName
@[simp, int_toBitVec] protected theorem toBitVec_not {a : $typeName} : (~~~a).toBitVec = ~~~a.toBitVec := rfl
@[simp, int_toBitVec] protected theorem toBitVec_and (a b : $typeName) : (a &&& b).toBitVec = a.toBitVec &&& b.toBitVec := rfl
@[simp, int_toBitVec] protected theorem toBitVec_or (a b : $typeName) : (a ||| b).toBitVec = a.toBitVec ||| b.toBitVec := rfl
@[simp, int_toBitVec] protected theorem toBitVec_xor (a b : $typeName) : (a ^^^ b).toBitVec = a.toBitVec ^^^ b.toBitVec := rfl
@[simp, int_toBitVec] protected theorem toBitVec_shiftLeft (a b : $typeName) : (a <<< b).toBitVec = a.toBitVec <<< (b.toBitVec % $bits) := rfl
@[simp, int_toBitVec] protected theorem toBitVec_shiftRight (a b : $typeName) : (a >>> b).toBitVec = a.toBitVec >>> (b.toBitVec % $bits) := rfl
@[simp, int_toBitVec] protected theorem toBitVec_not {a : $typeName} : (~~~a).toBitVec = ~~~a.toBitVec := (rfl)
@[simp, int_toBitVec] protected theorem toBitVec_and (a b : $typeName) : (a &&& b).toBitVec = a.toBitVec &&& b.toBitVec := (rfl)
@[simp, int_toBitVec] protected theorem toBitVec_or (a b : $typeName) : (a ||| b).toBitVec = a.toBitVec ||| b.toBitVec := (rfl)
@[simp, int_toBitVec] protected theorem toBitVec_xor (a b : $typeName) : (a ^^^ b).toBitVec = a.toBitVec ^^^ b.toBitVec := (rfl)
@[simp, int_toBitVec] protected theorem toBitVec_shiftLeft (a b : $typeName) : (a <<< b).toBitVec = a.toBitVec <<< (b.toBitVec % $bits) := (rfl)
@[simp, int_toBitVec] protected theorem toBitVec_shiftRight (a b : $typeName) : (a >>> b).toBitVec = a.toBitVec >>> (b.toBitVec % $bits) := (rfl)
@[simp] protected theorem toNat_and (a b : $typeName) : (a &&& b).toNat = a.toNat &&& b.toNat := by simp [toNat, -toNat_toBitVec]
@[simp] protected theorem toNat_or (a b : $typeName) : (a ||| b).toNat = a.toNat ||| b.toNat := by simp [toNat, -toNat_toBitVec]
@@ -29,10 +29,6 @@ namespace $typeName
@[simp] protected theorem toNat_shiftLeft (a b : $typeName) : (a <<< b).toNat = a.toNat <<< (b.toNat % $bits) % 2 ^ $bits := by simp [toNat, -toNat_toBitVec]
@[simp] protected theorem toNat_shiftRight (a b : $typeName) : (a >>> b).toNat = a.toNat >>> (b.toNat % $bits) := by simp [toNat, -toNat_toBitVec]
open $typeName (toNat_and) in
@[deprecated toNat_and (since := "2024-11-28")]
protected theorem and_toNat (a b : $typeName) : (a &&& b).toNat = a.toNat &&& b.toNat := BitVec.toNat_and ..
end $typeName
)
declare_bitwise_uint_theorems UInt8 8
@@ -75,25 +71,25 @@ theorem Bool.toBitVec_toUSize {b : Bool} :
@[simp] theorem UInt64.toFin_and (a b : UInt64) : (a &&& b).toFin = a.toFin &&& b.toFin := Fin.val_inj.1 (by simp)
@[simp] theorem USize.toFin_and (a b : USize) : (a &&& b).toFin = a.toFin &&& b.toFin := Fin.val_inj.1 (by simp)
@[simp] theorem UInt8.toUInt16_and (a b : UInt8) : (a &&& b).toUInt16 = a.toUInt16 &&& b.toUInt16 := rfl
@[simp] theorem UInt8.toUInt32_and (a b : UInt8) : (a &&& b).toUInt32 = a.toUInt32 &&& b.toUInt32 := rfl
@[simp] theorem UInt8.toUInt64_and (a b : UInt8) : (a &&& b).toUInt64 = a.toUInt64 &&& b.toUInt64 := rfl
@[simp] theorem UInt8.toUSize_and (a b : UInt8) : (a &&& b).toUSize = a.toUSize &&& b.toUSize := rfl
@[simp] theorem UInt8.toUInt16_and (a b : UInt8) : (a &&& b).toUInt16 = a.toUInt16 &&& b.toUInt16 := (rfl)
@[simp] theorem UInt8.toUInt32_and (a b : UInt8) : (a &&& b).toUInt32 = a.toUInt32 &&& b.toUInt32 := (rfl)
@[simp] theorem UInt8.toUInt64_and (a b : UInt8) : (a &&& b).toUInt64 = a.toUInt64 &&& b.toUInt64 := (rfl)
@[simp] theorem UInt8.toUSize_and (a b : UInt8) : (a &&& b).toUSize = a.toUSize &&& b.toUSize := (rfl)
@[simp] theorem UInt16.toUInt8_and (a b : UInt16) : (a &&& b).toUInt8 = a.toUInt8 &&& b.toUInt8 := UInt8.toBitVec_inj.1 (by simp)
@[simp] theorem UInt16.toUInt32_and (a b : UInt16) : (a &&& b).toUInt32 = a.toUInt32 &&& b.toUInt32 := rfl
@[simp] theorem UInt16.toUInt64_and (a b : UInt16) : (a &&& b).toUInt64 = a.toUInt64 &&& b.toUInt64 := rfl
@[simp] theorem UInt16.toUSize_and (a b : UInt16) : (a &&& b).toUSize = a.toUSize &&& b.toUSize := rfl
@[simp] theorem UInt16.toUInt32_and (a b : UInt16) : (a &&& b).toUInt32 = a.toUInt32 &&& b.toUInt32 := (rfl)
@[simp] theorem UInt16.toUInt64_and (a b : UInt16) : (a &&& b).toUInt64 = a.toUInt64 &&& b.toUInt64 := (rfl)
@[simp] theorem UInt16.toUSize_and (a b : UInt16) : (a &&& b).toUSize = a.toUSize &&& b.toUSize := (rfl)
@[simp] theorem UInt32.toUInt8_and (a b : UInt32) : (a &&& b).toUInt8 = a.toUInt8 &&& b.toUInt8 := UInt8.toBitVec_inj.1 (by simp)
@[simp] theorem UInt32.toUInt16_and (a b : UInt32) : (a &&& b).toUInt16 = a.toUInt16 &&& b.toUInt16 := UInt16.toBitVec_inj.1 (by simp)
@[simp] theorem UInt32.toUInt64_and (a b : UInt32) : (a &&& b).toUInt64 = a.toUInt64 &&& b.toUInt64 := rfl
@[simp] theorem UInt32.toUSize_and (a b : UInt32) : (a &&& b).toUSize = a.toUSize &&& b.toUSize := rfl
@[simp] theorem UInt32.toUInt64_and (a b : UInt32) : (a &&& b).toUInt64 = a.toUInt64 &&& b.toUInt64 := (rfl)
@[simp] theorem UInt32.toUSize_and (a b : UInt32) : (a &&& b).toUSize = a.toUSize &&& b.toUSize := (rfl)
@[simp] theorem USize.toUInt8_and (a b : USize) : (a &&& b).toUInt8 = a.toUInt8 &&& b.toUInt8 := UInt8.toBitVec_inj.1 (by simp)
@[simp] theorem USize.toUInt16_and (a b : USize) : (a &&& b).toUInt16 = a.toUInt16 &&& b.toUInt16 := UInt16.toBitVec_inj.1 (by simp)
@[simp] theorem USize.toUInt32_and (a b : USize) : (a &&& b).toUInt32 = a.toUInt32 &&& b.toUInt32 := UInt32.toBitVec_inj.1 (by simp)
@[simp] theorem USize.toUInt64_and (a b : USize) : (a &&& b).toUInt64 = a.toUInt64 &&& b.toUInt64 := rfl
@[simp] theorem USize.toUInt64_and (a b : USize) : (a &&& b).toUInt64 = a.toUInt64 &&& b.toUInt64 := (rfl)
@[simp] theorem UInt64.toUInt8_and (a b : UInt64) : (a &&& b).toUInt8 = a.toUInt8 &&& b.toUInt8 := UInt8.toBitVec_inj.1 (by simp)
@[simp] theorem UInt64.toUInt16_and (a b : UInt64) : (a &&& b).toUInt16 = a.toUInt16 &&& b.toUInt16 := UInt16.toBitVec_inj.1 (by simp)
@@ -106,25 +102,25 @@ theorem Bool.toBitVec_toUSize {b : Bool} :
@[simp] theorem UInt64.toFin_or (a b : UInt64) : (a ||| b).toFin = a.toFin ||| b.toFin := Fin.val_inj.1 (by simp)
@[simp] theorem USize.toFin_or (a b : USize) : (a ||| b).toFin = a.toFin ||| b.toFin := Fin.val_inj.1 (by simp)
@[simp] theorem UInt8.toUInt16_or (a b : UInt8) : (a ||| b).toUInt16 = a.toUInt16 ||| b.toUInt16 := rfl
@[simp] theorem UInt8.toUInt32_or (a b : UInt8) : (a ||| b).toUInt32 = a.toUInt32 ||| b.toUInt32 := rfl
@[simp] theorem UInt8.toUInt64_or (a b : UInt8) : (a ||| b).toUInt64 = a.toUInt64 ||| b.toUInt64 := rfl
@[simp] theorem UInt8.toUSize_or (a b : UInt8) : (a ||| b).toUSize = a.toUSize ||| b.toUSize := rfl
@[simp] theorem UInt8.toUInt16_or (a b : UInt8) : (a ||| b).toUInt16 = a.toUInt16 ||| b.toUInt16 := (rfl)
@[simp] theorem UInt8.toUInt32_or (a b : UInt8) : (a ||| b).toUInt32 = a.toUInt32 ||| b.toUInt32 := (rfl)
@[simp] theorem UInt8.toUInt64_or (a b : UInt8) : (a ||| b).toUInt64 = a.toUInt64 ||| b.toUInt64 := (rfl)
@[simp] theorem UInt8.toUSize_or (a b : UInt8) : (a ||| b).toUSize = a.toUSize ||| b.toUSize := (rfl)
@[simp] theorem UInt16.toUInt8_or (a b : UInt16) : (a ||| b).toUInt8 = a.toUInt8 ||| b.toUInt8 := UInt8.toBitVec_inj.1 (by simp)
@[simp] theorem UInt16.toUInt32_or (a b : UInt16) : (a ||| b).toUInt32 = a.toUInt32 ||| b.toUInt32 := rfl
@[simp] theorem UInt16.toUInt64_or (a b : UInt16) : (a ||| b).toUInt64 = a.toUInt64 ||| b.toUInt64 := rfl
@[simp] theorem UInt16.toUSize_or (a b : UInt16) : (a ||| b).toUSize = a.toUSize ||| b.toUSize := rfl
@[simp] theorem UInt16.toUInt32_or (a b : UInt16) : (a ||| b).toUInt32 = a.toUInt32 ||| b.toUInt32 := (rfl)
@[simp] theorem UInt16.toUInt64_or (a b : UInt16) : (a ||| b).toUInt64 = a.toUInt64 ||| b.toUInt64 := (rfl)
@[simp] theorem UInt16.toUSize_or (a b : UInt16) : (a ||| b).toUSize = a.toUSize ||| b.toUSize := (rfl)
@[simp] theorem UInt32.toUInt8_or (a b : UInt32) : (a ||| b).toUInt8 = a.toUInt8 ||| b.toUInt8 := UInt8.toBitVec_inj.1 (by simp)
@[simp] theorem UInt32.toUInt16_or (a b : UInt32) : (a ||| b).toUInt16 = a.toUInt16 ||| b.toUInt16 := UInt16.toBitVec_inj.1 (by simp)
@[simp] theorem UInt32.toUInt64_or (a b : UInt32) : (a ||| b).toUInt64 = a.toUInt64 ||| b.toUInt64 := rfl
@[simp] theorem UInt32.toUSize_or (a b : UInt32) : (a ||| b).toUSize = a.toUSize ||| b.toUSize := rfl
@[simp] theorem UInt32.toUInt64_or (a b : UInt32) : (a ||| b).toUInt64 = a.toUInt64 ||| b.toUInt64 := (rfl)
@[simp] theorem UInt32.toUSize_or (a b : UInt32) : (a ||| b).toUSize = a.toUSize ||| b.toUSize := (rfl)
@[simp] theorem USize.toUInt8_or (a b : USize) : (a ||| b).toUInt8 = a.toUInt8 ||| b.toUInt8 := UInt8.toBitVec_inj.1 (by simp)
@[simp] theorem USize.toUInt16_or (a b : USize) : (a ||| b).toUInt16 = a.toUInt16 ||| b.toUInt16 := UInt16.toBitVec_inj.1 (by simp)
@[simp] theorem USize.toUInt32_or (a b : USize) : (a ||| b).toUInt32 = a.toUInt32 ||| b.toUInt32 := UInt32.toBitVec_inj.1 (by simp)
@[simp] theorem USize.toUInt64_or (a b : USize) : (a ||| b).toUInt64 = a.toUInt64 ||| b.toUInt64 := rfl
@[simp] theorem USize.toUInt64_or (a b : USize) : (a ||| b).toUInt64 = a.toUInt64 ||| b.toUInt64 := (rfl)
@[simp] theorem UInt64.toUInt8_or (a b : UInt64) : (a ||| b).toUInt8 = a.toUInt8 ||| b.toUInt8 := UInt8.toBitVec_inj.1 (by simp)
@[simp] theorem UInt64.toUInt16_or (a b : UInt64) : (a ||| b).toUInt16 = a.toUInt16 ||| b.toUInt16 := UInt16.toBitVec_inj.1 (by simp)
@@ -137,25 +133,25 @@ theorem Bool.toBitVec_toUSize {b : Bool} :
@[simp] theorem UInt64.toFin_xor (a b : UInt64) : (a ^^^ b).toFin = a.toFin ^^^ b.toFin := Fin.val_inj.1 (by simp)
@[simp] theorem USize.toFin_xor (a b : USize) : (a ^^^ b).toFin = a.toFin ^^^ b.toFin := Fin.val_inj.1 (by simp)
@[simp] theorem UInt8.toUInt16_xor (a b : UInt8) : (a ^^^ b).toUInt16 = a.toUInt16 ^^^ b.toUInt16 := rfl
@[simp] theorem UInt8.toUInt32_xor (a b : UInt8) : (a ^^^ b).toUInt32 = a.toUInt32 ^^^ b.toUInt32 := rfl
@[simp] theorem UInt8.toUInt64_xor (a b : UInt8) : (a ^^^ b).toUInt64 = a.toUInt64 ^^^ b.toUInt64 := rfl
@[simp] theorem UInt8.toUSize_xor (a b : UInt8) : (a ^^^ b).toUSize = a.toUSize ^^^ b.toUSize := rfl
@[simp] theorem UInt8.toUInt16_xor (a b : UInt8) : (a ^^^ b).toUInt16 = a.toUInt16 ^^^ b.toUInt16 := (rfl)
@[simp] theorem UInt8.toUInt32_xor (a b : UInt8) : (a ^^^ b).toUInt32 = a.toUInt32 ^^^ b.toUInt32 := (rfl)
@[simp] theorem UInt8.toUInt64_xor (a b : UInt8) : (a ^^^ b).toUInt64 = a.toUInt64 ^^^ b.toUInt64 := (rfl)
@[simp] theorem UInt8.toUSize_xor (a b : UInt8) : (a ^^^ b).toUSize = a.toUSize ^^^ b.toUSize := (rfl)
@[simp] theorem UInt16.toUInt8_xor (a b : UInt16) : (a ^^^ b).toUInt8 = a.toUInt8 ^^^ b.toUInt8 := UInt8.toBitVec_inj.1 (by simp)
@[simp] theorem UInt16.toUInt32_xor (a b : UInt16) : (a ^^^ b).toUInt32 = a.toUInt32 ^^^ b.toUInt32 := rfl
@[simp] theorem UInt16.toUInt64_xor (a b : UInt16) : (a ^^^ b).toUInt64 = a.toUInt64 ^^^ b.toUInt64 := rfl
@[simp] theorem UInt16.toUSize_xor (a b : UInt16) : (a ^^^ b).toUSize = a.toUSize ^^^ b.toUSize := rfl
@[simp] theorem UInt16.toUInt32_xor (a b : UInt16) : (a ^^^ b).toUInt32 = a.toUInt32 ^^^ b.toUInt32 := (rfl)
@[simp] theorem UInt16.toUInt64_xor (a b : UInt16) : (a ^^^ b).toUInt64 = a.toUInt64 ^^^ b.toUInt64 := (rfl)
@[simp] theorem UInt16.toUSize_xor (a b : UInt16) : (a ^^^ b).toUSize = a.toUSize ^^^ b.toUSize := (rfl)
@[simp] theorem UInt32.toUInt8_xor (a b : UInt32) : (a ^^^ b).toUInt8 = a.toUInt8 ^^^ b.toUInt8 := UInt8.toBitVec_inj.1 (by simp)
@[simp] theorem UInt32.toUInt16_xor (a b : UInt32) : (a ^^^ b).toUInt16 = a.toUInt16 ^^^ b.toUInt16 := UInt16.toBitVec_inj.1 (by simp)
@[simp] theorem UInt32.toUInt64_xor (a b : UInt32) : (a ^^^ b).toUInt64 = a.toUInt64 ^^^ b.toUInt64 := rfl
@[simp] theorem UInt32.toUSize_xor (a b : UInt32) : (a ^^^ b).toUSize = a.toUSize ^^^ b.toUSize := rfl
@[simp] theorem UInt32.toUInt64_xor (a b : UInt32) : (a ^^^ b).toUInt64 = a.toUInt64 ^^^ b.toUInt64 := (rfl)
@[simp] theorem UInt32.toUSize_xor (a b : UInt32) : (a ^^^ b).toUSize = a.toUSize ^^^ b.toUSize := (rfl)
@[simp] theorem USize.toUInt8_xor (a b : USize) : (a ^^^ b).toUInt8 = a.toUInt8 ^^^ b.toUInt8 := UInt8.toBitVec_inj.1 (by simp)
@[simp] theorem USize.toUInt16_xor (a b : USize) : (a ^^^ b).toUInt16 = a.toUInt16 ^^^ b.toUInt16 := UInt16.toBitVec_inj.1 (by simp)
@[simp] theorem USize.toUInt32_xor (a b : USize) : (a ^^^ b).toUInt32 = a.toUInt32 ^^^ b.toUInt32 := UInt32.toBitVec_inj.1 (by simp)
@[simp] theorem USize.toUInt64_xor (a b : USize) : (a ^^^ b).toUInt64 = a.toUInt64 ^^^ b.toUInt64 := rfl
@[simp] theorem USize.toUInt64_xor (a b : USize) : (a ^^^ b).toUInt64 = a.toUInt64 ^^^ b.toUInt64 := (rfl)
@[simp] theorem UInt64.toUInt8_xor (a b : UInt64) : (a ^^^ b).toUInt8 = a.toUInt8 ^^^ b.toUInt8 := UInt8.toBitVec_inj.1 (by simp)
@[simp] theorem UInt64.toUInt16_xor (a b : UInt64) : (a ^^^ b).toUInt16 = a.toUInt16 ^^^ b.toUInt16 := UInt16.toBitVec_inj.1 (by simp)
@@ -433,11 +429,11 @@ expression `(a >>> b).toUInt8` is not a function of `a.toUInt8` and `b.toUInt8`.
@[simp] theorem UInt64.ofFin_and (a b : Fin UInt64.size) : UInt64.ofFin (a &&& b) = UInt64.ofFin a &&& UInt64.ofFin b := UInt64.toFin_inj.1 (by simp)
@[simp] theorem USize.ofFin_and (a b : Fin USize.size) : USize.ofFin (a &&& b) = USize.ofFin a &&& USize.ofFin b := USize.toFin_inj.1 (by simp)
@[simp] theorem UInt8.ofBitVec_and (a b : BitVec 8) : UInt8.ofBitVec (a &&& b) = UInt8.ofBitVec a &&& UInt8.ofBitVec b := rfl
@[simp] theorem UInt16.ofBitVec_and (a b : BitVec 16) : UInt16.ofBitVec (a &&& b) = UInt16.ofBitVec a &&& UInt16.ofBitVec b := rfl
@[simp] theorem UInt32.ofBitVec_and (a b : BitVec 32) : UInt32.ofBitVec (a &&& b) = UInt32.ofBitVec a &&& UInt32.ofBitVec b := rfl
@[simp] theorem UInt64.ofBitVec_and (a b : BitVec 64) : UInt64.ofBitVec (a &&& b) = UInt64.ofBitVec a &&& UInt64.ofBitVec b := rfl
@[simp] theorem USize.ofBitVec_and (a b : BitVec System.Platform.numBits) : USize.ofBitVec (a &&& b) = USize.ofBitVec a &&& USize.ofBitVec b := rfl
@[simp] theorem UInt8.ofBitVec_and (a b : BitVec 8) : UInt8.ofBitVec (a &&& b) = UInt8.ofBitVec a &&& UInt8.ofBitVec b := (rfl)
@[simp] theorem UInt16.ofBitVec_and (a b : BitVec 16) : UInt16.ofBitVec (a &&& b) = UInt16.ofBitVec a &&& UInt16.ofBitVec b := (rfl)
@[simp] theorem UInt32.ofBitVec_and (a b : BitVec 32) : UInt32.ofBitVec (a &&& b) = UInt32.ofBitVec a &&& UInt32.ofBitVec b := (rfl)
@[simp] theorem UInt64.ofBitVec_and (a b : BitVec 64) : UInt64.ofBitVec (a &&& b) = UInt64.ofBitVec a &&& UInt64.ofBitVec b := (rfl)
@[simp] theorem USize.ofBitVec_and (a b : BitVec System.Platform.numBits) : USize.ofBitVec (a &&& b) = USize.ofBitVec a &&& USize.ofBitVec b := (rfl)
@[simp] theorem UInt8.ofNat_and (a b : Nat) : UInt8.ofNat (a &&& b) = UInt8.ofNat a &&& UInt8.ofNat b :=
UInt8.toBitVec_inj.1 (by simp [UInt8.toBitVec_ofNat'])
@@ -469,11 +465,11 @@ expression `(a >>> b).toUInt8` is not a function of `a.toUInt8` and `b.toUInt8`.
@[simp] theorem UInt64.ofFin_or (a b : Fin UInt64.size) : UInt64.ofFin (a ||| b) = UInt64.ofFin a ||| UInt64.ofFin b := UInt64.toFin_inj.1 (by simp)
@[simp] theorem USize.ofFin_or (a b : Fin USize.size) : USize.ofFin (a ||| b) = USize.ofFin a ||| USize.ofFin b := USize.toFin_inj.1 (by simp)
@[simp] theorem UInt8.ofBitVec_or (a b : BitVec 8) : UInt8.ofBitVec (a ||| b) = UInt8.ofBitVec a ||| UInt8.ofBitVec b := rfl
@[simp] theorem UInt16.ofBitVec_or (a b : BitVec 16) : UInt16.ofBitVec (a ||| b) = UInt16.ofBitVec a ||| UInt16.ofBitVec b := rfl
@[simp] theorem UInt32.ofBitVec_or (a b : BitVec 32) : UInt32.ofBitVec (a ||| b) = UInt32.ofBitVec a ||| UInt32.ofBitVec b := rfl
@[simp] theorem UInt64.ofBitVec_or (a b : BitVec 64) : UInt64.ofBitVec (a ||| b) = UInt64.ofBitVec a ||| UInt64.ofBitVec b := rfl
@[simp] theorem USize.ofBitVec_or (a b : BitVec System.Platform.numBits) : USize.ofBitVec (a ||| b) = USize.ofBitVec a ||| USize.ofBitVec b := rfl
@[simp] theorem UInt8.ofBitVec_or (a b : BitVec 8) : UInt8.ofBitVec (a ||| b) = UInt8.ofBitVec a ||| UInt8.ofBitVec b := (rfl)
@[simp] theorem UInt16.ofBitVec_or (a b : BitVec 16) : UInt16.ofBitVec (a ||| b) = UInt16.ofBitVec a ||| UInt16.ofBitVec b := (rfl)
@[simp] theorem UInt32.ofBitVec_or (a b : BitVec 32) : UInt32.ofBitVec (a ||| b) = UInt32.ofBitVec a ||| UInt32.ofBitVec b := (rfl)
@[simp] theorem UInt64.ofBitVec_or (a b : BitVec 64) : UInt64.ofBitVec (a ||| b) = UInt64.ofBitVec a ||| UInt64.ofBitVec b := (rfl)
@[simp] theorem USize.ofBitVec_or (a b : BitVec System.Platform.numBits) : USize.ofBitVec (a ||| b) = USize.ofBitVec a ||| USize.ofBitVec b := (rfl)
@[simp] theorem UInt8.ofNat_or (a b : Nat) : UInt8.ofNat (a ||| b) = UInt8.ofNat a ||| UInt8.ofNat b :=
UInt8.toBitVec_inj.1 (by simp [UInt8.toBitVec_ofNat'])
@@ -505,11 +501,11 @@ expression `(a >>> b).toUInt8` is not a function of `a.toUInt8` and `b.toUInt8`.
@[simp] theorem UInt64.ofFin_xor (a b : Fin UInt64.size) : UInt64.ofFin (a ^^^ b) = UInt64.ofFin a ^^^ UInt64.ofFin b := UInt64.toFin_inj.1 (by simp)
@[simp] theorem USize.ofFin_xor (a b : Fin USize.size) : USize.ofFin (a ^^^ b) = USize.ofFin a ^^^ USize.ofFin b := USize.toFin_inj.1 (by simp)
@[simp] theorem UInt8.ofBitVec_xor (a b : BitVec 8) : UInt8.ofBitVec (a ^^^ b) = UInt8.ofBitVec a ^^^ UInt8.ofBitVec b := rfl
@[simp] theorem UInt16.ofBitVec_xor (a b : BitVec 16) : UInt16.ofBitVec (a ^^^ b) = UInt16.ofBitVec a ^^^ UInt16.ofBitVec b := rfl
@[simp] theorem UInt32.ofBitVec_xor (a b : BitVec 32) : UInt32.ofBitVec (a ^^^ b) = UInt32.ofBitVec a ^^^ UInt32.ofBitVec b := rfl
@[simp] theorem UInt64.ofBitVec_xor (a b : BitVec 64) : UInt64.ofBitVec (a ^^^ b) = UInt64.ofBitVec a ^^^ UInt64.ofBitVec b := rfl
@[simp] theorem USize.ofBitVec_xor (a b : BitVec System.Platform.numBits) : USize.ofBitVec (a ^^^ b) = USize.ofBitVec a ^^^ USize.ofBitVec b := rfl
@[simp] theorem UInt8.ofBitVec_xor (a b : BitVec 8) : UInt8.ofBitVec (a ^^^ b) = UInt8.ofBitVec a ^^^ UInt8.ofBitVec b := (rfl)
@[simp] theorem UInt16.ofBitVec_xor (a b : BitVec 16) : UInt16.ofBitVec (a ^^^ b) = UInt16.ofBitVec a ^^^ UInt16.ofBitVec b := (rfl)
@[simp] theorem UInt32.ofBitVec_xor (a b : BitVec 32) : UInt32.ofBitVec (a ^^^ b) = UInt32.ofBitVec a ^^^ UInt32.ofBitVec b := (rfl)
@[simp] theorem UInt64.ofBitVec_xor (a b : BitVec 64) : UInt64.ofBitVec (a ^^^ b) = UInt64.ofBitVec a ^^^ UInt64.ofBitVec b := (rfl)
@[simp] theorem USize.ofBitVec_xor (a b : BitVec System.Platform.numBits) : USize.ofBitVec (a ^^^ b) = USize.ofBitVec a ^^^ USize.ofBitVec b := (rfl)
@[simp] theorem UInt8.ofNat_xor (a b : Nat) : UInt8.ofNat (a ^^^ b) = UInt8.ofNat a ^^^ UInt8.ofNat b :=
UInt8.toBitVec_inj.1 (by simp [UInt8.toBitVec_ofNat'])
@@ -535,11 +531,11 @@ expression `(a >>> b).toUInt8` is not a function of `a.toUInt8` and `b.toUInt8`.
UInt64.ofNatLT (a ^^^ b) (Nat.xor_lt_two_pow ha hb) = UInt64.ofNatLT a ha ^^^ UInt64.ofNatLT b hb := by
simp [UInt64.ofNatLT_eq_ofNat]
@[simp] theorem UInt8.ofBitVec_not (a : BitVec 8) : UInt8.ofBitVec (~~~a) = ~~~UInt8.ofBitVec a := rfl
@[simp] theorem UInt16.ofBitVec_not (a : BitVec 16) : UInt16.ofBitVec (~~~a) = ~~~UInt16.ofBitVec a := rfl
@[simp] theorem UInt32.ofBitVec_not (a : BitVec 32) : UInt32.ofBitVec (~~~a) = ~~~UInt32.ofBitVec a := rfl
@[simp] theorem UInt64.ofBitVec_not (a : BitVec 64) : UInt64.ofBitVec (~~~a) = ~~~UInt64.ofBitVec a := rfl
@[simp] theorem USize.ofBitVec_not (a : BitVec System.Platform.numBits) : USize.ofBitVec (~~~a) = ~~~USize.ofBitVec a := rfl
@[simp] theorem UInt8.ofBitVec_not (a : BitVec 8) : UInt8.ofBitVec (~~~a) = ~~~UInt8.ofBitVec a := (rfl)
@[simp] theorem UInt16.ofBitVec_not (a : BitVec 16) : UInt16.ofBitVec (~~~a) = ~~~UInt16.ofBitVec a := (rfl)
@[simp] theorem UInt32.ofBitVec_not (a : BitVec 32) : UInt32.ofBitVec (~~~a) = ~~~UInt32.ofBitVec a := (rfl)
@[simp] theorem UInt64.ofBitVec_not (a : BitVec 64) : UInt64.ofBitVec (~~~a) = ~~~UInt64.ofBitVec a := (rfl)
@[simp] theorem USize.ofBitVec_not (a : BitVec System.Platform.numBits) : USize.ofBitVec (~~~a) = ~~~USize.ofBitVec a := (rfl)
@[simp] theorem UInt8.ofFin_rev (a : Fin UInt8.size) : UInt8.ofFin a.rev = ~~~UInt8.ofFin a := UInt8.toFin_inj.1 (by simp)
@[simp] theorem UInt16.ofFin_rev (a : Fin UInt16.size) : UInt16.ofFin a.rev = ~~~UInt16.ofFin a := UInt16.toFin_inj.1 (by simp)
@@ -600,7 +596,7 @@ expression `(a >>> b).toUInt8` is not a function of `a.toUInt8` and `b.toUInt8`.
USize.ofFin (a <<< (b % System.Platform.numBits, by cases System.Platform.numBits_eq <;> simp_all [USize.size])) = USize.ofFin a <<< USize.ofFin b := by
apply USize.toFin_inj.1
rw [toFin_ofFin, USize.shiftLeft_eq_shiftLeft_mod, USize.toFin_shiftLeft, toFin_ofFin, USize.toFin_mod,
toFin_ofFin, toFin_ofNat', Fin.ofNat'_val_eq_self System.Platform.numBits, _]
toFin_ofFin, toFin.ofNat, Fin.ofNat_val_eq_self System.Platform.numBits, _]
rw [USize.toNat_mod, toNat_ofNat']
cases System.Platform.numBits_eq <;> simpa [*] using Nat.mod_lt _ (by decide)
@@ -695,7 +691,7 @@ expression `(a >>> b).toUInt8` is not a function of `a.toUInt8` and `b.toUInt8`.
USize.ofFin (a >>> (b % System.Platform.numBits, by cases System.Platform.numBits_eq <;> simp_all [USize.size])) = USize.ofFin a >>> USize.ofFin b := by
apply USize.toFin_inj.1
rw [toFin_ofFin, USize.shiftRight_eq_shiftRight_mod, USize.toFin_shiftRight, toFin_ofFin, USize.toFin_mod,
toFin_ofFin, toFin_ofNat', Fin.ofNat'_val_eq_self System.Platform.numBits, _]
toFin_ofFin, toFin.ofNat, Fin.ofNat_val_eq_self System.Platform.numBits, _]
rw [USize.toNat_mod, toNat_ofNat']
cases System.Platform.numBits_eq <;> simpa [*] using Nat.mod_lt _ (by decide)
@@ -1003,16 +999,16 @@ instance : Std.LawfulCommIdentity (α := USize) (· ^^^ ·) 0 where
@[simp] theorem USize.xor_right_inj {a b : USize} (c : USize) : (c ^^^ a = c ^^^ b) a = b := by
simp [ USize.toBitVec_inj]
@[simp] theorem UInt8.not_zero : ~~~(0 : UInt8) = -1 := rfl
@[simp] theorem UInt16.not_zero : ~~~(0 : UInt16) = -1 := rfl
@[simp] theorem UInt32.not_zero : ~~~(0 : UInt32) = -1 := rfl
@[simp] theorem UInt64.not_zero : ~~~(0 : UInt64) = -1 := rfl
@[simp] theorem UInt8.not_zero : ~~~(0 : UInt8) = -1 := (rfl)
@[simp] theorem UInt16.not_zero : ~~~(0 : UInt16) = -1 := (rfl)
@[simp] theorem UInt32.not_zero : ~~~(0 : UInt32) = -1 := (rfl)
@[simp] theorem UInt64.not_zero : ~~~(0 : UInt64) = -1 := (rfl)
@[simp] theorem USize.not_zero : ~~~(0 : USize) = -1 := by simp [USize.not_eq_neg_sub]
@[simp] theorem UInt8.not_neg_one : ~~~(-1 : UInt8) = 0 := rfl
@[simp] theorem UInt16.not_neg_one : ~~~(-1 : UInt16) = 0 := rfl
@[simp] theorem UInt32.not_neg_one : ~~~(-1 : UInt32) = 0 := rfl
@[simp] theorem UInt64.not_neg_one : ~~~(-1 : UInt64) = 0 := rfl
@[simp] theorem UInt8.not_neg_one : ~~~(-1 : UInt8) = 0 := (rfl)
@[simp] theorem UInt16.not_neg_one : ~~~(-1 : UInt16) = 0 := (rfl)
@[simp] theorem UInt32.not_neg_one : ~~~(-1 : UInt32) = 0 := (rfl)
@[simp] theorem UInt64.not_neg_one : ~~~(-1 : UInt64) = 0 := (rfl)
@[simp] theorem USize.not_neg_one : ~~~(-1 : USize) = 0 := by simp [USize.not_eq_neg_sub]
@[simp] theorem UInt8.not_not {a : UInt8} : ~~~(~~~a) = a := by simp [ UInt8.toBitVec_inj]

File diff suppressed because it is too large Load Diff

View File

@@ -22,6 +22,7 @@ to apply `f`.
We replace this at runtime with a more efficient version via the `csimp` lemma `pmap_eq_pmapImpl`.
-/
@[expose]
def pmap {P : α Prop} (f : a, P a β) (xs : Vector α n) (H : a xs, P a) : Vector β n :=
Vector.mk (xs.toArray.pmap f (fun a m => H a (by simpa using m))) (by simp)
@@ -34,13 +35,13 @@ Unsafe implementation of `attachWith`, taking advantage of the fact that the rep
/-- `O(1)`. "Attach" a proof `P x` that holds for all the elements of `xs` to produce a new array
with the same elements but in the type `{x // P x}`. -/
@[implemented_by attachWithImpl] def attachWith
@[implemented_by attachWithImpl, expose] def attachWith
(xs : Vector α n) (P : α Prop) (H : x xs, P x) : Vector {x // P x} n :=
Vector.mk (xs.toArray.attachWith P fun x h => H x (by simpa using h)) (by simp)
/-- `O(1)`. "Attach" the proof that the elements of `xs` are in `xs` to produce a new vector
with the same elements but in the type `{x // x ∈ xs}`. -/
@[inline] def attach (xs : Vector α n) : Vector {x // x xs} n := xs.attachWith _ fun _ => id
@[inline, expose] def attach (xs : Vector α n) : Vector {x // x xs} n := xs.attachWith _ fun _ => id
@[simp] theorem attachWith_mk {xs : Array α} {h : xs.size = n} {P : α Prop} {H : x mk xs h, P x} :
(mk xs h).attachWith P H = mk (xs.attachWith P (by simpa using H)) (by simpa using h) := by
@@ -474,7 +475,10 @@ If not, usually the right approach is `simp [Vector.unattach, -Vector.map_subtyp
-/
def unattach {α : Type _} {p : α Prop} (xs : Vector { x // p x } n) : Vector α n := xs.map (·.val)
@[simp] theorem unattach_nil {p : α Prop} : (#v[] : Vector { x // p x } 0).unattach = #v[] := by simp
theorem unattach_empty {p : α Prop} : (#v[] : Vector { x // p x } 0).unattach = #v[] := by simp
@[deprecated unattach_empty (since := "2025-05-26")]
abbrev unattach_nil := @unattach_empty
@[simp] theorem unattach_push {p : α Prop} {a : { x // p x }} {xs : Vector { x // p x } n} :
(xs.push a).unattach = xs.unattach.push a.1 := by

View File

@@ -54,6 +54,7 @@ recommended_spelling "empty" for "#v[]" in [Vector.mk, «term#v[_,]»]
recommended_spelling "singleton" for "#v[x]" in [Vector.mk, «term#v[_,]»]
/-- Convert a vector to a list. -/
@[expose]
def toList (xs : Vector α n) : List α := xs.toArray.toList
/-- Custom eliminator for `Vector α n` through `Array α` -/
@@ -71,13 +72,13 @@ def elimAsList {motive : Vector α n → Sort u}
| xs, ha => mk xs ha
/-- Make an empty vector with pre-allocated capacity. -/
@[inline] def emptyWithCapacity (capacity : Nat) : Vector α 0 := .emptyWithCapacity capacity, by simp
@[inline, expose] def emptyWithCapacity (capacity : Nat) : Vector α 0 := .emptyWithCapacity capacity, by simp
@[deprecated emptyWithCapacity (since := "2025-03-12"), inherit_doc emptyWithCapacity]
abbrev mkEmpty := @emptyWithCapacity
/-- Makes a vector of size `n` with all cells containing `v`. -/
@[inline] def replicate (n) (v : α) : Vector α n := Array.replicate n v, by simp
@[inline, expose] def replicate (n) (v : α) : Vector α n := Array.replicate n v, by simp
@[deprecated replicate (since := "2025-03-18")]
abbrev mkVector := @replicate
@@ -86,23 +87,24 @@ instance : Nonempty (Vector α 0) := ⟨#v[]⟩
instance [Nonempty α] : Nonempty (Vector α n) := replicate _ Classical.ofNonempty
/-- Returns a vector of size `1` with element `v`. -/
@[inline] def singleton (v : α) : Vector α 1 := #[v], rfl
@[inline, expose] def singleton (v : α) : Vector α 1 := #[v], rfl
instance [Inhabited α] : Inhabited (Vector α n) where
default := replicate n default
/-- Get an element of a vector using a `Fin` index. -/
@[inline] def get (xs : Vector α n) (i : Fin n) : α :=
@[inline, expose] def get (xs : Vector α n) (i : Fin n) : α :=
xs.toArray[(i.cast xs.size_toArray.symm).1]
/-- Get an element of a vector using a `USize` index and a proof that the index is within bounds. -/
@[inline] def uget (xs : Vector α n) (i : USize) (h : i.toNat < n) : α :=
@[inline, expose] def uget (xs : Vector α n) (i : USize) (h : i.toNat < n) : α :=
xs.toArray.uget i (xs.size_toArray.symm h)
instance : GetElem (Vector α n) Nat α fun _ i => i < n where
getElem xs i h := get xs i, h
/-- Check if there is an element which satisfies `a == ·`. -/
@[expose]
def contains [BEq α] (xs : Vector α n) (a : α) : Bool := xs.toArray.contains a
/-- `a ∈ v` is a predicate which asserts that `a` is in the vector `v`. -/
@@ -116,27 +118,27 @@ instance : Membership α (Vector α n) where
Get an element of a vector using a `Nat` index. Returns the given default value if the index is out
of bounds.
-/
@[inline] def getD (xs : Vector α n) (i : Nat) (default : α) : α := xs.toArray.getD i default
@[inline, expose] def getD (xs : Vector α n) (i : Nat) (default : α) : α := xs.toArray.getD i default
/-- The last element of a vector. Panics if the vector is empty. -/
@[inline] def back! [Inhabited α] (xs : Vector α n) : α := xs.toArray.back!
@[inline, expose] def back! [Inhabited α] (xs : Vector α n) : α := xs.toArray.back!
/-- The last element of a vector, or `none` if the vector is empty. -/
@[inline] def back? (xs : Vector α n) : Option α := xs.toArray.back?
@[inline, expose] def back? (xs : Vector α n) : Option α := xs.toArray.back?
/-- The last element of a non-empty vector. -/
@[inline] def back [NeZero n] (xs : Vector α n) : α :=
@[inline, expose] def back [NeZero n] (xs : Vector α n) : α :=
xs[n - 1]'(Nat.sub_one_lt (NeZero.ne n))
/-- The first element of a non-empty vector. -/
@[inline] def head [NeZero n] (xs : Vector α n) := xs[0]'(Nat.pos_of_neZero n)
@[inline, expose] def head [NeZero n] (xs : Vector α n) := xs[0]'(Nat.pos_of_neZero n)
/-- Push an element `x` to the end of a vector. -/
@[inline] def push (xs : Vector α n) (x : α) : Vector α (n + 1) :=
@[inline, expose] def push (xs : Vector α n) (x : α) : Vector α (n + 1) :=
xs.toArray.push x, by simp
/-- Remove the last element of a vector. -/
@[inline] def pop (xs : Vector α n) : Vector α (n - 1) :=
@[inline, expose] def pop (xs : Vector α n) : Vector α (n - 1) :=
Array.pop xs.toArray, by simp
/--
@@ -145,7 +147,7 @@ bounds.
This will perform the update destructively provided that the vector has a reference count of 1.
-/
@[inline] def set (xs : Vector α n) (i : Nat) (x : α) (h : i < n := by get_elem_tactic): Vector α n :=
@[inline, expose] def set (xs : Vector α n) (i : Nat) (x : α) (h : i < n := by get_elem_tactic): Vector α n :=
xs.toArray.set i x (by simp [*]), by simp
/--
@@ -154,7 +156,7 @@ bounds.
This will perform the update destructively provided that the vector has a reference count of 1.
-/
@[inline] def setIfInBounds (xs : Vector α n) (i : Nat) (x : α) : Vector α n :=
@[inline, expose] def setIfInBounds (xs : Vector α n) (i : Nat) (x : α) : Vector α n :=
xs.toArray.setIfInBounds i x, by simp
/--
@@ -162,44 +164,46 @@ Set an element in a vector using a `Nat` index. Panics if the index is out of bo
This will perform the update destructively provided that the vector has a reference count of 1.
-/
@[inline] def set! (xs : Vector α n) (i : Nat) (x : α) : Vector α n :=
@[inline, expose] def set! (xs : Vector α n) (i : Nat) (x : α) : Vector α n :=
xs.toArray.set! i x, by simp
@[inline] def foldlM [Monad m] (f : β α m β) (b : β) (xs : Vector α n) : m β :=
@[inline, expose] def foldlM [Monad m] (f : β α m β) (b : β) (xs : Vector α n) : m β :=
xs.toArray.foldlM f b
@[inline] def foldrM [Monad m] (f : α β m β) (b : β) (xs : Vector α n) : m β :=
@[inline, expose] def foldrM [Monad m] (f : α β m β) (b : β) (xs : Vector α n) : m β :=
xs.toArray.foldrM f b
@[inline] def foldl (f : β α β) (b : β) (xs : Vector α n) : β :=
@[inline, expose] def foldl (f : β α β) (b : β) (xs : Vector α n) : β :=
xs.toArray.foldl f b
@[inline] def foldr (f : α β β) (b : β) (xs : Vector α n) : β :=
@[inline, expose] def foldr (f : α β β) (b : β) (xs : Vector α n) : β :=
xs.toArray.foldr f b
/-- Append two vectors. -/
@[inline] def append (xs : Vector α n) (ys : Vector α m) : Vector α (n + m) :=
@[inline, expose] def append (xs : Vector α n) (ys : Vector α m) : Vector α (n + m) :=
xs.toArray ++ ys.toArray, by simp
instance : HAppend (Vector α n) (Vector α m) (Vector α (n + m)) where
hAppend := append
/-- Creates a vector from another with a provably equal length. -/
@[inline] protected def cast (h : n = m) (xs : Vector α n) : Vector α m :=
@[inline, expose] protected def cast (h : n = m) (xs : Vector α n) : Vector α m :=
xs.toArray, by simp [*]
/--
Extracts the slice of a vector from indices `start` to `stop` (exclusive). If `start ≥ stop`, the
result is empty. If `stop` is greater than the size of the vector, the size is used instead.
-/
@[inline] def extract (xs : Vector α n) (start : Nat := 0) (stop : Nat := n) : Vector α (min stop n - start) :=
@[inline, expose] def extract (xs : Vector α n) (start : Nat := 0) (stop : Nat := n) : Vector α (min stop n - start) :=
xs.toArray.extract start stop, by simp
/--
Extract the first `i` elements of a vector. If `i` is greater than or equal to the size of the
vector then the vector is returned unchanged.
We immediately simplify this to the `extract` operation, so there is no verification API for this function.
-/
@[inline] def take (xs : Vector α n) (i : Nat) : Vector α (min i n) :=
@[inline, expose] def take (xs : Vector α n) (i : Nat) : Vector α (min i n) :=
xs.toArray.take i, by simp
@[simp] theorem take_eq_extract (xs : Vector α n) (i : Nat) : xs.take i = xs.extract 0 i := rfl
@@ -207,33 +211,39 @@ vector then the vector is returned unchanged.
/--
Deletes the first `i` elements of a vector. If `i` is greater than or equal to the size of the
vector then the empty vector is returned.
We immediately simplify this to the `extract` operation, so there is no verification API for this function.
-/
@[inline] def drop (xs : Vector α n) (i : Nat) : Vector α (n - i) :=
@[inline, expose] def drop (xs : Vector α n) (i : Nat) : Vector α (n - i) :=
xs.toArray.drop i, by simp
set_option linter.indexVariables false in
@[simp] theorem drop_eq_cast_extract (xs : Vector α n) (i : Nat) :
xs.drop i = (xs.extract i n).cast (by simp) := by
xs.drop i = (xs.extract i).cast (by simp) := by
simp [drop, extract, Vector.cast]
/-- Shrinks a vector to the first `m` elements, by repeatedly popping the last element. -/
@[inline] def shrink (xs : Vector α n) (i : Nat) : Vector α (min i n) :=
/--
Shrinks a vector to the first `m` elements, by repeatedly popping the last element.
We immediately simplify this to the `extract` operation, so there is no verification API for this function.
-/
@[inline, expose] def shrink (xs : Vector α n) (i : Nat) : Vector α (min i n) :=
xs.toArray.shrink i, by simp
@[simp] theorem shrink_eq_take (xs : Vector α n) (i : Nat) : xs.shrink i = xs.take i := by
simp [shrink, take]
/-- Maps elements of a vector using the function `f`. -/
@[inline] def map (f : α β) (xs : Vector α n) : Vector β n :=
@[inline, expose] def map (f : α β) (xs : Vector α n) : Vector β n :=
xs.toArray.map f, by simp
/-- Maps elements of a vector using the function `f`, which also receives the index of the element. -/
@[inline] def mapIdx (f : Nat α β) (xs : Vector α n) : Vector β n :=
@[inline, expose] def mapIdx (f : Nat α β) (xs : Vector α n) : Vector β n :=
xs.toArray.mapIdx f, by simp
/-- Maps elements of a vector using the function `f`,
which also receives the index of the element, and the fact that the index is less than the size of the vector. -/
@[inline] def mapFinIdx (xs : Vector α n) (f : (i : Nat) α (h : i < n) β) : Vector β n :=
@[inline, expose] def mapFinIdx (xs : Vector α n) (f : (i : Nat) α (h : i < n) β) : Vector β n :=
xs.toArray.mapFinIdx (fun i a h => f i a (by simpa [xs.size_toArray] using h)), by simp
/-- Map a monadic function over a vector. -/
@@ -246,7 +256,7 @@ where
else
return acc.cast (by omega)
@[inline] protected def forM [Monad m] (xs : Vector α n) (f : α m PUnit) : m PUnit :=
@[inline, expose] protected def forM [Monad m] (xs : Vector α n) (f : α m PUnit) : m PUnit :=
xs.toArray.forM f
@[inline] def flatMapM [Monad m] (xs : Vector α n) (f : α m (Vector β k)) : m (Vector β (n * k)) := do
@@ -259,7 +269,7 @@ where
return acc.cast (by congr; omega)
/-- Variant of `mapIdxM` which receives the index `i` along with the bound `i < n. -/
@[inline]
@[inline, expose]
def mapFinIdxM {α : Type u} {β : Type v} {m : Type v Type w} [Monad m]
(xs : Vector α n) (f : (i : Nat) α (h : i < n) m β) : m (Vector β n) :=
let rec @[specialize] map (i : Nat) (j : Nat) (inv : i + j = n) (ys : Vector β (n - i)) : m (Vector β n) := do
@@ -273,38 +283,38 @@ def mapFinIdxM {α : Type u} {β : Type v} {m : Type v → Type w} [Monad m]
map i (j+1) this ((ys.push ( f j xs[j] j_lt)).cast (by omega))
map n 0 rfl (#v[].cast (by simp))
@[inline]
@[inline, expose]
def mapIdxM {α : Type u} {β : Type v} {m : Type v Type w} [Monad m] (f : Nat α m β) (xs : Vector α n) : m (Vector β n) :=
xs.mapFinIdxM fun i a _ => f i a
@[inline] def firstM {α : Type u} {m : Type v Type w} [Alternative m] (f : α m β) (xs : Vector α n) : m β :=
@[inline, expose] def firstM {α : Type u} {m : Type v Type w} [Alternative m] (f : α m β) (xs : Vector α n) : m β :=
xs.toArray.firstM f
@[inline] def flatten (xs : Vector (Vector α n) m) : Vector α (m * n) :=
@[inline, expose] def flatten (xs : Vector (Vector α n) m) : Vector α (m * n) :=
(xs.toArray.map Vector.toArray).flatten,
by rcases xs; simp_all [Function.comp_def, Array.map_const']
@[inline] def flatMap (xs : Vector α n) (f : α Vector β m) : Vector β (n * m) :=
@[inline, expose] def flatMap (xs : Vector α n) (f : α Vector β m) : Vector β (n * m) :=
xs.toArray.flatMap fun a => (f a).toArray, by simp [Array.map_const']
@[inline] def zipIdx (xs : Vector α n) (k : Nat := 0) : Vector (α × Nat) n :=
@[inline, expose] def zipIdx (xs : Vector α n) (k : Nat := 0) : Vector (α × Nat) n :=
xs.toArray.zipIdx k, by simp
@[deprecated zipIdx (since := "2025-01-21")]
abbrev zipWithIndex := @zipIdx
@[inline] def zip (as : Vector α n) (bs : Vector β n) : Vector (α × β) n :=
@[inline, expose] def zip (as : Vector α n) (bs : Vector β n) : Vector (α × β) n :=
as.toArray.zip bs.toArray, by simp
/-- Maps corresponding elements of two vectors of equal size using the function `f`. -/
@[inline] def zipWith (f : α β φ) (as : Vector α n) (bs : Vector β n) : Vector φ n :=
@[inline, expose] def zipWith (f : α β φ) (as : Vector α n) (bs : Vector β n) : Vector φ n :=
as.toArray.zipWith f bs.toArray, by simp
@[inline] def unzip (xs : Vector (α × β) n) : Vector α n × Vector β n :=
@[inline, expose] def unzip (xs : Vector (α × β) n) : Vector α n × Vector β n :=
xs.toArray.unzip.1, by simp, xs.toArray.unzip.2, by simp
/-- The vector of length `n` whose `i`-th element is `f i`. -/
@[inline] def ofFn (f : Fin n α) : Vector α n :=
@[inline, expose] def ofFn (f : Fin n α) : Vector α n :=
Array.ofFn f, by simp
/-! See also `Vector.ofFnM` defined in `Init.Data.Vector.OfFn`. -/
@@ -314,7 +324,7 @@ Swap two elements of a vector using `Fin` indices.
This will perform the update destructively provided that the vector has a reference count of 1.
-/
@[inline] def swap (xs : Vector α n) (i j : Nat)
@[inline, expose] def swap (xs : Vector α n) (i j : Nat)
(hi : i < n := by get_elem_tactic) (hj : j < n := by get_elem_tactic) : Vector α n :=
xs.toArray.swap i j (by simpa using hi) (by simpa using hj), by simp
@@ -323,7 +333,7 @@ Swap two elements of a vector using `Nat` indices. Panics if either index is out
This will perform the update destructively provided that the vector has a reference count of 1.
-/
@[inline] def swapIfInBounds (xs : Vector α n) (i j : Nat) : Vector α n :=
@[inline, expose] def swapIfInBounds (xs : Vector α n) (i j : Nat) : Vector α n :=
xs.toArray.swapIfInBounds i j, by simp
/--
@@ -332,7 +342,7 @@ along with the updated vector.
This will perform the update destructively provided that the vector has a reference count of 1.
-/
@[inline] def swapAt (xs : Vector α n) (i : Nat) (x : α) (hi : i < n := by get_elem_tactic) :
@[inline, expose] def swapAt (xs : Vector α n) (i : Nat) (x : α) (hi : i < n := by get_elem_tactic) :
α × Vector α n :=
let a := xs.toArray.swapAt i x (by simpa using hi)
a.fst, a.snd, by simp [a]
@@ -343,38 +353,38 @@ bounds. The original value is returned along with the updated vector.
This will perform the update destructively provided that the vector has a reference count of 1.
-/
@[inline] def swapAt! (xs : Vector α n) (i : Nat) (x : α) : α × Vector α n :=
@[inline, expose] def swapAt! (xs : Vector α n) (i : Nat) (x : α) : α × Vector α n :=
let a := xs.toArray.swapAt! i x
a.fst, a.snd, by simp [a]
/-- The vector `#v[0, 1, 2, ..., n-1]`. -/
@[inline] def range (n : Nat) : Vector Nat n := Array.range n, by simp
@[inline, expose] def range (n : Nat) : Vector Nat n := Array.range n, by simp
/-- The vector `#v[start, start + step, start + 2 * step, ..., start + (size - 1) * step]`. -/
@[inline] def range' (start size : Nat) (step : Nat := 1) : Vector Nat size :=
@[inline, expose] def range' (start size : Nat) (step : Nat := 1) : Vector Nat size :=
Array.range' start size step, by simp
/--
Compares two vectors of the same size using a given boolean relation `r`. `isEqv v w r` returns
`true` if and only if `r v[i] w[i]` is true for all indices `i`.
-/
@[inline] def isEqv (xs ys : Vector α n) (r : α α Bool) : Bool :=
@[inline, expose] def isEqv (xs ys : Vector α n) (r : α α Bool) : Bool :=
Array.isEqvAux xs.toArray ys.toArray (by simp) r n (by simp)
instance [BEq α] : BEq (Vector α n) where
beq xs ys := isEqv xs ys (· == ·)
/-- Reverse the elements of a vector. -/
@[inline] def reverse (xs : Vector α n) : Vector α n :=
@[inline, expose] def reverse (xs : Vector α n) : Vector α n :=
xs.toArray.reverse, by simp
/-- Delete an element of a vector using a `Nat` index and a tactic provided proof. -/
@[inline] def eraseIdx (xs : Vector α n) (i : Nat) (h : i < n := by get_elem_tactic) :
@[inline, expose] def eraseIdx (xs : Vector α n) (i : Nat) (h : i < n := by get_elem_tactic) :
Vector α (n-1) :=
xs.toArray.eraseIdx i (xs.size_toArray.symm h), by simp [Array.size_eraseIdx]
/-- Delete an element of a vector using a `Nat` index. Panics if the index is out of bounds. -/
@[inline] def eraseIdx! (xs : Vector α n) (i : Nat) : Vector α (n-1) :=
@[inline, expose] def eraseIdx! (xs : Vector α n) (i : Nat) : Vector α (n-1) :=
if _ : i < n then
xs.eraseIdx i
else
@@ -382,30 +392,35 @@ instance [BEq α] : BEq (Vector α n) where
panic! "index out of bounds"
/-- Insert an element into a vector using a `Nat` index and a tactic provided proof. -/
@[inline] def insertIdx (xs : Vector α n) (i : Nat) (x : α) (h : i n := by get_elem_tactic) :
@[inline, expose] def insertIdx (xs : Vector α n) (i : Nat) (x : α) (h : i n := by get_elem_tactic) :
Vector α (n+1) :=
xs.toArray.insertIdx i x (xs.size_toArray.symm h), by simp [Array.size_insertIdx]
/-- Insert an element into a vector using a `Nat` index. Panics if the index is out of bounds. -/
@[inline] def insertIdx! (xs : Vector α n) (i : Nat) (x : α) : Vector α (n+1) :=
@[inline, expose] def insertIdx! (xs : Vector α n) (i : Nat) (x : α) : Vector α (n+1) :=
if _ : i n then
xs.insertIdx i x
else
have : Inhabited (Vector α (n+1)) := xs.push x
panic! "index out of bounds"
/-- Delete the first element of a vector. Returns the empty vector if the input vector is empty. -/
@[inline] def tail (xs : Vector α n) : Vector α (n-1) :=
if _ : 0 < n then
xs.eraseIdx 0
else
xs.cast (by omega)
/--
Delete the first element of a vector. Returns the empty vector if the input vector is empty.
We immediately simplify this to the `extract` operation, so there is no verification API for this function.
-/
@[inline, expose]
def tail (xs : Vector α n) : Vector α (n-1) :=
(xs.extract 1).cast (by omega)
@[simp] theorem tail_eq_cast_extract (xs : Vector α n) :
xs.tail = (xs.extract 1).cast (by omega) := rfl
/--
Finds the first index of a given value in a vector using `==` for comparison. Returns `none` if the
no element of the index matches the given value.
-/
@[inline] def finIdxOf? [BEq α] (xs : Vector α n) (x : α) : Option (Fin n) :=
@[inline, expose] def finIdxOf? [BEq α] (xs : Vector α n) (x : α) : Option (Fin n) :=
(xs.toArray.finIdxOf? x).map (Fin.cast xs.size_toArray)
@[deprecated finIdxOf? (since := "2025-01-29")]
@@ -413,70 +428,70 @@ abbrev indexOf? := @finIdxOf?
/-- Finds the first index of a given value in a vector using a predicate. Returns `none` if the
no element of the index matches the given value. -/
@[inline] def findFinIdx? (p : α Bool) (xs : Vector α n) : Option (Fin n) :=
@[inline, expose] def findFinIdx? (p : α Bool) (xs : Vector α n) : Option (Fin n) :=
(xs.toArray.findFinIdx? p).map (Fin.cast xs.size_toArray)
/--
Note that the universe level is constrained to `Type` here,
to avoid having to have the predicate live in `p : α → m (ULift Bool)`.
-/
@[inline] def findM? {α : Type} {m : Type Type} [Monad m] (f : α m Bool) (as : Vector α n) : m (Option α) :=
@[inline, expose] def findM? {α : Type} {m : Type Type} [Monad m] (f : α m Bool) (as : Vector α n) : m (Option α) :=
as.toArray.findM? f
@[inline] def findSomeM? [Monad m] (f : α m (Option β)) (as : Vector α n) : m (Option β) :=
@[inline, expose] def findSomeM? [Monad m] (f : α m (Option β)) (as : Vector α n) : m (Option β) :=
as.toArray.findSomeM? f
/--
Note that the universe level is constrained to `Type` here,
to avoid having to have the predicate live in `p : α → m (ULift Bool)`.
-/
@[inline] def findRevM? {α : Type} {m : Type Type} [Monad m] (f : α m Bool) (as : Vector α n) : m (Option α) :=
@[inline, expose] def findRevM? {α : Type} {m : Type Type} [Monad m] (f : α m Bool) (as : Vector α n) : m (Option α) :=
as.toArray.findRevM? f
@[inline] def findSomeRevM? [Monad m] (f : α m (Option β)) (as : Vector α n) : m (Option β) :=
@[inline, expose] def findSomeRevM? [Monad m] (f : α m (Option β)) (as : Vector α n) : m (Option β) :=
as.toArray.findSomeRevM? f
@[inline] def find? {α : Type} (f : α Bool) (as : Vector α n) : Option α :=
@[inline, expose] def find? {α : Type} (f : α Bool) (as : Vector α n) : Option α :=
as.toArray.find? f
@[inline] def findRev? {α : Type} (f : α Bool) (as : Vector α n) : Option α :=
@[inline, expose] def findRev? {α : Type} (f : α Bool) (as : Vector α n) : Option α :=
as.toArray.findRev? f
@[inline] def findSome? (f : α Option β) (as : Vector α n) : Option β :=
@[inline, expose] def findSome? (f : α Option β) (as : Vector α n) : Option β :=
as.toArray.findSome? f
@[inline] def findSomeRev? (f : α Option β) (as : Vector α n) : Option β :=
@[inline, expose] def findSomeRev? (f : α Option β) (as : Vector α n) : Option β :=
as.toArray.findSomeRev? f
/-- Returns `true` when `xs` is a prefix of the vector `ys`. -/
@[inline] def isPrefixOf [BEq α] (xs : Vector α m) (ys : Vector α n) : Bool :=
@[inline, expose] def isPrefixOf [BEq α] (xs : Vector α m) (ys : Vector α n) : Bool :=
xs.toArray.isPrefixOf ys.toArray
/-- Returns `true` with the monad if `p` returns `true` for any element of the vector. -/
@[inline] def anyM [Monad m] (p : α m Bool) (xs : Vector α n) : m Bool :=
@[inline, expose] def anyM [Monad m] (p : α m Bool) (xs : Vector α n) : m Bool :=
xs.toArray.anyM p
/-- Returns `true` with the monad if `p` returns `true` for all elements of the vector. -/
@[inline] def allM [Monad m] (p : α m Bool) (xs : Vector α n) : m Bool :=
@[inline, expose] def allM [Monad m] (p : α m Bool) (xs : Vector α n) : m Bool :=
xs.toArray.allM p
/-- Returns `true` if `p` returns `true` for any element of the vector. -/
@[inline] def any (xs : Vector α n) (p : α Bool) : Bool :=
@[inline, expose] def any (xs : Vector α n) (p : α Bool) : Bool :=
xs.toArray.any p
/-- Returns `true` if `p` returns `true` for all elements of the vector. -/
@[inline] def all (xs : Vector α n) (p : α Bool) : Bool :=
@[inline, expose] def all (xs : Vector α n) (p : α Bool) : Bool :=
xs.toArray.all p
/-- Count the number of elements of a vector that satisfy the predicate `p`. -/
@[inline] def countP (p : α Bool) (xs : Vector α n) : Nat :=
@[inline, expose] def countP (p : α Bool) (xs : Vector α n) : Nat :=
xs.toArray.countP p
/-- Count the number of elements of a vector that are equal to `a`. -/
@[inline] def count [BEq α] (a : α) (xs : Vector α n) : Nat :=
@[inline, expose] def count [BEq α] (a : α) (xs : Vector α n) : Nat :=
xs.toArray.count a
@[inline] def replace [BEq α] (xs : Vector α n) (a b : α) : Vector α n :=
@[inline, expose] def replace [BEq α] (xs : Vector α n) (a b : α) : Vector α n :=
xs.toArray.replace a b, by simp
/--
@@ -486,7 +501,7 @@ Examples:
* `#v[a, b, c].sum = a + (b + (c + 0))`
* `#v[1, 2, 5].sum = 8`
-/
@[inline] def sum [Add α] [Zero α] (xs : Vector α n) : α :=
@[inline, expose] def sum [Add α] [Zero α] (xs : Vector α n) : α :=
xs.toArray.sum
/--

View File

@@ -40,12 +40,12 @@ theorem countP_push {a : α} {xs : Vector α n} : countP p (xs.push a) = countP
rcases xs with xs, rfl
simp [Array.countP_push]
@[simp] theorem countP_singleton {a : α} : countP p #v[a] = if p a then 1 else 0 := by
simp [countP_push]
theorem countP_singleton {a : α} : countP p #v[a] = if p a then 1 else 0 := by
simp
theorem size_eq_countP_add_countP {xs : Vector α n} : n = countP p xs + countP (fun a => ¬p a) xs := by
rcases xs with xs, rfl
simp [List.length_eq_countP_add_countP (p := p)]
simp [Array.size_eq_countP_add_countP (p := p)]
theorem countP_le_size {xs : Vector α n} : countP p xs n := by
rcases xs with xs, rfl

View File

@@ -48,15 +48,18 @@ theorem beq_eq_decide [BEq α] (xs ys : Vector α n) :
(xs == ys) = decide ( (i : Nat) (h' : i < n), xs[i] == ys[i]) := by
simp [BEq.beq, isEqv_eq_decide]
@[simp] theorem beq_mk [BEq α] (xs ys : Array α) (ha : xs.size = n) (hb : ys.size = n) :
@[deprecated mk_beq_mk (since := "2025-05-26")]
theorem beq_mk [BEq α] (xs ys : Array α) (ha : xs.size = n) (hb : ys.size = n) :
(mk xs ha == mk ys hb) = (xs == ys) := by
simp [BEq.beq]
simp
@[simp, grind =] theorem beq_toArray [BEq α] (xs ys : Vector α n) : (xs.toArray == ys.toArray) = (xs == ys) := by
simp [beq_eq_decide, Array.beq_eq_decide]
@[deprecated toArray_beq_toArray (since := "2025-05-26")]
theorem beq_toArray [BEq α] (xs ys : Vector α n) : (xs.toArray == ys.toArray) = (xs == ys) := by
simp
@[simp] theorem beq_toList [BEq α] (xs ys : Vector α n) : (xs.toList == ys.toList) = (xs == ys) := by
simp [beq_eq_decide, List.beq_eq_decide]
@[deprecated toList_beq_toList (since := "2025-05-26")]
theorem beq_toList [BEq α] (xs ys : Vector α n) : (xs.toList == ys.toList) = (xs == ys) := by
simp
instance [BEq α] [ReflBEq α] : ReflBEq (Vector α n) where
rfl := by simp [BEq.beq, isEqv_self_beq]

View File

@@ -144,7 +144,7 @@ abbrev findSome?_mkVector_of_isNone := @findSome?_replicate_of_isNone
@[simp] theorem find?_empty : find? p #v[] = none := rfl
@[simp] theorem find?_singleton {a : α} {p : α Bool} :
theorem find?_singleton {a : α} {p : α Bool} :
#v[a].find? p = if p a then some a else none := by
simp
@@ -291,7 +291,8 @@ theorem find?_eq_some_iff_getElem {xs : Vector α n} {p : α → Bool} {b : α}
/-! ### findFinIdx? -/
@[simp] theorem findFinIdx?_empty {p : α Bool} : findFinIdx? p (#v[] : Vector α 0) = none := by simp
theorem findFinIdx?_empty {p : α Bool} : findFinIdx? p (#v[] : Vector α 0) = none := by simp
theorem findFinIdx?_singleton {a : α} {p : α Bool} :
#[a].findFinIdx? p = if p a then some 0, by simp else none := by
simp

View File

@@ -486,7 +486,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]
@[ext, grind 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
@@ -684,8 +684,7 @@ abbrev toList_eq_empty_iff {α n} (xs) := @toList_eq_nil_iff α n xs
/-! ### empty -/
@[simp] theorem empty_eq {xs : Vector α 0} : #v[] = xs xs = #v[] := by
cases xs
theorem empty_eq {xs : Vector α 0} : #v[] = xs xs = #v[] := by
simp
/-- A vector of length `0` is the empty vector. -/
@@ -699,7 +698,7 @@ protected theorem eq_empty {xs : Vector α 0} : xs = #v[] := by
theorem eq_empty_of_size_eq_zero {xs : Vector α n} (h : n = 0) : xs = #v[].cast h.symm := by
rcases xs with xs, rfl
apply toArray_inj.1
simp only [List.length_eq_zero_iff, Array.toList_eq_nil_iff] at h
simp only [Array.size_eq_zero_iff] at h
simp [h]
theorem size_eq_one {xs : Vector α 1} : a, xs = #v[a] := by
@@ -816,14 +815,11 @@ abbrev mkVector_eq_mk_mkArray := @replicate_eq_mk_replicate
/-! ## L[i] and L[i]? -/
@[simp] theorem getElem?_eq_none_iff {xs : Vector α n} : xs[i]? = none n i := by
by_cases h : i < n
· simp [getElem?_pos, h]
· rw [getElem?_neg xs i h]
simp_all
theorem getElem?_eq_none_iff {xs : Vector α n} : xs[i]? = none n i := by
simp
@[simp] theorem none_eq_getElem?_iff {xs : Vector α n} {i : Nat} : none = xs[i]? n i := by
simp [eq_comm (a := none)]
theorem none_eq_getElem?_iff {xs : Vector α n} {i : Nat} : none = xs[i]? n i := by
simp
theorem getElem?_eq_none {xs : Vector α n} (h : n i) : xs[i]? = none := by
simp [getElem?_eq_none_iff, h]
@@ -835,23 +831,23 @@ grind_pattern Vector.getElem?_eq_none => n ≤ i, xs[i]?
@[simp] theorem getElem?_eq_getElem {xs : Vector α n} {i : Nat} (h : i < n) : xs[i]? = some xs[i] :=
getElem?_pos ..
theorem getElem?_eq_some_iff {xs : Vector α n} : xs[i]? = some b h : i < n, xs[i] = b := by
simp [getElem?_def]
theorem getElem?_eq_some_iff {xs : Vector α n} : xs[i]? = some b h : i < n, xs[i] = b :=
_root_.getElem?_eq_some_iff
@[grind ]
theorem getElem_of_getElem? {xs : Vector α n} : xs[i]? = some a h : i < n, xs[i] = a :=
getElem?_eq_some_iff.mp
theorem some_eq_getElem?_iff {xs : Vector α n} : some b = xs[i]? h : i < n, xs[i] = b := by
rw [eq_comm, getElem?_eq_some_iff]
theorem some_eq_getElem?_iff {xs : Vector α n} : some b = xs[i]? h : i < n, xs[i] = b :=
_root_.some_eq_getElem?_iff
@[simp] theorem some_getElem_eq_getElem?_iff {xs : Vector α n} {i : Nat} (h : i < n) :
theorem some_getElem_eq_getElem?_iff {xs : Vector α n} {i : Nat} (h : i < n) :
(some xs[i] = xs[i]?) True := by
simp [h]
simp
@[simp] theorem getElem?_eq_some_getElem_iff {xs : Vector α n} {i : Nat} (h : i < n) :
theorem getElem?_eq_some_getElem_iff {xs : Vector α n} {i : Nat} (h : i < n) :
(xs[i]? = some xs[i]) True := by
simp [h]
simp
theorem getElem_eq_iff {xs : Vector α n} {i : Nat} {h : i < n} : xs[i] = x xs[i]? = some x := by
simp only [getElem?_eq_some_iff]
@@ -891,12 +887,11 @@ theorem getElem?_push {xs : Vector α n} {x : α} {i : Nat} : (xs.push x)[i]? =
(repeat' split) <;> first | rfl | omega
set_option linter.indexVariables false in
@[simp] theorem getElem?_push_size {xs : Vector α n} {x : α} : (xs.push x)[n]? = some x := by
simp [getElem?_push]
theorem getElem?_push_size {xs : Vector α n} {x : α} : (xs.push x)[n]? = some x := by
simp
@[simp] theorem getElem_singleton {a : α} (h : i < 1) : #v[a][i] = a :=
match i, h with
| 0, _ => rfl
theorem getElem_singleton {a : α} (h : i < 1) : #v[a][i] = a := by
simp
@[grind]
theorem getElem?_singleton {a : α} {i : Nat} : #v[a][i]? = if i = 0 then some a else none := by
@@ -908,7 +903,7 @@ theorem getElem?_singleton {a : α} {i : Nat} : #v[a][i]? = if i = 0 then some a
rcases xs with xs, rfl
simp
@[simp] theorem not_mem_empty (a : α) : ¬ a #v[] := nofun
theorem not_mem_empty (a : α) : ¬ a #v[] := nofun
@[simp] theorem mem_push {xs : Vector α n} {x y : α} : x xs.push y x xs x = y := by
rcases xs with xs, rfl
@@ -957,8 +952,7 @@ theorem size_zero_iff_forall_not_mem {xs : Vector α n} : n = 0 ↔ ∀ a, a ∉
theorem eq_of_mem_singleton (h : a #v[b]) : a = b := by
simpa using h
@[simp] theorem mem_singleton {a b : α} : a #v[b] a = b :=
eq_of_mem_singleton, (by simp [·])
theorem mem_singleton {a b : α} : a #v[b] a = b := by simp
theorem forall_mem_push {p : α Prop} {xs : Vector α n} {a : α} :
( x, x xs.push a p x) p a x, x xs p x := by
@@ -1444,10 +1438,9 @@ theorem back_eq_getElem [NeZero n] {xs : Vector α n} : xs.back = xs[n - 1]'(by
simp
/-- The empty vector maps to the empty vector. -/
@[simp, grind]
@[grind]
theorem map_empty {f : α β} : map f #v[] = #v[] := by
rw [map, mk.injEq]
exact Array.map_empty
simp
@[simp, grind] theorem map_push {f : α β} {as : Vector α n} {x : α} :
(as.push x).map f = (as.map f).push (f x) := by
@@ -1524,9 +1517,8 @@ theorem map_eq_push_iff {f : α → β} {xs : Vector α (n + 1)} {ys : Vector β
· rintro xs', a, h₁, h₂, rfl
refine xs'.toArray, a, by simp_all
@[simp] theorem map_eq_singleton_iff {f : α β} {xs : Vector α 1} {b : β} :
theorem map_eq_singleton_iff {f : α β} {xs : Vector α 1} {b : β} :
map f xs = #v[b] a, xs = #v[a] f a = b := by
cases xs
simp
theorem map_eq_map_iff {f g : α β} {xs : Vector α n} :
@@ -2105,7 +2097,7 @@ abbrev forall_mem_mkVector := @forall_mem_replicate
@[deprecated getElem_replicate (since := "2025-03-18")]
abbrev getElem_mkVector := @getElem_replicate
@[grind]theorem getElem?_replicate {a : α} {n i : Nat} : (replicate n a)[i]? = if i < n then some a else none := by
@[grind] theorem getElem?_replicate {a : α} {n i : Nat} : (replicate n a)[i]? = if i < n then some a else none := by
simp [getElem?_def]
@[deprecated getElem?_replicate (since := "2025-03-18")]
@@ -2361,13 +2353,13 @@ set_option linter.indexVariables false in
rcases ys with ys, rfl
simp
@[simp] theorem foldlM_empty [Monad m] {f : β α m β} {init : β} :
theorem foldlM_empty [Monad m] {f : β α m β} {init : β} :
foldlM f init #v[] = return init := by
simp [foldlM]
simp
@[simp, grind] theorem foldrM_empty [Monad m] {f : α β m β} {init : β} :
@[grind] theorem foldrM_empty [Monad m] {f : α β m β} {init : β} :
foldrM f init #v[] = return init := by
simp [foldrM]
simp
@[simp, grind] theorem foldlM_push [Monad m] [LawfulMonad m] {xs : Vector α n} {a : α} {f : β α m β} {b} :
(xs.push a).foldlM f b = xs.foldlM f b >>= fun b => f b a := by
@@ -2385,19 +2377,23 @@ theorem foldrM_pure [Monad m] [LawfulMonad m] {f : α → β → β} {b} {xs : V
Array.foldrM_pure
theorem foldl_eq_foldlM {f : β α β} {b} {xs : Vector α n} :
xs.foldl f b = xs.foldlM (m := Id) f b := by
rcases xs with xs, rfl
simp [Array.foldl_eq_foldlM]
xs.foldl f b = (xs.foldlM (m := Id) (pure <| f · ·) b).run := rfl
theorem foldr_eq_foldrM {f : α β β} {b} {xs : Vector α n} :
xs.foldr f b = xs.foldrM (m := Id) f b := by
rcases xs with xs, rfl
simp [Array.foldr_eq_foldrM]
xs.foldr f b = (xs.foldrM (m := Id) (pure <| f · ·) b).run := rfl
@[simp] theorem id_run_foldlM {f : β α Id β} {b} {xs : Vector α n} :
@[simp] theorem idRun_foldlM {f : β α Id β} {b} {xs : Vector α n} :
Id.run (xs.foldlM f b) = xs.foldl (f · · |>.run) b := foldl_eq_foldlM.symm
@[deprecated idRun_foldlM (since := "2025-05-21")]
theorem id_run_foldlM {f : β α Id β} {b} {xs : Vector α n} :
Id.run (xs.foldlM f b) = xs.foldl f b := foldl_eq_foldlM.symm
@[simp] theorem id_run_foldrM {f : α β Id β} {b} {xs : Vector α n} :
@[simp] theorem idRun_foldrM {f : α β Id β} {b} {xs : Vector α n} :
Id.run (xs.foldrM f b) = xs.foldr (f · · |>.run) b := foldr_eq_foldrM.symm
@[deprecated idRun_foldrM (since := "2025-05-21")]
theorem id_run_foldrM {f : α β Id β} {b} {xs : Vector α n} :
Id.run (xs.foldrM f b) = xs.foldr f b := foldr_eq_foldrM.symm
@[simp] theorem foldlM_reverse [Monad m] {xs : Vector α n} {f : β α m β} {b} :
@@ -2485,10 +2481,10 @@ theorem foldr_map_hom {g : α → β} {f : ααα} {f' : β → β →
simp
@[simp, grind _=_] theorem foldl_append {β : Type _} {f : β α β} {b} {xs : Vector α n} {ys : Vector α k} :
(xs ++ ys).foldl f b = ys.foldl f (xs.foldl f b) := by simp [foldl_eq_foldlM]
(xs ++ ys).foldl f b = ys.foldl f (xs.foldl f b) := foldlM_append
@[simp, grind _=_] theorem foldr_append {f : α β β} {b} {xs : Vector α n} {ys : Vector α k} :
(xs ++ ys).foldr f b = xs.foldr f (ys.foldr f b) := by simp [foldr_eq_foldrM]
(xs ++ ys).foldr f b = xs.foldr f (ys.foldr f b) := foldrM_append
@[simp, grind] theorem foldl_flatten {f : β α β} {b} {xss : Vector (Vector α m) n} :
(flatten xss).foldl f b = xss.foldl (fun b xs => xs.foldl f b) b := by
@@ -2501,7 +2497,8 @@ theorem foldr_map_hom {g : α → β} {f : ααα} {f' : β → β →
simp [Array.foldr_flatten', Array.foldr_map']
@[simp, grind] theorem foldl_reverse {xs : Vector α n} {f : β α β} {b} :
xs.reverse.foldl f b = xs.foldr (fun x y => f y x) b := by simp [foldl_eq_foldlM, foldr_eq_foldrM]
xs.reverse.foldl f b = xs.foldr (fun x y => f y x) b :=
foldlM_reverse
@[simp, grind] theorem foldr_reverse {xs : Vector α n} {f : α β β} {b} :
xs.reverse.foldr f b = xs.foldl (fun x y => f y x) b :=
@@ -2680,7 +2677,7 @@ theorem contains_iff_exists_mem_beq [BEq α] {xs : Vector α n} {a : α} :
rcases xs with xs, rfl
simp [Array.contains_iff_exists_mem_beq]
@[grind]
@[grind _=_]
theorem contains_iff_mem [BEq α] [LawfulBEq α] {xs : Vector α n} {a : α} :
xs.contains a a xs := by
simp
@@ -3053,8 +3050,7 @@ end replace
/-! Content below this point has not yet been aligned with `List` and `Array`. -/
set_option linter.indexVariables false in
@[simp] theorem getElem_push_last {xs : Vector α n} {x : α} : (xs.push x)[n] = x := by
rcases xs with xs, rfl
theorem getElem_push_last {xs : Vector α n} {x : α} : (xs.push x)[n] = x := by
simp
@[simp] theorem push_pop_back (xs : Vector α (n + 1)) : xs.pop.push xs.back = xs := by
@@ -3086,8 +3082,7 @@ set_option linter.indexVariables false in
/-! ### take -/
set_option linter.indexVariables false in
@[simp] theorem take_size {as : Vector α n} : as.take n = as.cast (by simp) := by
rcases as with as, rfl
theorem take_size {as : Vector α n} : as.take n = as.cast (by simp) := by
simp
/-! ### swap -/
@@ -3136,9 +3131,8 @@ theorem swap_comm {xs : Vector α n} {i j : Nat} (hi hj) :
/-! ### drop -/
@[simp, grind =] theorem getElem_drop {xs : Vector α n} {j : Nat} (hi : i < n - j) :
@[grind =] theorem getElem_drop {xs : Vector α n} {j : Nat} (hi : i < n - j) :
(xs.drop j)[i] = xs[j + i] := by
cases xs
simp
/-! ### Decidable quantifiers. -/

View File

@@ -58,9 +58,8 @@ protected theorem not_le_iff_gt [DecidableEq α] [LT α] [DecidableLT α] {xs ys
cases xs
simp_all
@[simp] theorem singleton_lex_singleton [BEq α] {lt : α α Bool} : #v[a].lex #v[b] lt = lt a b := by
simp only [lex, getElem_mk, List.getElem_toArray, List.getElem_singleton]
cases lt a b <;> cases a != b <;> simp [Id.run]
theorem singleton_lex_singleton [BEq α] {lt : α α Bool} : #v[a].lex #v[b] lt = lt a b := by
simp
protected theorem lt_irrefl [LT α] [Std.Irrefl (· < · : α α Prop)] (xs : Vector α n) : ¬ xs < xs :=
Array.lt_irrefl xs.toArray

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