From dfe493d9d885e8af1d11e1653e0e7b783d9f0138 Mon Sep 17 00:00:00 2001 From: Tobias Grosser Date: Mon, 12 Aug 2024 03:00:58 +0100 Subject: [PATCH] feat: add BitVec.[sshiftRight/shiftLeft]_*_distrib (#4951) After having added already `BitVec.ushiftRight_*_distrib`in https://github.com/leanprover/lean4/pull/4667 for ushiftRight, this PR now completes the `*_distrib` theorems for shift. --- src/Init/Data/BitVec/Lemmas.lean | 54 ++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/src/Init/Data/BitVec/Lemmas.lean b/src/Init/Data/BitVec/Lemmas.lean index 66c0925b5a03..eba2f38de0cf 100644 --- a/src/Init/Data/BitVec/Lemmas.lean +++ b/src/Init/Data/BitVec/Lemmas.lean @@ -577,6 +577,15 @@ instance : Std.Commutative (fun (x y : BitVec w) => x &&& y) := ⟨BitVec.and_co rw [← testBit_toNat, getLsb, getLsb] simp +@[simp] theorem getMsb_xor {x y : BitVec w} : + (x ^^^ y).getMsb i = (xor (x.getMsb i) (y.getMsb i)) := by + simp only [getMsb] + by_cases h : i < w <;> simp [h] + +@[simp] theorem msb_xor {x y : BitVec w} : + (x ^^^ y).msb = (xor x.msb y.msb) := by + simp [BitVec.msb] + @[simp] theorem truncate_xor {x y : BitVec w} : (x ^^^ y).truncate k = x.truncate k ^^^ y.truncate k := by ext @@ -676,6 +685,27 @@ theorem zero_shiftLeft (n : Nat) : 0#w <<< n = 0#w := by cases h₁ : decide (i < m) <;> cases h₂ : decide (n ≤ i) <;> cases h₃ : decide (i < n) all_goals { simp_all <;> omega } +theorem shiftLeft_xor_distrib (x y : BitVec w) (n : Nat) : + (x ^^^ y) <<< n = (x <<< n) ^^^ (y <<< n) := by + ext i + simp only [getLsb_shiftLeft, Fin.is_lt, decide_True, Bool.true_and, getLsb_xor] + by_cases h : i < n + <;> simp [h] + +theorem shiftLeft_and_distrib (x y : BitVec w) (n : Nat) : + (x &&& y) <<< n = (x <<< n) &&& (y <<< n) := by + ext i + simp only [getLsb_shiftLeft, Fin.is_lt, decide_True, Bool.true_and, getLsb_and] + by_cases h : i < n + <;> simp [h] + +theorem shiftLeft_or_distrib (x y : BitVec w) (n : Nat) : + (x ||| y) <<< n = (x <<< n) ||| (y <<< n) := by + ext i + simp only [getLsb_shiftLeft, Fin.is_lt, decide_True, Bool.true_and, getLsb_or] + by_cases h : i < n + <;> simp [h] + @[simp] theorem getMsb_shiftLeft (x : BitVec w) (i) : (x <<< i).getMsb k = x.getMsb (k + i) := by simp only [getMsb, getLsb_shiftLeft] @@ -847,6 +877,30 @@ theorem sshiftRight_eq_of_msb_true {x : BitVec w} {s : Nat} (h : x.msb = true) : Nat.not_lt, decide_eq_true_eq] omega +theorem sshiftRight_xor_distrib (x y : BitVec w) (n : Nat) : + (x ^^^ y).sshiftRight n = (x.sshiftRight n) ^^^ (y.sshiftRight n) := by + ext i + simp only [getLsb_sshiftRight, getLsb_xor, msb_xor] + split + <;> by_cases w ≤ i + <;> simp [*] + +theorem sshiftRight_and_distrib (x y : BitVec w) (n : Nat) : + (x &&& y).sshiftRight n = (x.sshiftRight n) &&& (y.sshiftRight n) := by + ext i + simp only [getLsb_sshiftRight, getLsb_and, msb_and] + split + <;> by_cases w ≤ i + <;> simp [*] + +theorem sshiftRight_or_distrib (x y : BitVec w) (n : Nat) : + (x ||| y).sshiftRight n = (x.sshiftRight n) ||| (y.sshiftRight n) := by + ext i + simp only [getLsb_sshiftRight, getLsb_or, msb_or] + split + <;> by_cases w ≤ i + <;> simp [*] + /-- The msb after arithmetic shifting right equals the original msb. -/ theorem sshiftRight_msb_eq_msb {n : Nat} {x : BitVec w} : (x.sshiftRight n).msb = x.msb := by