@@ -3401,6 +3401,22 @@ theorem twoPow_and (x : BitVec w) (i : Nat) :
34013401 (twoPow w i) &&& x = if x.getLsbD i then twoPow w i else 0 #w := by
34023402 rw [BitVec.and_comm, and_twoPow]
34033403
3404+ /-!
3405+ NOTE(confluence of multiplication by twoPow):
3406+ The three rewrite rules:
3407+ - mul_twoPow_eq_shiftLeft: x * twoPow w i = x << i
3408+ - twoPow_mul_eq_shiftLeft: twoPow w i * x = x << i
3409+ - twoPow_shiftLeft_eq_twoPow_add: `twoPow w i << j = twoPow w (i + j)`
3410+
3411+ ensure confluence in the case of `twoPow w i * twoPow w j`, which can get rewritten into:
3412+ - `twoPow w i * twoPow w j → twoPow w i << j → twoPow w (i + j)
3413+ - `twoPow w i * twoPow w j → twoPow w j << i → twoPow w (j + i)
3414+ - `twoPow w i * twoPow w j → twoPow w (i + j)
3415+
3416+ which produce the same right hand side, upto a commutation of `i + j`,
3417+ which is acceptable for constant folding.
3418+ -/
3419+
34043420@[simp]
34053421theorem mul_twoPow_eq_shiftLeft (x : BitVec w) (i : Nat) :
34063422 x * (twoPow w i) = x <<< i := by
@@ -3414,6 +3430,7 @@ theorem mul_twoPow_eq_shiftLeft (x : BitVec w) (i : Nat) :
34143430 apply Nat.pow_dvd_pow 2 (by omega)
34153431 simp [Nat.mul_mod, hpow]
34163432
3433+ @[simp]
34173434theorem twoPow_mul_eq_shiftLeft (x : BitVec w) (i : Nat) :
34183435 (twoPow w i) * x = x <<< i := by
34193436 rw [BitVec.mul_comm, mul_twoPow_eq_shiftLeft]
@@ -3429,11 +3446,15 @@ theorem shiftLeft_eq_mul_twoPow (x : BitVec w) (n : Nat) :
34293446 simp [getLsbD_shiftLeft, Fin.is_lt, decide_true, Bool.true_and, mul_twoPow_eq_shiftLeft]
34303447
34313448/-- 2^i * 2^j = 2^(i + j) with bitvectors as well -/
3432- theorem twoPow_mul_twoPow_eq {w : Nat} (i j : Nat) : twoPow w i * twoPow w j = twoPow w (i + j) := by
3449+ theorem twoPow_mul_twoPow_eq {w : Nat} (i j : Nat) : twoPow w i * twoPow w j = twoPow w (i + j) := by
34333450 apply BitVec.eq_of_toNat_eq
34343451 simp only [toNat_mul, toNat_twoPow]
34353452 rw [← Nat.mul_mod, Nat.pow_add]
34363453
3454+ @[simp]
3455+ theorem twoPow_shiftLeft_eq_twoPow_add {w i j : Nat} : twoPow w i <<< j = twoPow w (i + j) := by
3456+ rw [shiftLeft_eq_mul_twoPow, twoPow_mul_twoPow_eq]
3457+
34373458/--
34383459The unsigned division of `x` by `2^k` equals shifting `x` right by `k`,
34393460when `k` is less than the bitwidth `w`.
0 commit comments