Skip to content

Commit bff3ff2

Browse files
committed
bv_append
1 parent f50b863 commit bff3ff2

1 file changed

Lines changed: 192 additions & 0 deletions

File tree

src/Init/Data/BitVec/Lemmas.lean

Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -619,6 +619,8 @@ theorem le_toInt {w : Nat} {x : BitVec w} : -2 ^ w ≤ 2 * x.toInt := by
619619
· rw [← Nat.two_pow_pred_add_two_pow_pred (by omega), ← Nat.two_mul, Nat.add_sub_cancel]
620620
simp only [Nat.zero_lt_succ, Nat.mul_lt_mul_left, Int.natCast_mul, Int.Nat.cast_ofNat_Int]
621621
norm_cast; omega
622+
@[simp] theorem toInt_cast (h : w = v) (x : BitVec w) : (cast h x).toInt = x.toInt := by
623+
simp [toInt_eq_toNat_bmod, h]
622624

623625
/-! ### slt -/
624626

@@ -673,6 +675,12 @@ theorem zeroExtend_eq_setWidth {v : Nat} {x : BitVec w} :
673675
(x.setWidth v).toFin = Fin.ofNat' (2^v) x.toNat := by
674676
ext; simp
675677

678+
theorem setWidth'_eq {x : BitVec w} (h : w ≤ v) : x.setWidth' h = x.setWidth v := by
679+
apply eq_of_toNat_eq
680+
rw [toNat_setWidth, toNat_setWidth']
681+
rw [Nat.mod_eq_of_lt]
682+
exact Nat.lt_of_lt_of_le x.isLt (Nat.pow_le_pow_right (Nat.zero_lt_two) h)
683+
676684
@[simp] theorem setWidth_eq (x : BitVec n) : setWidth n x = x := by
677685
apply eq_of_toNat_eq
678686
let ⟨x, lt_n⟩ := x
@@ -2026,6 +2034,23 @@ theorem append_def (x : BitVec v) (y : BitVec w) :
20262034
(x ++ y).toNat = x.toNat <<< n ||| y.toNat :=
20272035
rfl
20282036

2037+
/-- Helper theorem to show that the expression in `(x ++ y).toFin` is inbounds. -/
2038+
theorem toNat_append_lt {m n : Nat} (x : BitVec m) (y : BitVec n) :
2039+
x.toNat <<< n ||| y.toNat < 2 ^ (m + n) := by
2040+
have hnLe : 2^n ≤ 2 ^(m + n) := by
2041+
rw [Nat.pow_add]
2042+
exact Nat.le_mul_of_pos_left (2 ^ n) (Nat.two_pow_pos m)
2043+
apply Nat.or_lt_two_pow
2044+
· have := Nat.two_pow_pos n
2045+
rw [Nat.shiftLeft_eq, Nat.pow_add, Nat.mul_lt_mul_right]
2046+
<;> omega
2047+
· omega
2048+
2049+
@[simp] theorem toFin_append {x : BitVec m} {y : BitVec n} :
2050+
(x ++ y).toFin = @Fin.mk (2^(m+n)) (x.toNat <<< n ||| y.toNat) (toNat_append_lt x y) := by
2051+
ext
2052+
simp
2053+
20292054
theorem getLsbD_append {x : BitVec n} {y : BitVec m} :
20302055
getLsbD (x ++ y) i = if i < m then getLsbD y i else getLsbD x (i - m) := by
20312056
simp only [append_def, getLsbD_or, getLsbD_shiftLeftZeroExtend, getLsbD_setWidth']
@@ -2072,6 +2097,173 @@ theorem msb_append {x : BitVec w} {y : BitVec v} :
20722097
ext
20732098
simp [getElem_append]
20742099

2100+
theorem append_zero {n m : Nat} {x : BitVec n} :
2101+
x ++ 0#m = x.signExtend (n + m) <<< m := by
2102+
induction m
2103+
case zero =>
2104+
simp [signExtend]
2105+
case succ i ih =>
2106+
simp [bv_toNat]
2107+
sorry
2108+
2109+
def lhs (x : BitVec n) (y : BitVec m) : Int := (x++y).toInt
2110+
def rhs (x : BitVec n) (y : BitVec m) : Int := if n == 0 then y.toInt else (x.toInt * (2^m)) + y.toNat
2111+
2112+
def eq (x: BitVec n) (y: BitVec m) : Bool := (lhs x y) = (rhs x y)
2113+
2114+
2115+
#eval (-5#10 ++ 3#2).toInt
2116+
2117+
def test : Bool := Id.run do
2118+
for i in [0, 1, 2, 3, 4, 5, 6, 7, 8] do
2119+
for j in [0, 1, 2, 3, 4, 5, 6, 7, 8] do
2120+
for n in [0, 1, 2, 3, 4] do
2121+
for m in [0, 1, 2, 3, 4] do
2122+
let x := BitVec.ofNat n i
2123+
let y := BitVec.ofNat m j
2124+
if (!eq x y) then
2125+
return false
2126+
return true
2127+
2128+
private theorem Nat.lt_mul_of_le_of_lt_of_lt {a b c : Nat} (hab : a ≤ b) (ha : 0 < a) (hc : 1 < c) :
2129+
a < b * c := by
2130+
have : a * 1 < b * c := Nat.mul_lt_mul_of_le_of_lt' (by omega) (by simp [hc]) (by omega)
2131+
simp at this
2132+
simp [this]
2133+
2134+
private theorem Nat.two_pow_lt_two_pow_add {n m : Nat} (h : m ≠ 0) :
2135+
2 ^ n < 2 ^ (n + m) := by
2136+
apply Nat.pow_lt_pow_of_lt (by omega) (by omega)
2137+
2138+
@[simp] theorem signExtend_shiftLeft_msb {n m : Nat} {x : BitVec n} :
2139+
(signExtend (n + m) x <<< m).msb = x.msb := by
2140+
induction m
2141+
case zero =>
2142+
simp [signExtend]
2143+
case succ i ih =>
2144+
rw [← ih]
2145+
rw [msb_setWidth]
2146+
2147+
unfold BitVec.msb getMsbD
2148+
simp
2149+
by_cases h : (0 < n + i)
2150+
·
2151+
rw [← Nat.add_assoc]
2152+
simp [h]
2153+
have h' : (0 < n + i + 1) := by omega
2154+
have hh : (n + i - (i + 1)) = (n + i - i - 1) := by
2155+
omega
2156+
rw [hh]
2157+
simp
2158+
have hhh : (n + i - 1 - i) = (n + i - i - 1) := by omega
2159+
rw [hhh]
2160+
simp
2161+
rw [getLsbD_signExtend]
2162+
2163+
2164+
2165+
2166+
2167+
2168+
simp [BitVec.msb, getMsbD]
2169+
2170+
by_cases h : 0 < n + (i + 1)
2171+
· simp [h]
2172+
2173+
sorry
2174+
· simp [h]
2175+
sorry
2176+
2177+
@[simp] theorem signExtend_toNat_shift_mod :
2178+
((signExtend (n + m) x).toNat <<< m) % ↑(2 ^ (n + m)) = (signExtend (n + m) x).toNat <<< m :=
2179+
sorry
2180+
2181+
@[simp] theorem toInt_append_zero {n m : Nat} {x : BitVec n} :
2182+
(x ++ 0#m).toInt = x.toInt * (2 ^ m) := by
2183+
by_cases m0 : m = 0
2184+
· subst m0
2185+
simp
2186+
· simp only [ofNat_eq_ofNat, append_zero, toInt_eq_msb_cond]
2187+
by_cases h1 : (signExtend (n + m) x <<< m).msb
2188+
· by_cases h2: x.msb
2189+
· norm_cast
2190+
simp [h1, h2]
2191+
norm_cast
2192+
rw [Int.sub_mul, Nat.pow_add]
2193+
norm_cast
2194+
simp
2195+
rw [Nat.shiftLeft_eq]
2196+
norm_cast
2197+
have aa := @Nat.pow_pos 2 m (by omega)
2198+
norm_cast
2199+
have bb := @Nat.mul_right_cancel_iff (2^m) ((signExtend (n + m) x).toNat)
2200+
apply bb
2201+
rfl
2202+
rw [Nat.mul_right_cancel (m := 2 ^ m)]
2203+
simp [aa]
2204+
rw [Nat.mod_eq_of_lt (a := x.toNat) (by omega)]
2205+
norm_cast
2206+
simp [h3]
2207+
simp_all
2208+
rw [Nat.shiftLeft_eq]
2209+
· simp only [signExtend_shiftLeft_of_lt] at h1
2210+
contradiction
2211+
· by_cases h2: x.msb
2212+
· simp [signExtend_shiftLeft_of_lt, h2] at h1
2213+
· sorry
2214+
2215+
@[simp] theorem toInt_append {x : BitVec n} {y : BitVec m} :
2216+
(x ++ y).toInt = if n == 0 then y.toInt else x.toInt * (2 ^ m) + y.toNat := by
2217+
by_cases n0 : n = 0
2218+
· subst n0
2219+
simp [BitVec.eq_nil x]
2220+
· by_cases m0 : m = 0
2221+
· subst m0
2222+
simp [BitVec.eq_nil y, n0]
2223+
· simp [m0]
2224+
by_cases y0 : y = 0
2225+
· simp [toInt_append_zero, y0, n0]
2226+
rw [toInt_eq_toNat_cond]
2227+
rw [toInt_eq_toNat_cond]
2228+
split
2229+
·
2230+
split
2231+
<;> norm_cast
2232+
<;> simp
2233+
<;> rw [Nat.mod_eq_of_lt (a := x.toNat) (by omega)]
2234+
<;> norm_cast
2235+
<;> simp [h3]
2236+
<;> simp_all
2237+
· rw [Nat.shiftLeft_eq]
2238+
· rename_i aa bb
2239+
rw [Nat.shiftLeft_eq] at aa
2240+
rw [Nat.pow_add] at aa
2241+
rw [← Nat.mul_assoc] at aa
2242+
2243+
sorry
2244+
·
2245+
split
2246+
<;> norm_cast
2247+
<;> simp
2248+
<;> rw [Nat.mod_eq_of_lt (a := x.toNat) (by omega)]
2249+
<;> norm_cast
2250+
<;> simp [h3]
2251+
<;> simp_all
2252+
· rename_i aa bb
2253+
rw [Nat.shiftLeft_eq] at aa
2254+
rw [Nat.pow_add] at aa
2255+
rw [← Nat.mul_assoc] at aa
2256+
2257+
2258+
2259+
2260+
simp_all
2261+
2262+
2263+
sorry
2264+
· simp [Nat.shiftLeft_eq, Int.sub_mul, Nat.pow_add]
2265+
· sorry
2266+
20752267
@[simp] theorem cast_append_right (h : w + v = w + v') (x : BitVec w) (y : BitVec v) :
20762268
(x ++ y).cast h = x ++ y.cast (by omega) := by
20772269
ext

0 commit comments

Comments
 (0)