[GOAL]
m : ℕ
xs : Bitvec m
b : Bool
⊢ Bitvec.toNat (xs++ₜb ::ᵥ Vector.nil) = Bitvec.toNat xs * 2 + Bitvec.toNat (b ::ᵥ Vector.nil)
[PROOFSTEP]
cases' xs with xs P
[GOAL]
case mk
m : ℕ
b : Bool
xs : List Bool
P : List.length xs = m
⊢ Bitvec.toNat ({ val := xs, property := P }++ₜb ::ᵥ Vector.nil) =
    Bitvec.toNat { val := xs, property := P } * 2 + Bitvec.toNat (b ::ᵥ Vector.nil)
[PROOFSTEP]
simp [bitsToNat_toList]
[GOAL]
case mk
m : ℕ
b : Bool
xs : List Bool
P : List.length xs = m
⊢ bitsToNat (xs ++ [b]) = bitsToNat [b] + bitsToNat xs * 2
[PROOFSTEP]
clear P
[GOAL]
case mk
m : ℕ
b : Bool
xs : List Bool
⊢ bitsToNat (xs ++ [b]) = bitsToNat [b] + bitsToNat xs * 2
[PROOFSTEP]
unfold bitsToNat
[GOAL]
case mk
m : ℕ
b : Bool
xs : List Bool
⊢ List.foldl addLsb 0 (xs ++ [b]) = List.foldl addLsb 0 [b] + List.foldl addLsb 0 xs * 2
[PROOFSTEP]
rw [List.foldl, List.foldl]
  -- generalize the accumulator of foldl
[GOAL]
case mk
m : ℕ
b : Bool
xs : List Bool
⊢ List.foldl addLsb 0 (xs ++ [b]) = addLsb 0 b + List.foldl addLsb 0 xs * 2
[PROOFSTEP]
generalize h : 0 = x
[GOAL]
case mk
m : ℕ
b : Bool
xs : List Bool
x : ℕ
h : 0 = x
⊢ List.foldl addLsb x (xs ++ [b]) = addLsb x b + List.foldl addLsb x xs * 2
[PROOFSTEP]
conv in addLsb x b => rw [← h]
[GOAL]
m : ℕ
b : Bool
xs : List Bool
x : ℕ
h : 0 = x
| addLsb x b
[PROOFSTEP]
rw [← h]
[GOAL]
m : ℕ
b : Bool
xs : List Bool
x : ℕ
h : 0 = x
| addLsb x b
[PROOFSTEP]
rw [← h]
[GOAL]
m : ℕ
b : Bool
xs : List Bool
x : ℕ
h : 0 = x
| addLsb x b
[PROOFSTEP]
rw [← h]
[GOAL]
case mk
m : ℕ
b : Bool
xs : List Bool
x : ℕ
h : 0 = x
⊢ List.foldl addLsb x (xs ++ [b]) = addLsb 0 b + List.foldl addLsb x xs * 2
[PROOFSTEP]
clear h
[GOAL]
case mk
m : ℕ
b : Bool
xs : List Bool
x : ℕ
⊢ List.foldl addLsb x (xs ++ [b]) = addLsb 0 b + List.foldl addLsb x xs * 2
[PROOFSTEP]
simp
[GOAL]
case mk
m : ℕ
b : Bool
xs : List Bool
x : ℕ
⊢ addLsb (List.foldl addLsb x xs) b = addLsb 0 b + List.foldl addLsb x xs * 2
[PROOFSTEP]
induction' xs with x xs xs_ih generalizing x
[GOAL]
case mk.nil
m : ℕ
b : Bool
x✝ x : ℕ
⊢ addLsb (List.foldl addLsb x []) b = addLsb 0 b + List.foldl addLsb x [] * 2
[PROOFSTEP]
simp
[GOAL]
case mk.nil
m : ℕ
b : Bool
x✝ x : ℕ
⊢ addLsb x b = addLsb 0 b + x * 2
[PROOFSTEP]
unfold addLsb
[GOAL]
case mk.nil
m : ℕ
b : Bool
x✝ x : ℕ
⊢ (x + x + bif b then 1 else 0) = (0 + 0 + bif b then 1 else 0) + x * 2
[PROOFSTEP]
simp [Nat.mul_succ]
[GOAL]
case mk.cons
m : ℕ
b : Bool
x✝¹ : ℕ
x✝ : Bool
xs : List Bool
xs_ih : ∀ (x : ℕ), addLsb (List.foldl addLsb x xs) b = addLsb 0 b + List.foldl addLsb x xs * 2
x : ℕ
⊢ addLsb (List.foldl addLsb x (x✝ :: xs)) b = addLsb 0 b + List.foldl addLsb x (x✝ :: xs) * 2
[PROOFSTEP]
simp
[GOAL]
case mk.cons
m : ℕ
b : Bool
x✝¹ : ℕ
x✝ : Bool
xs : List Bool
xs_ih : ∀ (x : ℕ), addLsb (List.foldl addLsb x xs) b = addLsb 0 b + List.foldl addLsb x xs * 2
x : ℕ
⊢ addLsb (List.foldl addLsb (addLsb x x✝) xs) b = addLsb 0 b + List.foldl addLsb (addLsb x x✝) xs * 2
[PROOFSTEP]
apply xs_ih
[GOAL]
n : ℕ
⊢ Bitvec.toNat (decide (n % 2 = 1) ::ᵥ Vector.nil) = n % 2
[PROOFSTEP]
simp [bitsToNat_toList]
[GOAL]
n : ℕ
⊢ bitsToNat [decide (n % 2 = 1)] = n % 2
[PROOFSTEP]
unfold bitsToNat addLsb List.foldl
[GOAL]
n : ℕ
⊢ List.foldl (fun r b => r + r + bif b then 1 else 0) (0 + 0 + bif decide (n % 2 = 1) then 1 else 0) [] = n % 2
[PROOFSTEP]
simp [Nat.cond_decide_mod_two, -Bool.cond_decide]
[GOAL]
k n : ℕ
⊢ Bitvec.toNat (Bitvec.ofNat k n) = n % 2 ^ k
[PROOFSTEP]
induction' k with k ih generalizing n
[GOAL]
case zero
n✝ n : ℕ
⊢ Bitvec.toNat (Bitvec.ofNat zero n) = n % 2 ^ zero
[PROOFSTEP]
simp [Nat.mod_one]
[GOAL]
case zero
n✝ n : ℕ
⊢ Bitvec.toNat (Bitvec.ofNat 0 n) = 0
[PROOFSTEP]
rfl
[GOAL]
case succ
n✝ k : ℕ
ih : ∀ {n : ℕ}, Bitvec.toNat (Bitvec.ofNat k n) = n % 2 ^ k
n : ℕ
⊢ Bitvec.toNat (Bitvec.ofNat (succ k) n) = n % 2 ^ succ k
[PROOFSTEP]
rw [ofNat_succ, toNat_append, ih, bits_toNat_decide, mod_pow_succ, Nat.mul_comm]
[GOAL]
n : ℕ
i : Fin (2 ^ n)
⊢ Bitvec.toNat (ofFin i) = ↑i
[PROOFSTEP]
rw [ofFin, toNat_ofNat, Nat.mod_eq_of_lt]
[GOAL]
n : ℕ
i : Fin (2 ^ n)
⊢ ↑i < 2 ^ n
[PROOFSTEP]
apply i.is_lt
[GOAL]
x : ℕ
b : Bool
⊢ addLsb x b = 2 * x + bif b then 1 else 0
[PROOFSTEP]
simp [addLsb, two_mul]
[GOAL]
n : ℕ
v : Bitvec n
⊢ Bitvec.toNat v = List.foldr (flip addLsb) 0 (List.reverse (Vector.toList v))
[PROOFSTEP]
rw [List.foldr_reverse]
[GOAL]
n : ℕ
v : Bitvec n
⊢ Bitvec.toNat v = List.foldl (fun x y => flip addLsb y x) 0 (Vector.toList v)
[PROOFSTEP]
rfl
[GOAL]
n : ℕ
v : Bitvec n
⊢ Bitvec.toNat v < 2 ^ n
[PROOFSTEP]
suffices : v.toNat + 1 ≤ 2 ^ n
[GOAL]
n : ℕ
v : Bitvec n
this : Bitvec.toNat v + 1 ≤ 2 ^ n
⊢ Bitvec.toNat v < 2 ^ n
case this n : ℕ v : Bitvec n ⊢ Bitvec.toNat v + 1 ≤ 2 ^ n
[PROOFSTEP]
simpa
[GOAL]
case this
n : ℕ
v : Bitvec n
⊢ Bitvec.toNat v + 1 ≤ 2 ^ n
[PROOFSTEP]
rw [toNat_eq_foldr_reverse]
[GOAL]
case this
n : ℕ
v : Bitvec n
⊢ List.foldr (flip addLsb) 0 (List.reverse (Vector.toList v)) + 1 ≤ 2 ^ n
[PROOFSTEP]
cases' v with xs h
[GOAL]
case this.mk
n : ℕ
xs : List Bool
h : List.length xs = n
⊢ List.foldr (flip addLsb) 0 (List.reverse (Vector.toList { val := xs, property := h })) + 1 ≤ 2 ^ n
[PROOFSTEP]
dsimp [Bitvec.toNat, bitsToNat]
[GOAL]
case this.mk
n : ℕ
xs : List Bool
h : List.length xs = n
⊢ List.foldr (flip addLsb) 0 (List.reverse xs) + 1 ≤ 2 ^ n
[PROOFSTEP]
rw [← List.length_reverse] at h 
[GOAL]
case this.mk
n : ℕ
xs : List Bool
h : List.length (List.reverse xs) = n
⊢ List.foldr (flip addLsb) 0 (List.reverse xs) + 1 ≤ 2 ^ n
[PROOFSTEP]
generalize xs.reverse = ys at h 
[GOAL]
case this.mk
n : ℕ
xs ys : List Bool
h : List.length ys = n
⊢ List.foldr (flip addLsb) 0 ys + 1 ≤ 2 ^ n
[PROOFSTEP]
induction' ys with head tail ih generalizing n
[GOAL]
case this.mk.nil
n✝ : ℕ
xs ys : List Bool
h✝ : List.length ys = n✝
n : ℕ
h : List.length [] = n
⊢ List.foldr (flip addLsb) 0 [] + 1 ≤ 2 ^ n
[PROOFSTEP]
simp [← h]
[GOAL]
case this.mk.cons
n✝ : ℕ
xs ys : List Bool
h✝ : List.length ys = n✝
head : Bool
tail : List Bool
ih : ∀ {n : ℕ}, List.length tail = n → List.foldr (flip addLsb) 0 tail + 1 ≤ 2 ^ n
n : ℕ
h : List.length (head :: tail) = n
⊢ List.foldr (flip addLsb) 0 (head :: tail) + 1 ≤ 2 ^ n
[PROOFSTEP]
simp only [← h, pow_add, flip, List.length, List.foldr, pow_one]
[GOAL]
case this.mk.cons
n✝ : ℕ
xs ys : List Bool
h✝ : List.length ys = n✝
head : Bool
tail : List Bool
ih : ∀ {n : ℕ}, List.length tail = n → List.foldr (flip addLsb) 0 tail + 1 ≤ 2 ^ n
n : ℕ
h : List.length (head :: tail) = n
⊢ addLsb (List.foldr (fun b a => addLsb a b) 0 tail) head + 1 ≤ 2 ^ List.length tail * 2
[PROOFSTEP]
rw [addLsb_eq_twice_add_one]
[GOAL]
case this.mk.cons
n✝ : ℕ
xs ys : List Bool
h✝ : List.length ys = n✝
head : Bool
tail : List Bool
ih : ∀ {n : ℕ}, List.length tail = n → List.foldr (flip addLsb) 0 tail + 1 ≤ 2 ^ n
n : ℕ
h : List.length (head :: tail) = n
⊢ (2 * List.foldr (fun b a => addLsb a b) 0 tail + bif head then 1 else 0) + 1 ≤ 2 ^ List.length tail * 2
[PROOFSTEP]
trans
  2 * List.foldr (fun (x : Bool) (y : ℕ) => addLsb y x) 0 tail +
    2 *
      1
        -- Porting note: removed `ac_mono`, `mono` calls
[GOAL]
n✝ : ℕ
xs ys : List Bool
h✝ : List.length ys = n✝
head : Bool
tail : List Bool
ih : ∀ {n : ℕ}, List.length tail = n → List.foldr (flip addLsb) 0 tail + 1 ≤ 2 ^ n
n : ℕ
h : List.length (head :: tail) = n
⊢ (2 * List.foldr (fun b a => addLsb a b) 0 tail + bif head then 1 else 0) + 1 ≤
    2 * List.foldr (fun x y => addLsb y x) 0 tail + 2 * 1
[PROOFSTEP]
rw [add_assoc]
[GOAL]
n✝ : ℕ
xs ys : List Bool
h✝ : List.length ys = n✝
head : Bool
tail : List Bool
ih : ∀ {n : ℕ}, List.length tail = n → List.foldr (flip addLsb) 0 tail + 1 ≤ 2 ^ n
n : ℕ
h : List.length (head :: tail) = n
⊢ 2 * List.foldr (fun b a => addLsb a b) 0 tail + ((bif head then 1 else 0) + 1) ≤
    2 * List.foldr (fun x y => addLsb y x) 0 tail + 2 * 1
[PROOFSTEP]
apply Nat.add_le_add_left
[GOAL]
case h
n✝ : ℕ
xs ys : List Bool
h✝ : List.length ys = n✝
head : Bool
tail : List Bool
ih : ∀ {n : ℕ}, List.length tail = n → List.foldr (flip addLsb) 0 tail + 1 ≤ 2 ^ n
n : ℕ
h : List.length (head :: tail) = n
⊢ (bif head then 1 else 0) + 1 ≤ 2 * 1
[PROOFSTEP]
cases head
[GOAL]
case h.false
n✝ : ℕ
xs ys : List Bool
h✝ : List.length ys = n✝
tail : List Bool
ih : ∀ {n : ℕ}, List.length tail = n → List.foldr (flip addLsb) 0 tail + 1 ≤ 2 ^ n
n : ℕ
h : List.length (false :: tail) = n
⊢ (bif false then 1 else 0) + 1 ≤ 2 * 1
[PROOFSTEP]
simp only
[GOAL]
case h.true
n✝ : ℕ
xs ys : List Bool
h✝ : List.length ys = n✝
tail : List Bool
ih : ∀ {n : ℕ}, List.length tail = n → List.foldr (flip addLsb) 0 tail + 1 ≤ 2 ^ n
n : ℕ
h : List.length (true :: tail) = n
⊢ (bif true then 1 else 0) + 1 ≤ 2 * 1
[PROOFSTEP]
simp only
[GOAL]
n✝ : ℕ
xs ys : List Bool
h✝ : List.length ys = n✝
head : Bool
tail : List Bool
ih : ∀ {n : ℕ}, List.length tail = n → List.foldr (flip addLsb) 0 tail + 1 ≤ 2 ^ n
n : ℕ
h : List.length (head :: tail) = n
⊢ 2 * List.foldr (fun x y => addLsb y x) 0 tail + 2 * 1 ≤ 2 ^ List.length tail * 2
[PROOFSTEP]
rw [← left_distrib]
[GOAL]
n✝ : ℕ
xs ys : List Bool
h✝ : List.length ys = n✝
head : Bool
tail : List Bool
ih : ∀ {n : ℕ}, List.length tail = n → List.foldr (flip addLsb) 0 tail + 1 ≤ 2 ^ n
n : ℕ
h : List.length (head :: tail) = n
⊢ 2 * (List.foldr (fun x y => addLsb y x) 0 tail + 1) ≤ 2 ^ List.length tail * 2
[PROOFSTEP]
rw [mul_comm _ 2]
[GOAL]
n✝ : ℕ
xs ys : List Bool
h✝ : List.length ys = n✝
head : Bool
tail : List Bool
ih : ∀ {n : ℕ}, List.length tail = n → List.foldr (flip addLsb) 0 tail + 1 ≤ 2 ^ n
n : ℕ
h : List.length (head :: tail) = n
⊢ 2 * (List.foldr (fun x y => addLsb y x) 0 tail + 1) ≤ 2 * 2 ^ List.length tail
[PROOFSTEP]
apply Nat.mul_le_mul_left
[GOAL]
case h
n✝ : ℕ
xs ys : List Bool
h✝ : List.length ys = n✝
head : Bool
tail : List Bool
ih : ∀ {n : ℕ}, List.length tail = n → List.foldr (flip addLsb) 0 tail + 1 ≤ 2 ^ n
n : ℕ
h : List.length (head :: tail) = n
⊢ List.foldr (fun x y => addLsb y x) 0 tail + 1 ≤ 2 ^ List.length tail
[PROOFSTEP]
exact ih rfl
[GOAL]
x : ℕ
b : Bool
⊢ addLsb x b / 2 = x
[PROOFSTEP]
cases b
[GOAL]
case false
x : ℕ
⊢ addLsb x false / 2 = x
[PROOFSTEP]
simp only [Nat.add_mul_div_left, addLsb, ← two_mul, add_comm, Nat.succ_pos', Nat.mul_div_right, gt_iff_lt, zero_add,
  cond]
[GOAL]
case true
x : ℕ
⊢ addLsb x true / 2 = x
[PROOFSTEP]
simp only [Nat.add_mul_div_left, addLsb, ← two_mul, add_comm, Nat.succ_pos', Nat.mul_div_right, gt_iff_lt, zero_add,
  cond]
[GOAL]
case true
x : ℕ
⊢ x + 1 / 2 = x
[PROOFSTEP]
norm_num
[GOAL]
x : ℕ
b : Bool
⊢ decide (addLsb x b % 2 = 1) = b
[PROOFSTEP]
cases b
[GOAL]
case false
x : ℕ
⊢ decide (addLsb x false % 2 = 1) = false
[PROOFSTEP]
simp only [Bool.decide_iff, Nat.add_mul_mod_self_left, addLsb, ← two_mul, add_comm, Bool.decide_False,
  Nat.mul_mod_right, zero_add, cond, zero_ne_one]
[GOAL]
case true
x : ℕ
⊢ decide (addLsb x true % 2 = 1) = true
[PROOFSTEP]
simp only [Bool.decide_iff, Nat.add_mul_mod_self_left, addLsb, ← two_mul, add_comm, Bool.decide_False,
  Nat.mul_mod_right, zero_add, cond, zero_ne_one]
[GOAL]
n : ℕ
v : Bitvec n
⊢ Bitvec.ofNat n (Bitvec.toNat v) = v
[PROOFSTEP]
cases' v with xs h
[GOAL]
case mk
n : ℕ
xs : List Bool
h : List.length xs = n
⊢ Bitvec.ofNat n (Bitvec.toNat { val := xs, property := h }) = { val := xs, property := h }
[PROOFSTEP]
apply Subtype.ext
[GOAL]
case mk.a
n : ℕ
xs : List Bool
h : List.length xs = n
⊢ ↑(Bitvec.ofNat n (Bitvec.toNat { val := xs, property := h })) = ↑{ val := xs, property := h }
[PROOFSTEP]
change Vector.toList _ = xs
[GOAL]
case mk.a
n : ℕ
xs : List Bool
h : List.length xs = n
⊢ Vector.toList (Bitvec.ofNat n (Bitvec.toNat { val := xs, property := h })) = xs
[PROOFSTEP]
dsimp [Bitvec.toNat, bitsToNat]
[GOAL]
case mk.a
n : ℕ
xs : List Bool
h : List.length xs = n
⊢ Vector.toList (Bitvec.ofNat n (List.foldl addLsb 0 xs)) = xs
[PROOFSTEP]
rw [← List.length_reverse] at h 
[GOAL]
case mk.a
n : ℕ
xs : List Bool
h : List.length (List.reverse xs) = n
⊢ Vector.toList (Bitvec.ofNat n (List.foldl addLsb 0 xs)) = xs
[PROOFSTEP]
rw [← List.reverse_reverse xs, List.foldl_reverse]
[GOAL]
case mk.a
n : ℕ
xs : List Bool
h : List.length (List.reverse xs) = n
⊢ Vector.toList (Bitvec.ofNat n (List.foldr (fun x y => addLsb y x) 0 (List.reverse xs))) =
    List.reverse (List.reverse xs)
[PROOFSTEP]
generalize xs.reverse = ys at h ⊢
[GOAL]
case mk.a
n : ℕ
xs ys : List Bool
h : List.length ys = n
⊢ Vector.toList (Bitvec.ofNat n (List.foldr (fun x y => addLsb y x) 0 ys)) = List.reverse ys
[PROOFSTEP]
clear xs
[GOAL]
case mk.a
n : ℕ
ys : List Bool
h : List.length ys = n
⊢ Vector.toList (Bitvec.ofNat n (List.foldr (fun x y => addLsb y x) 0 ys)) = List.reverse ys
[PROOFSTEP]
induction' ys with ys_head ys_tail ys_ih generalizing n
[GOAL]
case mk.a.nil
n✝ : ℕ
ys : List Bool
h✝ : List.length ys = n✝
n : ℕ
h : List.length [] = n
⊢ Vector.toList (Bitvec.ofNat n (List.foldr (fun x y => addLsb y x) 0 [])) = List.reverse []
[PROOFSTEP]
cases h
[GOAL]
case mk.a.nil.refl
n : ℕ
ys : List Bool
h : List.length ys = n
⊢ Vector.toList (Bitvec.ofNat (List.length []) (List.foldr (fun x y => addLsb y x) 0 [])) = List.reverse []
[PROOFSTEP]
simp [Bitvec.ofNat]
[GOAL]
case mk.a.cons
n✝ : ℕ
ys : List Bool
h✝ : List.length ys = n✝
ys_head : Bool
ys_tail : List Bool
ys_ih :
  ∀ {n : ℕ},
    List.length ys_tail = n →
      Vector.toList (Bitvec.ofNat n (List.foldr (fun x y => addLsb y x) 0 ys_tail)) = List.reverse ys_tail
n : ℕ
h : List.length (ys_head :: ys_tail) = n
⊢ Vector.toList (Bitvec.ofNat n (List.foldr (fun x y => addLsb y x) 0 (ys_head :: ys_tail))) =
    List.reverse (ys_head :: ys_tail)
[PROOFSTEP]
simp only [← Nat.succ_eq_add_one, List.length] at h 
[GOAL]
case mk.a.cons
n✝ : ℕ
ys : List Bool
h✝ : List.length ys = n✝
ys_head : Bool
ys_tail : List Bool
ys_ih :
  ∀ {n : ℕ},
    List.length ys_tail = n →
      Vector.toList (Bitvec.ofNat n (List.foldr (fun x y => addLsb y x) 0 ys_tail)) = List.reverse ys_tail
n : ℕ
h : succ (List.length ys_tail) = n
⊢ Vector.toList (Bitvec.ofNat n (List.foldr (fun x y => addLsb y x) 0 (ys_head :: ys_tail))) =
    List.reverse (ys_head :: ys_tail)
[PROOFSTEP]
subst n
[GOAL]
case mk.a.cons
n : ℕ
ys : List Bool
h : List.length ys = n
ys_head : Bool
ys_tail : List Bool
ys_ih :
  ∀ {n : ℕ},
    List.length ys_tail = n →
      Vector.toList (Bitvec.ofNat n (List.foldr (fun x y => addLsb y x) 0 ys_tail)) = List.reverse ys_tail
⊢ Vector.toList
      (Bitvec.ofNat (succ (List.length ys_tail)) (List.foldr (fun x y => addLsb y x) 0 (ys_head :: ys_tail))) =
    List.reverse (ys_head :: ys_tail)
[PROOFSTEP]
simp only [Bitvec.ofNat, Vector.toList_cons, Vector.toList_nil, List.reverse_cons, Vector.toList_append, List.foldr]
[GOAL]
case mk.a.cons
n : ℕ
ys : List Bool
h : List.length ys = n
ys_head : Bool
ys_tail : List Bool
ys_ih :
  ∀ {n : ℕ},
    List.length ys_tail = n →
      Vector.toList (Bitvec.ofNat n (List.foldr (fun x y => addLsb y x) 0 ys_tail)) = List.reverse ys_tail
⊢ Vector.toList
        (Bitvec.ofNat (List.length ys_tail) (addLsb (List.foldr (fun x y => addLsb y x) 0 ys_tail) ys_head / 2)) ++
      [decide (addLsb (List.foldr (fun x y => addLsb y x) 0 ys_tail) ys_head % 2 = 1)] =
    List.reverse ys_tail ++ [ys_head]
[PROOFSTEP]
erw [addLsb_div_two, decide_addLsb_mod_two]
[GOAL]
case mk.a.cons
n : ℕ
ys : List Bool
h : List.length ys = n
ys_head : Bool
ys_tail : List Bool
ys_ih :
  ∀ {n : ℕ},
    List.length ys_tail = n →
      Vector.toList (Bitvec.ofNat n (List.foldr (fun x y => addLsb y x) 0 ys_tail)) = List.reverse ys_tail
⊢ Vector.toList (Bitvec.ofNat (List.length ys_tail) (List.foldr (fun x y => addLsb y x) 0 ys_tail)) ++ [ys_head] =
    List.reverse ys_tail ++ [ys_head]
[PROOFSTEP]
congr
[GOAL]
case mk.a.cons.e_a
n : ℕ
ys : List Bool
h : List.length ys = n
ys_head : Bool
ys_tail : List Bool
ys_ih :
  ∀ {n : ℕ},
    List.length ys_tail = n →
      Vector.toList (Bitvec.ofNat n (List.foldr (fun x y => addLsb y x) 0 ys_tail)) = List.reverse ys_tail
⊢ Vector.toList (Bitvec.ofNat (List.length ys_tail) (List.foldr (fun x y => addLsb y x) 0 ys_tail)) =
    List.reverse ys_tail
[PROOFSTEP]
apply ys_ih
[GOAL]
case mk.a.cons.e_a.h
n : ℕ
ys : List Bool
h : List.length ys = n
ys_head : Bool
ys_tail : List Bool
ys_ih :
  ∀ {n : ℕ},
    List.length ys_tail = n →
      Vector.toList (Bitvec.ofNat n (List.foldr (fun x y => addLsb y x) 0 ys_tail)) = List.reverse ys_tail
⊢ List.length ys_tail = List.length ys_tail
[PROOFSTEP]
rfl
[GOAL]
n : ℕ
v : Bitvec n
⊢ ↑(toFin v) = Bitvec.toNat v
[PROOFSTEP]
rw [toFin, Fin.coe_ofNat_eq_mod, Nat.mod_eq_of_lt]
[GOAL]
n : ℕ
v : Bitvec n
⊢ Bitvec.toNat v < 2 ^ n
[PROOFSTEP]
apply toNat_lt
[GOAL]
n : ℕ
v₀ v₁ : Bitvec n
h : v₀ ≤ v₁
⊢ ↑(toFin v₀) ≤ ↑(toFin v₁)
[PROOFSTEP]
rw [toFin_val, toFin_val]
[GOAL]
n : ℕ
v₀ v₁ : Bitvec n
h : v₀ ≤ v₁
⊢ Bitvec.toNat v₀ ≤ Bitvec.toNat v₁
[PROOFSTEP]
exact h
[GOAL]
n : ℕ
i j : Fin (2 ^ n)
h : i ≤ j
⊢ Bitvec.toNat (Bitvec.ofNat n ↑i) ≤ Bitvec.toNat (Bitvec.ofNat n ↑j)
[PROOFSTEP]
simp only [toNat_ofNat, Nat.mod_eq_of_lt, Fin.is_lt]
[GOAL]
n : ℕ
i j : Fin (2 ^ n)
h : i ≤ j
⊢ ↑i ≤ ↑j
[PROOFSTEP]
exact h
[GOAL]
n : ℕ
i : Fin (2 ^ n)
⊢ ↑(toFin (ofFin i)) = ↑i
[PROOFSTEP]
simp [toFin_val, ofFin, toNat_ofNat, Nat.mod_eq_of_lt, i.is_lt]
[GOAL]
n : ℕ
v : Bitvec n
⊢ ofFin (toFin v) = v
[PROOFSTEP]
dsimp [ofFin]
[GOAL]
n : ℕ
v : Bitvec n
⊢ Bitvec.ofNat n ↑(toFin v) = v
[PROOFSTEP]
rw [toFin_val, ofNat_toNat]
