File: Mathlib/Data/Nat/Bitwise.lean

full_name: Nat.bitwise_zero_left
code: @[simp]
lemma bitwise_zero_left (m : Nat) : bitwise f 0 m = if f false true then m else 0 
goal: Nat.bitwise f 0 m = if f false true = true then m else 0

full_name: Nat.bitwise_zero_right
code: @[simp]
lemma bitwise_zero_right (n : Nat) : bitwise f n 0 = if f true false then n else 0 
goal: Nat.bitwise f n 0 = if f true false = true then n else 0

full_name: Nat.bitwise_zero
code: lemma bitwise_zero : bitwise f 0 0 = 0 
goal: Nat.bitwise f 0 0 = 0

full_name: Nat.bitwise_of_ne_zero
code: lemma bitwise_of_ne_zero {n m : Nat} (hn : n ≠ 0) (hm : m ≠ 0) :
    bitwise f n m = bit (f (bodd n) (bodd m)) (bitwise f (n / 2) (m / 2)) 
goal: Nat.bitwise f n m = Nat.bit (f n.bodd m.bodd) (Nat.bitwise f (n / 2) (m / 2))

full_name: Nat.binaryRec_of_ne_zero
code: theorem binaryRec_of_ne_zero {C : Nat → Sort*} (z : C 0) (f : ∀ b n, C n → C (bit b n)) {n}
    (h : n ≠ 0) :
    binaryRec z f n = bit_decomp n ▸ f (bodd n) (div2 n) (binaryRec z f (div2 n)) 
goal: Nat.binaryRec z f n = ⋯ ▸ f n.bodd n.div2 (Nat.binaryRec z f n.div2)

full_name: Nat.bitwise_bit
code: @[simp]
lemma bitwise_bit {f : Bool → Bool → Bool} (h : f false false = false := by rfl) (a m b n) :
    bitwise f (bit a m) (bit b n) = bit (f a b) (bitwise f m n) 
goal: Nat.bitwise f (Nat.bit a m) (Nat.bit b n) = Nat.bit (f a b) (Nat.bitwise f m n)

full_name: Nat.bit_mod_two
code: lemma bit_mod_two (a : Bool) (x : ℕ) :
    bit a x % 2 = if a then 1 else 0 
goal: Nat.bit a x % 2 = if a = true then 1 else 0

full_name: Nat.bit_mod_two_eq_zero_iff
code: @[simp]
lemma bit_mod_two_eq_zero_iff (a x) :
    bit a x % 2 = 0 ↔ !a 
goal: Nat.bit a x % 2 = 0 ↔ (!a) = true

full_name: Nat.bit_mod_two_eq_one_iff
code: @[simp]
lemma bit_mod_two_eq_one_iff (a x) :
    bit a x % 2 = 1 ↔ a 
goal: Nat.bit a x % 2 = 1 ↔ a = true

full_name: Nat.lor_bit
code: @[simp]
theorem lor_bit : ∀ a m b n, bit a m ||| bit b n = bit (a || b) (m ||| n) 
goal: Nat.bit a m ||| Nat.bit b n = Nat.bit (a || b) (m ||| n)

full_name: Nat.land_bit
code: @[simp]
theorem land_bit : ∀ a m b n, bit a m &&& bit b n = bit (a && b) (m &&& n) 
goal: Nat.bit a m &&& Nat.bit b n = Nat.bit (a && b) (m &&& n)

full_name: Nat.ldiff_bit
code: @[simp]
theorem ldiff_bit : ∀ a m b n, ldiff (bit a m) (bit b n) = bit (a && not b) (ldiff m n) 
goal: (Nat.bit a m).ldiff (Nat.bit b n) = Nat.bit (a && !b) (m.ldiff n)

full_name: Nat.xor_bit
code: @[simp]
theorem xor_bit : ∀ a m b n, bit a m ^^^ bit b n = bit (bne a b) (m ^^^ n) 
goal: Nat.bit a m ^^^ Nat.bit b n = Nat.bit (a != b) (m ^^^ n)

full_name: Nat.testBit_lor
code: theorem testBit_lor : ∀ m n k, testBit (m ||| n) k = (testBit m k || testBit n k) 
goal: (m ||| n).testBit k = (m.testBit k || n.testBit k)

full_name: Nat.testBit_land
code: theorem testBit_land : ∀ m n k, testBit (m &&& n) k = (testBit m k && testBit n k) 
goal: (m &&& n).testBit k = (m.testBit k && n.testBit k)

full_name: Nat.testBit_ldiff
code: @[simp]
theorem testBit_ldiff : ∀ m n k, testBit (ldiff m n) k = (testBit m k && not (testBit n k)) 
goal: (m.ldiff n).testBit k = (m.testBit k && !n.testBit k)

full_name: Nat.bit_false
code: @[simp]
theorem bit_false : bit false = (2 * ·) 
goal: Nat.bit false = fun x => 2 * x

full_name: Nat.bit_true
code: @[simp]
theorem bit_true : bit true = (2 * · + 1) 
goal: Nat.bit true = fun x => 2 * x + 1

full_name: Nat.bit_eq_zero
code: @[simp]
theorem bit_eq_zero {n : ℕ} {b : Bool} : n.bit b = 0 ↔ n = 0 ∧ b = false 
goal: Nat.bit b n = 0 ↔ n = 0 ∧ b = false

full_name: Nat.bit_ne_zero_iff
code: theorem bit_ne_zero_iff {n : ℕ} {b : Bool} : n.bit b ≠ 0 ↔ n = 0 → b = true 
goal: Nat.bit b n ≠ 0 ↔ n = 0 → b = true

full_name: Nat.bitwise_bit'
code: /-- An alternative for `bitwise_bit` which replaces the `f false false = false` assumption
with assumptions that neither `bit a m` nor `bit b n` are `0`
(albeit, phrased as the implications `m = 0 → a = true` and `n = 0 → b = true`) -/
lemma bitwise_bit' {f : Bool → Bool → Bool} (a : Bool) (m : Nat) (b : Bool) (n : Nat)
    (ham : m = 0 → a = true) (hbn : n = 0 → b = true) :
    bitwise f (bit a m) (bit b n) = bit (f a b) (bitwise f m n) 
goal: Nat.bitwise f (Nat.bit a m) (Nat.bit b n) = Nat.bit (f a b) (Nat.bitwise f m n)

full_name: Nat.bitwise_eq_binaryRec
code: lemma bitwise_eq_binaryRec (f : Bool → Bool → Bool) :
    bitwise f =
    binaryRec (fun n => cond (f false true) n 0) fun a m Ia =>
      binaryRec (cond (f true false) (bit a m) 0) fun b n _ => bit (f a b) (Ia n) 
goal: Nat.bitwise f =
  Nat.binaryRec (fun n => bif f false true then n else 0) fun a m Ia =>
    Nat.binaryRec (bif f true false then Nat.bit a m else 0) fun b n x => Nat.bit (f a b) (Ia n)

full_name: Nat.zero_of_testBit_eq_false
code: theorem zero_of_testBit_eq_false {n : ℕ} (h : ∀ i, testBit n i = false) : n = 0 
goal: n = 0

full_name: Nat.testBit_eq_false_of_lt
code: theorem testBit_eq_false_of_lt {n i} (h : n < 2 ^ i) : n.testBit i = false 
goal: n.testBit i = false

full_name: Nat.testBit_eq_inth
code: /-- The ith bit is the ith element of `n.bits`. -/
theorem testBit_eq_inth (n i : ℕ) : n.testBit i = n.bits.getI i 
goal: n.testBit i = n.bits.getI i

full_name: Nat.exists_most_significant_bit
code: theorem exists_most_significant_bit {n : ℕ} (h : n ≠ 0) :
    ∃ i, testBit n i = true ∧ ∀ j, i < j → testBit n j = false 
goal: ∃ i, n.testBit i = true ∧ ∀ (j : ℕ), i < j → n.testBit j = false

full_name: Nat.lt_of_testBit
code: theorem lt_of_testBit {n m : ℕ} (i : ℕ) (hn : testBit n i = false) (hm : testBit m i = true)
    (hnm : ∀ j, i < j → testBit n j = testBit m j) : n < m 
goal: n < m

full_name: Nat.testBit_two_pow_self
code: @[simp]
theorem testBit_two_pow_self (n : ℕ) : testBit (2 ^ n) n = true 
goal: (2 ^ n).testBit n = true

full_name: Nat.testBit_two_pow_of_ne
code: theorem testBit_two_pow_of_ne {n m : ℕ} (hm : n ≠ m) : testBit (2 ^ n) m = false 
goal: (2 ^ n).testBit m = false

full_name: Nat.testBit_two_pow
code: theorem testBit_two_pow (n m : ℕ) : testBit (2 ^ n) m = (n = m) 
goal: ((2 ^ n).testBit m = true) = (n = m)

full_name: Nat.bitwise_swap
code: theorem bitwise_swap {f : Bool → Bool → Bool} :
    bitwise (Function.swap f) = Function.swap (bitwise f) 
goal: Nat.bitwise (Function.swap f) = Function.swap (Nat.bitwise f)

full_name: Nat.bitwise_comm
code: /-- If `f` is a commutative operation on bools such that `f false false = false`, then `bitwise f`
    is also commutative. -/
theorem bitwise_comm {f : Bool → Bool → Bool} (hf : ∀ b b', f b b' = f b' b) (n m : ℕ) :
    bitwise f n m = bitwise f m n 
goal: Nat.bitwise f n m = Nat.bitwise f m n

full_name: Nat.lor_comm
code: theorem lor_comm (n m : ℕ) : n ||| m = m ||| n 
goal: n ||| m = m ||| n

full_name: Nat.land_comm
code: theorem land_comm (n m : ℕ) : n &&& m = m &&& n 
goal: n &&& m = m &&& n

full_name: Nat.xor_comm
code: protected lemma xor_comm (n m : ℕ) : n ^^^ m = m ^^^ n 
goal: n ^^^ m = m ^^^ n

full_name: Nat.and_two_pow
code: lemma and_two_pow (n i : ℕ) : n &&& 2 ^ i = (n.testBit i).toNat * 2 ^ i 
goal: n &&& 2 ^ i = (n.testBit i).toNat * 2 ^ i

full_name: Nat.two_pow_and
code: lemma two_pow_and (n i : ℕ) : 2 ^ i &&& n = 2 ^ i * (n.testBit i).toNat 
goal: 2 ^ i &&& n = 2 ^ i * (n.testBit i).toNat

full_name: Nat.zero_xor
code: @[simp]
theorem zero_xor (n : ℕ) : 0 ^^^ n = n 
goal: 0 ^^^ n = n

full_name: Nat.xor_zero
code: @[simp]
theorem xor_zero (n : ℕ) : n ^^^ 0 = n 
goal: n ^^^ 0 = n

full_name: Nat._aux_Mathlib_Data_Nat_Bitwise___macroRules_Nat_tacticBitwise_assoc_tac_1
code: macro "bitwise_assoc_tac" : tactic => set_option hygiene false in `(tactic| (
  induction' n using Nat.binaryRec with b n hn generalizing m k
  · simp
  induction' m using Nat.binaryRec with b' m hm
  · simp
  induction' k using Nat.binaryRec with b'' k hk
  -- porting note (#10745): was `simp [hn]`
  -- This is necessary because these are simp lemmas in mathlib
  <;> simp [hn, Bool.or_assoc, Bool.and_assoc, Bool.bne_eq_xor]))
goal: Lean.Macro

full_name: Nat.tacticBitwise_assoc_tac
code: macro "bitwise_assoc_tac" : tactic => set_option hygiene false in `(tactic| (
  induction' n using Nat.binaryRec with b n hn generalizing m k
  · simp
  induction' m using Nat.binaryRec with b' m hm
  · simp
  induction' k using Nat.binaryRec with b'' k hk
  -- porting note (#10745): was `simp [hn]`
  -- This is necessary because these are simp lemmas in mathlib
  <;> simp [hn, Bool.or_assoc, Bool.and_assoc, Bool.bne_eq_xor]))
goal: Lean.ParserDescr

full_name: Nat.xor_assoc
code: protected lemma xor_assoc (n m k : ℕ) : (n ^^^ m) ^^^ k = n ^^^ (m ^^^ k) 
goal: n ^^^ m ^^^ k = n ^^^ (m ^^^ k)

full_name: Nat.land_assoc
code: theorem land_assoc (n m k : ℕ) : (n &&& m) &&& k = n &&& (m &&& k) 
goal: n &&& m &&& k = n &&& (m &&& k)

full_name: Nat.lor_assoc
code: theorem lor_assoc (n m k : ℕ) : (n ||| m) ||| k = n ||| (m ||| k) 
goal: n ||| m ||| k = n ||| (m ||| k)

full_name: Nat.xor_self
code: @[simp]
theorem xor_self (n : ℕ) : n ^^^ n = 0 
goal: n ^^^ n = 0

full_name: Nat.xor_cancel_right
code: theorem xor_cancel_right (n m : ℕ) : (m ^^^ n) ^^^ n = m 
goal: m ^^^ n ^^^ n = m

full_name: Nat.xor_cancel_left
code: theorem xor_cancel_left (n m : ℕ) : n ^^^ (n ^^^ m) = m 
goal: n ^^^ (n ^^^ m) = m

full_name: Nat.xor_right_injective
code: theorem xor_right_injective {n : ℕ} : Function.Injective (HXor.hXor n : ℕ → ℕ) 
goal: Function.Injective (HXor.hXor n)

full_name: Nat.xor_left_injective
code: theorem xor_left_injective {n : ℕ} : Function.Injective fun m => m ^^^ n 
goal: Function.Injective fun m => m ^^^ n

full_name: Nat.xor_right_inj
code: @[simp]
theorem xor_right_inj {n m m' : ℕ} : n ^^^ m = n ^^^ m' ↔ m = m' 
goal: n ^^^ m = n ^^^ m' ↔ m = m'

full_name: Nat.xor_left_inj
code: @[simp]
theorem xor_left_inj {n m m' : ℕ} : m ^^^ n = m' ^^^ n ↔ m = m' 
goal: m ^^^ n = m' ^^^ n ↔ m = m'

full_name: Nat.xor_eq_zero
code: @[simp]
theorem xor_eq_zero {n m : ℕ} : n ^^^ m = 0 ↔ n = m 
goal: n ^^^ m = 0 ↔ n = m

full_name: Nat.xor_ne_zero
code: theorem xor_ne_zero {n m : ℕ} : n ^^^ m ≠ 0 ↔ n ≠ m 
goal: n ^^^ m ≠ 0 ↔ n ≠ m

full_name: Nat.xor_trichotomy
code: theorem xor_trichotomy {a b c : ℕ} (h : a ≠ b ^^^ c) :
    b ^^^ c < a ∨ a ^^^ c < b ∨ a ^^^ b < c 
goal: b ^^^ c < a ∨ a ^^^ c < b ∨ a ^^^ b < c

full_name: Nat.lt_xor_cases
code: theorem lt_xor_cases {a b c : ℕ} (h : a < b ^^^ c) : a ^^^ c < b ∨ a ^^^ b < c 
goal: a ^^^ c < b ∨ a ^^^ b < c

full_name: Nat.bit_lt_two_pow_succ_iff
code: @[simp] theorem bit_lt_two_pow_succ_iff {b x n} : bit b x < 2 ^ (n + 1) ↔ x < 2 ^ n 
goal: Nat.bit b x < 2 ^ (n + 1) ↔ x < 2 ^ n

full_name: Nat.bitwise_lt
code: /-- If `x` and `y` fit within `n` bits, then the result of any bitwise operation on `x` and `y` also
fits within `n` bits -/
theorem bitwise_lt {f x y n} (hx : x < 2 ^ n) (hy : y < 2 ^ n) :
    bitwise f x y < 2 ^ n 
goal: Nat.bitwise f x y < 2 ^ n

full_name: Nat.shiftLeft_lt
code: lemma shiftLeft_lt {x n m : ℕ} (h : x < 2 ^ n) : x <<< m < 2 ^ (n + m) 
goal: x <<< m < 2 ^ (n + m)

full_name: Nat.append_lt
code: /-- Note that the LHS is the expression used within `Std.BitVec.append`, hence the name. -/
lemma append_lt {x y n m} (hx : x < 2 ^ n) (hy : y < 2 ^ m) : y <<< n ||| x < 2 ^ (n + m) 
goal: y <<< n ||| x < 2 ^ (n + m)