File: Mathlib/Tactic/NormNum/Pow.lean

full_name: Mathlib.Meta.NormNum.natPow_zero
code: theorem natPow_zero : Nat.pow a (nat_lit 0) = nat_lit 1 
goal: a.pow 0 = 1

full_name: Mathlib.Meta.NormNum.natPow_one
code: theorem natPow_one : Nat.pow a (nat_lit 1) = a 
goal: a.pow 1 = a

full_name: Mathlib.Meta.NormNum.zero_natPow
code: theorem zero_natPow : Nat.pow (nat_lit 0) (Nat.succ b) = nat_lit 0 
goal: Nat.pow 0 b.succ = 0

full_name: Mathlib.Meta.NormNum.one_natPow
code: theorem one_natPow : Nat.pow (nat_lit 1) b = nat_lit 1 
goal: Nat.pow 1 b = 1

full_name: Mathlib.Meta.NormNum.IsNatPowT
code: /-- This is an opaque wrapper around `Nat.pow` to prevent lean from unfolding the definition of
`Nat.pow` on numerals. The arbitrary precondition `p` is actually a formula of the form
`Nat.pow a' b' = c'` but we usually don't care to unfold this proposition so we just carry a
reference to it. -/
structure IsNatPowT (p : Prop) (a b c : Nat) : Prop where
  /-- Unfolds the assertion. -/
  run' : p → Nat.pow a b = c
goal: Prop

full_name: Mathlib.Meta.NormNum.IsNatPowT.run'
code: /-- This is an opaque wrapper around `Nat.pow` to prevent lean from unfolding the definition of
`Nat.pow` on numerals. The arbitrary precondition `p` is actually a formula of the form
`Nat.pow a' b' = c'` but we usually don't care to unfold this proposition so we just carry a
reference to it. -/
structure IsNatPowT (p : Prop) (a b c : Nat) : Prop where
  /-- Unfolds the assertion. -/
  run' : p → Nat.pow a b = c
goal: p → a.pow b = c

full_name: Mathlib.Meta.NormNum.IsNatPowT.run
code: theorem IsNatPowT.run
    (p : IsNatPowT (Nat.pow a (nat_lit 1) = a) a b c) : Nat.pow a b = c 
goal: a.pow b = c

full_name: Mathlib.Meta.NormNum.IsNatPowT.trans
code: /-- This is the key to making the proof proceed as a balanced tree of applications instead of
a linear sequence. It is just modus ponens after unwrapping the definitions. -/
theorem IsNatPowT.trans {p : Prop} {b' c' : ℕ} (h1 : IsNatPowT p a b c)
    (h2 : IsNatPowT (Nat.pow a b = c) a b' c') : IsNatPowT p a b' c' 
goal: Mathlib.Meta.NormNum.IsNatPowT p a b' c'

full_name: Mathlib.Meta.NormNum.IsNatPowT.bit0
code: theorem IsNatPowT.bit0 : IsNatPowT (Nat.pow a b = c) a (nat_lit 2 * b) (Nat.mul c c) 
goal: Mathlib.Meta.NormNum.IsNatPowT (a.pow b = c) a (2 * b) (c.mul c)

full_name: Mathlib.Meta.NormNum.IsNatPowT.bit1
code: theorem IsNatPowT.bit1 :
    IsNatPowT (Nat.pow a b = c) a (nat_lit 2 * b + nat_lit 1) (Nat.mul c (Nat.mul c a)) 
goal: Mathlib.Meta.NormNum.IsNatPowT (a.pow b = c) a (2 * b + 1) (c.mul (c.mul a))

full_name: Mathlib.Meta.NormNum.evalNatPow
code: /--
Proves `Nat.pow a b = c` where `a` and `b` are raw nat literals. This could be done by just
`rfl` but the kernel does not have a special case implementation for `Nat.pow` so this would
proceed by unary recursion on `b`, which is too slow and also leads to deep recursion.

We instead do the proof by binary recursion, but this can still lead to deep recursion,
so we use an additional trick to do binary subdivision on `log2 b`. As a result this produces
a proof of depth `log (log b)` which will essentially never overflow before the numbers involved
themselves exceed memory limits.
-/
partial def evalNatPow (a b : Q(ℕ)) : (c : Q(ℕ)) × Q(Nat.pow $a $b = $c) 
goal: (c : Q(ℕ)) × Q(«$a».pow «$b» = «$c»)

full_name: Mathlib.Meta.NormNum.evalNatPow.go
code: /--
Proves `Nat.pow a b = c` where `a` and `b` are raw nat literals. This could be done by just
`rfl` but the kernel does not have a special case implementation for `Nat.pow` so this would
proceed by unary recursion on `b`, which is too slow and also leads to deep recursion.

We instead do the proof by binary recursion, but this can still lead to deep recursion,
so we use an additional trick to do binary subdivision on `log2 b`. As a result this produces
a proof of depth `log (log b)` which will essentially never overflow before the numbers involved
themselves exceed memory limits.
-/
partial def evalNatPow (a b : Q(ℕ)) : (c : Q(ℕ)) × Q(Nat.pow $a $b = $c) 
goal: (c : Q(ℕ)) × Q(Mathlib.Meta.NormNum.IsNatPowT «$p» «$a» «$b» «$c»)

full_name: Mathlib.Meta.NormNum.intPow_ofNat
code: theorem intPow_ofNat (h1 : Nat.pow a b = c) :
    Int.pow (Int.ofNat a) b = Int.ofNat c 
goal: (Int.ofNat a).pow b = Int.ofNat c

full_name: Mathlib.Meta.NormNum.intPow_negOfNat_bit0
code: theorem intPow_negOfNat_bit0 {b' c' : ℕ} (h1 : Nat.pow a b' = c')
    (hb : nat_lit 2 * b' = b) (hc : c' * c' = c) :
    Int.pow (Int.negOfNat a) b = Int.ofNat c 
goal: (Int.negOfNat a).pow b = Int.ofNat c

full_name: Mathlib.Meta.NormNum.intPow_negOfNat_bit1
code: theorem intPow_negOfNat_bit1 {b' c' : ℕ} (h1 : Nat.pow a b' = c')
    (hb : nat_lit 2 * b' + nat_lit 1 = b) (hc : c' * (c' * a) = c) :
    Int.pow (Int.negOfNat a) b = Int.negOfNat c 
goal: (Int.negOfNat a).pow b = Int.negOfNat c

full_name: Mathlib.Meta.NormNum.evalIntPow
code: /-- Evaluates `Int.pow a b = c` where `a` and `b` are raw integer literals. -/
partial def evalIntPow (za : ℤ) (a : Q(ℤ)) (b : Q(ℕ)) : ℤ × (c : Q(ℤ)) × Q(Int.pow $a $b = $c) 
goal: ℤ × (c : Q(ℤ)) × Q(«$a».pow «$b» = «$c»)

full_name: Mathlib.Meta.NormNum.isNat_pow
code: theorem isNat_pow {α} [Semiring α] : ∀ {f : α → ℕ → α} {a : α} {b a' b' c : ℕ},
    f = HPow.hPow → IsNat a a' → IsNat b b' → Nat.pow a' b' = c → IsNat (f a b) c
  
goal: f = HPow.hPow →
  Mathlib.Meta.NormNum.IsNat a a' →
    Mathlib.Meta.NormNum.IsNat b b' → a'.pow b' = c → Mathlib.Meta.NormNum.IsNat (f a b) c

full_name: Mathlib.Meta.NormNum.isInt_pow
code: theorem isInt_pow {α} [Ring α] : ∀ {f : α → ℕ → α} {a : α} {b : ℕ} {a' : ℤ} {b' : ℕ} {c : ℤ},
    f = HPow.hPow → IsInt a a' → IsNat b b' → Int.pow a' b' = c → IsInt (f a b) c
  
goal: f = HPow.hPow →
  Mathlib.Meta.NormNum.IsInt a a' →
    Mathlib.Meta.NormNum.IsNat b b' → a'.pow b' = c → Mathlib.Meta.NormNum.IsInt (f a b) c

full_name: Mathlib.Meta.NormNum.isRat_pow
code: theorem isRat_pow {α} [Ring α] {f : α → ℕ → α} {a : α} {an cn : ℤ} {ad b b' cd : ℕ} :
    f = HPow.hPow → IsRat a an ad → IsNat b b' →
    Int.pow an b' = cn → Nat.pow ad b' = cd →
    IsRat (f a b) cn cd 
goal: f = HPow.hPow →
  Mathlib.Meta.NormNum.IsRat a an ad →
    Mathlib.Meta.NormNum.IsNat b b' → an.pow b' = cn → ad.pow b' = cd → Mathlib.Meta.NormNum.IsRat (f a b) cn cd

full_name: Mathlib.Meta.NormNum.evalPow
code: /-- The `norm_num` extension which identifies expressions of the form `a ^ b`,
such that `norm_num` successfully recognises both `a` and `b`, with `b : ℕ`. -/
@[norm_num _ ^ (_ : ℕ)]
def evalPow : NormNumExt 
goal: Mathlib.Meta.NormNum.NormNumExt

full_name: Mathlib.Meta.NormNum.evalPow.core
code: /-- The `norm_num` extension which identifies expressions of the form `a ^ b`,
such that `norm_num` successfully recognises both `a` and `b`, with `b : ℕ`. -/
@[norm_num _ ^ (_ : ℕ)]
def evalPow : NormNumExt 
goal: Option (Mathlib.Meta.NormNum.Result e)

full_name: Mathlib.Meta.NormNum.isNat_zpow_pos
code: theorem isNat_zpow_pos {α : Type*} [DivisionSemiring α] {a : α} {b : ℤ} {nb ne : ℕ}
    (pb : IsNat b nb) (pe' : IsNat (a ^ nb) ne) :
    IsNat (a ^ b) ne 
goal: Mathlib.Meta.NormNum.IsNat (a ^ b) ne

full_name: Mathlib.Meta.NormNum.isNat_zpow_neg
code: theorem isNat_zpow_neg {α : Type*} [DivisionSemiring α] {a : α} {b : ℤ} {nb ne : ℕ}
    (pb : IsInt b (Int.negOfNat nb)) (pe' : IsNat (a ^ nb)⁻¹ ne) :
    IsNat (a ^ b) ne 
goal: Mathlib.Meta.NormNum.IsNat (a ^ b) ne

full_name: Mathlib.Meta.NormNum.isInt_zpow_pos
code: theorem isInt_zpow_pos {α : Type*} [DivisionRing α] {a : α} {b : ℤ} {nb ne : ℕ}
    (pb : IsNat b nb) (pe' : IsInt (a ^ nb) (Int.negOfNat ne)) :
    IsInt (a ^ b) (Int.negOfNat ne) 
goal: Mathlib.Meta.NormNum.IsInt (a ^ b) (Int.negOfNat ne)

full_name: Mathlib.Meta.NormNum.isInt_zpow_neg
code: theorem isInt_zpow_neg {α : Type*} [DivisionRing α] {a : α} {b : ℤ} {nb ne : ℕ}
    (pb : IsInt b (Int.negOfNat nb)) (pe' : IsInt (a ^ nb)⁻¹ (Int.negOfNat ne)) :
    IsInt (a ^ b) (Int.negOfNat ne) 
goal: Mathlib.Meta.NormNum.IsInt (a ^ b) (Int.negOfNat ne)

full_name: Mathlib.Meta.NormNum.isRat_zpow_pos
code: theorem isRat_zpow_pos {α : Type*} [DivisionRing α] {a : α} {b : ℤ} {nb : ℕ}
    {num : ℤ} {den : ℕ}
    (pb : IsNat b nb) (pe' : IsRat (a^nb) num den) :
    IsRat (a^b) num den 
goal: Mathlib.Meta.NormNum.IsRat (a ^ b) num den

full_name: Mathlib.Meta.NormNum.isRat_zpow_neg
code: theorem isRat_zpow_neg {α : Type*} [DivisionRing α] {a : α} {b : ℤ} {nb : ℕ}
    {num : ℤ} {den : ℕ}
    (pb : IsInt b (Int.negOfNat nb)) (pe' : IsRat ((a^nb)⁻¹) num den) :
    IsRat (a^b) num den 
goal: Mathlib.Meta.NormNum.IsRat (a ^ b) num den

full_name: Mathlib.Meta.NormNum.evalZPow
code: /-- The `norm_num` extension which identifies expressions of the form `a ^ b`,
such that `norm_num` successfully recognises both `a` and `b`, with `b : ℤ`. -/
@[norm_num _ ^ (_ : ℤ)]
def evalZPow : NormNumExt 
goal: Mathlib.Meta.NormNum.NormNumExt