File: .lake/packages/lean4/src/lean/Init/Data/BitVec/Bitblast.lean

full_name: Bool.atLeastTwo
code: /-- At least two out of three booleans are true. -/
abbrev atLeastTwo (a b c : Bool) : Bool 
goal: Bool

full_name: Bool.atLeastTwo_false_left
code: @[simp] theorem atLeastTwo_false_left  : atLeastTwo false b c = (b && c) 
goal: false.atLeastTwo b c = (b && c)

full_name: Bool.atLeastTwo_false_mid
code: @[simp] theorem atLeastTwo_false_mid   : atLeastTwo a false c = (a && c) 
goal: a.atLeastTwo false c = (a && c)

full_name: Bool.atLeastTwo_false_right
code: @[simp] theorem atLeastTwo_false_right : atLeastTwo a b false = (a && b) 
goal: a.atLeastTwo b false = (a && b)

full_name: Bool.atLeastTwo_true_left
code: @[simp] theorem atLeastTwo_true_left   : atLeastTwo true b c  = (b || c) 
goal: true.atLeastTwo b c = (b || c)

full_name: Bool.atLeastTwo_true_mid
code: @[simp] theorem atLeastTwo_true_mid    : atLeastTwo a true c  = (a || c) 
goal: a.atLeastTwo true c = (a || c)

full_name: Bool.atLeastTwo_true_right
code: @[simp] theorem atLeastTwo_true_right  : atLeastTwo a b true  = (a || b) 
goal: a.atLeastTwo b true = (a || b)

full_name: _private.«.lake».packages.lean4.src.lean.Init.Data.BitVec.Bitblast.0.BitVec.testBit_limit
code: private theorem testBit_limit {x i : Nat} (x_lt_succ : x < 2^(i+1)) :
    testBit x i = decide (x ≥ 2^i) 
goal: x.testBit i = decide (x ≥ 2 ^ i)

full_name: _private.«.lake».packages.lean4.src.lean.Init.Data.BitVec.Bitblast.0.BitVec.mod_two_pow_succ
code: private theorem mod_two_pow_succ (x i : Nat) :
    x % 2^(i+1) = 2^i*(x.testBit i).toNat + x % (2 ^ i)
goal: x % 2 ^ (i + 1) = 2 ^ i * (x.testBit i).toNat + x % 2 ^ i

full_name: _private.«.lake».packages.lean4.src.lean.Init.Data.BitVec.Bitblast.0.BitVec.mod_two_pow_add_mod_two_pow_add_bool_lt_two_pow_succ
code: private theorem mod_two_pow_add_mod_two_pow_add_bool_lt_two_pow_succ
     (x y i : Nat) (c : Bool) : x % 2^i + (y % 2^i + c.toNat) < 2^(i+1) 
goal: x % 2 ^ i + (y % 2 ^ i + c.toNat) < 2 ^ (i + 1)

full_name: BitVec.carry
code: /-- carry i x y c returns true if the `i` carry bit is true when computing `x + y + c`. -/
def carry (i : Nat) (x y : BitVec w) (c : Bool) : Bool 
goal: Bool

full_name: BitVec.carry_zero
code: @[simp] theorem carry_zero : carry 0 x y c = c 
goal: ∀ {w : Nat} {x y : BitVec w} {c : Bool}, BitVec.carry 0 x y c = c

full_name: BitVec.carry_succ
code: theorem carry_succ (i : Nat) (x y : BitVec w) (c : Bool) :
    carry (i+1) x y c = atLeastTwo (x.getLsb i) (y.getLsb i) (carry i x y c) 
goal: BitVec.carry (i + 1) x y c = (x.getLsb i).atLeastTwo (y.getLsb i) (BitVec.carry i x y c)

full_name: BitVec.adcb
code: /-- Carry function for bitwise addition. -/
def adcb (x y c : Bool) : Bool × Bool 
goal: Bool × Bool

full_name: BitVec.adc
code: /-- Bitwise addition implemented via a ripple carry adder. -/
def adc (x y : BitVec w) : Bool → Bool × BitVec w 
goal: Bool → Bool × BitVec w

full_name: BitVec.getLsb_add_add_bool
code: theorem getLsb_add_add_bool {i : Nat} (i_lt : i < w) (x y : BitVec w) (c : Bool) :
    getLsb (x + y + zeroExtend w (ofBool c)) i =
      Bool.xor (getLsb x i) (Bool.xor (getLsb y i) (carry i x y c)) 
goal: (x + y + BitVec.zeroExtend w (BitVec.ofBool c)).getLsb i = (x.getLsb i).xor ((y.getLsb i).xor (BitVec.carry i x y c))

full_name: BitVec.getLsb_add
code: theorem getLsb_add {i : Nat} (i_lt : i < w) (x y : BitVec w) :
    getLsb (x + y) i =
      Bool.xor (getLsb x i) (Bool.xor (getLsb y i) (carry i x y false)) 
goal: (x + y).getLsb i = (x.getLsb i).xor ((y.getLsb i).xor (BitVec.carry i x y false))

full_name: BitVec.adc_spec
code: theorem adc_spec (x y : BitVec w) (c : Bool) :
    adc x y c = (carry w x y c, x + y + zeroExtend w (ofBool c)) 
goal: x.adc y c = (BitVec.carry w x y c, x + y + BitVec.zeroExtend w (BitVec.ofBool c))

full_name: BitVec.add_eq_adc
code: theorem add_eq_adc (w : Nat) (x y : BitVec w) : x + y = (adc x y false).snd 
goal: x + y = (x.adc y false).snd

full_name: BitVec.add_not_self
code: /-- Adding a bitvector to its own complement yields the all ones bitpattern -/
@[simp] theorem add_not_self (x : BitVec w) : x + ~~~x = allOnes w 
goal: x + ~~~x = BitVec.allOnes w

full_name: BitVec.allOnes_sub_eq_not
code: /-- Subtracting `x` from the all ones bitvector is equivalent to taking its complement -/
theorem allOnes_sub_eq_not (x : BitVec w) : allOnes w - x = ~~~x 
goal: BitVec.allOnes w - x = ~~~x

full_name: BitVec.bit_not_testBit
code: theorem bit_not_testBit (x : BitVec w) (i : Fin w) :
  getLsb (((iunfoldr (fun (i : Fin w) c => (c, !(x.getLsb i)))) ()).snd) i.val = !(getLsb x i.val) 
goal: (BitVec.iunfoldr (fun i c => (c, !x.getLsb ↑i)) ()).snd.getLsb ↑i = !x.getLsb ↑i

full_name: BitVec.bit_not_add_self
code: theorem bit_not_add_self (x : BitVec w) :
  ((iunfoldr (fun (i : Fin w) c => (c, !(x.getLsb i)))) ()).snd + x  = -1 
goal: (BitVec.iunfoldr (fun i c => (c, !x.getLsb ↑i)) ()).snd + x = -1

full_name: BitVec.bit_not_eq_not
code: theorem bit_not_eq_not (x : BitVec w) :
  ((iunfoldr (fun i c => (c, !(x.getLsb i)))) ()).snd = ~~~ x 
goal: (BitVec.iunfoldr (fun i c => (c, !x.getLsb ↑i)) ()).snd = ~~~x

full_name: BitVec.bit_neg_eq_neg
code: theorem bit_neg_eq_neg (x : BitVec w) : -x = (adc (((iunfoldr (fun (i : Fin w) c => (c, !(x.getLsb i)))) ()).snd) (BitVec.ofNat w 1) false).snd
goal: -x = ((BitVec.iunfoldr (fun i c => (c, !x.getLsb ↑i)) ()).snd.adc (1#w) false).snd

full_name: BitVec.ult_eq_not_carry
code: theorem ult_eq_not_carry (x y : BitVec w) : x.ult y = !carry w x (~~~y) true 
goal: x.ult y = !BitVec.carry w x (~~~y) true

full_name: BitVec.ule_eq_not_ult
code: theorem ule_eq_not_ult (x y : BitVec w) : x.ule y = !y.ult x 
goal: x.ule y = !y.ult x

full_name: BitVec.ule_eq_carry
code: theorem ule_eq_carry (x y : BitVec w) : x.ule y = carry w y (~~~x) true 
goal: x.ule y = BitVec.carry w y (~~~x) true

full_name: BitVec.slt_eq_ult_of_msb_eq
code: /-- If two bitvectors have the same `msb`, then signed and unsigned comparisons coincide -/
theorem slt_eq_ult_of_msb_eq {x y : BitVec w} (h : x.msb = y.msb) :
    x.slt y = x.ult y 
goal: x.slt y = x.ult y

full_name: BitVec.ult_eq_msb_of_msb_neq
code: /-- If two bitvectors have different `msb`s, then unsigned comparison is determined by this bit -/
theorem ult_eq_msb_of_msb_neq {x y : BitVec w} (h : x.msb ≠ y.msb) :
    x.ult y = y.msb 
goal: x.ult y = y.msb

full_name: BitVec.slt_eq_not_ult_of_msb_neq
code: /-- If two bitvectors have different `msb`s, then signed and unsigned comparisons are opposites -/
theorem slt_eq_not_ult_of_msb_neq {x y : BitVec w} (h : x.msb ≠ y.msb) :
    x.slt y = !x.ult y 
goal: x.slt y = !x.ult y

full_name: BitVec.slt_eq_ult
code: theorem slt_eq_ult (x y : BitVec w) :
    x.slt y = (x.msb != y.msb).xor (x.ult y) 
goal: x.slt y = (x.msb != y.msb).xor (x.ult y)

full_name: BitVec.slt_eq_not_carry
code: theorem slt_eq_not_carry (x y : BitVec w) :
    x.slt y = (x.msb == y.msb).xor (carry w x (~~~y) true) 
goal: x.slt y = (x.msb == y.msb).xor (BitVec.carry w x (~~~y) true)

full_name: BitVec.sle_eq_not_slt
code: theorem sle_eq_not_slt (x y : BitVec w) : x.sle y = !y.slt x 
goal: x.sle y = !y.slt x

full_name: BitVec.sle_eq_carry
code: theorem sle_eq_carry (x y : BitVec w) :
    x.sle y = !((x.msb == y.msb).xor (carry w y (~~~x) true)) 
goal: x.sle y = !(x.msb == y.msb).xor (BitVec.carry w y (~~~x) true)