l3lab/ntp-mathlib huggingface dataset:
/-- There is a rational power between any two positive elements of an archimedean ordered field. -/
theorem exists_rat_pow_btwn {α : Type*} [LinearOrderedField α] [Archimedean α] (hn : n ≠ 0)
    {x y : α} (h : x < y) (hy : 0 < y) : ∃ q : ℚ, 0 < q ∧ x < (q : α) ^ n ∧ (q : α) ^ n < y := by
  obtain ⟨q₂, hx₂, hy₂⟩ := exists_rat_btwn (max_lt h hy)
  obtain ⟨q₁, hx₁, hq₁₂⟩ := exists_rat_btwn hx₂
  have : (0 : α) < q₂ := (le_max_right _ _).trans_lt hx₂
  norm_cast at hq₁₂ this
  obtain ⟨q, hq, hq₁, hq₂⟩ := exists_rat_pow_btwn_rat hn hq₁₂ this
  

Proof state:
case intro.intro.intro.intro.intro.intro.intro
z x✝ y✝ : ℝ
n : ℕ
α : Type u_1
inst✝¹ : LinearOrderedField α
inst✝ : Archimedean α
hn : n ≠ 0
x y : α
h : x < y
hy : 0 < y
q₂ : ℚ
hx₂ : max x 0 < ↑q₂
hy₂ : ↑q₂ < y
q₁ : ℚ
hx₁ : max x 0 < ↑q₁
hq₁₂ : q₁ < q₂
this : 0 < q₂
q : ℚ
hq : 0 < q
hq₁ : q₁ < q ^ n
hq₂ : q ^ n < q₂
⊢ ∃ q, 0 < q ∧ x < ↑q ^ n ∧ ↑q ^ n < y

Next tactic:
refine' ⟨q, hq, (le_max_left _ _).trans_lt <| hx₁.trans _, hy₂.trans' _⟩
/-- There is a rational power between any two positive elements of an archimedean ordered field. -/
theorem exists_rat_pow_btwn {α : Type*} [LinearOrderedField α] [Archimedean α] (hn : n ≠ 0)
    {x y : α} (h : x < y) (hy : 0 < y) : ∃ q : ℚ, 0 < q ∧ x < (q : α) ^ n ∧ (q : α) ^ n < y := by
  obtain ⟨q₂, hx₂, hy₂⟩ := exists_rat_btwn (max_lt h hy)
  obtain ⟨q₁, hx₁, hq₁₂⟩ := exists_rat_btwn hx₂
  have : (0 : α) < q₂ := (le_max_right _ _).trans_lt hx₂
  norm_cast at hq₁₂ this
  obtain ⟨q, hq, hq₁, hq₂⟩ := exists_rat_pow_btwn_rat hn hq₁₂ this
  refine' ⟨q, hq, (le_max_left _ _).trans_lt <| hx₁.trans _, hy₂.trans' _⟩ <;> 

Proof state:
case intro.intro.intro.intro.intro.intro.intro.refine'_1
z x✝ y✝ : ℝ
n : ℕ
α : Type u_1
inst✝¹ : LinearOrderedField α
inst✝ : Archimedean α
hn : n ≠ 0
x y : α
h : x < y
hy : 0 < y
q₂ : ℚ
hx₂ : max x 0 < ↑q₂
hy₂ : ↑q₂ < y
q₁ : ℚ
hx₁ : max x 0 < ↑q₁
hq₁₂ : q₁ < q₂
this : 0 < q₂
q : ℚ
hq : 0 < q
hq₁ : q₁ < q ^ n
hq₂ : q ^ n < q₂
⊢ ↑q₁ < ↑q ^ n

Next tactic:
assumption_mod_cast
/-- There is a rational power between any two positive elements of an archimedean ordered field. -/
theorem exists_rat_pow_btwn {α : Type*} [LinearOrderedField α] [Archimedean α] (hn : n ≠ 0)
    {x y : α} (h : x < y) (hy : 0 < y) : ∃ q : ℚ, 0 < q ∧ x < (q : α) ^ n ∧ (q : α) ^ n < y := by
  obtain ⟨q₂, hx₂, hy₂⟩ := exists_rat_btwn (max_lt h hy)
  obtain ⟨q₁, hx₁, hq₁₂⟩ := exists_rat_btwn hx₂
  have : (0 : α) < q₂ := (le_max_right _ _).trans_lt hx₂
  norm_cast at hq₁₂ this
  obtain ⟨q, hq, hq₁, hq₂⟩ := exists_rat_pow_btwn_rat hn hq₁₂ this
  refine' ⟨q, hq, (le_max_left _ _).trans_lt <| hx₁.trans _, hy₂.trans' _⟩ <;> 

Proof state:
case intro.intro.intro.intro.intro.intro.intro.refine'_2
z x✝ y✝ : ℝ
n : ℕ
α : Type u_1
inst✝¹ : LinearOrderedField α
inst✝ : Archimedean α
hn : n ≠ 0
x y : α
h : x < y
hy : 0 < y
q₂ : ℚ
hx₂ : max x 0 < ↑q₂
hy₂ : ↑q₂ < y
q₁ : ℚ
hx₁ : max x 0 < ↑q₁
hq₁₂ : q₁ < q₂
this : 0 < q₂
q : ℚ
hq : 0 < q
hq₁ : q₁ < q ^ n
hq₂ : q ^ n < q₂
⊢ ↑q ^ n < ↑q₂

Next tactic:
assumption_mod_cast
lemma cpow_inv_two_re (x : ℂ) : (x ^ (2⁻¹ : ℂ)).re = sqrt ((abs x + x.re) / 2) := by
  

Proof state:
x : ℂ
⊢ (x ^ 2⁻¹).re = sqrt ((abs x + x.re) / 2)

Next tactic:
rw [← ofReal_ofNat, ← ofReal_inv, cpow_ofReal_re, ← div_eq_mul_inv, ← one_div,
    ← Real.sqrt_eq_rpow, cos_half, ← sqrt_mul, ← mul_div_assoc, mul_add, mul_one, abs_mul_cos_arg]
lemma cpow_inv_two_re (x : ℂ) : (x ^ (2⁻¹ : ℂ)).re = sqrt ((abs x + x.re) / 2) := by
  rw [← ofReal_ofNat, ← ofReal_inv, cpow_ofReal_re, ← div_eq_mul_inv, ← one_div,
    ← Real.sqrt_eq_rpow, cos_half, ← sqrt_mul, ← mul_div_assoc, mul_add, mul_one, abs_mul_cos_arg]
  

Proof state:
case hx
x : ℂ
⊢ 0 ≤ abs x
case hl
x : ℂ
⊢ -π ≤ arg x
case hr x : ℂ ⊢ arg x ≤ π

Next tactic:
exacts [abs.nonneg _, (neg_pi_lt_arg _).le, arg_le_pi _]
lemma cpow_inv_two_im_eq_sqrt {x : ℂ} (hx : 0 ≤ x.im) :
    (x ^ (2⁻¹ : ℂ)).im = sqrt ((abs x - x.re) / 2) := by
  

Proof state:
x : ℂ
hx : 0 ≤ x.im
⊢ (x ^ 2⁻¹).im = sqrt ((abs x - x.re) / 2)

Next tactic:
rw [← ofReal_ofNat, ← ofReal_inv, cpow_ofReal_im, ← div_eq_mul_inv, ← one_div,
    ← Real.sqrt_eq_rpow, sin_half_eq_sqrt, ← sqrt_mul (abs.nonneg _), ← mul_div_assoc, mul_sub,
    mul_one, abs_mul_cos_arg]
lemma cpow_inv_two_im_eq_sqrt {x : ℂ} (hx : 0 ≤ x.im) :
    (x ^ (2⁻¹ : ℂ)).im = sqrt ((abs x - x.re) / 2) := by
  rw [← ofReal_ofNat, ← ofReal_inv, cpow_ofReal_im, ← div_eq_mul_inv, ← one_div,
    ← Real.sqrt_eq_rpow, sin_half_eq_sqrt, ← sqrt_mul (abs.nonneg _), ← mul_div_assoc, mul_sub,
    mul_one, abs_mul_cos_arg]
  · 

Proof state:
case hl
x : ℂ
hx : 0 ≤ x.im
⊢ 0 ≤ arg x

Next tactic:
rwa [arg_nonneg_iff]
lemma cpow_inv_two_im_eq_sqrt {x : ℂ} (hx : 0 ≤ x.im) :
    (x ^ (2⁻¹ : ℂ)).im = sqrt ((abs x - x.re) / 2) := by
  rw [← ofReal_ofNat, ← ofReal_inv, cpow_ofReal_im, ← div_eq_mul_inv, ← one_div,
    ← Real.sqrt_eq_rpow, sin_half_eq_sqrt, ← sqrt_mul (abs.nonneg _), ← mul_div_assoc, mul_sub,
    mul_one, abs_mul_cos_arg]
  · rwa [arg_nonneg_iff]
  · 

Proof state:
case hr
x : ℂ
hx : 0 ≤ x.im
⊢ arg x ≤ 2 * π

Next tactic:
linarith [pi_pos, arg_le_pi x]
lemma cpow_inv_two_im_eq_neg_sqrt {x : ℂ} (hx : x.im < 0) :
    (x ^ (2⁻¹ : ℂ)).im = -sqrt ((abs x - x.re) / 2) := by
  

Proof state:
x : ℂ
hx : x.im < 0
⊢ (x ^ 2⁻¹).im = -sqrt ((abs x - x.re) / 2)

Next tactic:
rw [← ofReal_ofNat, ← ofReal_inv, cpow_ofReal_im, ← div_eq_mul_inv, ← one_div,
    ← Real.sqrt_eq_rpow, sin_half_eq_neg_sqrt, mul_neg, ← sqrt_mul (abs.nonneg _),
    ← mul_div_assoc, mul_sub, mul_one, abs_mul_cos_arg]
lemma cpow_inv_two_im_eq_neg_sqrt {x : ℂ} (hx : x.im < 0) :
    (x ^ (2⁻¹ : ℂ)).im = -sqrt ((abs x - x.re) / 2) := by
  rw [← ofReal_ofNat, ← ofReal_inv, cpow_ofReal_im, ← div_eq_mul_inv, ← one_div,
    ← Real.sqrt_eq_rpow, sin_half_eq_neg_sqrt, mul_neg, ← sqrt_mul (abs.nonneg _),
    ← mul_div_assoc, mul_sub, mul_one, abs_mul_cos_arg]
  · 

Proof state:
case hl
x : ℂ
hx : x.im < 0
⊢ -(2 * π) ≤ arg x

Next tactic:
linarith [pi_pos, neg_pi_lt_arg x]
lemma cpow_inv_two_im_eq_neg_sqrt {x : ℂ} (hx : x.im < 0) :
    (x ^ (2⁻¹ : ℂ)).im = -sqrt ((abs x - x.re) / 2) := by
  rw [← ofReal_ofNat, ← ofReal_inv, cpow_ofReal_im, ← div_eq_mul_inv, ← one_div,
    ← Real.sqrt_eq_rpow, sin_half_eq_neg_sqrt, mul_neg, ← sqrt_mul (abs.nonneg _),
    ← mul_div_assoc, mul_sub, mul_one, abs_mul_cos_arg]
  · linarith [pi_pos, neg_pi_lt_arg x]
  · 

Proof state:
case hr
x : ℂ
hx : x.im < 0
⊢ arg x ≤ 0

Next tactic:
exact (arg_neg_iff.2 hx).le
lemma abs_cpow_inv_two_im (x : ℂ) : |(x ^ (2⁻¹ : ℂ)).im| = sqrt ((abs x - x.re) / 2) := by
  

Proof state:
x : ℂ
⊢ |(x ^ 2⁻¹).im| = sqrt ((abs x - x.re) / 2)

Next tactic:
rw [← ofReal_ofNat, ← ofReal_inv, cpow_ofReal_im, ← div_eq_mul_inv, ← one_div,
    ← Real.sqrt_eq_rpow, _root_.abs_mul, _root_.abs_of_nonneg (sqrt_nonneg _), abs_sin_half,
    ← sqrt_mul (abs.nonneg _), ← mul_div_assoc, mul_sub, mul_one, abs_mul_cos_arg]
instance linearOverField : Linear k (ModuleCat.{v} A) where
  --Porting note: used to be `by infer_instance` instead of `LinearMap.module`
  homModule M N := LinearMap.module
  smul_comp := by
    -- Porting note: this was automatic by `aesop_cat`
    

Proof state:
k : Type u
inst✝² : Field k
A : Type w
inst✝¹ : Ring A
inst✝ : Algebra k A
⊢ ∀ (X Y Z : ModuleCat A) (r : k) (f : X ⟶ Y) (g : Y ⟶ Z), (r • f) ≫ g = r • f ≫ g

Next tactic:
intros
instance linearOverField : Linear k (ModuleCat.{v} A) where
  --Porting note: used to be `by infer_instance` instead of `LinearMap.module`
  homModule M N := LinearMap.module
  smul_comp := by
    -- Porting note: this was automatic by `aesop_cat`
    intros
    

Proof state:
k : Type u
inst✝² : Field k
A : Type w
inst✝¹ : Ring A
inst✝ : Algebra k A
X✝ Y✝ Z✝ : ModuleCat A
r✝ : k
f✝ : X✝ ⟶ Y✝
g✝ : Y✝ ⟶ Z✝
⊢ (r✝ • f✝) ≫ g✝ = r✝ • f✝ ≫ g✝

Next tactic:
ext
instance linearOverField : Linear k (ModuleCat.{v} A) where
  --Porting note: used to be `by infer_instance` instead of `LinearMap.module`
  homModule M N := LinearMap.module
  smul_comp := by
    -- Porting note: this was automatic by `aesop_cat`
    intros
    ext
    

Proof state:
case h
k : Type u
inst✝² : Field k
A : Type w
inst✝¹ : Ring A
inst✝ : Algebra k A
X✝ Y✝ Z✝ : ModuleCat A
r✝ : k
f✝ : X✝ ⟶ Y✝
g✝ : Y✝ ⟶ Z✝
x✝ : ↑X✝
⊢ ((r✝ • f✝) ≫ g✝) x✝ = (r✝ • f✝ ≫ g✝) x✝

Next tactic:
dsimp only [coe_comp, Function.comp_apply]
instance linearOverField : Linear k (ModuleCat.{v} A) where
  --Porting note: used to be `by infer_instance` instead of `LinearMap.module`
  homModule M N := LinearMap.module
  smul_comp := by
    -- Porting note: this was automatic by `aesop_cat`
    intros
    ext
    dsimp only [coe_comp, Function.comp_apply]
    

Proof state:
case h
k : Type u
inst✝² : Field k
A : Type w
inst✝¹ : Ring A
inst✝ : Algebra k A
X✝ Y✝ Z✝ : ModuleCat A
r✝ : k
f✝ : X✝ ⟶ Y✝
g✝ : Y✝ ⟶ Z✝
x✝ : ↑X✝
⊢ g✝ ((r✝ • f✝) x✝) = (r✝ • f✝ ≫ g✝) x✝

Next tactic:
rw [LinearMap.smul_apply, LinearMap.map_smul_of_tower]
instance linearOverField : Linear k (ModuleCat.{v} A) where
  --Porting note: used to be `by infer_instance` instead of `LinearMap.module`
  homModule M N := LinearMap.module
  smul_comp := by
    -- Porting note: this was automatic by `aesop_cat`
    intros
    ext
    dsimp only [coe_comp, Function.comp_apply]
    rw [LinearMap.smul_apply, LinearMap.map_smul_of_tower]
    

Proof state:
case h
k : Type u
inst✝² : Field k
A : Type w
inst✝¹ : Ring A
inst✝ : Algebra k A
X✝ Y✝ Z✝ : ModuleCat A
r✝ : k
f✝ : X✝ ⟶ Y✝
g✝ : Y✝ ⟶ Z✝
x✝ : ↑X✝
⊢ r✝ • g✝ (f✝ x✝) = (r✝ • f✝ ≫ g✝) x✝

Next tactic:
rfl
theorem IsConformalMap.preserves_angle {f' : E →L[ℝ] F} (h : IsConformalMap f') (u v : E) :
    angle (f' u) (f' v) = angle u v := by
  

Proof state:
E : Type u_1
F : Type u_2
inst✝³ : NormedAddCommGroup E
inst✝² : NormedAddCommGroup F
inst✝¹ : InnerProductSpace ℝ E
inst✝ : InnerProductSpace ℝ F
f' : E →L[ℝ] F
h : IsConformalMap f'
u v : E
⊢ angle (f' u) (f' v) = angle u v

Next tactic:
obtain ⟨c, hc, li, rfl⟩ := h
theorem IsConformalMap.preserves_angle {f' : E →L[ℝ] F} (h : IsConformalMap f') (u v : E) :
    angle (f' u) (f' v) = angle u v := by
  obtain ⟨c, hc, li, rfl⟩ := h
  

Proof state:
case intro.intro.intro
E : Type u_1
F : Type u_2
inst✝³ : NormedAddCommGroup E
inst✝² : NormedAddCommGroup F
inst✝¹ : InnerProductSpace ℝ E
inst✝ : InnerProductSpace ℝ F
u v : E
c : ℝ
hc : c ≠ 0
li : E →ₗᵢ[ℝ] F
⊢ angle ((c • LinearIsometry.toContinuousLinearMap li) u) ((c • LinearIsometry.toContinuousLinearMap li) v) = angle u v

Next tactic:
exact (angle_smul_smul hc _ _).trans (li.angle_map _ _)
/-- Construct a `StrictOrderedRing` by designating a positive cone in an existing `Ring`. -/
def StrictOrderedRing.mkOfPositiveCone (C : PositiveCone α) : StrictOrderedRing α :=
  { ‹Ring α›, OrderedAddCommGroup.mkOfPositiveCone C.toPositiveCone with
    exists_pair_ne := ⟨0, 1, fun h => by 

Proof state:
α : Type u_1
inst✝¹ : Ring α
inst✝ : Nontrivial α
C : PositiveCone α
src✝¹ : Ring α := inst✝¹
src✝ : OrderedAddCommGroup α := OrderedAddCommGroup.mkOfPositiveCone C.toPositiveCone
h : 0 = 1
⊢ False

Next tactic:
simpa [← h, C.pos_iff] using C.one_pos
/-- Construct a `StrictOrderedRing` by designating a positive cone in an existing `Ring`. -/
def StrictOrderedRing.mkOfPositiveCone (C : PositiveCone α) : StrictOrderedRing α :=
  { ‹Ring α›, OrderedAddCommGroup.mkOfPositiveCone C.toPositiveCone with
    exists_pair_ne := ⟨0, 1, fun h => by simpa [← h, C.pos_iff] using C.one_pos⟩,
    zero_le_one := by
      

Proof state:
α : Type u_1
inst✝¹ : Ring α
inst✝ : Nontrivial α
C : PositiveCone α
src✝¹ : Ring α := inst✝¹
src✝ : OrderedAddCommGroup α := OrderedAddCommGroup.mkOfPositiveCone C.toPositiveCone
⊢ 0 ≤ 1

Next tactic:
change C.nonneg (1 - 0)
/-- Construct a `StrictOrderedRing` by designating a positive cone in an existing `Ring`. -/
def StrictOrderedRing.mkOfPositiveCone (C : PositiveCone α) : StrictOrderedRing α :=
  { ‹Ring α›, OrderedAddCommGroup.mkOfPositiveCone C.toPositiveCone with
    exists_pair_ne := ⟨0, 1, fun h => by simpa [← h, C.pos_iff] using C.one_pos⟩,
    zero_le_one := by
      change C.nonneg (1 - 0)
      

Proof state:
α : Type u_1
inst✝¹ : Ring α
inst✝ : Nontrivial α
C : PositiveCone α
src✝¹ : Ring α := inst✝¹
src✝ : OrderedAddCommGroup α := OrderedAddCommGroup.mkOfPositiveCone C.toPositiveCone
⊢ AddCommGroup.PositiveCone.nonneg C.toPositiveCone (1 - 0)

Next tactic:
convert C.one_nonneg
/-- Construct a `StrictOrderedRing` by designating a positive cone in an existing `Ring`. -/
def StrictOrderedRing.mkOfPositiveCone (C : PositiveCone α) : StrictOrderedRing α :=
  { ‹Ring α›, OrderedAddCommGroup.mkOfPositiveCone C.toPositiveCone with
    exists_pair_ne := ⟨0, 1, fun h => by simpa [← h, C.pos_iff] using C.one_pos⟩,
    zero_le_one := by
      change C.nonneg (1 - 0)
      convert C.one_nonneg
      

Proof state:
case h.e'_4
α : Type u_1
inst✝¹ : Ring α
inst✝ : Nontrivial α
C : PositiveCone α
src✝¹ : Ring α := inst✝¹
src✝ : OrderedAddCommGroup α := OrderedAddCommGroup.mkOfPositiveCone C.toPositiveCone
⊢ 1 - 0 = 1

Next tactic:
simp
/-- Construct a `StrictOrderedRing` by designating a positive cone in an existing `Ring`. -/
def StrictOrderedRing.mkOfPositiveCone (C : PositiveCone α) : StrictOrderedRing α :=
  { ‹Ring α›, OrderedAddCommGroup.mkOfPositiveCone C.toPositiveCone with
    exists_pair_ne := ⟨0, 1, fun h => by simpa [← h, C.pos_iff] using C.one_pos⟩,
    zero_le_one := by
      change C.nonneg (1 - 0)
      convert C.one_nonneg
      simp,
    mul_pos := fun x y xp yp => by
      

Proof state:
α : Type u_1
inst✝¹ : Ring α
inst✝ : Nontrivial α
C : PositiveCone α
src✝¹ : Ring α := inst✝¹
src✝ : OrderedAddCommGroup α := OrderedAddCommGroup.mkOfPositiveCone C.toPositiveCone
x y : α
xp : 0 < x
yp : 0 < y
⊢ 0 < x * y

Next tactic:
change C.pos (x * y - 0)
/-- Construct a `StrictOrderedRing` by designating a positive cone in an existing `Ring`. -/
def StrictOrderedRing.mkOfPositiveCone (C : PositiveCone α) : StrictOrderedRing α :=
  { ‹Ring α›, OrderedAddCommGroup.mkOfPositiveCone C.toPositiveCone with
    exists_pair_ne := ⟨0, 1, fun h => by simpa [← h, C.pos_iff] using C.one_pos⟩,
    zero_le_one := by
      change C.nonneg (1 - 0)
      convert C.one_nonneg
      simp,
    mul_pos := fun x y xp yp => by
      change C.pos (x * y - 0)
      -- porting note: used to be convert, but it relied on unfolding definitions
      

Proof state:
α : Type u_1
inst✝¹ : Ring α
inst✝ : Nontrivial α
C : PositiveCone α
src✝¹ : Ring α := inst✝¹
src✝ : OrderedAddCommGroup α := OrderedAddCommGroup.mkOfPositiveCone C.toPositiveCone
x y : α
xp : 0 < x
yp : 0 < y
⊢ AddCommGroup.PositiveCone.pos C.toPositiveCone (x * y - 0)

Next tactic:
rw [sub_zero]
/-- Construct a `StrictOrderedRing` by designating a positive cone in an existing `Ring`. -/
def StrictOrderedRing.mkOfPositiveCone (C : PositiveCone α) : StrictOrderedRing α :=
  { ‹Ring α›, OrderedAddCommGroup.mkOfPositiveCone C.toPositiveCone with
    exists_pair_ne := ⟨0, 1, fun h => by simpa [← h, C.pos_iff] using C.one_pos⟩,
    zero_le_one := by
      change C.nonneg (1 - 0)
      convert C.one_nonneg
      simp,
    mul_pos := fun x y xp yp => by
      change C.pos (x * y - 0)
      -- porting note: used to be convert, but it relied on unfolding definitions
      rw [sub_zero]
      

Proof state:
α : Type u_1
inst✝¹ : Ring α
inst✝ : Nontrivial α
C : PositiveCone α
src✝¹ : Ring α := inst✝¹
src✝ : OrderedAddCommGroup α := OrderedAddCommGroup.mkOfPositiveCone C.toPositiveCone
x y : α
xp : 0 < x
yp : 0 < y
⊢ AddCommGroup.PositiveCone.pos C.toPositiveCone (x * y)

Next tactic:
exact C.mul_pos x y (by rwa [← sub_zero x]) (by rwa [← sub_zero y])
/-- Construct a `StrictOrderedRing` by designating a positive cone in an existing `Ring`. -/
def StrictOrderedRing.mkOfPositiveCone (C : PositiveCone α) : StrictOrderedRing α :=
  { ‹Ring α›, OrderedAddCommGroup.mkOfPositiveCone C.toPositiveCone with
    exists_pair_ne := ⟨0, 1, fun h => by simpa [← h, C.pos_iff] using C.one_pos⟩,
    zero_le_one := by
      change C.nonneg (1 - 0)
      convert C.one_nonneg
      simp,
    mul_pos := fun x y xp yp => by
      change C.pos (x * y - 0)
      -- porting note: used to be convert, but it relied on unfolding definitions
      rw [sub_zero]
      exact C.mul_pos x y (by 

Proof state:
α : Type u_1
inst✝¹ : Ring α
inst✝ : Nontrivial α
C : PositiveCone α
src✝¹ : Ring α := inst✝¹
src✝ : OrderedAddCommGroup α := OrderedAddCommGroup.mkOfPositiveCone C.toPositiveCone
x y : α
xp : 0 < x
yp : 0 < y
⊢ AddCommGroup.PositiveCone.pos C.toPositiveCone x

Next tactic:
rwa [← sub_zero x]
/-- Construct a `StrictOrderedRing` by designating a positive cone in an existing `Ring`. -/
def StrictOrderedRing.mkOfPositiveCone (C : PositiveCone α) : StrictOrderedRing α :=
  { ‹Ring α›, OrderedAddCommGroup.mkOfPositiveCone C.toPositiveCone with
    exists_pair_ne := ⟨0, 1, fun h => by simpa [← h, C.pos_iff] using C.one_pos⟩,
    zero_le_one := by
      change C.nonneg (1 - 0)
      convert C.one_nonneg
      simp,
    mul_pos := fun x y xp yp => by
      change C.pos (x * y - 0)
      -- porting note: used to be convert, but it relied on unfolding definitions
      rw [sub_zero]
      exact C.mul_pos x y (by rwa [← sub_zero x]) (by 

Proof state:
α : Type u_1
inst✝¹ : Ring α
inst✝ : Nontrivial α
C : PositiveCone α
src✝¹ : Ring α := inst✝¹
src✝ : OrderedAddCommGroup α := OrderedAddCommGroup.mkOfPositiveCone C.toPositiveCone
x y : α
xp : 0 < x
yp : 0 < y
⊢ AddCommGroup.PositiveCone.pos C.toPositiveCone y

Next tactic:
rwa [← sub_zero y]
/-- The symbol `J(a | 0)` has the value `1`. -/
@[simp]
theorem zero_right (a : ℤ) : J(a | 0) = 1 := by
  

Proof state:
a : ℤ
⊢ J(a | 0) = 1

Next tactic:
simp only [jacobiSym, factors_zero, List.prod_nil, List.pmap]
/-- The symbol `J(a | 1)` has the value `1`. -/
@[simp]
theorem one_right (a : ℤ) : J(a | 1) = 1 := by
  

Proof state:
a : ℤ
⊢ J(a | 1) = 1

Next tactic:
simp only [jacobiSym, factors_one, List.prod_nil, List.pmap]
/-- The Legendre symbol `legendreSym p a` with an integer `a` and a prime number `p`
is the same as the Jacobi symbol `J(a | p)`. -/
theorem legendreSym.to_jacobiSym (p : ℕ) [fp : Fact p.Prime] (a : ℤ) : legendreSym p a = J(a | p) :=
  by 

Proof state:
p : ℕ
fp : Fact (Nat.Prime p)
a : ℤ
⊢ legendreSym p a = J(a | p)

Next tactic:
simp only [jacobiSym, factors_prime fp.1, List.prod_cons, List.prod_nil, mul_one, List.pmap]
/-- The Jacobi symbol is multiplicative in its second argument. -/
theorem mul_right' (a : ℤ) {b₁ b₂ : ℕ} (hb₁ : b₁ ≠ 0) (hb₂ : b₂ ≠ 0) :
    J(a | b₁ * b₂) = J(a | b₁) * J(a | b₂) := by
  

Proof state:
a : ℤ
b₁ b₂ : ℕ
hb₁ : b₁ ≠ 0
hb₂ : b₂ ≠ 0
⊢ J(a | b₁ * b₂) = J(a | b₁) * J(a | b₂)

Next tactic:
rw [jacobiSym, ((perm_factors_mul hb₁ hb₂).pmap _).prod_eq, List.pmap_append, List.prod_append]
/-- The Jacobi symbol is multiplicative in its second argument. -/
theorem mul_right' (a : ℤ) {b₁ b₂ : ℕ} (hb₁ : b₁ ≠ 0) (hb₂ : b₂ ≠ 0) :
    J(a | b₁ * b₂) = J(a | b₁) * J(a | b₂) := by
  rw [jacobiSym, ((perm_factors_mul hb₁ hb₂).pmap _).prod_eq, List.pmap_append, List.prod_append]
  

Proof state:
a : ℤ
b₁ b₂ : ℕ
hb₁ : b₁ ≠ 0
hb₂ : b₂ ≠ 0
⊢ List.prod (List.pmap (fun p pp => legendreSym p a) (factors b₁) (_ : ∀ a ∈ factors b₁, Nat.Prime a)) *
      List.prod (List.pmap (fun p pp => legendreSym p a) (factors b₂) (_ : ∀ a ∈ factors b₂, Nat.Prime a)) =
    J(a | b₁) * J(a | b₂)
case h
a : ℤ
b₁ b₂ : ℕ
hb₁ : b₁ ≠ 0
hb₂ : b₂ ≠ 0
⊢ ∀ a ∈ factors b₁ ++ factors b₂, Nat.Prime a
case h a : ℤ b₁ b₂ : ℕ hb₁ : b₁ ≠ 0 hb₂ : b₂ ≠ 0 ⊢ ∀ a ∈ factors b₁ ++ factors b₂, Nat.Prime a

Next tactic:
case h => exact fun p hp => (List.mem_append.mp hp).elim prime_of_mem_factors prime_of_mem_factors
/-- The Jacobi symbol is multiplicative in its second argument. -/
theorem mul_right' (a : ℤ) {b₁ b₂ : ℕ} (hb₁ : b₁ ≠ 0) (hb₂ : b₂ ≠ 0) :
    J(a | b₁ * b₂) = J(a | b₁) * J(a | b₂) := by
  rw [jacobiSym, ((perm_factors_mul hb₁ hb₂).pmap _).prod_eq, List.pmap_append, List.prod_append]
  

Proof state:
a : ℤ
b₁ b₂ : ℕ
hb₁ : b₁ ≠ 0
hb₂ : b₂ ≠ 0
⊢ ∀ a ∈ factors b₁ ++ factors b₂, Nat.Prime a

Next tactic:
case h => exact fun p hp => (List.mem_append.mp hp).elim prime_of_mem_factors prime_of_mem_factors
/-- The Jacobi symbol is multiplicative in its second argument. -/
theorem mul_right' (a : ℤ) {b₁ b₂ : ℕ} (hb₁ : b₁ ≠ 0) (hb₂ : b₂ ≠ 0) :
    J(a | b₁ * b₂) = J(a | b₁) * J(a | b₂) := by
  rw [jacobiSym, ((perm_factors_mul hb₁ hb₂).pmap _).prod_eq, List.pmap_append, List.prod_append]
  case h => 

Proof state:
a : ℤ
b₁ b₂ : ℕ
hb₁ : b₁ ≠ 0
hb₂ : b₂ ≠ 0
⊢ ∀ a ∈ factors b₁ ++ factors b₂, Nat.Prime a

Next tactic:
exact fun p hp => (List.mem_append.mp hp).elim prime_of_mem_factors prime_of_mem_factors
/-- The Jacobi symbol is multiplicative in its second argument. -/
theorem mul_right' (a : ℤ) {b₁ b₂ : ℕ} (hb₁ : b₁ ≠ 0) (hb₂ : b₂ ≠ 0) :
    J(a | b₁ * b₂) = J(a | b₁) * J(a | b₂) := by
  rw [jacobiSym, ((perm_factors_mul hb₁ hb₂).pmap _).prod_eq, List.pmap_append, List.prod_append]
  case h => exact fun p hp => (List.mem_append.mp hp).elim prime_of_mem_factors prime_of_mem_factors
  

Proof state:
a : ℤ
b₁ b₂ : ℕ
hb₁ : b₁ ≠ 0
hb₂ : b₂ ≠ 0
⊢ List.prod (List.pmap (fun p pp => legendreSym p a) (factors b₁) (_ : ∀ a ∈ factors b₁, Nat.Prime a)) *
      List.prod (List.pmap (fun p pp => legendreSym p a) (factors b₂) (_ : ∀ a ∈ factors b₂, Nat.Prime a)) =
    J(a | b₁) * J(a | b₂)

Next tactic:
case _ => rfl
/-- The Jacobi symbol is multiplicative in its second argument. -/
theorem mul_right' (a : ℤ) {b₁ b₂ : ℕ} (hb₁ : b₁ ≠ 0) (hb₂ : b₂ ≠ 0) :
    J(a | b₁ * b₂) = J(a | b₁) * J(a | b₂) := by
  rw [jacobiSym, ((perm_factors_mul hb₁ hb₂).pmap _).prod_eq, List.pmap_append, List.prod_append]
  case h => exact fun p hp => (List.mem_append.mp hp).elim prime_of_mem_factors prime_of_mem_factors
  case _ => 

Proof state:
a : ℤ
b₁ b₂ : ℕ
hb₁ : b₁ ≠ 0
hb₂ : b₂ ≠ 0
⊢ List.prod (List.pmap (fun p pp => legendreSym p a) (factors b₁) (_ : ∀ a ∈ factors b₁, Nat.Prime a)) *
      List.prod (List.pmap (fun p pp => legendreSym p a) (factors b₂) (_ : ∀ a ∈ factors b₂, Nat.Prime a)) =
    J(a | b₁) * J(a | b₂)

Next tactic:
rfl
/-- The Jacobi symbol takes only the values `0`, `1` and `-1`. -/
theorem trichotomy (a : ℤ) (b : ℕ) : J(a | b) = 0 ∨ J(a | b) = 1 ∨ J(a | b) = -1 :=
  ((@SignType.castHom ℤ _ _).toMonoidHom.mrange.copy {0, 1, -1} <| by
    

Proof state:
a : ℤ
b : ℕ
⊢ {0, 1, -1} = ↑(MonoidHom.mrange ↑SignType.castHom)

Next tactic:
rw [Set.pair_comm]
/-- The Jacobi symbol takes only the values `0`, `1` and `-1`. -/
theorem trichotomy (a : ℤ) (b : ℕ) : J(a | b) = 0 ∨ J(a | b) = 1 ∨ J(a | b) = -1 :=
  ((@SignType.castHom ℤ _ _).toMonoidHom.mrange.copy {0, 1, -1} <| by
    rw [Set.pair_comm];
    

Proof state:
a : ℤ
b : ℕ
⊢ {0, -1, 1} = ↑(MonoidHom.mrange ↑SignType.castHom)

Next tactic:
exact (SignType.range_eq SignType.castHom).symm
/-- The Jacobi symbol takes only the values `0`, `1` and `-1`. -/
theorem trichotomy (a : ℤ) (b : ℕ) : J(a | b) = 0 ∨ J(a | b) = 1 ∨ J(a | b) = -1 :=
  ((@SignType.castHom ℤ _ _).toMonoidHom.mrange.copy {0, 1, -1} <| by
    rw [Set.pair_comm];
    exact (SignType.range_eq SignType.castHom).symm).list_prod_mem
      (by
        

Proof state:
a : ℤ
b : ℕ
⊢ ∀ x ∈ List.pmap (fun p pp => legendreSym p a) (factors b) (_ : ∀ x ∈ factors b, Nat.Prime x),
    x ∈
      Submonoid.copy (MonoidHom.mrange ↑SignType.castHom) {0, 1, -1}
        (_ : {0, 1, -1} = ↑(MonoidHom.mrange ↑SignType.castHom))

Next tactic:
intro _ ha'
/-- The Jacobi symbol takes only the values `0`, `1` and `-1`. -/
theorem trichotomy (a : ℤ) (b : ℕ) : J(a | b) = 0 ∨ J(a | b) = 1 ∨ J(a | b) = -1 :=
  ((@SignType.castHom ℤ _ _).toMonoidHom.mrange.copy {0, 1, -1} <| by
    rw [Set.pair_comm];
    exact (SignType.range_eq SignType.castHom).symm).list_prod_mem
      (by
        intro _ ha'
        

Proof state:
a : ℤ
b : ℕ
x✝ : ℤ
ha' : x✝ ∈ List.pmap (fun p pp => legendreSym p a) (factors b) (_ : ∀ x ∈ factors b, Nat.Prime x)
⊢ x✝ ∈
    Submonoid.copy (MonoidHom.mrange ↑SignType.castHom) {0, 1, -1}
      (_ : {0, 1, -1} = ↑(MonoidHom.mrange ↑SignType.castHom))

Next tactic:
rcases List.mem_pmap.mp ha' with ⟨p, hp, rfl⟩