l3lab/ntp-mathlib huggingface dataset:
theorem frobenius_nnnorm_mul (A : Matrix l m α) (B : Matrix m n α) : ‖A * B‖₊ ≤ ‖A‖₊ * ‖B‖₊ := by
  simp_rw [frobenius_nnnorm_def, Matrix.mul_apply]
  rw [← NNReal.mul_rpow, @Finset.sum_comm _ n m, Finset.sum_mul_sum, Finset.sum_product]
  gcongr with i _ j
  rw [← NNReal.rpow_le_rpow_iff one_half_pos, ← NNReal.rpow_mul,
    mul_div_cancel' (1 : ℝ) two_ne_zero, NNReal.rpow_one, NNReal.mul_rpow]
  dsimp only
  

Proof state:
case h₁.h.h.h
R : Type u_1
l : Type u_2
m : Type u_3
n : Type u_4
α : Type u_5
β : Type u_6
inst✝³ : Fintype l
inst✝² : Fintype m
inst✝¹ : Fintype n
inst✝ : IsROrC α
A : Matrix l m α
B : Matrix m n α
i : l
a✝¹ : i ∈ Finset.univ
j : n
a✝ : j ∈ Finset.univ
⊢ ‖∑ j_1 : m, A i j_1 * B j_1 j‖₊ ≤ (∑ j : m, ‖A i j‖₊ ^ 2) ^ (1 / 2) * (∑ x : m, ‖B x j‖₊ ^ 2) ^ (1 / 2)

Next tactic:
have :=
    @nnnorm_inner_le_nnnorm α _ _ _ _ ((WithLp.equiv 2 <| _ → α).symm fun j => star (A i j))
      ((WithLp.equiv 2 <| _ → α).symm fun k => B k j)
theorem frobenius_nnnorm_mul (A : Matrix l m α) (B : Matrix m n α) : ‖A * B‖₊ ≤ ‖A‖₊ * ‖B‖₊ := by
  simp_rw [frobenius_nnnorm_def, Matrix.mul_apply]
  rw [← NNReal.mul_rpow, @Finset.sum_comm _ n m, Finset.sum_mul_sum, Finset.sum_product]
  gcongr with i _ j
  rw [← NNReal.rpow_le_rpow_iff one_half_pos, ← NNReal.rpow_mul,
    mul_div_cancel' (1 : ℝ) two_ne_zero, NNReal.rpow_one, NNReal.mul_rpow]
  dsimp only
  have :=
    @nnnorm_inner_le_nnnorm α _ _ _ _ ((WithLp.equiv 2 <| _ → α).symm fun j => star (A i j))
      ((WithLp.equiv 2 <| _ → α).symm fun k => B k j)
  

Proof state:
case h₁.h.h.h
R : Type u_1
l : Type u_2
m : Type u_3
n : Type u_4
α : Type u_5
β : Type u_6
inst✝³ : Fintype l
inst✝² : Fintype m
inst✝¹ : Fintype n
inst✝ : IsROrC α
A : Matrix l m α
B : Matrix m n α
i : l
a✝¹ : i ∈ Finset.univ
j : n
a✝ : j ∈ Finset.univ
this :
  ‖inner ((WithLp.equiv 2 (m → α)).symm fun j => star (A i j)) ((WithLp.equiv 2 (m → α)).symm fun k => B k j)‖₊ ≤
    ‖(WithLp.equiv 2 (m → α)).symm fun j => star (A i j)‖₊ * ‖(WithLp.equiv 2 (m → α)).symm fun k => B k j‖₊
⊢ ‖∑ j_1 : m, A i j_1 * B j_1 j‖₊ ≤ (∑ j : m, ‖A i j‖₊ ^ 2) ^ (1 / 2) * (∑ x : m, ‖B x j‖₊ ^ 2) ^ (1 / 2)

Next tactic:
simpa only [WithLp.equiv_symm_pi_apply, PiLp.inner_apply, IsROrC.inner_apply, starRingEnd_apply,
    Pi.nnnorm_def, PiLp.nnnorm_eq_of_L2, star_star, nnnorm_star, NNReal.sqrt_eq_rpow,
    NNReal.rpow_two] using this
theorem dvd_of_dvd_pow (hp : Prime p) {a : α} {n : ℕ} (h : p ∣ a ^ n) : p ∣ a := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CommMonoidWithZero α
p : α
hp✝ hp : Prime p
a : α
n : ℕ
h : p ∣ a ^ n
⊢ p ∣ a

Next tactic:
induction' n with n ih
theorem dvd_of_dvd_pow (hp : Prime p) {a : α} {n : ℕ} (h : p ∣ a ^ n) : p ∣ a := by
  induction' n with n ih
  · 

Proof state:
case zero
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CommMonoidWithZero α
p : α
hp✝ hp : Prime p
a : α
h : p ∣ a ^ Nat.zero
⊢ p ∣ a

Next tactic:
rw [pow_zero] at h
theorem dvd_of_dvd_pow (hp : Prime p) {a : α} {n : ℕ} (h : p ∣ a ^ n) : p ∣ a := by
  induction' n with n ih
  · rw [pow_zero] at h
    

Proof state:
case zero
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CommMonoidWithZero α
p : α
hp✝ hp : Prime p
a : α
h : p ∣ 1
⊢ p ∣ a

Next tactic:
have := isUnit_of_dvd_one h
theorem dvd_of_dvd_pow (hp : Prime p) {a : α} {n : ℕ} (h : p ∣ a ^ n) : p ∣ a := by
  induction' n with n ih
  · rw [pow_zero] at h
    have := isUnit_of_dvd_one h
    

Proof state:
case zero
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CommMonoidWithZero α
p : α
hp✝ hp : Prime p
a : α
h : p ∣ 1
this : IsUnit p
⊢ p ∣ a

Next tactic:
have := not_unit hp
theorem dvd_of_dvd_pow (hp : Prime p) {a : α} {n : ℕ} (h : p ∣ a ^ n) : p ∣ a := by
  induction' n with n ih
  · rw [pow_zero] at h
    have := isUnit_of_dvd_one h
    have := not_unit hp
    

Proof state:
case zero
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CommMonoidWithZero α
p : α
hp✝ hp : Prime p
a : α
h : p ∣ 1
this✝ : IsUnit p
this : ¬IsUnit p
⊢ p ∣ a

Next tactic:
contradiction
theorem dvd_of_dvd_pow (hp : Prime p) {a : α} {n : ℕ} (h : p ∣ a ^ n) : p ∣ a := by
  induction' n with n ih
  · rw [pow_zero] at h
    have := isUnit_of_dvd_one h
    have := not_unit hp
    contradiction
  

Proof state:
case succ
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CommMonoidWithZero α
p : α
hp✝ hp : Prime p
a : α
n : ℕ
ih : p ∣ a ^ n → p ∣ a
h : p ∣ a ^ Nat.succ n
⊢ p ∣ a

Next tactic:
rw [pow_succ] at h
theorem dvd_of_dvd_pow (hp : Prime p) {a : α} {n : ℕ} (h : p ∣ a ^ n) : p ∣ a := by
  induction' n with n ih
  · rw [pow_zero] at h
    have := isUnit_of_dvd_one h
    have := not_unit hp
    contradiction
  rw [pow_succ] at h
  

Proof state:
case succ
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CommMonoidWithZero α
p : α
hp✝ hp : Prime p
a : α
n : ℕ
ih : p ∣ a ^ n → p ∣ a
h : p ∣ a * a ^ n
⊢ p ∣ a

Next tactic:
cases' dvd_or_dvd hp h with dvd_a dvd_pow
theorem dvd_of_dvd_pow (hp : Prime p) {a : α} {n : ℕ} (h : p ∣ a ^ n) : p ∣ a := by
  induction' n with n ih
  · rw [pow_zero] at h
    have := isUnit_of_dvd_one h
    have := not_unit hp
    contradiction
  rw [pow_succ] at h
  cases' dvd_or_dvd hp h with dvd_a dvd_pow
  · 

Proof state:
case succ.inl
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CommMonoidWithZero α
p : α
hp✝ hp : Prime p
a : α
n : ℕ
ih : p ∣ a ^ n → p ∣ a
h : p ∣ a * a ^ n
dvd_a : p ∣ a
⊢ p ∣ a

Next tactic:
assumption
theorem dvd_of_dvd_pow (hp : Prime p) {a : α} {n : ℕ} (h : p ∣ a ^ n) : p ∣ a := by
  induction' n with n ih
  · rw [pow_zero] at h
    have := isUnit_of_dvd_one h
    have := not_unit hp
    contradiction
  rw [pow_succ] at h
  cases' dvd_or_dvd hp h with dvd_a dvd_pow
  · assumption
  

Proof state:
case succ.inr
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CommMonoidWithZero α
p : α
hp✝ hp : Prime p
a : α
n : ℕ
ih : p ∣ a ^ n → p ∣ a
h : p ∣ a * a ^ n
dvd_pow : p ∣ a ^ n
⊢ p ∣ a

Next tactic:
exact ih dvd_pow
theorem comap_prime (hinv : ∀ a, g (f a : β) = a) (hp : Prime (f p)) : Prime p :=
  ⟨fun h => hp.1 <| by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝³ : CommMonoidWithZero α
inst✝² : CommMonoidWithZero β
F : Type u_5
G : Type u_6
inst✝¹ : MonoidWithZeroHomClass F α β
inst✝ : MulHomClass G β α
f : F
g : G
p : α
hinv : ∀ (a : α), g (f a) = a
hp : Prime (f p)
h : p = 0
⊢ f p = 0

Next tactic:
simp [h]
theorem comap_prime (hinv : ∀ a, g (f a : β) = a) (hp : Prime (f p)) : Prime p :=
  ⟨fun h => hp.1 <| by simp [h], fun h => hp.2.1 <| h.map f, fun a b h => by
    

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝³ : CommMonoidWithZero α
inst✝² : CommMonoidWithZero β
F : Type u_5
G : Type u_6
inst✝¹ : MonoidWithZeroHomClass F α β
inst✝ : MulHomClass G β α
f : F
g : G
p : α
hinv : ∀ (a : α), g (f a) = a
hp : Prime (f p)
a b : α
h : p ∣ a * b
⊢ p ∣ a ∨ p ∣ b

Next tactic:
refine'
        (hp.2.2 (f a) (f b) <| by
              convert map_dvd f h
              simp).imp
          _ _
theorem comap_prime (hinv : ∀ a, g (f a : β) = a) (hp : Prime (f p)) : Prime p :=
  ⟨fun h => hp.1 <| by simp [h], fun h => hp.2.1 <| h.map f, fun a b h => by
    refine'
        (hp.2.2 (f a) (f b) <| by
              

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝³ : CommMonoidWithZero α
inst✝² : CommMonoidWithZero β
F : Type u_5
G : Type u_6
inst✝¹ : MonoidWithZeroHomClass F α β
inst✝ : MulHomClass G β α
f : F
g : G
p : α
hinv : ∀ (a : α), g (f a) = a
hp : Prime (f p)
a b : α
h : p ∣ a * b
⊢ f p ∣ f a * f b

Next tactic:
convert map_dvd f h
theorem comap_prime (hinv : ∀ a, g (f a : β) = a) (hp : Prime (f p)) : Prime p :=
  ⟨fun h => hp.1 <| by simp [h], fun h => hp.2.1 <| h.map f, fun a b h => by
    refine'
        (hp.2.2 (f a) (f b) <| by
              convert map_dvd f h
              

Proof state:
case h.e'_4
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝³ : CommMonoidWithZero α
inst✝² : CommMonoidWithZero β
F : Type u_5
G : Type u_6
inst✝¹ : MonoidWithZeroHomClass F α β
inst✝ : MulHomClass G β α
f : F
g : G
p : α
hinv : ∀ (a : α), g (f a) = a
hp : Prime (f p)
a b : α
h : p ∣ a * b
⊢ f a * f b = f (a * b)

Next tactic:
simp
theorem comap_prime (hinv : ∀ a, g (f a : β) = a) (hp : Prime (f p)) : Prime p :=
  ⟨fun h => hp.1 <| by simp [h], fun h => hp.2.1 <| h.map f, fun a b h => by
    refine'
        (hp.2.2 (f a) (f b) <| by
              convert map_dvd f h
              simp).imp
          _ _ <;>
      · 

Proof state:
case refine'_1
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝³ : CommMonoidWithZero α
inst✝² : CommMonoidWithZero β
F : Type u_5
G : Type u_6
inst✝¹ : MonoidWithZeroHomClass F α β
inst✝ : MulHomClass G β α
f : F
g : G
p : α
hinv : ∀ (a : α), g (f a) = a
hp : Prime (f p)
a b : α
h : p ∣ a * b
⊢ f p ∣ f a → p ∣ a

Next tactic:
intro h
theorem comap_prime (hinv : ∀ a, g (f a : β) = a) (hp : Prime (f p)) : Prime p :=
  ⟨fun h => hp.1 <| by simp [h], fun h => hp.2.1 <| h.map f, fun a b h => by
    refine'
        (hp.2.2 (f a) (f b) <| by
              convert map_dvd f h
              simp).imp
          _ _ <;>
      · intro h
        

Proof state:
case refine'_1
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝³ : CommMonoidWithZero α
inst✝² : CommMonoidWithZero β
F : Type u_5
G : Type u_6
inst✝¹ : MonoidWithZeroHomClass F α β
inst✝ : MulHomClass G β α
f : F
g : G
p : α
hinv : ∀ (a : α), g (f a) = a
hp : Prime (f p)
a b : α
h✝ : p ∣ a * b
h : f p ∣ f a
⊢ p ∣ a

Next tactic:
convert ← map_dvd g h
theorem comap_prime (hinv : ∀ a, g (f a : β) = a) (hp : Prime (f p)) : Prime p :=
  ⟨fun h => hp.1 <| by simp [h], fun h => hp.2.1 <| h.map f, fun a b h => by
    refine'
        (hp.2.2 (f a) (f b) <| by
              convert map_dvd f h
              simp).imp
          _ _ <;>
      · intro h
        convert ← map_dvd g h <;> 

Proof state:
case h.e'_3
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝³ : CommMonoidWithZero α
inst✝² : CommMonoidWithZero β
F : Type u_5
G : Type u_6
inst✝¹ : MonoidWithZeroHomClass F α β
inst✝ : MulHomClass G β α
f : F
g : G
p : α
hinv : ∀ (a : α), g (f a) = a
hp : Prime (f p)
a b : α
h✝ : p ∣ a * b
h : f p ∣ f a
⊢ g (f p) = p

Next tactic:
apply hinv
theorem comap_prime (hinv : ∀ a, g (f a : β) = a) (hp : Prime (f p)) : Prime p :=
  ⟨fun h => hp.1 <| by simp [h], fun h => hp.2.1 <| h.map f, fun a b h => by
    refine'
        (hp.2.2 (f a) (f b) <| by
              convert map_dvd f h
              simp).imp
          _ _ <;>
      · intro h
        convert ← map_dvd g h <;> 

Proof state:
case h.e'_4
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝³ : CommMonoidWithZero α
inst✝² : CommMonoidWithZero β
F : Type u_5
G : Type u_6
inst✝¹ : MonoidWithZeroHomClass F α β
inst✝ : MulHomClass G β α
f : F
g : G
p : α
hinv : ∀ (a : α), g (f a) = a
hp : Prime (f p)
a b : α
h✝ : p ∣ a * b
h : f p ∣ f a
⊢ g (f a) = a

Next tactic:
apply hinv
theorem comap_prime (hinv : ∀ a, g (f a : β) = a) (hp : Prime (f p)) : Prime p :=
  ⟨fun h => hp.1 <| by simp [h], fun h => hp.2.1 <| h.map f, fun a b h => by
    refine'
        (hp.2.2 (f a) (f b) <| by
              convert map_dvd f h
              simp).imp
          _ _ <;>
      · 

Proof state:
case refine'_2
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝³ : CommMonoidWithZero α
inst✝² : CommMonoidWithZero β
F : Type u_5
G : Type u_6
inst✝¹ : MonoidWithZeroHomClass F α β
inst✝ : MulHomClass G β α
f : F
g : G
p : α
hinv : ∀ (a : α), g (f a) = a
hp : Prime (f p)
a b : α
h : p ∣ a * b
⊢ f p ∣ f b → p ∣ b

Next tactic:
intro h
theorem comap_prime (hinv : ∀ a, g (f a : β) = a) (hp : Prime (f p)) : Prime p :=
  ⟨fun h => hp.1 <| by simp [h], fun h => hp.2.1 <| h.map f, fun a b h => by
    refine'
        (hp.2.2 (f a) (f b) <| by
              convert map_dvd f h
              simp).imp
          _ _ <;>
      · intro h
        

Proof state:
case refine'_2
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝³ : CommMonoidWithZero α
inst✝² : CommMonoidWithZero β
F : Type u_5
G : Type u_6
inst✝¹ : MonoidWithZeroHomClass F α β
inst✝ : MulHomClass G β α
f : F
g : G
p : α
hinv : ∀ (a : α), g (f a) = a
hp : Prime (f p)
a b : α
h✝ : p ∣ a * b
h : f p ∣ f b
⊢ p ∣ b

Next tactic:
convert ← map_dvd g h
theorem comap_prime (hinv : ∀ a, g (f a : β) = a) (hp : Prime (f p)) : Prime p :=
  ⟨fun h => hp.1 <| by simp [h], fun h => hp.2.1 <| h.map f, fun a b h => by
    refine'
        (hp.2.2 (f a) (f b) <| by
              convert map_dvd f h
              simp).imp
          _ _ <;>
      · intro h
        convert ← map_dvd g h <;> 

Proof state:
case h.e'_3
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝³ : CommMonoidWithZero α
inst✝² : CommMonoidWithZero β
F : Type u_5
G : Type u_6
inst✝¹ : MonoidWithZeroHomClass F α β
inst✝ : MulHomClass G β α
f : F
g : G
p : α
hinv : ∀ (a : α), g (f a) = a
hp : Prime (f p)
a b : α
h✝ : p ∣ a * b
h : f p ∣ f b
⊢ g (f p) = p

Next tactic:
apply hinv
theorem comap_prime (hinv : ∀ a, g (f a : β) = a) (hp : Prime (f p)) : Prime p :=
  ⟨fun h => hp.1 <| by simp [h], fun h => hp.2.1 <| h.map f, fun a b h => by
    refine'
        (hp.2.2 (f a) (f b) <| by
              convert map_dvd f h
              simp).imp
          _ _ <;>
      · intro h
        convert ← map_dvd g h <;> 

Proof state:
case h.e'_4
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝³ : CommMonoidWithZero α
inst✝² : CommMonoidWithZero β
F : Type u_5
G : Type u_6
inst✝¹ : MonoidWithZeroHomClass F α β
inst✝ : MulHomClass G β α
f : F
g : G
p : α
hinv : ∀ (a : α), g (f a) = a
hp : Prime (f p)
a b : α
h✝ : p ∣ a * b
h : f p ∣ f b
⊢ g (f b) = b

Next tactic:
apply hinv
theorem MulEquiv.prime_iff (e : α ≃* β) : Prime p ↔ Prime (e p) :=
  ⟨fun h => (comap_prime e.symm e fun a => by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝³ : CommMonoidWithZero α
inst✝² : CommMonoidWithZero β
F : Type u_5
G : Type u_6
inst✝¹ : MonoidWithZeroHomClass F α β
inst✝ : MulHomClass G β α
f : F
g : G
p : α
e : α ≃* β
h : Prime p
a : β
⊢ e ((symm e) a) = a

Next tactic:
simp
theorem MulEquiv.prime_iff (e : α ≃* β) : Prime p ↔ Prime (e p) :=
  ⟨fun h => (comap_prime e.symm e fun a => by simp) <| (e.symm_apply_apply p).substr h,
    comap_prime e e.symm fun a => by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝³ : CommMonoidWithZero α
inst✝² : CommMonoidWithZero β
F : Type u_5
G : Type u_6
inst✝¹ : MonoidWithZeroHomClass F α β
inst✝ : MulHomClass G β α
f : F
g : G
p : α
e : α ≃* β
a : α
⊢ (symm e) (e a) = a

Next tactic:
simp
theorem Prime.left_dvd_or_dvd_right_of_dvd_mul [CancelCommMonoidWithZero α] {p : α} (hp : Prime p)
    {a b : α} : a ∣ p * b → p ∣ a ∨ a ∣ b := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CancelCommMonoidWithZero α
p : α
hp : Prime p
a b : α
⊢ a ∣ p * b → p ∣ a ∨ a ∣ b

Next tactic:
rintro ⟨c, hc⟩
theorem Prime.left_dvd_or_dvd_right_of_dvd_mul [CancelCommMonoidWithZero α] {p : α} (hp : Prime p)
    {a b : α} : a ∣ p * b → p ∣ a ∨ a ∣ b := by
  rintro ⟨c, hc⟩
  

Proof state:
case intro
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CancelCommMonoidWithZero α
p : α
hp : Prime p
a b c : α
hc : p * b = a * c
⊢ p ∣ a ∨ a ∣ b

Next tactic:
rcases hp.2.2 a c (hc ▸ dvd_mul_right _ _) with (h | ⟨x, rfl⟩)
theorem Prime.left_dvd_or_dvd_right_of_dvd_mul [CancelCommMonoidWithZero α] {p : α} (hp : Prime p)
    {a b : α} : a ∣ p * b → p ∣ a ∨ a ∣ b := by
  rintro ⟨c, hc⟩
  rcases hp.2.2 a c (hc ▸ dvd_mul_right _ _) with (h | ⟨x, rfl⟩)
  · 

Proof state:
case intro.inl
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CancelCommMonoidWithZero α
p : α
hp : Prime p
a b c : α
hc : p * b = a * c
h : p ∣ a
⊢ p ∣ a ∨ a ∣ b

Next tactic:
exact Or.inl h
theorem Prime.left_dvd_or_dvd_right_of_dvd_mul [CancelCommMonoidWithZero α] {p : α} (hp : Prime p)
    {a b : α} : a ∣ p * b → p ∣ a ∨ a ∣ b := by
  rintro ⟨c, hc⟩
  rcases hp.2.2 a c (hc ▸ dvd_mul_right _ _) with (h | ⟨x, rfl⟩)
  · exact Or.inl h
  · 

Proof state:
case intro.inr.intro
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CancelCommMonoidWithZero α
p : α
hp : Prime p
a b x : α
hc : p * b = a * (p * x)
⊢ p ∣ a ∨ a ∣ b

Next tactic:
rw [mul_left_comm, mul_right_inj' hp.ne_zero] at hc
theorem Prime.left_dvd_or_dvd_right_of_dvd_mul [CancelCommMonoidWithZero α] {p : α} (hp : Prime p)
    {a b : α} : a ∣ p * b → p ∣ a ∨ a ∣ b := by
  rintro ⟨c, hc⟩
  rcases hp.2.2 a c (hc ▸ dvd_mul_right _ _) with (h | ⟨x, rfl⟩)
  · exact Or.inl h
  · rw [mul_left_comm, mul_right_inj' hp.ne_zero] at hc
    

Proof state:
case intro.inr.intro
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CancelCommMonoidWithZero α
p : α
hp : Prime p
a b x : α
hc : b = a * x
⊢ p ∣ a ∨ a ∣ b

Next tactic:
exact Or.inr (hc.symm ▸ dvd_mul_right _ _)
theorem Prime.pow_dvd_of_dvd_mul_left [CancelCommMonoidWithZero α] {p a b : α} (hp : Prime p)
    (n : ℕ) (h : ¬p ∣ a) (h' : p ^ n ∣ a * b) : p ^ n ∣ b := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CancelCommMonoidWithZero α
p a b : α
hp : Prime p
n : ℕ
h : ¬p ∣ a
h' : p ^ n ∣ a * b
⊢ p ^ n ∣ b

Next tactic:
induction' n with n ih
theorem Prime.pow_dvd_of_dvd_mul_left [CancelCommMonoidWithZero α] {p a b : α} (hp : Prime p)
    (n : ℕ) (h : ¬p ∣ a) (h' : p ^ n ∣ a * b) : p ^ n ∣ b := by
  induction' n with n ih
  · 

Proof state:
case zero
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CancelCommMonoidWithZero α
p a b : α
hp : Prime p
h : ¬p ∣ a
h' : p ^ Nat.zero ∣ a * b
⊢ p ^ Nat.zero ∣ b

Next tactic:
rw [pow_zero]
theorem Prime.pow_dvd_of_dvd_mul_left [CancelCommMonoidWithZero α] {p a b : α} (hp : Prime p)
    (n : ℕ) (h : ¬p ∣ a) (h' : p ^ n ∣ a * b) : p ^ n ∣ b := by
  induction' n with n ih
  · rw [pow_zero]
    

Proof state:
case zero
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CancelCommMonoidWithZero α
p a b : α
hp : Prime p
h : ¬p ∣ a
h' : p ^ Nat.zero ∣ a * b
⊢ 1 ∣ b

Next tactic:
exact one_dvd b
theorem Prime.pow_dvd_of_dvd_mul_left [CancelCommMonoidWithZero α] {p a b : α} (hp : Prime p)
    (n : ℕ) (h : ¬p ∣ a) (h' : p ^ n ∣ a * b) : p ^ n ∣ b := by
  induction' n with n ih
  · rw [pow_zero]
    exact one_dvd b
  · 

Proof state:
case succ
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CancelCommMonoidWithZero α
p a b : α
hp : Prime p
h : ¬p ∣ a
n : ℕ
ih : p ^ n ∣ a * b → p ^ n ∣ b
h' : p ^ Nat.succ n ∣ a * b
⊢ p ^ Nat.succ n ∣ b

Next tactic:
obtain ⟨c, rfl⟩ := ih (dvd_trans (pow_dvd_pow p n.le_succ) h')
theorem Prime.pow_dvd_of_dvd_mul_left [CancelCommMonoidWithZero α] {p a b : α} (hp : Prime p)
    (n : ℕ) (h : ¬p ∣ a) (h' : p ^ n ∣ a * b) : p ^ n ∣ b := by
  induction' n with n ih
  · rw [pow_zero]
    exact one_dvd b
  · obtain ⟨c, rfl⟩ := ih (dvd_trans (pow_dvd_pow p n.le_succ) h')
    

Proof state:
case succ.intro
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CancelCommMonoidWithZero α
p a : α
hp : Prime p
h : ¬p ∣ a
n : ℕ
c : α
ih : p ^ n ∣ a * (p ^ n * c) → p ^ n ∣ p ^ n * c
h' : p ^ Nat.succ n ∣ a * (p ^ n * c)
⊢ p ^ Nat.succ n ∣ p ^ n * c

Next tactic:
rw [pow_succ']
theorem Prime.pow_dvd_of_dvd_mul_left [CancelCommMonoidWithZero α] {p a b : α} (hp : Prime p)
    (n : ℕ) (h : ¬p ∣ a) (h' : p ^ n ∣ a * b) : p ^ n ∣ b := by
  induction' n with n ih
  · rw [pow_zero]
    exact one_dvd b
  · obtain ⟨c, rfl⟩ := ih (dvd_trans (pow_dvd_pow p n.le_succ) h')
    rw [pow_succ']
    

Proof state:
case succ.intro
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CancelCommMonoidWithZero α
p a : α
hp : Prime p
h : ¬p ∣ a
n : ℕ
c : α
ih : p ^ n ∣ a * (p ^ n * c) → p ^ n ∣ p ^ n * c
h' : p ^ Nat.succ n ∣ a * (p ^ n * c)
⊢ p ^ n * p ∣ p ^ n * c

Next tactic:
apply mul_dvd_mul_left _ ((hp.dvd_or_dvd _).resolve_left h)
theorem Prime.pow_dvd_of_dvd_mul_left [CancelCommMonoidWithZero α] {p a b : α} (hp : Prime p)
    (n : ℕ) (h : ¬p ∣ a) (h' : p ^ n ∣ a * b) : p ^ n ∣ b := by
  induction' n with n ih
  · rw [pow_zero]
    exact one_dvd b
  · obtain ⟨c, rfl⟩ := ih (dvd_trans (pow_dvd_pow p n.le_succ) h')
    rw [pow_succ']
    apply mul_dvd_mul_left _ ((hp.dvd_or_dvd _).resolve_left h)
    

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CancelCommMonoidWithZero α
p a : α
hp : Prime p
h : ¬p ∣ a
n : ℕ
c : α
ih : p ^ n ∣ a * (p ^ n * c) → p ^ n ∣ p ^ n * c
h' : p ^ Nat.succ n ∣ a * (p ^ n * c)
⊢ p ∣ a * c

Next tactic:
rwa [← mul_dvd_mul_iff_left (pow_ne_zero n hp.ne_zero), ← pow_succ', mul_left_comm]
theorem Prime.pow_dvd_of_dvd_mul_right [CancelCommMonoidWithZero α] {p a b : α} (hp : Prime p)
    (n : ℕ) (h : ¬p ∣ b) (h' : p ^ n ∣ a * b) : p ^ n ∣ a := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CancelCommMonoidWithZero α
p a b : α
hp : Prime p
n : ℕ
h : ¬p ∣ b
h' : p ^ n ∣ a * b
⊢ p ^ n ∣ a

Next tactic:
rw [mul_comm] at h'
theorem Prime.pow_dvd_of_dvd_mul_right [CancelCommMonoidWithZero α] {p a b : α} (hp : Prime p)
    (n : ℕ) (h : ¬p ∣ b) (h' : p ^ n ∣ a * b) : p ^ n ∣ a := by
  rw [mul_comm] at h'
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CancelCommMonoidWithZero α
p a b : α
hp : Prime p
n : ℕ
h : ¬p ∣ b
h' : p ^ n ∣ b * a
⊢ p ^ n ∣ a

Next tactic:
exact hp.pow_dvd_of_dvd_mul_left n h h'
theorem Prime.dvd_of_pow_dvd_pow_mul_pow_of_square_not_dvd [CancelCommMonoidWithZero α] {p a b : α}
    {n : ℕ} (hp : Prime p) (hpow : p ^ n.succ ∣ a ^ n.succ * b ^ n) (hb : ¬p ^ 2 ∣ b) : p ∣ a := by
  -- Suppose `p ∣ b`, write `b = p * x` and `hy : a ^ n.succ * b ^ n = p ^ n.succ * y`.
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CancelCommMonoidWithZero α
p a b : α
n : ℕ
hp : Prime p
hpow : p ^ Nat.succ n ∣ a ^ Nat.succ n * b ^ n
hb : ¬p ^ 2 ∣ b
⊢ p ∣ a

Next tactic:
cases' hp.dvd_or_dvd ((dvd_pow_self p (Nat.succ_ne_zero n)).trans hpow) with H hbdiv
theorem Prime.dvd_of_pow_dvd_pow_mul_pow_of_square_not_dvd [CancelCommMonoidWithZero α] {p a b : α}
    {n : ℕ} (hp : Prime p) (hpow : p ^ n.succ ∣ a ^ n.succ * b ^ n) (hb : ¬p ^ 2 ∣ b) : p ∣ a := by
  -- Suppose `p ∣ b`, write `b = p * x` and `hy : a ^ n.succ * b ^ n = p ^ n.succ * y`.
  cases' hp.dvd_or_dvd ((dvd_pow_self p (Nat.succ_ne_zero n)).trans hpow) with H hbdiv
  · 

Proof state:
case inl
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CancelCommMonoidWithZero α
p a b : α
n : ℕ
hp : Prime p
hpow : p ^ Nat.succ n ∣ a ^ Nat.succ n * b ^ n
hb : ¬p ^ 2 ∣ b
H : p ∣ a ^ Nat.succ n
⊢ p ∣ a

Next tactic:
exact hp.dvd_of_dvd_pow H
theorem Prime.dvd_of_pow_dvd_pow_mul_pow_of_square_not_dvd [CancelCommMonoidWithZero α] {p a b : α}
    {n : ℕ} (hp : Prime p) (hpow : p ^ n.succ ∣ a ^ n.succ * b ^ n) (hb : ¬p ^ 2 ∣ b) : p ∣ a := by
  -- Suppose `p ∣ b`, write `b = p * x` and `hy : a ^ n.succ * b ^ n = p ^ n.succ * y`.
  cases' hp.dvd_or_dvd ((dvd_pow_self p (Nat.succ_ne_zero n)).trans hpow) with H hbdiv
  · exact hp.dvd_of_dvd_pow H
  

Proof state:
case inr
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CancelCommMonoidWithZero α
p a b : α
n : ℕ
hp : Prime p
hpow : p ^ Nat.succ n ∣ a ^ Nat.succ n * b ^ n
hb : ¬p ^ 2 ∣ b
hbdiv : p ∣ b ^ n
⊢ p ∣ a

Next tactic:
obtain ⟨x, rfl⟩ := hp.dvd_of_dvd_pow hbdiv
theorem Prime.dvd_of_pow_dvd_pow_mul_pow_of_square_not_dvd [CancelCommMonoidWithZero α] {p a b : α}
    {n : ℕ} (hp : Prime p) (hpow : p ^ n.succ ∣ a ^ n.succ * b ^ n) (hb : ¬p ^ 2 ∣ b) : p ∣ a := by
  -- Suppose `p ∣ b`, write `b = p * x` and `hy : a ^ n.succ * b ^ n = p ^ n.succ * y`.
  cases' hp.dvd_or_dvd ((dvd_pow_self p (Nat.succ_ne_zero n)).trans hpow) with H hbdiv
  · exact hp.dvd_of_dvd_pow H
  obtain ⟨x, rfl⟩ := hp.dvd_of_dvd_pow hbdiv
  

Proof state:
case inr.intro
α : Type u_1
β : Type u_2
γ : Type u_3
δ : Type u_4
inst✝ : CancelCommMonoidWithZero α
p a : α
n : ℕ
hp : Prime p
x : α
hpow : p ^ Nat.succ n ∣ a ^ Nat.succ n * (p * x) ^ n
hb : ¬p ^ 2 ∣ p * x
hbdiv : p ∣ (p * x) ^ n
⊢ p ∣ a

Next tactic:
obtain ⟨y, hy⟩ := hpow