l3lab/ntp-mathlib huggingface dataset:
theorem cmp_compares : ∀ a b : NONote, (cmp a b).Compares a b
  | ⟨a, ha⟩, ⟨b, hb⟩ => by
    dsimp [cmp]
    have := ONote.cmp_compares a b
    cases h: ONote.cmp a b <;> 

Proof state:
case gt
a : ONote
ha : ONote.NF a
b : ONote
hb : ONote.NF b
this : Ordering.Compares (ONote.cmp a b) a b
h : ONote.cmp a b = Ordering.gt
⊢ Ordering.Compares Ordering.gt { val := a, property := ha } { val := b, property := hb }

Next tactic:
simp only [h] at this
theorem cmp_compares : ∀ a b : NONote, (cmp a b).Compares a b
  | ⟨a, ha⟩, ⟨b, hb⟩ => by
    dsimp [cmp]
    have := ONote.cmp_compares a b
    cases h: ONote.cmp a b <;> simp only [h] at this <;> 

Proof state:
case lt
a : ONote
ha : ONote.NF a
b : ONote
hb : ONote.NF b
h : ONote.cmp a b = Ordering.lt
this : Ordering.Compares Ordering.lt a b
⊢ Ordering.Compares Ordering.lt { val := a, property := ha } { val := b, property := hb }

Next tactic:
try exact this
theorem cmp_compares : ∀ a b : NONote, (cmp a b).Compares a b
  | ⟨a, ha⟩, ⟨b, hb⟩ => by
    dsimp [cmp]
    have := ONote.cmp_compares a b
    cases h: ONote.cmp a b <;> simp only [h] at this <;> try 

Proof state:
case lt
a : ONote
ha : ONote.NF a
b : ONote
hb : ONote.NF b
h : ONote.cmp a b = Ordering.lt
this : Ordering.Compares Ordering.lt a b
⊢ Ordering.Compares Ordering.lt { val := a, property := ha } { val := b, property := hb }

Next tactic:
exact this
theorem cmp_compares : ∀ a b : NONote, (cmp a b).Compares a b
  | ⟨a, ha⟩, ⟨b, hb⟩ => by
    dsimp [cmp]
    have := ONote.cmp_compares a b
    cases h: ONote.cmp a b <;> simp only [h] at this <;> 

Proof state:
case eq
a : ONote
ha : ONote.NF a
b : ONote
hb : ONote.NF b
h : ONote.cmp a b = Ordering.eq
this : Ordering.Compares Ordering.eq a b
⊢ Ordering.Compares Ordering.eq { val := a, property := ha } { val := b, property := hb }

Next tactic:
try exact this
theorem cmp_compares : ∀ a b : NONote, (cmp a b).Compares a b
  | ⟨a, ha⟩, ⟨b, hb⟩ => by
    dsimp [cmp]
    have := ONote.cmp_compares a b
    cases h: ONote.cmp a b <;> simp only [h] at this <;> try 

Proof state:
case eq
a : ONote
ha : ONote.NF a
b : ONote
hb : ONote.NF b
h : ONote.cmp a b = Ordering.eq
this : Ordering.Compares Ordering.eq a b
⊢ Ordering.Compares Ordering.eq { val := a, property := ha } { val := b, property := hb }

Next tactic:
exact this
theorem cmp_compares : ∀ a b : NONote, (cmp a b).Compares a b
  | ⟨a, ha⟩, ⟨b, hb⟩ => by
    dsimp [cmp]
    have := ONote.cmp_compares a b
    cases h: ONote.cmp a b <;> simp only [h] at this <;> 

Proof state:
case gt
a : ONote
ha : ONote.NF a
b : ONote
hb : ONote.NF b
h : ONote.cmp a b = Ordering.gt
this : Ordering.Compares Ordering.gt a b
⊢ Ordering.Compares Ordering.gt { val := a, property := ha } { val := b, property := hb }

Next tactic:
try exact this
theorem cmp_compares : ∀ a b : NONote, (cmp a b).Compares a b
  | ⟨a, ha⟩, ⟨b, hb⟩ => by
    dsimp [cmp]
    have := ONote.cmp_compares a b
    cases h: ONote.cmp a b <;> simp only [h] at this <;> try 

Proof state:
case gt
a : ONote
ha : ONote.NF a
b : ONote
hb : ONote.NF b
h : ONote.cmp a b = Ordering.gt
this : Ordering.Compares Ordering.gt a b
⊢ Ordering.Compares Ordering.gt { val := a, property := ha } { val := b, property := hb }

Next tactic:
exact this
theorem cmp_compares : ∀ a b : NONote, (cmp a b).Compares a b
  | ⟨a, ha⟩, ⟨b, hb⟩ => by
    dsimp [cmp]
    have := ONote.cmp_compares a b
    cases h: ONote.cmp a b <;> simp only [h] at this <;> try exact this
    

Proof state:
case eq
a : ONote
ha : ONote.NF a
b : ONote
hb : ONote.NF b
h : ONote.cmp a b = Ordering.eq
this : Ordering.Compares Ordering.eq a b
⊢ Ordering.Compares Ordering.eq { val := a, property := ha } { val := b, property := hb }

Next tactic:
exact Subtype.mk_eq_mk.2 this
/-- This is a recursor-like theorem for `NONote` suggesting an
  inductive definition, which can't actually be defined this
  way due to conflicting dependencies. -/
@[elab_as_elim]
def recOn {C : NONote → Sort*} (o : NONote) (H0 : C 0)
    (H1 : ∀ e n a h, C e → C a → C (oadd e n a h)) : C o := by
  

Proof state:
C : NONote → Sort u_1
o : NONote
H0 : C 0
H1 : (e : NONote) → (n : ℕ+) → (a : NONote) → (h : below a e) → C e → C a → C (oadd e n a h)
⊢ C o

Next tactic:
cases' o with o h
/-- This is a recursor-like theorem for `NONote` suggesting an
  inductive definition, which can't actually be defined this
  way due to conflicting dependencies. -/
@[elab_as_elim]
def recOn {C : NONote → Sort*} (o : NONote) (H0 : C 0)
    (H1 : ∀ e n a h, C e → C a → C (oadd e n a h)) : C o := by
  cases' o with o h; 

Proof state:
case mk
C : NONote → Sort u_1
H0 : C 0
H1 : (e : NONote) → (n : ℕ+) → (a : NONote) → (h : below a e) → C e → C a → C (oadd e n a h)
o : ONote
h : ONote.NF o
⊢ C { val := o, property := h }

Next tactic:
induction' o with e n a IHe IHa
/-- This is a recursor-like theorem for `NONote` suggesting an
  inductive definition, which can't actually be defined this
  way due to conflicting dependencies. -/
@[elab_as_elim]
def recOn {C : NONote → Sort*} (o : NONote) (H0 : C 0)
    (H1 : ∀ e n a h, C e → C a → C (oadd e n a h)) : C o := by
  cases' o with o h; induction' o with e n a IHe IHa
  · 

Proof state:
case mk.zero
C : NONote → Sort u_1
H0 : C 0
H1 : (e : NONote) → (n : ℕ+) → (a : NONote) → (h : below a e) → C e → C a → C (oadd e n a h)
h : ONote.NF ONote.zero
⊢ C { val := ONote.zero, property := h }

Next tactic:
exact H0
/-- This is a recursor-like theorem for `NONote` suggesting an
  inductive definition, which can't actually be defined this
  way due to conflicting dependencies. -/
@[elab_as_elim]
def recOn {C : NONote → Sort*} (o : NONote) (H0 : C 0)
    (H1 : ∀ e n a h, C e → C a → C (oadd e n a h)) : C o := by
  cases' o with o h; induction' o with e n a IHe IHa
  · exact H0
  · 

Proof state:
case mk.oadd
C : NONote → Sort u_1
H0 : C 0
H1 : (e : NONote) → (n : ℕ+) → (a : NONote) → (h : below a e) → C e → C a → C (oadd e n a h)
e : ONote
n : ℕ+
a : ONote
IHe : (h : ONote.NF e) → C { val := e, property := h }
IHa : (h : ONote.NF a) → C { val := a, property := h }
h : ONote.NF (ONote.oadd e n a)
⊢ C { val := ONote.oadd e n a, property := h }

Next tactic:
exact H1 ⟨e, h.fst⟩ n ⟨a, h.snd⟩ h.snd' (IHe _) (IHa _)
@[simp]
theorem aeval_T (x : A) (n : ℕ) : aeval x (T R n) = (T A n).eval x := by
  

Proof state:
R : Type u_1
A : Type u_2
inst✝² : CommRing R
inst✝¹ : CommRing A
inst✝ : Algebra R A
x : A
n : ℕ
⊢ (aeval x) (T R n) = eval x (T A n)

Next tactic:
rw [aeval_def, eval₂_eq_eval_map, map_T]
@[simp]
theorem aeval_U (x : A) (n : ℕ) : aeval x (U R n) = (U A n).eval x := by
  

Proof state:
R : Type u_1
A : Type u_2
inst✝² : CommRing R
inst✝¹ : CommRing A
inst✝ : Algebra R A
x : A
n : ℕ
⊢ (aeval x) (U R n) = eval x (U A n)

Next tactic:
rw [aeval_def, eval₂_eq_eval_map, map_U]
@[simp]
theorem algebraMap_eval_T (x : R) (n : ℕ) :
    algebraMap R A ((T R n).eval x) = (T A n).eval (algebraMap R A x) := by
  

Proof state:
R : Type u_1
A : Type u_2
inst✝² : CommRing R
inst✝¹ : CommRing A
inst✝ : Algebra R A
x : R
n : ℕ
⊢ (algebraMap R A) (eval x (T R n)) = eval ((algebraMap R A) x) (T A n)

Next tactic:
rw [← aeval_algebraMap_apply_eq_algebraMap_eval, aeval_T]
@[simp]
theorem algebraMap_eval_U (x : R) (n : ℕ) :
    algebraMap R A ((U R n).eval x) = (U A n).eval (algebraMap R A x) := by
  

Proof state:
R : Type u_1
A : Type u_2
inst✝² : CommRing R
inst✝¹ : CommRing A
inst✝ : Algebra R A
x : R
n : ℕ
⊢ (algebraMap R A) (eval x (U R n)) = eval ((algebraMap R A) x) (U A n)

Next tactic:
rw [← aeval_algebraMap_apply_eq_algebraMap_eval, aeval_U]
/-- The `n`-th Chebyshev polynomial of the first kind evaluates on `cos θ` to the
value `cos (n * θ)`. -/
@[simp]
theorem T_complex_cos : ∀ n, (T ℂ n).eval (cos θ) = cos (n * θ)
  | 0 => by 

Proof state:
R : Type u_1
A : Type u_2
inst✝² : CommRing R
inst✝¹ : CommRing A
inst✝ : Algebra R A
θ : ℂ
⊢ eval (cos θ) (T ℂ 0) = cos (↑0 * θ)

Next tactic:
simp only [T_zero, eval_one, Nat.cast_zero, zero_mul, cos_zero]
/-- The `n`-th Chebyshev polynomial of the first kind evaluates on `cos θ` to the
value `cos (n * θ)`. -/
@[simp]
theorem T_complex_cos : ∀ n, (T ℂ n).eval (cos θ) = cos (n * θ)
  | 0 => by simp only [T_zero, eval_one, Nat.cast_zero, zero_mul, cos_zero]
  | 1 => by 

Proof state:
R : Type u_1
A : Type u_2
inst✝² : CommRing R
inst✝¹ : CommRing A
inst✝ : Algebra R A
θ : ℂ
⊢ eval (cos θ) (T ℂ 1) = cos (↑1 * θ)

Next tactic:
simp only [eval_X, one_mul, T_one, Nat.cast_one]
/-- The `n`-th Chebyshev polynomial of the first kind evaluates on `cos θ` to the
value `cos (n * θ)`. -/
@[simp]
theorem T_complex_cos : ∀ n, (T ℂ n).eval (cos θ) = cos (n * θ)
  | 0 => by simp only [T_zero, eval_one, Nat.cast_zero, zero_mul, cos_zero]
  | 1 => by simp only [eval_X, one_mul, T_one, Nat.cast_one]
  | n + 2 => by
    -- Porting note: partially rewrote proof for lean4 numerals.
    

Proof state:
R : Type u_1
A : Type u_2
inst✝² : CommRing R
inst✝¹ : CommRing A
inst✝ : Algebra R A
θ : ℂ
n : ℕ
⊢ eval (cos θ) (T ℂ (n + 2)) = cos (↑(n + 2) * θ)

Next tactic:
have : (2 : ℂ[X]) = (2 : ℕ) := by norm_num
/-- The `n`-th Chebyshev polynomial of the first kind evaluates on `cos θ` to the
value `cos (n * θ)`. -/
@[simp]
theorem T_complex_cos : ∀ n, (T ℂ n).eval (cos θ) = cos (n * θ)
  | 0 => by simp only [T_zero, eval_one, Nat.cast_zero, zero_mul, cos_zero]
  | 1 => by simp only [eval_X, one_mul, T_one, Nat.cast_one]
  | n + 2 => by
    -- Porting note: partially rewrote proof for lean4 numerals.
    have : (2 : ℂ[X]) = (2 : ℕ) := by 

Proof state:
R : Type u_1
A : Type u_2
inst✝² : CommRing R
inst✝¹ : CommRing A
inst✝ : Algebra R A
θ : ℂ
n : ℕ
⊢ 2 = ↑2

Next tactic:
norm_num
/-- The `n`-th Chebyshev polynomial of the first kind evaluates on `cos θ` to the
value `cos (n * θ)`. -/
@[simp]
theorem T_complex_cos : ∀ n, (T ℂ n).eval (cos θ) = cos (n * θ)
  | 0 => by simp only [T_zero, eval_one, Nat.cast_zero, zero_mul, cos_zero]
  | 1 => by simp only [eval_X, one_mul, T_one, Nat.cast_one]
  | n + 2 => by
    -- Porting note: partially rewrote proof for lean4 numerals.
    have : (2 : ℂ[X]) = (2 : ℕ) := by norm_num
    

Proof state:
R : Type u_1
A : Type u_2
inst✝² : CommRing R
inst✝¹ : CommRing A
inst✝ : Algebra R A
θ : ℂ
n : ℕ
this : 2 = ↑2
⊢ eval (cos θ) (T ℂ (n + 2)) = cos (↑(n + 2) * θ)

Next tactic:
simp only [this, eval_X, eval_one, T_add_two, eval_sub, eval_mul, eval_nat_cast]
/-- The `n`-th Chebyshev polynomial of the first kind evaluates on `cos θ` to the
value `cos (n * θ)`. -/
@[simp]
theorem T_complex_cos : ∀ n, (T ℂ n).eval (cos θ) = cos (n * θ)
  | 0 => by simp only [T_zero, eval_one, Nat.cast_zero, zero_mul, cos_zero]
  | 1 => by simp only [eval_X, one_mul, T_one, Nat.cast_one]
  | n + 2 => by
    -- Porting note: partially rewrote proof for lean4 numerals.
    have : (2 : ℂ[X]) = (2 : ℕ) := by norm_num
    simp only [this, eval_X, eval_one, T_add_two, eval_sub, eval_mul, eval_nat_cast]
    

Proof state:
R : Type u_1
A : Type u_2
inst✝² : CommRing R
inst✝¹ : CommRing A
inst✝ : Algebra R A
θ : ℂ
n : ℕ
this : 2 = ↑2
⊢ ↑2 * cos θ * eval (cos θ) (T ℂ (n + 1)) - eval (cos θ) (T ℂ n) = cos (↑(n + 2) * θ)

Next tactic:
simp only [Nat.cast_ofNat, Nat.cast_add]
/-- The `n`-th Chebyshev polynomial of the first kind evaluates on `cos θ` to the
value `cos (n * θ)`. -/
@[simp]
theorem T_complex_cos : ∀ n, (T ℂ n).eval (cos θ) = cos (n * θ)
  | 0 => by simp only [T_zero, eval_one, Nat.cast_zero, zero_mul, cos_zero]
  | 1 => by simp only [eval_X, one_mul, T_one, Nat.cast_one]
  | n + 2 => by
    -- Porting note: partially rewrote proof for lean4 numerals.
    have : (2 : ℂ[X]) = (2 : ℕ) := by norm_num
    simp only [this, eval_X, eval_one, T_add_two, eval_sub, eval_mul, eval_nat_cast]
    simp only [Nat.cast_ofNat, Nat.cast_add]
    

Proof state:
R : Type u_1
A : Type u_2
inst✝² : CommRing R
inst✝¹ : CommRing A
inst✝ : Algebra R A
θ : ℂ
n : ℕ
this : 2 = ↑2
⊢ 2 * cos θ * eval (cos θ) (T ℂ (n + 1)) - eval (cos θ) (T ℂ n) = cos ((↑n + 2) * θ)

Next tactic:
rw [T_complex_cos (n + 1), T_complex_cos n]
/-- The `n`-th Chebyshev polynomial of the first kind evaluates on `cos θ` to the
value `cos (n * θ)`. -/
@[simp]
theorem T_complex_cos : ∀ n, (T ℂ n).eval (cos θ) = cos (n * θ)
  | 0 => by simp only [T_zero, eval_one, Nat.cast_zero, zero_mul, cos_zero]
  | 1 => by simp only [eval_X, one_mul, T_one, Nat.cast_one]
  | n + 2 => by
    -- Porting note: partially rewrote proof for lean4 numerals.
    have : (2 : ℂ[X]) = (2 : ℕ) := by norm_num
    simp only [this, eval_X, eval_one, T_add_two, eval_sub, eval_mul, eval_nat_cast]
    simp only [Nat.cast_ofNat, Nat.cast_add]
    rw [T_complex_cos (n + 1), T_complex_cos n]
    

Proof state:
R : Type u_1
A : Type u_2
inst✝² : CommRing R
inst✝¹ : CommRing A
inst✝ : Algebra R A
θ : ℂ
n : ℕ
this : 2 = ↑2
⊢ 2 * cos θ * cos (↑(n + 1) * θ) - cos (↑n * θ) = cos ((↑n + 2) * θ)

Next tactic:
simp only [Nat.cast_add, Nat.cast_one, add_mul, cos_add, one_mul, mul_assoc, sin_two_mul,
      cos_two_mul]
/-- The `n`-th Chebyshev polynomial of the first kind evaluates on `cos θ` to the
value `cos (n * θ)`. -/
@[simp]
theorem T_complex_cos : ∀ n, (T ℂ n).eval (cos θ) = cos (n * θ)
  | 0 => by simp only [T_zero, eval_one, Nat.cast_zero, zero_mul, cos_zero]
  | 1 => by simp only [eval_X, one_mul, T_one, Nat.cast_one]
  | n + 2 => by
    -- Porting note: partially rewrote proof for lean4 numerals.
    have : (2 : ℂ[X]) = (2 : ℕ) := by norm_num
    simp only [this, eval_X, eval_one, T_add_two, eval_sub, eval_mul, eval_nat_cast]
    simp only [Nat.cast_ofNat, Nat.cast_add]
    rw [T_complex_cos (n + 1), T_complex_cos n]
    simp only [Nat.cast_add, Nat.cast_one, add_mul, cos_add, one_mul, mul_assoc, sin_two_mul,
      cos_two_mul]
    

Proof state:
R : Type u_1
A : Type u_2
inst✝² : CommRing R
inst✝¹ : CommRing A
inst✝ : Algebra R A
θ : ℂ
n : ℕ
this : 2 = ↑2
⊢ 2 * (cos θ * (cos (↑n * θ) * cos θ - sin (↑n * θ) * sin θ)) - cos (↑n * θ) =
    cos (↑n * θ) * (2 * cos θ ^ 2 - 1) - sin (↑n * θ) * (2 * (sin θ * cos θ))

Next tactic:
ring
/-- The `n`-th Chebyshev polynomial of the second kind evaluates on `cos θ` to the
value `sin ((n + 1) * θ) / sin θ`. -/
@[simp]
theorem U_complex_cos (n : ℕ) : (U ℂ n).eval (cos θ) * sin θ = sin ((n + 1) * θ) := by
  

Proof state:
R : Type u_1
A : Type u_2
inst✝² : CommRing R
inst✝¹ : CommRing A
inst✝ : Algebra R A
θ : ℂ
n : ℕ
⊢ eval (cos θ) (U ℂ n) * sin θ = sin ((↑n + 1) * θ)

Next tactic:
induction' n with d hd
/-- The `n`-th Chebyshev polynomial of the second kind evaluates on `cos θ` to the
value `sin ((n + 1) * θ) / sin θ`. -/
@[simp]
theorem U_complex_cos (n : ℕ) : (U ℂ n).eval (cos θ) * sin θ = sin ((n + 1) * θ) := by
  induction' n with d hd
  · 

Proof state:
case zero
R : Type u_1
A : Type u_2
inst✝² : CommRing R
inst✝¹ : CommRing A
inst✝ : Algebra R A
θ : ℂ
⊢ eval (cos θ) (U ℂ Nat.zero) * sin θ = sin ((↑Nat.zero + 1) * θ)

Next tactic:
simp [U_zero, eval_one, zero_add, one_mul, Nat.zero_eq, CharP.cast_eq_zero]
/-- The `n`-th Chebyshev polynomial of the second kind evaluates on `cos θ` to the
value `sin ((n + 1) * θ) / sin θ`. -/
@[simp]
theorem U_complex_cos (n : ℕ) : (U ℂ n).eval (cos θ) * sin θ = sin ((n + 1) * θ) := by
  induction' n with d hd
  · simp [U_zero, eval_one, zero_add, one_mul, Nat.zero_eq, CharP.cast_eq_zero]
  · 

Proof state:
case succ
R : Type u_1
A : Type u_2
inst✝² : CommRing R
inst✝¹ : CommRing A
inst✝ : Algebra R A
θ : ℂ
d : ℕ
hd : eval (cos θ) (U ℂ d) * sin θ = sin ((↑d + 1) * θ)
⊢ eval (cos θ) (U ℂ (Nat.succ d)) * sin θ = sin ((↑(Nat.succ d) + 1) * θ)

Next tactic:
rw [U_eq_X_mul_U_add_T]
/-- The `n`-th Chebyshev polynomial of the second kind evaluates on `cos θ` to the
value `sin ((n + 1) * θ) / sin θ`. -/
@[simp]
theorem U_complex_cos (n : ℕ) : (U ℂ n).eval (cos θ) * sin θ = sin ((n + 1) * θ) := by
  induction' n with d hd
  · simp [U_zero, eval_one, zero_add, one_mul, Nat.zero_eq, CharP.cast_eq_zero]
  · rw [U_eq_X_mul_U_add_T]
    

Proof state:
case succ
R : Type u_1
A : Type u_2
inst✝² : CommRing R
inst✝¹ : CommRing A
inst✝ : Algebra R A
θ : ℂ
d : ℕ
hd : eval (cos θ) (U ℂ d) * sin θ = sin ((↑d + 1) * θ)
⊢ eval (cos θ) (X * U ℂ d + T ℂ (d + 1)) * sin θ = sin ((↑(Nat.succ d) + 1) * θ)

Next tactic:
simp only [eval_add, eval_mul, eval_X, T_complex_cos, add_mul, mul_assoc, hd, one_mul]
/-- The `n`-th Chebyshev polynomial of the second kind evaluates on `cos θ` to the
value `sin ((n + 1) * θ) / sin θ`. -/
@[simp]
theorem U_complex_cos (n : ℕ) : (U ℂ n).eval (cos θ) * sin θ = sin ((n + 1) * θ) := by
  induction' n with d hd
  · simp [U_zero, eval_one, zero_add, one_mul, Nat.zero_eq, CharP.cast_eq_zero]
  · rw [U_eq_X_mul_U_add_T]
    simp only [eval_add, eval_mul, eval_X, T_complex_cos, add_mul, mul_assoc, hd, one_mul]
    -- Porting note: added `trans` to prevent `rw` from going on a wild goose chase applying `rfl`
    

Proof state:
case succ
R : Type u_1
A : Type u_2
inst✝² : CommRing R
inst✝¹ : CommRing A
inst✝ : Algebra R A
θ : ℂ
d : ℕ
hd : eval (cos θ) (U ℂ d) * sin θ = sin ((↑d + 1) * θ)
⊢ cos θ * sin (↑d * θ + θ) + cos (↑(d + 1) * θ) * sin θ = sin (↑(Nat.succ d) * θ + θ)

Next tactic:
trans cos θ * sin (↑(d.succ) * θ) + cos (↑(d.succ) * θ) * sin θ
/-- The `n`-th Chebyshev polynomial of the second kind evaluates on `cos θ` to the
value `sin ((n + 1) * θ) / sin θ`. -/
@[simp]
theorem U_complex_cos (n : ℕ) : (U ℂ n).eval (cos θ) * sin θ = sin ((n + 1) * θ) := by
  induction' n with d hd
  · simp [U_zero, eval_one, zero_add, one_mul, Nat.zero_eq, CharP.cast_eq_zero]
  · rw [U_eq_X_mul_U_add_T]
    simp only [eval_add, eval_mul, eval_X, T_complex_cos, add_mul, mul_assoc, hd, one_mul]
    -- Porting note: added `trans` to prevent `rw` from going on a wild goose chase applying `rfl`
    trans cos θ * sin (↑(d.succ) * θ) + cos (↑(d.succ) * θ) * sin θ
    

Proof state:
R : Type u_1
A : Type u_2
inst✝² : CommRing R
inst✝¹ : CommRing A
inst✝ : Algebra R A
θ : ℂ
d : ℕ
hd : eval (cos θ) (U ℂ d) * sin θ = sin ((↑d + 1) * θ)
⊢ cos θ * sin (↑d * θ + θ) + cos (↑(d + 1) * θ) * sin θ =
    cos θ * sin (↑(Nat.succ d) * θ) + cos (↑(Nat.succ d) * θ) * sin θ
R : Type u_1
A : Type u_2
inst✝² : CommRing R
inst✝¹ : CommRing A
inst✝ : Algebra R A
θ : ℂ
d : ℕ
hd : eval (cos θ) (U ℂ d) * sin θ = sin ((↑d + 1) * θ)
⊢ cos θ * sin (↑(Nat.succ d) * θ) + cos (↑(Nat.succ d) * θ) * sin θ = sin (↑(Nat.succ d) * θ + θ)

Next tactic:
swap
/-- The `n`-th Chebyshev polynomial of the second kind evaluates on `cos θ` to the
value `sin ((n + 1) * θ) / sin θ`. -/
@[simp]
theorem U_complex_cos (n : ℕ) : (U ℂ n).eval (cos θ) * sin θ = sin ((n + 1) * θ) := by
  induction' n with d hd
  · simp [U_zero, eval_one, zero_add, one_mul, Nat.zero_eq, CharP.cast_eq_zero]
  · rw [U_eq_X_mul_U_add_T]
    simp only [eval_add, eval_mul, eval_X, T_complex_cos, add_mul, mul_assoc, hd, one_mul]
    -- Porting note: added `trans` to prevent `rw` from going on a wild goose chase applying `rfl`
    trans cos θ * sin (↑(d.succ) * θ) + cos (↑(d.succ) * θ) * sin θ
    swap
    · 

Proof state:
R : Type u_1
A : Type u_2
inst✝² : CommRing R
inst✝¹ : CommRing A
inst✝ : Algebra R A
θ : ℂ
d : ℕ
hd : eval (cos θ) (U ℂ d) * sin θ = sin ((↑d + 1) * θ)
⊢ cos θ * sin (↑(Nat.succ d) * θ) + cos (↑(Nat.succ d) * θ) * sin θ = sin (↑(Nat.succ d) * θ + θ)

Next tactic:
conv_rhs => rw [sin_add, mul_comm]
/-- The `n`-th Chebyshev polynomial of the second kind evaluates on `cos θ` to the
value `sin ((n + 1) * θ) / sin θ`. -/
@[simp]
theorem U_complex_cos (n : ℕ) : (U ℂ n).eval (cos θ) * sin θ = sin ((n + 1) * θ) := by
  induction' n with d hd
  · simp [U_zero, eval_one, zero_add, one_mul, Nat.zero_eq, CharP.cast_eq_zero]
  · rw [U_eq_X_mul_U_add_T]
    simp only [eval_add, eval_mul, eval_X, T_complex_cos, add_mul, mul_assoc, hd, one_mul]
    -- Porting note: added `trans` to prevent `rw` from going on a wild goose chase applying `rfl`
    trans cos θ * sin (↑(d.succ) * θ) + cos (↑(d.succ) * θ) * sin θ
    swap
    · conv_rhs => 

Proof state:
R : Type u_1
A : Type u_2
inst✝² : CommRing R
inst✝¹ : CommRing A
inst✝ : Algebra R A
θ : ℂ
d : ℕ
hd : eval (cos θ) (U ℂ d) * sin θ = sin ((↑d + 1) * θ)
| sin (↑(Nat.succ d) * θ + θ)

Next tactic:
rw [sin_add, mul_comm]
/-- The `n`-th Chebyshev polynomial of the second kind evaluates on `cos θ` to the
value `sin ((n + 1) * θ) / sin θ`. -/
@[simp]
theorem U_complex_cos (n : ℕ) : (U ℂ n).eval (cos θ) * sin θ = sin ((n + 1) * θ) := by
  induction' n with d hd
  · simp [U_zero, eval_one, zero_add, one_mul, Nat.zero_eq, CharP.cast_eq_zero]
  · rw [U_eq_X_mul_U_add_T]
    simp only [eval_add, eval_mul, eval_X, T_complex_cos, add_mul, mul_assoc, hd, one_mul]
    -- Porting note: added `trans` to prevent `rw` from going on a wild goose chase applying `rfl`
    trans cos θ * sin (↑(d.succ) * θ) + cos (↑(d.succ) * θ) * sin θ
    swap
    · conv_rhs => rw [sin_add, mul_comm]
    

Proof state:
R : Type u_1
A : Type u_2
inst✝² : CommRing R
inst✝¹ : CommRing A
inst✝ : Algebra R A
θ : ℂ
d : ℕ
hd : eval (cos θ) (U ℂ d) * sin θ = sin ((↑d + 1) * θ)
⊢ cos θ * sin (↑d * θ + θ) + cos (↑(d + 1) * θ) * sin θ =
    cos θ * sin (↑(Nat.succ d) * θ) + cos (↑(Nat.succ d) * θ) * sin θ

Next tactic:
push_cast
/-- The `n`-th Chebyshev polynomial of the second kind evaluates on `cos θ` to the
value `sin ((n + 1) * θ) / sin θ`. -/
@[simp]
theorem U_complex_cos (n : ℕ) : (U ℂ n).eval (cos θ) * sin θ = sin ((n + 1) * θ) := by
  induction' n with d hd
  · simp [U_zero, eval_one, zero_add, one_mul, Nat.zero_eq, CharP.cast_eq_zero]
  · rw [U_eq_X_mul_U_add_T]
    simp only [eval_add, eval_mul, eval_X, T_complex_cos, add_mul, mul_assoc, hd, one_mul]
    -- Porting note: added `trans` to prevent `rw` from going on a wild goose chase applying `rfl`
    trans cos θ * sin (↑(d.succ) * θ) + cos (↑(d.succ) * θ) * sin θ
    swap
    · conv_rhs => rw [sin_add, mul_comm]
    push_cast
    

Proof state:
R : Type u_1
A : Type u_2
inst✝² : CommRing R
inst✝¹ : CommRing A
inst✝ : Algebra R A
θ : ℂ
d : ℕ
hd : eval (cos θ) (U ℂ d) * sin θ = sin ((↑d + 1) * θ)
⊢ cos θ * sin (↑d * θ + θ) + cos ((↑d + 1) * θ) * sin θ = cos θ * sin ((↑d + 1) * θ) + cos ((↑d + 1) * θ) * sin θ

Next tactic:
simp only [add_mul, one_mul]
@[simp]
theorem mem_neLocus {f g : Π₀ a, N a} {a : α} : a ∈ f.neLocus g ↔ f a ≠ g a := by
  

Proof state:
α : Type u_1
N : α → Type u_2
inst✝² : DecidableEq α
inst✝¹ : (a : α) → DecidableEq (N a)
inst✝ : (a : α) → Zero (N a)
f✝ g✝ f g : Π₀ (a : α), N a
a : α
⊢ a ∈ neLocus f g ↔ f a ≠ g a

Next tactic:
simpa only [neLocus, Finset.mem_filter, Finset.mem_union, mem_support_iff,
    and_iff_right_iff_imp] using Ne.ne_or_ne _
@[simp]
theorem neLocus_eq_empty {f g : Π₀ a, N a} : f.neLocus g = ∅ ↔ f = g :=
  ⟨fun h ↦
    ext fun a ↦ not_not.mp (mem_neLocus.not.mp (Finset.eq_empty_iff_forall_not_mem.mp h a)),
    fun h ↦ h ▸ by 

Proof state:
α : Type u_1
N : α → Type u_2
inst✝² : DecidableEq α
inst✝¹ : (a : α) → DecidableEq (N a)
inst✝ : (a : α) → Zero (N a)
f✝ g✝ f g : Π₀ (a : α), N a
h : f = g
⊢ neLocus f f = ∅

Next tactic:
simp only [neLocus, Ne.def, eq_self_iff_true, not_true, Finset.filter_False]
theorem neLocus_comm : f.neLocus g = g.neLocus f := by
  

Proof state:
α : Type u_1
N : α → Type u_2
inst✝² : DecidableEq α
inst✝¹ : (a : α) → DecidableEq (N a)
inst✝ : (a : α) → Zero (N a)
f g : Π₀ (a : α), N a
⊢ neLocus f g = neLocus g f

Next tactic:
simp_rw [neLocus, Finset.union_comm, ne_comm]
@[simp]
theorem neLocus_zero_right : f.neLocus 0 = f.support := by
  

Proof state:
α : Type u_1
N : α → Type u_2
inst✝² : DecidableEq α
inst✝¹ : (a : α) → DecidableEq (N a)
inst✝ : (a : α) → Zero (N a)
f g : Π₀ (a : α), N a
⊢ neLocus f 0 = support f

Next tactic:
ext
@[simp]
theorem neLocus_zero_right : f.neLocus 0 = f.support := by
  ext
  

Proof state:
case a
α : Type u_1
N : α → Type u_2
inst✝² : DecidableEq α
inst✝¹ : (a : α) → DecidableEq (N a)
inst✝ : (a : α) → Zero (N a)
f g : Π₀ (a : α), N a
a✝ : α
⊢ a✝ ∈ neLocus f 0 ↔ a✝ ∈ support f

Next tactic:
rw [mem_neLocus, mem_support_iff, coe_zero, Pi.zero_apply]