l3lab/ntp-mathlib huggingface dataset:
theorem mul_omega_opow_opow {a b : Ordinal} (a0 : 0 < a) (h : a < (omega^omega^b)) :
    a * (omega^omega^b) = (omega^omega^b) := by
  by_cases b0 : b = 0;
  · rw [b0, opow_zero, opow_one] at h ⊢
    exact mul_omega a0 h
  refine'
    le_antisymm _
      (by simpa only [one_mul] using mul_le_mul_right' (one_le_iff_pos.2 a0) (omega^omega^b))
  

Proof state:
case neg
a b : Ordinal.{u_1}
a0 : 0 < a
h : a < ω ^ ω ^ b
b0 : ¬b = 0
⊢ a * ω ^ ω ^ b ≤ ω ^ ω ^ b

Next tactic:
rcases (lt_opow_of_limit omega_ne_zero (opow_isLimit_left omega_isLimit b0)).1 h with ⟨x, xb, ax⟩
theorem mul_omega_opow_opow {a b : Ordinal} (a0 : 0 < a) (h : a < (omega^omega^b)) :
    a * (omega^omega^b) = (omega^omega^b) := by
  by_cases b0 : b = 0;
  · rw [b0, opow_zero, opow_one] at h ⊢
    exact mul_omega a0 h
  refine'
    le_antisymm _
      (by simpa only [one_mul] using mul_le_mul_right' (one_le_iff_pos.2 a0) (omega^omega^b))
  rcases (lt_opow_of_limit omega_ne_zero (opow_isLimit_left omega_isLimit b0)).1 h with ⟨x, xb, ax⟩
  

Proof state:
case neg.intro.intro
a b : Ordinal.{u_1}
a0 : 0 < a
h : a < ω ^ ω ^ b
b0 : ¬b = 0
x : Ordinal.{u_1}
xb : x < ω ^ b
ax : a < ω ^ x
⊢ a * ω ^ ω ^ b ≤ ω ^ ω ^ b

Next tactic:
apply (mul_le_mul_right' (le_of_lt ax) _).trans
theorem mul_omega_opow_opow {a b : Ordinal} (a0 : 0 < a) (h : a < (omega^omega^b)) :
    a * (omega^omega^b) = (omega^omega^b) := by
  by_cases b0 : b = 0;
  · rw [b0, opow_zero, opow_one] at h ⊢
    exact mul_omega a0 h
  refine'
    le_antisymm _
      (by simpa only [one_mul] using mul_le_mul_right' (one_le_iff_pos.2 a0) (omega^omega^b))
  rcases (lt_opow_of_limit omega_ne_zero (opow_isLimit_left omega_isLimit b0)).1 h with ⟨x, xb, ax⟩
  apply (mul_le_mul_right' (le_of_lt ax) _).trans
  

Proof state:
case neg.intro.intro
a b : Ordinal.{u_1}
a0 : 0 < a
h : a < ω ^ ω ^ b
b0 : ¬b = 0
x : Ordinal.{u_1}
xb : x < ω ^ b
ax : a < ω ^ x
⊢ ω ^ x * ω ^ ω ^ b ≤ ω ^ ω ^ b

Next tactic:
rw [← opow_add, add_omega_opow xb]
theorem principal_add_of_principal_mul_opow {o b : Ordinal} (hb : 1 < b)
    (ho : Principal (· * ·) (b^o)) : Principal (· + ·) o := fun x y hx hy => by
  

Proof state:
o b : Ordinal.{u_1}
hb : 1 < b
ho : Principal (fun x x_1 => x * x_1) (b ^ o)
x y : Ordinal.{u_1}
hx : x < o
hy : y < o
⊢ (fun x x_1 => x + x_1) x y < o

Next tactic:
have := ho ((opow_lt_opow_iff_right hb).2 hx) ((opow_lt_opow_iff_right hb).2 hy)
theorem principal_add_of_principal_mul_opow {o b : Ordinal} (hb : 1 < b)
    (ho : Principal (· * ·) (b^o)) : Principal (· + ·) o := fun x y hx hy => by
  have := ho ((opow_lt_opow_iff_right hb).2 hx) ((opow_lt_opow_iff_right hb).2 hy)
  

Proof state:
o b : Ordinal.{u_1}
hb : 1 < b
ho : Principal (fun x x_1 => x * x_1) (b ^ o)
x y : Ordinal.{u_1}
hx : x < o
hy : y < o
this : (fun x x_1 => x * x_1) (b ^ x) (b ^ y) < b ^ o
⊢ (fun x x_1 => x + x_1) x y < o

Next tactic:
dsimp only at *
theorem principal_add_of_principal_mul_opow {o b : Ordinal} (hb : 1 < b)
    (ho : Principal (· * ·) (b^o)) : Principal (· + ·) o := fun x y hx hy => by
  have := ho ((opow_lt_opow_iff_right hb).2 hx) ((opow_lt_opow_iff_right hb).2 hy)
  dsimp only at *; 

Proof state:
o b : Ordinal.{u_1}
hb : 1 < b
ho : Principal (fun x x_1 => x * x_1) (b ^ o)
x y : Ordinal.{u_1}
hx : x < o
hy : y < o
this : b ^ x * b ^ y < b ^ o
⊢ x + y < o

Next tactic:
rwa [← opow_add, opow_lt_opow_iff_right hb] at this
/-- The main characterization theorem for multiplicative principal ordinals. -/
theorem principal_mul_iff_le_two_or_omega_opow_opow {o : Ordinal} :
    Principal (· * ·) o ↔ o ≤ 2 ∨ ∃ a : Ordinal, o = (omega^omega^a) := by
  

Proof state:
o : Ordinal.{u_1}
⊢ Principal (fun x x_1 => x * x_1) o ↔ o ≤ 2 ∨ ∃ a, o = ω ^ ω ^ a

Next tactic:
refine' ⟨fun ho => _, _⟩
/-- The main characterization theorem for multiplicative principal ordinals. -/
theorem principal_mul_iff_le_two_or_omega_opow_opow {o : Ordinal} :
    Principal (· * ·) o ↔ o ≤ 2 ∨ ∃ a : Ordinal, o = (omega^omega^a) := by
  refine' ⟨fun ho => _, _⟩
  · 

Proof state:
case refine'_1
o : Ordinal.{u_1}
ho : Principal (fun x x_1 => x * x_1) o
⊢ o ≤ 2 ∨ ∃ a, o = ω ^ ω ^ a

Next tactic:
rcases le_or_lt o 2 with ho₂ | ho₂
/-- The main characterization theorem for multiplicative principal ordinals. -/
theorem principal_mul_iff_le_two_or_omega_opow_opow {o : Ordinal} :
    Principal (· * ·) o ↔ o ≤ 2 ∨ ∃ a : Ordinal, o = (omega^omega^a) := by
  refine' ⟨fun ho => _, _⟩
  · rcases le_or_lt o 2 with ho₂ | ho₂
    · 

Proof state:
case refine'_1.inl
o : Ordinal.{u_1}
ho : Principal (fun x x_1 => x * x_1) o
ho₂ : o ≤ 2
⊢ o ≤ 2 ∨ ∃ a, o = ω ^ ω ^ a

Next tactic:
exact Or.inl ho₂
/-- The main characterization theorem for multiplicative principal ordinals. -/
theorem principal_mul_iff_le_two_or_omega_opow_opow {o : Ordinal} :
    Principal (· * ·) o ↔ o ≤ 2 ∨ ∃ a : Ordinal, o = (omega^omega^a) := by
  refine' ⟨fun ho => _, _⟩
  · rcases le_or_lt o 2 with ho₂ | ho₂
    · exact Or.inl ho₂
    

Proof state:
case refine'_1.inr
o : Ordinal.{u_1}
ho : Principal (fun x x_1 => x * x_1) o
ho₂ : 2 < o
⊢ o ≤ 2 ∨ ∃ a, o = ω ^ ω ^ a

Next tactic:
rcases principal_add_iff_zero_or_omega_opow.1 (principal_add_of_principal_mul ho ho₂.ne') with
      (rfl | ⟨a, rfl⟩)
/-- The main characterization theorem for multiplicative principal ordinals. -/
theorem principal_mul_iff_le_two_or_omega_opow_opow {o : Ordinal} :
    Principal (· * ·) o ↔ o ≤ 2 ∨ ∃ a : Ordinal, o = (omega^omega^a) := by
  refine' ⟨fun ho => _, _⟩
  · rcases le_or_lt o 2 with ho₂ | ho₂
    · exact Or.inl ho₂
    rcases principal_add_iff_zero_or_omega_opow.1 (principal_add_of_principal_mul ho ho₂.ne') with
      (rfl | ⟨a, rfl⟩)
    · 

Proof state:
case refine'_1.inr.inl
ho : Principal (fun x x_1 => x * x_1) 0
ho₂ : 2 < 0
⊢ 0 ≤ 2 ∨ ∃ a, 0 = ω ^ ω ^ a

Next tactic:
exact (Ordinal.not_lt_zero 2 ho₂).elim
/-- The main characterization theorem for multiplicative principal ordinals. -/
theorem principal_mul_iff_le_two_or_omega_opow_opow {o : Ordinal} :
    Principal (· * ·) o ↔ o ≤ 2 ∨ ∃ a : Ordinal, o = (omega^omega^a) := by
  refine' ⟨fun ho => _, _⟩
  · rcases le_or_lt o 2 with ho₂ | ho₂
    · exact Or.inl ho₂
    rcases principal_add_iff_zero_or_omega_opow.1 (principal_add_of_principal_mul ho ho₂.ne') with
      (rfl | ⟨a, rfl⟩)
    · exact (Ordinal.not_lt_zero 2 ho₂).elim
    

Proof state:
case refine'_1.inr.inr.intro
a : Ordinal.{u_1}
ho : Principal (fun x x_1 => x * x_1) (ω ^ a)
ho₂ : 2 < ω ^ a
⊢ ω ^ a ≤ 2 ∨ ∃ a_1, ω ^ a = ω ^ ω ^ a_1

Next tactic:
rcases principal_add_iff_zero_or_omega_opow.1
        (principal_add_of_principal_mul_opow one_lt_omega ho) with
      (rfl | ⟨b, rfl⟩)
/-- The main characterization theorem for multiplicative principal ordinals. -/
theorem principal_mul_iff_le_two_or_omega_opow_opow {o : Ordinal} :
    Principal (· * ·) o ↔ o ≤ 2 ∨ ∃ a : Ordinal, o = (omega^omega^a) := by
  refine' ⟨fun ho => _, _⟩
  · rcases le_or_lt o 2 with ho₂ | ho₂
    · exact Or.inl ho₂
    rcases principal_add_iff_zero_or_omega_opow.1 (principal_add_of_principal_mul ho ho₂.ne') with
      (rfl | ⟨a, rfl⟩)
    · exact (Ordinal.not_lt_zero 2 ho₂).elim
    rcases principal_add_iff_zero_or_omega_opow.1
        (principal_add_of_principal_mul_opow one_lt_omega ho) with
      (rfl | ⟨b, rfl⟩)
    · 

Proof state:
case refine'_1.inr.inr.intro.inl
ho : Principal (fun x x_1 => x * x_1) (ω ^ 0)
ho₂ : 2 < ω ^ 0
⊢ ω ^ 0 ≤ 2 ∨ ∃ a, ω ^ 0 = ω ^ ω ^ a

Next tactic:
left
/-- The main characterization theorem for multiplicative principal ordinals. -/
theorem principal_mul_iff_le_two_or_omega_opow_opow {o : Ordinal} :
    Principal (· * ·) o ↔ o ≤ 2 ∨ ∃ a : Ordinal, o = (omega^omega^a) := by
  refine' ⟨fun ho => _, _⟩
  · rcases le_or_lt o 2 with ho₂ | ho₂
    · exact Or.inl ho₂
    rcases principal_add_iff_zero_or_omega_opow.1 (principal_add_of_principal_mul ho ho₂.ne') with
      (rfl | ⟨a, rfl⟩)
    · exact (Ordinal.not_lt_zero 2 ho₂).elim
    rcases principal_add_iff_zero_or_omega_opow.1
        (principal_add_of_principal_mul_opow one_lt_omega ho) with
      (rfl | ⟨b, rfl⟩)
    · left
      

Proof state:
case refine'_1.inr.inr.intro.inl.h
ho : Principal (fun x x_1 => x * x_1) (ω ^ 0)
ho₂ : 2 < ω ^ 0
⊢ ω ^ 0 ≤ 2

Next tactic:
simpa using one_le_two
/-- The main characterization theorem for multiplicative principal ordinals. -/
theorem principal_mul_iff_le_two_or_omega_opow_opow {o : Ordinal} :
    Principal (· * ·) o ↔ o ≤ 2 ∨ ∃ a : Ordinal, o = (omega^omega^a) := by
  refine' ⟨fun ho => _, _⟩
  · rcases le_or_lt o 2 with ho₂ | ho₂
    · exact Or.inl ho₂
    rcases principal_add_iff_zero_or_omega_opow.1 (principal_add_of_principal_mul ho ho₂.ne') with
      (rfl | ⟨a, rfl⟩)
    · exact (Ordinal.not_lt_zero 2 ho₂).elim
    rcases principal_add_iff_zero_or_omega_opow.1
        (principal_add_of_principal_mul_opow one_lt_omega ho) with
      (rfl | ⟨b, rfl⟩)
    · left
      simpa using one_le_two
    

Proof state:
case refine'_1.inr.inr.intro.inr.intro
b : Ordinal.{u_1}
ho : Principal (fun x x_1 => x * x_1) (ω ^ ω ^ b)
ho₂ : 2 < ω ^ ω ^ b
⊢ ω ^ ω ^ b ≤ 2 ∨ ∃ a, ω ^ ω ^ b = ω ^ ω ^ a

Next tactic:
exact Or.inr ⟨b, rfl⟩
/-- The main characterization theorem for multiplicative principal ordinals. -/
theorem principal_mul_iff_le_two_or_omega_opow_opow {o : Ordinal} :
    Principal (· * ·) o ↔ o ≤ 2 ∨ ∃ a : Ordinal, o = (omega^omega^a) := by
  refine' ⟨fun ho => _, _⟩
  · rcases le_or_lt o 2 with ho₂ | ho₂
    · exact Or.inl ho₂
    rcases principal_add_iff_zero_or_omega_opow.1 (principal_add_of_principal_mul ho ho₂.ne') with
      (rfl | ⟨a, rfl⟩)
    · exact (Ordinal.not_lt_zero 2 ho₂).elim
    rcases principal_add_iff_zero_or_omega_opow.1
        (principal_add_of_principal_mul_opow one_lt_omega ho) with
      (rfl | ⟨b, rfl⟩)
    · left
      simpa using one_le_two
    exact Or.inr ⟨b, rfl⟩
  · 

Proof state:
case refine'_2
o : Ordinal.{u_1}
⊢ (o ≤ 2 ∨ ∃ a, o = ω ^ ω ^ a) → Principal (fun x x_1 => x * x_1) o

Next tactic:
rintro (ho₂ | ⟨a, rfl⟩)
/-- The main characterization theorem for multiplicative principal ordinals. -/
theorem principal_mul_iff_le_two_or_omega_opow_opow {o : Ordinal} :
    Principal (· * ·) o ↔ o ≤ 2 ∨ ∃ a : Ordinal, o = (omega^omega^a) := by
  refine' ⟨fun ho => _, _⟩
  · rcases le_or_lt o 2 with ho₂ | ho₂
    · exact Or.inl ho₂
    rcases principal_add_iff_zero_or_omega_opow.1 (principal_add_of_principal_mul ho ho₂.ne') with
      (rfl | ⟨a, rfl⟩)
    · exact (Ordinal.not_lt_zero 2 ho₂).elim
    rcases principal_add_iff_zero_or_omega_opow.1
        (principal_add_of_principal_mul_opow one_lt_omega ho) with
      (rfl | ⟨b, rfl⟩)
    · left
      simpa using one_le_two
    exact Or.inr ⟨b, rfl⟩
  · rintro (ho₂ | ⟨a, rfl⟩)
    · 

Proof state:
case refine'_2.inl
o : Ordinal.{u_1}
ho₂ : o ≤ 2
⊢ Principal (fun x x_1 => x * x_1) o

Next tactic:
exact principal_mul_of_le_two ho₂
/-- The main characterization theorem for multiplicative principal ordinals. -/
theorem principal_mul_iff_le_two_or_omega_opow_opow {o : Ordinal} :
    Principal (· * ·) o ↔ o ≤ 2 ∨ ∃ a : Ordinal, o = (omega^omega^a) := by
  refine' ⟨fun ho => _, _⟩
  · rcases le_or_lt o 2 with ho₂ | ho₂
    · exact Or.inl ho₂
    rcases principal_add_iff_zero_or_omega_opow.1 (principal_add_of_principal_mul ho ho₂.ne') with
      (rfl | ⟨a, rfl⟩)
    · exact (Ordinal.not_lt_zero 2 ho₂).elim
    rcases principal_add_iff_zero_or_omega_opow.1
        (principal_add_of_principal_mul_opow one_lt_omega ho) with
      (rfl | ⟨b, rfl⟩)
    · left
      simpa using one_le_two
    exact Or.inr ⟨b, rfl⟩
  · rintro (ho₂ | ⟨a, rfl⟩)
    · exact principal_mul_of_le_two ho₂
    · 

Proof state:
case refine'_2.inr.intro
a : Ordinal.{u_1}
⊢ Principal (fun x x_1 => x * x_1) (ω ^ ω ^ a)

Next tactic:
exact principal_mul_omega_opow_opow a
theorem mul_omega_dvd {a : Ordinal} (a0 : 0 < a) (ha : a < omega) : ∀ {b}, omega ∣ b → a * b = b
  | _, ⟨b, rfl⟩ => by 

Proof state:
a : Ordinal.{u_1}
a0 : 0 < a
ha : a < ω
b : Ordinal.{u_1}
⊢ a * (ω * b) = ω * b

Next tactic:
rw [← mul_assoc, mul_omega a0 ha]
theorem mul_eq_opow_log_succ {a b : Ordinal.{u}} (ha : a ≠ 0) (hb : Principal (· * ·) b)
    (hb₂ : 2 < b) : a * b = (b^succ (log b a)) := by
  

Proof state:
a b : Ordinal.{u}
ha : a ≠ 0
hb : Principal (fun x x_1 => x * x_1) b
hb₂ : 2 < b
⊢ a * b = b ^ succ (log b a)

Next tactic:
apply le_antisymm
theorem mul_eq_opow_log_succ {a b : Ordinal.{u}} (ha : a ≠ 0) (hb : Principal (· * ·) b)
    (hb₂ : 2 < b) : a * b = (b^succ (log b a)) := by
  apply le_antisymm
  · 

Proof state:
case a
a b : Ordinal.{u}
ha : a ≠ 0
hb : Principal (fun x x_1 => x * x_1) b
hb₂ : 2 < b
⊢ a * b ≤ b ^ succ (log b a)

Next tactic:
have hbl := principal_mul_isLimit hb₂ hb
theorem mul_eq_opow_log_succ {a b : Ordinal.{u}} (ha : a ≠ 0) (hb : Principal (· * ·) b)
    (hb₂ : 2 < b) : a * b = (b^succ (log b a)) := by
  apply le_antisymm
  · have hbl := principal_mul_isLimit hb₂ hb
    

Proof state:
case a
a b : Ordinal.{u}
ha : a ≠ 0
hb : Principal (fun x x_1 => x * x_1) b
hb₂ : 2 < b
hbl : IsLimit b
⊢ a * b ≤ b ^ succ (log b a)

Next tactic:
rw [← IsNormal.bsup_eq.{u, u} (mul_isNormal (Ordinal.pos_iff_ne_zero.2 ha)) hbl, bsup_le_iff]
theorem mul_eq_opow_log_succ {a b : Ordinal.{u}} (ha : a ≠ 0) (hb : Principal (· * ·) b)
    (hb₂ : 2 < b) : a * b = (b^succ (log b a)) := by
  apply le_antisymm
  · have hbl := principal_mul_isLimit hb₂ hb
    rw [← IsNormal.bsup_eq.{u, u} (mul_isNormal (Ordinal.pos_iff_ne_zero.2 ha)) hbl, bsup_le_iff]
    

Proof state:
case a
a b : Ordinal.{u}
ha : a ≠ 0
hb : Principal (fun x x_1 => x * x_1) b
hb₂ : 2 < b
hbl : IsLimit b
⊢ ∀ i < b, a * i ≤ b ^ succ (log b a)

Next tactic:
intro c hcb
theorem mul_eq_opow_log_succ {a b : Ordinal.{u}} (ha : a ≠ 0) (hb : Principal (· * ·) b)
    (hb₂ : 2 < b) : a * b = (b^succ (log b a)) := by
  apply le_antisymm
  · have hbl := principal_mul_isLimit hb₂ hb
    rw [← IsNormal.bsup_eq.{u, u} (mul_isNormal (Ordinal.pos_iff_ne_zero.2 ha)) hbl, bsup_le_iff]
    intro c hcb
    

Proof state:
case a
a b : Ordinal.{u}
ha : a ≠ 0
hb : Principal (fun x x_1 => x * x_1) b
hb₂ : 2 < b
hbl : IsLimit b
c : Ordinal.{u}
hcb : c < b
⊢ a * c ≤ b ^ succ (log b a)

Next tactic:
have hb₁ : 1 < b := (lt_succ 1).trans (by simpa using hb₂)
theorem mul_eq_opow_log_succ {a b : Ordinal.{u}} (ha : a ≠ 0) (hb : Principal (· * ·) b)
    (hb₂ : 2 < b) : a * b = (b^succ (log b a)) := by
  apply le_antisymm
  · have hbl := principal_mul_isLimit hb₂ hb
    rw [← IsNormal.bsup_eq.{u, u} (mul_isNormal (Ordinal.pos_iff_ne_zero.2 ha)) hbl, bsup_le_iff]
    intro c hcb
    have hb₁ : 1 < b := (lt_succ 1).trans (by 

Proof state:
a b : Ordinal.{u}
ha : a ≠ 0
hb : Principal (fun x x_1 => x * x_1) b
hb₂ : 2 < b
hbl : IsLimit b
c : Ordinal.{u}
hcb : c < b
⊢ succ 1 < b

Next tactic:
simpa using hb₂
theorem mul_eq_opow_log_succ {a b : Ordinal.{u}} (ha : a ≠ 0) (hb : Principal (· * ·) b)
    (hb₂ : 2 < b) : a * b = (b^succ (log b a)) := by
  apply le_antisymm
  · have hbl := principal_mul_isLimit hb₂ hb
    rw [← IsNormal.bsup_eq.{u, u} (mul_isNormal (Ordinal.pos_iff_ne_zero.2 ha)) hbl, bsup_le_iff]
    intro c hcb
    have hb₁ : 1 < b := (lt_succ 1).trans (by simpa using hb₂)
    

Proof state:
case a
a b : Ordinal.{u}
ha : a ≠ 0
hb : Principal (fun x x_1 => x * x_1) b
hb₂ : 2 < b
hbl : IsLimit b
c : Ordinal.{u}
hcb : c < b
hb₁ : 1 < b
⊢ a * c ≤ b ^ succ (log b a)

Next tactic:
have hbo₀ : (b^b.log a) ≠ 0 := Ordinal.pos_iff_ne_zero.1 (opow_pos _ (zero_lt_one.trans hb₁))
theorem mul_eq_opow_log_succ {a b : Ordinal.{u}} (ha : a ≠ 0) (hb : Principal (· * ·) b)
    (hb₂ : 2 < b) : a * b = (b^succ (log b a)) := by
  apply le_antisymm
  · have hbl := principal_mul_isLimit hb₂ hb
    rw [← IsNormal.bsup_eq.{u, u} (mul_isNormal (Ordinal.pos_iff_ne_zero.2 ha)) hbl, bsup_le_iff]
    intro c hcb
    have hb₁ : 1 < b := (lt_succ 1).trans (by simpa using hb₂)
    have hbo₀ : (b^b.log a) ≠ 0 := Ordinal.pos_iff_ne_zero.1 (opow_pos _ (zero_lt_one.trans hb₁))
    

Proof state:
case a
a b : Ordinal.{u}
ha : a ≠ 0
hb : Principal (fun x x_1 => x * x_1) b
hb₂ : 2 < b
hbl : IsLimit b
c : Ordinal.{u}
hcb : c < b
hb₁ : 1 < b
hbo₀ : b ^ log b a ≠ 0
⊢ a * c ≤ b ^ succ (log b a)

Next tactic:
apply le_trans (mul_le_mul_right' (le_of_lt (lt_mul_succ_div a hbo₀)) c)
theorem mul_eq_opow_log_succ {a b : Ordinal.{u}} (ha : a ≠ 0) (hb : Principal (· * ·) b)
    (hb₂ : 2 < b) : a * b = (b^succ (log b a)) := by
  apply le_antisymm
  · have hbl := principal_mul_isLimit hb₂ hb
    rw [← IsNormal.bsup_eq.{u, u} (mul_isNormal (Ordinal.pos_iff_ne_zero.2 ha)) hbl, bsup_le_iff]
    intro c hcb
    have hb₁ : 1 < b := (lt_succ 1).trans (by simpa using hb₂)
    have hbo₀ : (b^b.log a) ≠ 0 := Ordinal.pos_iff_ne_zero.1 (opow_pos _ (zero_lt_one.trans hb₁))
    apply le_trans (mul_le_mul_right' (le_of_lt (lt_mul_succ_div a hbo₀)) c)
    

Proof state:
case a
a b : Ordinal.{u}
ha : a ≠ 0
hb : Principal (fun x x_1 => x * x_1) b
hb₂ : 2 < b
hbl : IsLimit b
c : Ordinal.{u}
hcb : c < b
hb₁ : 1 < b
hbo₀ : b ^ log b a ≠ 0
⊢ b ^ log b a * succ (a / b ^ log b a) * c ≤ b ^ succ (log b a)

Next tactic:
rw [mul_assoc, opow_succ]
theorem mul_eq_opow_log_succ {a b : Ordinal.{u}} (ha : a ≠ 0) (hb : Principal (· * ·) b)
    (hb₂ : 2 < b) : a * b = (b^succ (log b a)) := by
  apply le_antisymm
  · have hbl := principal_mul_isLimit hb₂ hb
    rw [← IsNormal.bsup_eq.{u, u} (mul_isNormal (Ordinal.pos_iff_ne_zero.2 ha)) hbl, bsup_le_iff]
    intro c hcb
    have hb₁ : 1 < b := (lt_succ 1).trans (by simpa using hb₂)
    have hbo₀ : (b^b.log a) ≠ 0 := Ordinal.pos_iff_ne_zero.1 (opow_pos _ (zero_lt_one.trans hb₁))
    apply le_trans (mul_le_mul_right' (le_of_lt (lt_mul_succ_div a hbo₀)) c)
    rw [mul_assoc, opow_succ]
    

Proof state:
case a
a b : Ordinal.{u}
ha : a ≠ 0
hb : Principal (fun x x_1 => x * x_1) b
hb₂ : 2 < b
hbl : IsLimit b
c : Ordinal.{u}
hcb : c < b
hb₁ : 1 < b
hbo₀ : b ^ log b a ≠ 0
⊢ b ^ log b a * (succ (a / b ^ log b a) * c) ≤ b ^ log b a * b

Next tactic:
refine' mul_le_mul_left' (le_of_lt (hb (hbl.2 _ _) hcb)) _
theorem mul_eq_opow_log_succ {a b : Ordinal.{u}} (ha : a ≠ 0) (hb : Principal (· * ·) b)
    (hb₂ : 2 < b) : a * b = (b^succ (log b a)) := by
  apply le_antisymm
  · have hbl := principal_mul_isLimit hb₂ hb
    rw [← IsNormal.bsup_eq.{u, u} (mul_isNormal (Ordinal.pos_iff_ne_zero.2 ha)) hbl, bsup_le_iff]
    intro c hcb
    have hb₁ : 1 < b := (lt_succ 1).trans (by simpa using hb₂)
    have hbo₀ : (b^b.log a) ≠ 0 := Ordinal.pos_iff_ne_zero.1 (opow_pos _ (zero_lt_one.trans hb₁))
    apply le_trans (mul_le_mul_right' (le_of_lt (lt_mul_succ_div a hbo₀)) c)
    rw [mul_assoc, opow_succ]
    refine' mul_le_mul_left' (le_of_lt (hb (hbl.2 _ _) hcb)) _
    

Proof state:
case a
a b : Ordinal.{u}
ha : a ≠ 0
hb : Principal (fun x x_1 => x * x_1) b
hb₂ : 2 < b
hbl : IsLimit b
c : Ordinal.{u}
hcb : c < b
hb₁ : 1 < b
hbo₀ : b ^ log b a ≠ 0
⊢ a / b ^ log b a < b

Next tactic:
rw [div_lt hbo₀, ← opow_succ]
theorem mul_eq_opow_log_succ {a b : Ordinal.{u}} (ha : a ≠ 0) (hb : Principal (· * ·) b)
    (hb₂ : 2 < b) : a * b = (b^succ (log b a)) := by
  apply le_antisymm
  · have hbl := principal_mul_isLimit hb₂ hb
    rw [← IsNormal.bsup_eq.{u, u} (mul_isNormal (Ordinal.pos_iff_ne_zero.2 ha)) hbl, bsup_le_iff]
    intro c hcb
    have hb₁ : 1 < b := (lt_succ 1).trans (by simpa using hb₂)
    have hbo₀ : (b^b.log a) ≠ 0 := Ordinal.pos_iff_ne_zero.1 (opow_pos _ (zero_lt_one.trans hb₁))
    apply le_trans (mul_le_mul_right' (le_of_lt (lt_mul_succ_div a hbo₀)) c)
    rw [mul_assoc, opow_succ]
    refine' mul_le_mul_left' (le_of_lt (hb (hbl.2 _ _) hcb)) _
    rw [div_lt hbo₀, ← opow_succ]
    

Proof state:
case a
a b : Ordinal.{u}
ha : a ≠ 0
hb : Principal (fun x x_1 => x * x_1) b
hb₂ : 2 < b
hbl : IsLimit b
c : Ordinal.{u}
hcb : c < b
hb₁ : 1 < b
hbo₀ : b ^ log b a ≠ 0
⊢ a < b ^ succ (log b a)

Next tactic:
exact lt_opow_succ_log_self hb₁ _
theorem mul_eq_opow_log_succ {a b : Ordinal.{u}} (ha : a ≠ 0) (hb : Principal (· * ·) b)
    (hb₂ : 2 < b) : a * b = (b^succ (log b a)) := by
  apply le_antisymm
  · have hbl := principal_mul_isLimit hb₂ hb
    rw [← IsNormal.bsup_eq.{u, u} (mul_isNormal (Ordinal.pos_iff_ne_zero.2 ha)) hbl, bsup_le_iff]
    intro c hcb
    have hb₁ : 1 < b := (lt_succ 1).trans (by simpa using hb₂)
    have hbo₀ : (b^b.log a) ≠ 0 := Ordinal.pos_iff_ne_zero.1 (opow_pos _ (zero_lt_one.trans hb₁))
    apply le_trans (mul_le_mul_right' (le_of_lt (lt_mul_succ_div a hbo₀)) c)
    rw [mul_assoc, opow_succ]
    refine' mul_le_mul_left' (le_of_lt (hb (hbl.2 _ _) hcb)) _
    rw [div_lt hbo₀, ← opow_succ]
    exact lt_opow_succ_log_self hb₁ _
  · 

Proof state:
case a
a b : Ordinal.{u}
ha : a ≠ 0
hb : Principal (fun x x_1 => x * x_1) b
hb₂ : 2 < b
⊢ b ^ succ (log b a) ≤ a * b

Next tactic:
rw [opow_succ]
theorem mul_eq_opow_log_succ {a b : Ordinal.{u}} (ha : a ≠ 0) (hb : Principal (· * ·) b)
    (hb₂ : 2 < b) : a * b = (b^succ (log b a)) := by
  apply le_antisymm
  · have hbl := principal_mul_isLimit hb₂ hb
    rw [← IsNormal.bsup_eq.{u, u} (mul_isNormal (Ordinal.pos_iff_ne_zero.2 ha)) hbl, bsup_le_iff]
    intro c hcb
    have hb₁ : 1 < b := (lt_succ 1).trans (by simpa using hb₂)
    have hbo₀ : (b^b.log a) ≠ 0 := Ordinal.pos_iff_ne_zero.1 (opow_pos _ (zero_lt_one.trans hb₁))
    apply le_trans (mul_le_mul_right' (le_of_lt (lt_mul_succ_div a hbo₀)) c)
    rw [mul_assoc, opow_succ]
    refine' mul_le_mul_left' (le_of_lt (hb (hbl.2 _ _) hcb)) _
    rw [div_lt hbo₀, ← opow_succ]
    exact lt_opow_succ_log_self hb₁ _
  · rw [opow_succ]
    

Proof state:
case a
a b : Ordinal.{u}
ha : a ≠ 0
hb : Principal (fun x x_1 => x * x_1) b
hb₂ : 2 < b
⊢ b ^ log b a * b ≤ a * b

Next tactic:
exact mul_le_mul_right' (opow_log_le_self b ha) b
theorem principal_opow_omega : Principal (·^·) omega := fun a b ha hb =>
  match a, b, lt_omega.1 ha, lt_omega.1 hb with
  | _, _, ⟨m, rfl⟩, ⟨n, rfl⟩ => by
    

Proof state:
a b : Ordinal.{u_1}
m n : ℕ
ha : ↑m < ω
hb : ↑n < ω
⊢ (fun x x_1 => x ^ x_1) ↑m ↑n < ω

Next tactic:
simp_rw [← nat_cast_opow]
theorem principal_opow_omega : Principal (·^·) omega := fun a b ha hb =>
  match a, b, lt_omega.1 ha, lt_omega.1 hb with
  | _, _, ⟨m, rfl⟩, ⟨n, rfl⟩ => by
    simp_rw [← nat_cast_opow]
    

Proof state:
a b : Ordinal.{u_1}
m n : ℕ
ha : ↑m < ω
hb : ↑n < ω
⊢ ↑(m ^ n) < ω

Next tactic:
apply nat_lt_omega
private lemma and_imp_left_of_imp_imp {p q r : Prop} (h : r → p → q) : r ∧ p → r ∧ q := by 

Proof state:
p q r : Prop
h : r → p → q
⊢ r ∧ p → r ∧ q

Next tactic:
tauto
private theorem eventually_congr {α : Type*} {p q : α → Prop} {f : Filter α}
    (hq : ∀ (x : α), p x ↔ q x) : (∀ᶠ (x : α) in f, p x) ↔ ∀ᶠ (x : α) in f, q x := by
  

Proof state:
α : Type u_1
p q : α → Prop
f : Filter α
hq : ∀ (x : α), p x ↔ q x
⊢ (∀ᶠ (x : α) in f, p x) ↔ ∀ᶠ (x : α) in f, q x

Next tactic:
congr! 2
private theorem eventually_congr {α : Type*} {p q : α → Prop} {f : Filter α}
    (hq : ∀ (x : α), p x ↔ q x) : (∀ᶠ (x : α) in f, p x) ↔ ∀ᶠ (x : α) in f, q x := by
  congr! 2; 

Proof state:
case a.h.e'_2.h.a
α : Type u_1
p q : α → Prop
f : Filter α
hq : ∀ (x : α), p x ↔ q x
x✝ : α
⊢ p x✝ ↔ q x✝

Next tactic:
exact hq _
private theorem frequently_congr {α : Type*} {p q : α → Prop} {f : Filter α}
    (hq : ∀ (x : α), p x ↔ q x) : (∃ᶠ (x : α) in f, p x) ↔ ∃ᶠ (x : α) in f, q x := by
  

Proof state:
α : Type u_1
p q : α → Prop
f : Filter α
hq : ∀ (x : α), p x ↔ q x
⊢ (∃ᶠ (x : α) in f, p x) ↔ ∃ᶠ (x : α) in f, q x

Next tactic:
congr! 2
private theorem frequently_congr {α : Type*} {p q : α → Prop} {f : Filter α}
    (hq : ∀ (x : α), p x ↔ q x) : (∃ᶠ (x : α) in f, p x) ↔ ∃ᶠ (x : α) in f, q x := by
  congr! 2; 

Proof state:
case a.h.e'_2.h.a
α : Type u_1
p q : α → Prop
f : Filter α
hq : ∀ (x : α), p x ↔ q x
x✝ : α
⊢ p x✝ ↔ q x✝

Next tactic:
exact hq _
@[simp]
theorem Equiv.Perm.decomposeFin_symm_of_refl {n : ℕ} (p : Fin (n + 1)) :
    Equiv.Perm.decomposeFin.symm (p, Equiv.refl _) = swap 0 p := by
  

Proof state:
n : ℕ
p : Fin (n + 1)
⊢ decomposeFin.symm (p, Equiv.refl (Fin n)) = swap 0 p

Next tactic:
simp [Equiv.Perm.decomposeFin, Equiv.permCongr_def]
@[simp]
theorem Equiv.Perm.decomposeFin_symm_apply_zero {n : ℕ} (p : Fin (n + 1)) (e : Perm (Fin n)) :
    Equiv.Perm.decomposeFin.symm (p, e) 0 = p := by 

Proof state:
n : ℕ
p : Fin (n + 1)
e : Perm (Fin n)
⊢ (decomposeFin.symm (p, e)) 0 = p

Next tactic:
simp [Equiv.Perm.decomposeFin]