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 Nat.[shiftLeft_or_distrib, shiftLeft_xor_distrib, shiftLeft_and_distrib, testBit_mul_two_pow, bitwise_mul_two_pow, shiftLeft_bitwise_distrib] #6630

Merged
merged 21 commits into from
Jan 16, 2025
Merged
Changes from 18 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
0fdb812
feat: testBit_mul_two_pow
luisacicolini Jan 13, 2025
805a88a
chore: start proofs
luisacicolini Jan 13, 2025
23f367a
feat: proved!
luisacicolini Jan 13, 2025
427df3f
chore: update simp onlys and remove useless lemma
luisacicolini Jan 13, 2025
6743930
feat: add and and xor distrib
luisacicolini Jan 13, 2025
e7973a4
chore: fix formatting in bitwise_mul_two_pow
luisacicolini Jan 13, 2025
70d4a45
chore: split proof of testBit_mul_two_pow and rtemove useless hypotheses
luisacicolini Jan 13, 2025
43f82c4
chore: remove useless rw in testBit_mul_two_pow_gt
luisacicolini Jan 13, 2025
17f1531
chore: inline redundant omega
luisacicolini Jan 13, 2025
57edc99
chore: simplify suffices further
luisacicolini Jan 14, 2025
1fa28d5
chore: remove omega where res suffice
luisacicolini Jan 14, 2025
465522b
chore: inline more omegas where possible
luisacicolini Jan 14, 2025
79ba4ba
chore: simplify _gt proof further
luisacicolini Jan 14, 2025
340e8d6
chore: remove ugly suffices
luisacicolini Jan 14, 2025
159a9f2
chore: golf testBit_mul_two_pow proof
luisacicolini Jan 14, 2025
4946b2e
chore: replace testBit_mul_pow_ge proof strategy with calc and suffices
luisacicolini Jan 14, 2025
f585dd6
chore: replace haves with calc in testBit_mul_two_pow_le strategy
luisacicolini Jan 14, 2025
3203e11
chore: replace haves with calc in testBit_mul_two_pow_le strategy
luisacicolini Jan 14, 2025
e299ea1
chore: remove useless theorem, simplify testBit_mul_two_pow
luisacicolini Jan 15, 2025
4dc9290
chore: fix theorems ordering
luisacicolini Jan 15, 2025
32bbf2f
chore: remove useless newline
luisacicolini Jan 16, 2025
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
50 changes: 50 additions & 0 deletions src/Init/Data/Nat/Bitwise/Lemmas.lean
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,34 @@ theorem testBit_add (x i n : Nat) : testBit x (i + n) = testBit (x / 2 ^ n) i :=
rw [← Nat.add_assoc, testBit_add_one, ih (x / 2),
Nat.pow_succ, Nat.div_div_eq_div_mul, Nat.mul_comm]

theorem testBit_mul_two_pow_le {x i n : Nat} (h : n ≤ i) :
testBit (x * 2 ^ n) i = testBit x (i - n) := by
simp only [testBit, one_and_eq_mod_two, mod_two_bne_zero]
let j := i - n
congr 2
calc (x * 2 ^ n) >>> i
_ = (x * 2 ^ n) >>> (n + j) := by simp [show i = n + j by omega, shiftRight_eq_div_pow, Nat.pow_add]
_ = x >>> j := by simp [Nat.shiftRight_add, shiftRight_eq_div_pow (n := n), Nat.mul_div_cancel, Nat.pow_pos (a := 2) (n := n) (by omega)];

theorem testBit_mul_two_pow_gt {x i n : Nat} (h : i < n) :
testBit (x * 2 ^ n) i = false := by
simp only [testBit, ← shiftLeft_eq, one_and_eq_mod_two, mod_two_bne_zero, beq_eq_false_iff_ne,
ne_eq]
suffices ∃ y, x <<< n >>> i = 2 * y by omega
let k := n - i
refine ⟨x * 2 ^ (k - 1), ?_⟩
calc x <<< n >>> i
_ = x <<< (k + i) >>> i := by rw [Nat.sub_add_cancel (by omega)]
_ = x * 2 ^ k := by rw [Nat.shiftLeft_add, Nat.shiftLeft_shiftRight, shiftLeft_eq]
_ = x * 2 ^ (k - 1 + 1) := by rw [Nat.sub_add_cancel (by omega)]
_ = 2 * _ := by rw [Nat.pow_succ, ← Nat.mul_assoc, Nat.mul_comm]
luisacicolini marked this conversation as resolved.
Show resolved Hide resolved

theorem testBit_mul_two_pow (x i n : Nat) :
testBit (x * 2 ^ n) i = if n ≤ i then testBit x (i - n) else false := by
split
· simpa [*] using testBit_mul_two_pow_le (by assumption)
· simpa [*] using testBit_mul_two_pow_gt (by omega)

theorem testBit_div_two (x i : Nat) : testBit (x / 2) i = testBit x (i + 1) := by
simp

Expand Down Expand Up @@ -452,6 +480,15 @@ theorem bitwise_lt_two_pow (left : x < 2^n) (right : y < 2^n) : (Nat.bitwise f x
case neg =>
apply Nat.add_lt_add <;> exact hyp1

theorem bitwise_mul_two_pow (of_false_false : f false false = false := by rfl) :
(bitwise f x y) * 2 ^ n = bitwise f (x * 2 ^ n) (y * 2 ^ n) := by
apply Nat.eq_of_testBit_eq
simp only [testBit_mul_two_pow, testBit_bitwise of_false_false, Bool.if_false_right]
intro i
by_cases hn : n ≤ i
· simp [hn]
· simp [hn, of_false_false]

theorem bitwise_div_two_pow (of_false_false : f false false = false := by rfl) :
(bitwise f x y) / 2 ^ n = bitwise f (x / 2 ^ n) (y / 2 ^ n) := by
apply Nat.eq_of_testBit_eq
Expand Down Expand Up @@ -711,6 +748,19 @@ theorem mul_add_lt_is_or {b : Nat} (b_lt : b < 2^i) (a : Nat) : 2^i * a + b = 2^
rw [mod_two_eq_one_iff_testBit_zero, testBit_shiftLeft]
simp

theorem shiftLeft_bitwise_distrib {a b : Nat} (of_false_false : f false false = false := by rfl) :
(bitwise f a b) <<< i = bitwise f (a <<< i) (b <<< i) := by
simp [shiftLeft_eq, bitwise_mul_two_pow of_false_false]

theorem shiftLeft_and_distrib {a b : Nat} : (a &&& b) <<< i = a <<< i &&& b <<< i :=
shiftLeft_bitwise_distrib

theorem shiftLeft_or_distrib {a b : Nat} : (a ||| b) <<< i = a <<< i ||| b <<< i :=
shiftLeft_bitwise_distrib

luisacicolini marked this conversation as resolved.
Show resolved Hide resolved
theorem shiftLeft_xor_distrib {a b : Nat} : (a ^^^ b) <<< i = a <<< i ^^^ b <<< i :=
shiftLeft_bitwise_distrib

@[simp] theorem decide_shiftRight_mod_two_eq_one :
decide (x >>> i % 2 = 1) = x.testBit i := by
simp only [testBit, one_and_eq_mod_two, mod_two_bne_zero]
Expand Down
Loading