l3lab/ntp-mathlib huggingface dataset:
theorem opow_add (a b c : Ordinal) : a ^ (b + c) = a ^ b * a ^ c := by
  rcases eq_or_ne a 0 with (rfl | a0)
  · rcases eq_or_ne c 0 with (rfl | c0)
    · simp
    have : b + c ≠ 0 := ((Ordinal.pos_iff_ne_zero.2 c0).trans_le (le_add_left _ _)).ne'
    simp only [zero_opow c0, zero_opow this, mul_zero]
  rcases eq_or_lt_of_le (one_le_iff_ne_zero.2 a0) with (rfl | a1)
  · simp only [one_opow, mul_one]
  induction c using limitRecOn with
  

Proof state:
case inr.inr.H₁
a b : Ordinal.{u_1}
a0 : a ≠ 0
a1 : 1 < a
⊢ a ^ (b + 0) = a ^ b * a ^ 0

Next tactic:
| H₁ => simp
theorem opow_add (a b c : Ordinal) : a ^ (b + c) = a ^ b * a ^ c := by
  rcases eq_or_ne a 0 with (rfl | a0)
  · rcases eq_or_ne c 0 with (rfl | c0)
    · simp
    have : b + c ≠ 0 := ((Ordinal.pos_iff_ne_zero.2 c0).trans_le (le_add_left _ _)).ne'
    simp only [zero_opow c0, zero_opow this, mul_zero]
  rcases eq_or_lt_of_le (one_le_iff_ne_zero.2 a0) with (rfl | a1)
  · simp only [one_opow, mul_one]
  induction c using limitRecOn with
  | H₁ => 

Proof state:
case inr.inr.H₁
a b : Ordinal.{u_1}
a0 : a ≠ 0
a1 : 1 < a
⊢ a ^ (b + 0) = a ^ b * a ^ 0

Next tactic:
simp
theorem opow_add (a b c : Ordinal) : a ^ (b + c) = a ^ b * a ^ c := by
  rcases eq_or_ne a 0 with (rfl | a0)
  · rcases eq_or_ne c 0 with (rfl | c0)
    · simp
    have : b + c ≠ 0 := ((Ordinal.pos_iff_ne_zero.2 c0).trans_le (le_add_left _ _)).ne'
    simp only [zero_opow c0, zero_opow this, mul_zero]
  rcases eq_or_lt_of_le (one_le_iff_ne_zero.2 a0) with (rfl | a1)
  · simp only [one_opow, mul_one]
  induction c using limitRecOn with
  | H₁ => simp
  

Proof state:
case inr.inr.H₂
a b : Ordinal.{u_1}
a0 : a ≠ 0
a1 : 1 < a
c : Ordinal.{u_1}
IH : a ^ (b + c) = a ^ b * a ^ c
⊢ a ^ (b + succ c) = a ^ b * a ^ succ c

Next tactic:
| H₂ c IH =>
    rw [add_succ, opow_succ, IH, opow_succ, mul_assoc]
theorem opow_add (a b c : Ordinal) : a ^ (b + c) = a ^ b * a ^ c := by
  rcases eq_or_ne a 0 with (rfl | a0)
  · rcases eq_or_ne c 0 with (rfl | c0)
    · simp
    have : b + c ≠ 0 := ((Ordinal.pos_iff_ne_zero.2 c0).trans_le (le_add_left _ _)).ne'
    simp only [zero_opow c0, zero_opow this, mul_zero]
  rcases eq_or_lt_of_le (one_le_iff_ne_zero.2 a0) with (rfl | a1)
  · simp only [one_opow, mul_one]
  induction c using limitRecOn with
  | H₁ => simp
  | H₂ c IH =>
    

Proof state:
case inr.inr.H₂
a b : Ordinal.{u_1}
a0 : a ≠ 0
a1 : 1 < a
c : Ordinal.{u_1}
IH : a ^ (b + c) = a ^ b * a ^ c
⊢ a ^ (b + succ c) = a ^ b * a ^ succ c

Next tactic:
rw [add_succ, opow_succ, IH, opow_succ, mul_assoc]
theorem opow_add (a b c : Ordinal) : a ^ (b + c) = a ^ b * a ^ c := by
  rcases eq_or_ne a 0 with (rfl | a0)
  · rcases eq_or_ne c 0 with (rfl | c0)
    · simp
    have : b + c ≠ 0 := ((Ordinal.pos_iff_ne_zero.2 c0).trans_le (le_add_left _ _)).ne'
    simp only [zero_opow c0, zero_opow this, mul_zero]
  rcases eq_or_lt_of_le (one_le_iff_ne_zero.2 a0) with (rfl | a1)
  · simp only [one_opow, mul_one]
  induction c using limitRecOn with
  | H₁ => simp
  | H₂ c IH =>
    rw [add_succ, opow_succ, IH, opow_succ, mul_assoc]
  

Proof state:
case inr.inr.H₃
a b : Ordinal.{u_1}
a0 : a ≠ 0
a1 : 1 < a
c : Ordinal.{u_1}
l : IsLimit c
IH : ∀ o' < c, a ^ (b + o') = a ^ b * a ^ o'
⊢ a ^ (b + c) = a ^ b * a ^ c

Next tactic:
| H₃ c l IH =>
    refine'
      eq_of_forall_ge_iff fun d =>
        (((opow_isNormal a1).trans (add_isNormal b)).limit_le l).trans _
    dsimp only [Function.comp_def]
    simp (config := { contextual := true }) only [IH]
    exact
      (((mul_isNormal <| opow_pos b (Ordinal.pos_iff_ne_zero.2 a0)).trans
              (opow_isNormal a1)).limit_le
          l).symm
theorem opow_add (a b c : Ordinal) : a ^ (b + c) = a ^ b * a ^ c := by
  rcases eq_or_ne a 0 with (rfl | a0)
  · rcases eq_or_ne c 0 with (rfl | c0)
    · simp
    have : b + c ≠ 0 := ((Ordinal.pos_iff_ne_zero.2 c0).trans_le (le_add_left _ _)).ne'
    simp only [zero_opow c0, zero_opow this, mul_zero]
  rcases eq_or_lt_of_le (one_le_iff_ne_zero.2 a0) with (rfl | a1)
  · simp only [one_opow, mul_one]
  induction c using limitRecOn with
  | H₁ => simp
  | H₂ c IH =>
    rw [add_succ, opow_succ, IH, opow_succ, mul_assoc]
  | H₃ c l IH =>
    

Proof state:
case inr.inr.H₃
a b : Ordinal.{u_1}
a0 : a ≠ 0
a1 : 1 < a
c : Ordinal.{u_1}
l : IsLimit c
IH : ∀ o' < c, a ^ (b + o') = a ^ b * a ^ o'
⊢ a ^ (b + c) = a ^ b * a ^ c

Next tactic:
refine'
      eq_of_forall_ge_iff fun d =>
        (((opow_isNormal a1).trans (add_isNormal b)).limit_le l).trans _
theorem opow_add (a b c : Ordinal) : a ^ (b + c) = a ^ b * a ^ c := by
  rcases eq_or_ne a 0 with (rfl | a0)
  · rcases eq_or_ne c 0 with (rfl | c0)
    · simp
    have : b + c ≠ 0 := ((Ordinal.pos_iff_ne_zero.2 c0).trans_le (le_add_left _ _)).ne'
    simp only [zero_opow c0, zero_opow this, mul_zero]
  rcases eq_or_lt_of_le (one_le_iff_ne_zero.2 a0) with (rfl | a1)
  · simp only [one_opow, mul_one]
  induction c using limitRecOn with
  | H₁ => simp
  | H₂ c IH =>
    rw [add_succ, opow_succ, IH, opow_succ, mul_assoc]
  | H₃ c l IH =>
    refine'
      eq_of_forall_ge_iff fun d =>
        (((opow_isNormal a1).trans (add_isNormal b)).limit_le l).trans _
    

Proof state:
case inr.inr.H₃
a b : Ordinal.{u_1}
a0 : a ≠ 0
a1 : 1 < a
c : Ordinal.{u_1}
l : IsLimit c
IH : ∀ o' < c, a ^ (b + o') = a ^ b * a ^ o'
d : Ordinal.{u_1}
⊢ (∀ b_1 < c, ((fun x => a ^ x) ∘ fun x => b + x) b_1 ≤ d) ↔ a ^ b * a ^ c ≤ d

Next tactic:
dsimp only [Function.comp_def]
theorem opow_add (a b c : Ordinal) : a ^ (b + c) = a ^ b * a ^ c := by
  rcases eq_or_ne a 0 with (rfl | a0)
  · rcases eq_or_ne c 0 with (rfl | c0)
    · simp
    have : b + c ≠ 0 := ((Ordinal.pos_iff_ne_zero.2 c0).trans_le (le_add_left _ _)).ne'
    simp only [zero_opow c0, zero_opow this, mul_zero]
  rcases eq_or_lt_of_le (one_le_iff_ne_zero.2 a0) with (rfl | a1)
  · simp only [one_opow, mul_one]
  induction c using limitRecOn with
  | H₁ => simp
  | H₂ c IH =>
    rw [add_succ, opow_succ, IH, opow_succ, mul_assoc]
  | H₃ c l IH =>
    refine'
      eq_of_forall_ge_iff fun d =>
        (((opow_isNormal a1).trans (add_isNormal b)).limit_le l).trans _
    dsimp only [Function.comp_def]
    

Proof state:
case inr.inr.H₃
a b : Ordinal.{u_1}
a0 : a ≠ 0
a1 : 1 < a
c : Ordinal.{u_1}
l : IsLimit c
IH : ∀ o' < c, a ^ (b + o') = a ^ b * a ^ o'
d : Ordinal.{u_1}
⊢ (∀ b_1 < c, a ^ (b + b_1) ≤ d) ↔ a ^ b * a ^ c ≤ d

Next tactic:
simp (config := { contextual := true }) only [IH]
theorem opow_add (a b c : Ordinal) : a ^ (b + c) = a ^ b * a ^ c := by
  rcases eq_or_ne a 0 with (rfl | a0)
  · rcases eq_or_ne c 0 with (rfl | c0)
    · simp
    have : b + c ≠ 0 := ((Ordinal.pos_iff_ne_zero.2 c0).trans_le (le_add_left _ _)).ne'
    simp only [zero_opow c0, zero_opow this, mul_zero]
  rcases eq_or_lt_of_le (one_le_iff_ne_zero.2 a0) with (rfl | a1)
  · simp only [one_opow, mul_one]
  induction c using limitRecOn with
  | H₁ => simp
  | H₂ c IH =>
    rw [add_succ, opow_succ, IH, opow_succ, mul_assoc]
  | H₃ c l IH =>
    refine'
      eq_of_forall_ge_iff fun d =>
        (((opow_isNormal a1).trans (add_isNormal b)).limit_le l).trans _
    dsimp only [Function.comp_def]
    simp (config := { contextual := true }) only [IH]
    

Proof state:
case inr.inr.H₃
a b : Ordinal.{u_1}
a0 : a ≠ 0
a1 : 1 < a
c : Ordinal.{u_1}
l : IsLimit c
IH : ∀ o' < c, a ^ (b + o') = a ^ b * a ^ o'
d : Ordinal.{u_1}
⊢ (∀ b_1 < c, a ^ b * a ^ b_1 ≤ d) ↔ a ^ b * a ^ c ≤ d

Next tactic:
exact
      (((mul_isNormal <| opow_pos b (Ordinal.pos_iff_ne_zero.2 a0)).trans
              (opow_isNormal a1)).limit_le
          l).symm
theorem opow_one_add (a b : Ordinal) : a ^ (1 + b) = a * a ^ b := by 

Proof state:
a b : Ordinal.{u_1}
⊢ a ^ (1 + b) = a * a ^ b

Next tactic:
rw [opow_add, opow_one]
theorem opow_dvd_opow (a : Ordinal) {b c : Ordinal} (h : b ≤ c) : a ^ b ∣ a ^ c :=
  ⟨a ^ (c - b), by 

Proof state:
a b c : Ordinal.{u_1}
h : b ≤ c
⊢ a ^ c = a ^ b * a ^ (c - b)

Next tactic:
rw [← opow_add, Ordinal.add_sub_cancel_of_le h]
theorem opow_mul (a b c : Ordinal) : a ^ (b * c) = (a ^ b) ^ c := by
  

Proof state:
a b c : Ordinal.{u_1}
⊢ a ^ (b * c) = (a ^ b) ^ c

Next tactic:
by_cases b0 : b = 0
theorem opow_mul (a b c : Ordinal) : a ^ (b * c) = (a ^ b) ^ c := by
  by_cases b0 : b = 0; · 

Proof state:
case pos
a b c : Ordinal.{u_1}
b0 : b = 0
⊢ a ^ (b * c) = (a ^ b) ^ c

Next tactic:
simp only [b0, zero_mul, opow_zero, one_opow]
theorem opow_mul (a b c : Ordinal) : a ^ (b * c) = (a ^ b) ^ c := by
  by_cases b0 : b = 0; · simp only [b0, zero_mul, opow_zero, one_opow]
  

Proof state:
case neg
a b c : Ordinal.{u_1}
b0 : ¬b = 0
⊢ a ^ (b * c) = (a ^ b) ^ c

Next tactic:
by_cases a0 : a = 0
theorem opow_mul (a b c : Ordinal) : a ^ (b * c) = (a ^ b) ^ c := by
  by_cases b0 : b = 0; · simp only [b0, zero_mul, opow_zero, one_opow]
  by_cases a0 : a = 0
  · 

Proof state:
case pos
a b c : Ordinal.{u_1}
b0 : ¬b = 0
a0 : a = 0
⊢ a ^ (b * c) = (a ^ b) ^ c

Next tactic:
subst a
theorem opow_mul (a b c : Ordinal) : a ^ (b * c) = (a ^ b) ^ c := by
  by_cases b0 : b = 0; · simp only [b0, zero_mul, opow_zero, one_opow]
  by_cases a0 : a = 0
  · subst a
    

Proof state:
case pos
b c : Ordinal.{u_1}
b0 : ¬b = 0
⊢ 0 ^ (b * c) = (0 ^ b) ^ c

Next tactic:
by_cases c0 : c = 0
theorem opow_mul (a b c : Ordinal) : a ^ (b * c) = (a ^ b) ^ c := by
  by_cases b0 : b = 0; · simp only [b0, zero_mul, opow_zero, one_opow]
  by_cases a0 : a = 0
  · subst a
    by_cases c0 : c = 0
    · 

Proof state:
case pos
b c : Ordinal.{u_1}
b0 : ¬b = 0
c0 : c = 0
⊢ 0 ^ (b * c) = (0 ^ b) ^ c

Next tactic:
simp only [c0, mul_zero, opow_zero]
theorem opow_mul (a b c : Ordinal) : a ^ (b * c) = (a ^ b) ^ c := by
  by_cases b0 : b = 0; · simp only [b0, zero_mul, opow_zero, one_opow]
  by_cases a0 : a = 0
  · subst a
    by_cases c0 : c = 0
    · simp only [c0, mul_zero, opow_zero]
    

Proof state:
case neg
b c : Ordinal.{u_1}
b0 : ¬b = 0
c0 : ¬c = 0
⊢ 0 ^ (b * c) = (0 ^ b) ^ c

Next tactic:
simp only [zero_opow b0, zero_opow c0, zero_opow (mul_ne_zero b0 c0)]
theorem opow_mul (a b c : Ordinal) : a ^ (b * c) = (a ^ b) ^ c := by
  by_cases b0 : b = 0; · simp only [b0, zero_mul, opow_zero, one_opow]
  by_cases a0 : a = 0
  · subst a
    by_cases c0 : c = 0
    · simp only [c0, mul_zero, opow_zero]
    simp only [zero_opow b0, zero_opow c0, zero_opow (mul_ne_zero b0 c0)]
  

Proof state:
case neg
a b c : Ordinal.{u_1}
b0 : ¬b = 0
a0 : ¬a = 0
⊢ a ^ (b * c) = (a ^ b) ^ c

Next tactic:
cases' eq_or_lt_of_le (one_le_iff_ne_zero.2 a0) with a1 a1
theorem opow_mul (a b c : Ordinal) : a ^ (b * c) = (a ^ b) ^ c := by
  by_cases b0 : b = 0; · simp only [b0, zero_mul, opow_zero, one_opow]
  by_cases a0 : a = 0
  · subst a
    by_cases c0 : c = 0
    · simp only [c0, mul_zero, opow_zero]
    simp only [zero_opow b0, zero_opow c0, zero_opow (mul_ne_zero b0 c0)]
  cases' eq_or_lt_of_le (one_le_iff_ne_zero.2 a0) with a1 a1
  · 

Proof state:
case neg.inl
a b c : Ordinal.{u_1}
b0 : ¬b = 0
a0 : ¬a = 0
a1 : 1 = a
⊢ a ^ (b * c) = (a ^ b) ^ c

Next tactic:
subst a1
theorem opow_mul (a b c : Ordinal) : a ^ (b * c) = (a ^ b) ^ c := by
  by_cases b0 : b = 0; · simp only [b0, zero_mul, opow_zero, one_opow]
  by_cases a0 : a = 0
  · subst a
    by_cases c0 : c = 0
    · simp only [c0, mul_zero, opow_zero]
    simp only [zero_opow b0, zero_opow c0, zero_opow (mul_ne_zero b0 c0)]
  cases' eq_or_lt_of_le (one_le_iff_ne_zero.2 a0) with a1 a1
  · subst a1
    

Proof state:
case neg.inl
b c : Ordinal.{u_1}
b0 : ¬b = 0
a0 : ¬1 = 0
⊢ 1 ^ (b * c) = (1 ^ b) ^ c

Next tactic:
simp only [one_opow]
theorem opow_mul (a b c : Ordinal) : a ^ (b * c) = (a ^ b) ^ c := by
  by_cases b0 : b = 0; · simp only [b0, zero_mul, opow_zero, one_opow]
  by_cases a0 : a = 0
  · subst a
    by_cases c0 : c = 0
    · simp only [c0, mul_zero, opow_zero]
    simp only [zero_opow b0, zero_opow c0, zero_opow (mul_ne_zero b0 c0)]
  cases' eq_or_lt_of_le (one_le_iff_ne_zero.2 a0) with a1 a1
  · subst a1
    simp only [one_opow]
  

Proof state:
case neg.inr
a b c : Ordinal.{u_1}
b0 : ¬b = 0
a0 : ¬a = 0
a1 : 1 < a
⊢ a ^ (b * c) = (a ^ b) ^ c

Next tactic:
induction c using limitRecOn with
  | H₁ => simp only [mul_zero, opow_zero]
  | H₂ c IH =>
    rw [mul_succ, opow_add, IH, opow_succ]
  | H₃ c l IH =>
    refine'
      eq_of_forall_ge_iff fun d =>
        (((opow_isNormal a1).trans (mul_isNormal (Ordinal.pos_iff_ne_zero.2 b0))).limit_le
              l).trans
          _
    dsimp only [Function.comp_def]
    simp (config := { contextual := true }) only [IH]
    exact (opow_le_of_limit (opow_ne_zero _ a0) l).symm
theorem opow_mul (a b c : Ordinal) : a ^ (b * c) = (a ^ b) ^ c := by
  by_cases b0 : b = 0; · simp only [b0, zero_mul, opow_zero, one_opow]
  by_cases a0 : a = 0
  · subst a
    by_cases c0 : c = 0
    · simp only [c0, mul_zero, opow_zero]
    simp only [zero_opow b0, zero_opow c0, zero_opow (mul_ne_zero b0 c0)]
  cases' eq_or_lt_of_le (one_le_iff_ne_zero.2 a0) with a1 a1
  · subst a1
    simp only [one_opow]
  induction c using limitRecOn with
  

Proof state:
case neg.inr.H₁
a b : Ordinal.{u_1}
b0 : ¬b = 0
a0 : ¬a = 0
a1 : 1 < a
⊢ a ^ (b * 0) = (a ^ b) ^ 0

Next tactic:
| H₁ => simp only [mul_zero, opow_zero]
theorem opow_mul (a b c : Ordinal) : a ^ (b * c) = (a ^ b) ^ c := by
  by_cases b0 : b = 0; · simp only [b0, zero_mul, opow_zero, one_opow]
  by_cases a0 : a = 0
  · subst a
    by_cases c0 : c = 0
    · simp only [c0, mul_zero, opow_zero]
    simp only [zero_opow b0, zero_opow c0, zero_opow (mul_ne_zero b0 c0)]
  cases' eq_or_lt_of_le (one_le_iff_ne_zero.2 a0) with a1 a1
  · subst a1
    simp only [one_opow]
  induction c using limitRecOn with
  | H₁ => 

Proof state:
case neg.inr.H₁
a b : Ordinal.{u_1}
b0 : ¬b = 0
a0 : ¬a = 0
a1 : 1 < a
⊢ a ^ (b * 0) = (a ^ b) ^ 0

Next tactic:
simp only [mul_zero, opow_zero]
theorem opow_mul (a b c : Ordinal) : a ^ (b * c) = (a ^ b) ^ c := by
  by_cases b0 : b = 0; · simp only [b0, zero_mul, opow_zero, one_opow]
  by_cases a0 : a = 0
  · subst a
    by_cases c0 : c = 0
    · simp only [c0, mul_zero, opow_zero]
    simp only [zero_opow b0, zero_opow c0, zero_opow (mul_ne_zero b0 c0)]
  cases' eq_or_lt_of_le (one_le_iff_ne_zero.2 a0) with a1 a1
  · subst a1
    simp only [one_opow]
  induction c using limitRecOn with
  | H₁ => simp only [mul_zero, opow_zero]
  

Proof state:
case neg.inr.H₂
a b : Ordinal.{u_1}
b0 : ¬b = 0
a0 : ¬a = 0
a1 : 1 < a
c : Ordinal.{u_1}
IH : a ^ (b * c) = (a ^ b) ^ c
⊢ a ^ (b * succ c) = (a ^ b) ^ succ c

Next tactic:
| H₂ c IH =>
    rw [mul_succ, opow_add, IH, opow_succ]
theorem opow_mul (a b c : Ordinal) : a ^ (b * c) = (a ^ b) ^ c := by
  by_cases b0 : b = 0; · simp only [b0, zero_mul, opow_zero, one_opow]
  by_cases a0 : a = 0
  · subst a
    by_cases c0 : c = 0
    · simp only [c0, mul_zero, opow_zero]
    simp only [zero_opow b0, zero_opow c0, zero_opow (mul_ne_zero b0 c0)]
  cases' eq_or_lt_of_le (one_le_iff_ne_zero.2 a0) with a1 a1
  · subst a1
    simp only [one_opow]
  induction c using limitRecOn with
  | H₁ => simp only [mul_zero, opow_zero]
  | H₂ c IH =>
    

Proof state:
case neg.inr.H₂
a b : Ordinal.{u_1}
b0 : ¬b = 0
a0 : ¬a = 0
a1 : 1 < a
c : Ordinal.{u_1}
IH : a ^ (b * c) = (a ^ b) ^ c
⊢ a ^ (b * succ c) = (a ^ b) ^ succ c

Next tactic:
rw [mul_succ, opow_add, IH, opow_succ]
theorem opow_mul (a b c : Ordinal) : a ^ (b * c) = (a ^ b) ^ c := by
  by_cases b0 : b = 0; · simp only [b0, zero_mul, opow_zero, one_opow]
  by_cases a0 : a = 0
  · subst a
    by_cases c0 : c = 0
    · simp only [c0, mul_zero, opow_zero]
    simp only [zero_opow b0, zero_opow c0, zero_opow (mul_ne_zero b0 c0)]
  cases' eq_or_lt_of_le (one_le_iff_ne_zero.2 a0) with a1 a1
  · subst a1
    simp only [one_opow]
  induction c using limitRecOn with
  | H₁ => simp only [mul_zero, opow_zero]
  | H₂ c IH =>
    rw [mul_succ, opow_add, IH, opow_succ]
  

Proof state:
case neg.inr.H₃
a b : Ordinal.{u_1}
b0 : ¬b = 0
a0 : ¬a = 0
a1 : 1 < a
c : Ordinal.{u_1}
l : IsLimit c
IH : ∀ o' < c, a ^ (b * o') = (a ^ b) ^ o'
⊢ a ^ (b * c) = (a ^ b) ^ c

Next tactic:
| H₃ c l IH =>
    refine'
      eq_of_forall_ge_iff fun d =>
        (((opow_isNormal a1).trans (mul_isNormal (Ordinal.pos_iff_ne_zero.2 b0))).limit_le
              l).trans
          _
    dsimp only [Function.comp_def]
    simp (config := { contextual := true }) only [IH]
    exact (opow_le_of_limit (opow_ne_zero _ a0) l).symm
theorem opow_mul (a b c : Ordinal) : a ^ (b * c) = (a ^ b) ^ c := by
  by_cases b0 : b = 0; · simp only [b0, zero_mul, opow_zero, one_opow]
  by_cases a0 : a = 0
  · subst a
    by_cases c0 : c = 0
    · simp only [c0, mul_zero, opow_zero]
    simp only [zero_opow b0, zero_opow c0, zero_opow (mul_ne_zero b0 c0)]
  cases' eq_or_lt_of_le (one_le_iff_ne_zero.2 a0) with a1 a1
  · subst a1
    simp only [one_opow]
  induction c using limitRecOn with
  | H₁ => simp only [mul_zero, opow_zero]
  | H₂ c IH =>
    rw [mul_succ, opow_add, IH, opow_succ]
  | H₃ c l IH =>
    

Proof state:
case neg.inr.H₃
a b : Ordinal.{u_1}
b0 : ¬b = 0
a0 : ¬a = 0
a1 : 1 < a
c : Ordinal.{u_1}
l : IsLimit c
IH : ∀ o' < c, a ^ (b * o') = (a ^ b) ^ o'
⊢ a ^ (b * c) = (a ^ b) ^ c

Next tactic:
refine'
      eq_of_forall_ge_iff fun d =>
        (((opow_isNormal a1).trans (mul_isNormal (Ordinal.pos_iff_ne_zero.2 b0))).limit_le
              l).trans
          _
theorem opow_mul (a b c : Ordinal) : a ^ (b * c) = (a ^ b) ^ c := by
  by_cases b0 : b = 0; · simp only [b0, zero_mul, opow_zero, one_opow]
  by_cases a0 : a = 0
  · subst a
    by_cases c0 : c = 0
    · simp only [c0, mul_zero, opow_zero]
    simp only [zero_opow b0, zero_opow c0, zero_opow (mul_ne_zero b0 c0)]
  cases' eq_or_lt_of_le (one_le_iff_ne_zero.2 a0) with a1 a1
  · subst a1
    simp only [one_opow]
  induction c using limitRecOn with
  | H₁ => simp only [mul_zero, opow_zero]
  | H₂ c IH =>
    rw [mul_succ, opow_add, IH, opow_succ]
  | H₃ c l IH =>
    refine'
      eq_of_forall_ge_iff fun d =>
        (((opow_isNormal a1).trans (mul_isNormal (Ordinal.pos_iff_ne_zero.2 b0))).limit_le
              l).trans
          _
    

Proof state:
case neg.inr.H₃
a b : Ordinal.{u_1}
b0 : ¬b = 0
a0 : ¬a = 0
a1 : 1 < a
c : Ordinal.{u_1}
l : IsLimit c
IH : ∀ o' < c, a ^ (b * o') = (a ^ b) ^ o'
d : Ordinal.{u_1}
⊢ (∀ b_1 < c, ((fun x => a ^ x) ∘ fun x => b * x) b_1 ≤ d) ↔ (a ^ b) ^ c ≤ d

Next tactic:
dsimp only [Function.comp_def]
theorem opow_mul (a b c : Ordinal) : a ^ (b * c) = (a ^ b) ^ c := by
  by_cases b0 : b = 0; · simp only [b0, zero_mul, opow_zero, one_opow]
  by_cases a0 : a = 0
  · subst a
    by_cases c0 : c = 0
    · simp only [c0, mul_zero, opow_zero]
    simp only [zero_opow b0, zero_opow c0, zero_opow (mul_ne_zero b0 c0)]
  cases' eq_or_lt_of_le (one_le_iff_ne_zero.2 a0) with a1 a1
  · subst a1
    simp only [one_opow]
  induction c using limitRecOn with
  | H₁ => simp only [mul_zero, opow_zero]
  | H₂ c IH =>
    rw [mul_succ, opow_add, IH, opow_succ]
  | H₃ c l IH =>
    refine'
      eq_of_forall_ge_iff fun d =>
        (((opow_isNormal a1).trans (mul_isNormal (Ordinal.pos_iff_ne_zero.2 b0))).limit_le
              l).trans
          _
    dsimp only [Function.comp_def]
    

Proof state:
case neg.inr.H₃
a b : Ordinal.{u_1}
b0 : ¬b = 0
a0 : ¬a = 0
a1 : 1 < a
c : Ordinal.{u_1}
l : IsLimit c
IH : ∀ o' < c, a ^ (b * o') = (a ^ b) ^ o'
d : Ordinal.{u_1}
⊢ (∀ b_1 < c, a ^ (b * b_1) ≤ d) ↔ (a ^ b) ^ c ≤ d

Next tactic:
simp (config := { contextual := true }) only [IH]
theorem opow_mul (a b c : Ordinal) : a ^ (b * c) = (a ^ b) ^ c := by
  by_cases b0 : b = 0; · simp only [b0, zero_mul, opow_zero, one_opow]
  by_cases a0 : a = 0
  · subst a
    by_cases c0 : c = 0
    · simp only [c0, mul_zero, opow_zero]
    simp only [zero_opow b0, zero_opow c0, zero_opow (mul_ne_zero b0 c0)]
  cases' eq_or_lt_of_le (one_le_iff_ne_zero.2 a0) with a1 a1
  · subst a1
    simp only [one_opow]
  induction c using limitRecOn with
  | H₁ => simp only [mul_zero, opow_zero]
  | H₂ c IH =>
    rw [mul_succ, opow_add, IH, opow_succ]
  | H₃ c l IH =>
    refine'
      eq_of_forall_ge_iff fun d =>
        (((opow_isNormal a1).trans (mul_isNormal (Ordinal.pos_iff_ne_zero.2 b0))).limit_le
              l).trans
          _
    dsimp only [Function.comp_def]
    simp (config := { contextual := true }) only [IH]
    

Proof state:
case neg.inr.H₃
a b : Ordinal.{u_1}
b0 : ¬b = 0
a0 : ¬a = 0
a1 : 1 < a
c : Ordinal.{u_1}
l : IsLimit c
IH : ∀ o' < c, a ^ (b * o') = (a ^ b) ^ o'
d : Ordinal.{u_1}
⊢ (∀ b_1 < c, (a ^ b) ^ b_1 ≤ d) ↔ (a ^ b) ^ c ≤ d

Next tactic:
exact (opow_le_of_limit (opow_ne_zero _ a0) l).symm
theorem log_def {b : Ordinal} (h : 1 < b) (x : Ordinal) : log b x = pred (sInf { o | x < b ^ o }) :=
  by 

Proof state:
b : Ordinal.{u_1}
h : 1 < b
x : Ordinal.{u_1}
⊢ log b x = pred (sInf {o | x < b ^ o})

Next tactic:
simp only [log, dif_pos h]
theorem log_of_not_one_lt_left {b : Ordinal} (h : ¬1 < b) (x : Ordinal) : log b x = 0 := by
  

Proof state:
b : Ordinal.{u_1}
h : ¬1 < b
x : Ordinal.{u_1}
⊢ log b x = 0

Next tactic:
simp only [log, dif_neg h]
@[simp]
theorem log_zero_right (b : Ordinal) : log b 0 = 0 :=
  if b1 : 1 < b then by
    

Proof state:
b : Ordinal.{u_1}
b1 : 1 < b
⊢ log b 0 = 0

Next tactic:
rw [log_def b1, ← Ordinal.le_zero, pred_le]
@[simp]
theorem log_zero_right (b : Ordinal) : log b 0 = 0 :=
  if b1 : 1 < b then by
    rw [log_def b1, ← Ordinal.le_zero, pred_le]
    

Proof state:
b : Ordinal.{u_1}
b1 : 1 < b
⊢ sInf {o | 0 < b ^ o} ≤ succ 0

Next tactic:
apply csInf_le'
@[simp]
theorem log_zero_right (b : Ordinal) : log b 0 = 0 :=
  if b1 : 1 < b then by
    rw [log_def b1, ← Ordinal.le_zero, pred_le]
    apply csInf_le'
    

Proof state:
case h
b : Ordinal.{u_1}
b1 : 1 < b
⊢ succ 0 ∈ {o | 0 < b ^ o}

Next tactic:
dsimp
@[simp]
theorem log_zero_right (b : Ordinal) : log b 0 = 0 :=
  if b1 : 1 < b then by
    rw [log_def b1, ← Ordinal.le_zero, pred_le]
    apply csInf_le'
    dsimp
    

Proof state:
case h
b : Ordinal.{u_1}
b1 : 1 < b
⊢ 0 < b ^ succ 0

Next tactic:
rw [succ_zero, opow_one]
@[simp]
theorem log_zero_right (b : Ordinal) : log b 0 = 0 :=
  if b1 : 1 < b then by
    rw [log_def b1, ← Ordinal.le_zero, pred_le]
    apply csInf_le'
    dsimp
    rw [succ_zero, opow_one]
    

Proof state:
case h
b : Ordinal.{u_1}
b1 : 1 < b
⊢ 0 < b

Next tactic:
exact zero_lt_one.trans b1
@[simp]
theorem log_zero_right (b : Ordinal) : log b 0 = 0 :=
  if b1 : 1 < b then by
    rw [log_def b1, ← Ordinal.le_zero, pred_le]
    apply csInf_le'
    dsimp
    rw [succ_zero, opow_one]
    exact zero_lt_one.trans b1
  else by 

Proof state:
b : Ordinal.{u_1}
b1 : ¬1 < b
⊢ log b 0 = 0

Next tactic:
simp only [log_of_not_one_lt_left b1]
theorem succ_log_def {b x : Ordinal} (hb : 1 < b) (hx : x ≠ 0) :
    succ (log b x) = sInf { o : Ordinal | x < b ^ o } := by
  

Proof state:
b x : Ordinal.{u_1}
hb : 1 < b
hx : x ≠ 0
⊢ succ (log b x) = sInf {o | x < b ^ o}

Next tactic:
let t := sInf { o : Ordinal | x < b ^ o }
theorem succ_log_def {b x : Ordinal} (hb : 1 < b) (hx : x ≠ 0) :
    succ (log b x) = sInf { o : Ordinal | x < b ^ o } := by
  let t := sInf { o : Ordinal | x < b ^ o }
  

Proof state:
b x : Ordinal.{u_1}
hb : 1 < b
hx : x ≠ 0
t : Ordinal.{u_1} := sInf {o | x < b ^ o}
⊢ succ (log b x) = sInf {o | x < b ^ o}

Next tactic:
have : x < (b^t) := csInf_mem (log_nonempty hb)
theorem succ_log_def {b x : Ordinal} (hb : 1 < b) (hx : x ≠ 0) :
    succ (log b x) = sInf { o : Ordinal | x < b ^ o } := by
  let t := sInf { o : Ordinal | x < b ^ o }
  have : x < (b^t) := csInf_mem (log_nonempty hb)
  

Proof state:
b x : Ordinal.{u_1}
hb : 1 < b
hx : x ≠ 0
t : Ordinal.{u_1} := sInf {o | x < b ^ o}
this : x < b ^ t
⊢ succ (log b x) = sInf {o | x < b ^ o}

Next tactic:
rcases zero_or_succ_or_limit t with (h | h | h)
theorem succ_log_def {b x : Ordinal} (hb : 1 < b) (hx : x ≠ 0) :
    succ (log b x) = sInf { o : Ordinal | x < b ^ o } := by
  let t := sInf { o : Ordinal | x < b ^ o }
  have : x < (b^t) := csInf_mem (log_nonempty hb)
  rcases zero_or_succ_or_limit t with (h | h | h)
  · 

Proof state:
case inl
b x : Ordinal.{u_1}
hb : 1 < b
hx : x ≠ 0
t : Ordinal.{u_1} := sInf {o | x < b ^ o}
this : x < b ^ t
h : t = 0
⊢ succ (log b x) = sInf {o | x < b ^ o}

Next tactic:
refine' ((one_le_iff_ne_zero.2 hx).not_lt _).elim