Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add BitVec.ofFn and lemmas #1078

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Batteries.lean
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import Batteries.Data.Array
import Batteries.Data.AssocList
import Batteries.Data.BinaryHeap
import Batteries.Data.BinomialHeap
import Batteries.Data.BitVec
import Batteries.Data.ByteArray
import Batteries.Data.ByteSubarray
import Batteries.Data.Char
Expand Down
42 changes: 42 additions & 0 deletions Batteries/Data/BitVec.lean
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/-
Copyright (c) 2024 François G. Dorais. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: François G. Dorais
-/

namespace BitVec

theorem getElem_shifConcat (v : BitVec n) (b : Bool) (i) (h : i < n) :
fgdorais marked this conversation as resolved.
Show resolved Hide resolved
(v.shiftConcat b)[i] = if i = 0 then b else v[i-1] := by
rw [← getLsbD_eq_getElem, getLsbD_shiftConcat, getLsbD_eq_getElem, decide_eq_true h,
Bool.true_and]

@[simp] theorem getElem_shiftConcat_zero (v : BitVec n) (b : Bool) (h : 0 < n) :
(v.shiftConcat b)[0] = b := by simp [getElem_shifConcat]

@[simp] theorem getElem_shiftConcat_succ (v : BitVec n) (b : Bool) (h : i + 1 < n) :
(v.shiftConcat b)[i+1] = v[i] := by simp [getElem_shifConcat]

/-- `ofFnAux f` returns the `BitVec m` whose `i`th bit is `f i` when `i < m` -/
@[inline] def ofFnAux (m : Nat) (f : Fin n → Bool) : BitVec m :=
Fin.foldr n (fun i v => v.shiftConcat (f i)) 0

/-- `ofFn f` returns the `BitVec n` whose `i`th bit is `f i` -/
fgdorais marked this conversation as resolved.
Show resolved Hide resolved
abbrev ofFn (f : Fin n → Bool) : BitVec n := ofFnAux n f
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New functions creating BitVecs should have simp lemmas for toNat, toFin, and ideally also toInt.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't that need the Nat/Fin/Int functions to already exist in some way? I would probably just implement those using the BitVec version.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added Nat.ofBits and Fin.ofBits, little endian only since that's the way Nat.testBit works. I will try to think about what the right Int version should be.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding Int.ofBits would require upstreaming Int.testBit from Mathlib. Let me know if you think that's a good idea and I will get it done.


theorem getElem_ofFnAux (f : Fin n → Bool) (i) (h : i < n) (h' : i < m) :
(ofFnAux m f)[i] = f ⟨i, h⟩ := by
simp only [ofFnAux]
induction n generalizing i m with
| zero => contradiction
| succ n ih =>
simp only [Fin.foldr_succ, getElem_shifConcat]
cases i with
| zero =>
simp
| succ i =>
rw [ih (fun i => f i.succ)] <;> try omega
simp

@[simp] theorem getElem_ofFn (f : Fin n → Bool) (i) (h : i < n) : (ofFn f)[i] = f ⟨i, h⟩ :=
getElem_ofFnAux ..
Loading