l3lab/ntp-mathlib huggingface dataset:
/-- `eval` is an additive homomorphism except when a denominator evaluates to `0`.

Counterexample: `eval _ 1 (X / (X-1)) + eval _ 1 (-1 / (X-1)) = 0`
`... ≠ 1 = eval _ 1 ((X-1) / (X-1))`.

See also `RatFunc.eval₂_denom_ne_zero` to make the hypotheses simpler but less general.
-/
theorem eval_add {x y : RatFunc K} (hx : Polynomial.eval₂ f a (denom x) ≠ 0)
    (hy : Polynomial.eval₂ f a (denom y) ≠ 0) : eval f a (x + y) = eval f a x + eval f a y := by
  unfold eval
  by_cases hxy : Polynomial.eval₂ f a (denom (x + y)) = 0
  · have := Polynomial.eval₂_eq_zero_of_dvd_of_eval₂_eq_zero f a (denom_add_dvd x y) hxy
    rw [Polynomial.eval₂_mul] at this
    cases mul_eq_zero.mp this <;> contradiction
  

Proof state:
case neg
K : Type u
inst✝¹ : Field K
L : Type u_1
inst✝ : Field L
f : K →+* L
a : L
x y : RatFunc K
hx : Polynomial.eval₂ f a (denom x) ≠ 0
hy : Polynomial.eval₂ f a (denom y) ≠ 0
hxy : ¬Polynomial.eval₂ f a (denom (x + y)) = 0
⊢ Polynomial.eval₂ f a (num (x + y)) / Polynomial.eval₂ f a (denom (x + y)) =
    Polynomial.eval₂ f a (num x) / Polynomial.eval₂ f a (denom x) +
      Polynomial.eval₂ f a (num y) / Polynomial.eval₂ f a (denom y)

Next tactic:
rw [div_add_div _ _ hx hy, eq_div_iff (mul_ne_zero hx hy), div_eq_mul_inv, mul_right_comm, ←
    div_eq_mul_inv, div_eq_iff hxy]
/-- `eval` is an additive homomorphism except when a denominator evaluates to `0`.

Counterexample: `eval _ 1 (X / (X-1)) + eval _ 1 (-1 / (X-1)) = 0`
`... ≠ 1 = eval _ 1 ((X-1) / (X-1))`.

See also `RatFunc.eval₂_denom_ne_zero` to make the hypotheses simpler but less general.
-/
theorem eval_add {x y : RatFunc K} (hx : Polynomial.eval₂ f a (denom x) ≠ 0)
    (hy : Polynomial.eval₂ f a (denom y) ≠ 0) : eval f a (x + y) = eval f a x + eval f a y := by
  unfold eval
  by_cases hxy : Polynomial.eval₂ f a (denom (x + y)) = 0
  · have := Polynomial.eval₂_eq_zero_of_dvd_of_eval₂_eq_zero f a (denom_add_dvd x y) hxy
    rw [Polynomial.eval₂_mul] at this
    cases mul_eq_zero.mp this <;> contradiction
  rw [div_add_div _ _ hx hy, eq_div_iff (mul_ne_zero hx hy), div_eq_mul_inv, mul_right_comm, ←
    div_eq_mul_inv, div_eq_iff hxy]
  

Proof state:
case neg
K : Type u
inst✝¹ : Field K
L : Type u_1
inst✝ : Field L
f : K →+* L
a : L
x y : RatFunc K
hx : Polynomial.eval₂ f a (denom x) ≠ 0
hy : Polynomial.eval₂ f a (denom y) ≠ 0
hxy : ¬Polynomial.eval₂ f a (denom (x + y)) = 0
⊢ Polynomial.eval₂ f a (num (x + y)) * (Polynomial.eval₂ f a (denom x) * Polynomial.eval₂ f a (denom y)) =
    (Polynomial.eval₂ f a (num x) * Polynomial.eval₂ f a (denom y) +
        Polynomial.eval₂ f a (denom x) * Polynomial.eval₂ f a (num y)) *
      Polynomial.eval₂ f a (denom (x + y))

Next tactic:
simp only [← Polynomial.eval₂_mul, ← Polynomial.eval₂_add]
/-- `eval` is an additive homomorphism except when a denominator evaluates to `0`.

Counterexample: `eval _ 1 (X / (X-1)) + eval _ 1 (-1 / (X-1)) = 0`
`... ≠ 1 = eval _ 1 ((X-1) / (X-1))`.

See also `RatFunc.eval₂_denom_ne_zero` to make the hypotheses simpler but less general.
-/
theorem eval_add {x y : RatFunc K} (hx : Polynomial.eval₂ f a (denom x) ≠ 0)
    (hy : Polynomial.eval₂ f a (denom y) ≠ 0) : eval f a (x + y) = eval f a x + eval f a y := by
  unfold eval
  by_cases hxy : Polynomial.eval₂ f a (denom (x + y)) = 0
  · have := Polynomial.eval₂_eq_zero_of_dvd_of_eval₂_eq_zero f a (denom_add_dvd x y) hxy
    rw [Polynomial.eval₂_mul] at this
    cases mul_eq_zero.mp this <;> contradiction
  rw [div_add_div _ _ hx hy, eq_div_iff (mul_ne_zero hx hy), div_eq_mul_inv, mul_right_comm, ←
    div_eq_mul_inv, div_eq_iff hxy]
  simp only [← Polynomial.eval₂_mul, ← Polynomial.eval₂_add]
  

Proof state:
case neg
K : Type u
inst✝¹ : Field K
L : Type u_1
inst✝ : Field L
f : K →+* L
a : L
x y : RatFunc K
hx : Polynomial.eval₂ f a (denom x) ≠ 0
hy : Polynomial.eval₂ f a (denom y) ≠ 0
hxy : ¬Polynomial.eval₂ f a (denom (x + y)) = 0
⊢ Polynomial.eval₂ f a (num (x + y) * (denom x * denom y)) =
    Polynomial.eval₂ f a ((num x * denom y + denom x * num y) * denom (x + y))

Next tactic:
congr 1
/-- `eval` is an additive homomorphism except when a denominator evaluates to `0`.

Counterexample: `eval _ 1 (X / (X-1)) + eval _ 1 (-1 / (X-1)) = 0`
`... ≠ 1 = eval _ 1 ((X-1) / (X-1))`.

See also `RatFunc.eval₂_denom_ne_zero` to make the hypotheses simpler but less general.
-/
theorem eval_add {x y : RatFunc K} (hx : Polynomial.eval₂ f a (denom x) ≠ 0)
    (hy : Polynomial.eval₂ f a (denom y) ≠ 0) : eval f a (x + y) = eval f a x + eval f a y := by
  unfold eval
  by_cases hxy : Polynomial.eval₂ f a (denom (x + y)) = 0
  · have := Polynomial.eval₂_eq_zero_of_dvd_of_eval₂_eq_zero f a (denom_add_dvd x y) hxy
    rw [Polynomial.eval₂_mul] at this
    cases mul_eq_zero.mp this <;> contradiction
  rw [div_add_div _ _ hx hy, eq_div_iff (mul_ne_zero hx hy), div_eq_mul_inv, mul_right_comm, ←
    div_eq_mul_inv, div_eq_iff hxy]
  simp only [← Polynomial.eval₂_mul, ← Polynomial.eval₂_add]
  congr 1
  

Proof state:
case neg.e_p
K : Type u
inst✝¹ : Field K
L : Type u_1
inst✝ : Field L
f : K →+* L
a : L
x y : RatFunc K
hx : Polynomial.eval₂ f a (denom x) ≠ 0
hy : Polynomial.eval₂ f a (denom y) ≠ 0
hxy : ¬Polynomial.eval₂ f a (denom (x + y)) = 0
⊢ num (x + y) * (denom x * denom y) = (num x * denom y + denom x * num y) * denom (x + y)

Next tactic:
apply num_denom_add
/-- `eval` is a multiplicative homomorphism except when a denominator evaluates to `0`.

Counterexample: `eval _ 0 X * eval _ 0 (1/X) = 0 ≠ 1 = eval _ 0 1 = eval _ 0 (X * 1/X)`.

See also `RatFunc.eval₂_denom_ne_zero` to make the hypotheses simpler but less general.
-/
theorem eval_mul {x y : RatFunc K} (hx : Polynomial.eval₂ f a (denom x) ≠ 0)
    (hy : Polynomial.eval₂ f a (denom y) ≠ 0) : eval f a (x * y) = eval f a x * eval f a y := by
  

Proof state:
K : Type u
inst✝¹ : Field K
L : Type u_1
inst✝ : Field L
f : K →+* L
a : L
x y : RatFunc K
hx : Polynomial.eval₂ f a (denom x) ≠ 0
hy : Polynomial.eval₂ f a (denom y) ≠ 0
⊢ eval f a (x * y) = eval f a x * eval f a y

Next tactic:
unfold eval
/-- `eval` is a multiplicative homomorphism except when a denominator evaluates to `0`.

Counterexample: `eval _ 0 X * eval _ 0 (1/X) = 0 ≠ 1 = eval _ 0 1 = eval _ 0 (X * 1/X)`.

See also `RatFunc.eval₂_denom_ne_zero` to make the hypotheses simpler but less general.
-/
theorem eval_mul {x y : RatFunc K} (hx : Polynomial.eval₂ f a (denom x) ≠ 0)
    (hy : Polynomial.eval₂ f a (denom y) ≠ 0) : eval f a (x * y) = eval f a x * eval f a y := by
  unfold eval
  

Proof state:
K : Type u
inst✝¹ : Field K
L : Type u_1
inst✝ : Field L
f : K →+* L
a : L
x y : RatFunc K
hx : Polynomial.eval₂ f a (denom x) ≠ 0
hy : Polynomial.eval₂ f a (denom y) ≠ 0
⊢ Polynomial.eval₂ f a (num (x * y)) / Polynomial.eval₂ f a (denom (x * y)) =
    Polynomial.eval₂ f a (num x) / Polynomial.eval₂ f a (denom x) *
      (Polynomial.eval₂ f a (num y) / Polynomial.eval₂ f a (denom y))

Next tactic:
by_cases hxy : Polynomial.eval₂ f a (denom (x * y)) = 0
/-- `eval` is a multiplicative homomorphism except when a denominator evaluates to `0`.

Counterexample: `eval _ 0 X * eval _ 0 (1/X) = 0 ≠ 1 = eval _ 0 1 = eval _ 0 (X * 1/X)`.

See also `RatFunc.eval₂_denom_ne_zero` to make the hypotheses simpler but less general.
-/
theorem eval_mul {x y : RatFunc K} (hx : Polynomial.eval₂ f a (denom x) ≠ 0)
    (hy : Polynomial.eval₂ f a (denom y) ≠ 0) : eval f a (x * y) = eval f a x * eval f a y := by
  unfold eval
  by_cases hxy : Polynomial.eval₂ f a (denom (x * y)) = 0
  · 

Proof state:
case pos
K : Type u
inst✝¹ : Field K
L : Type u_1
inst✝ : Field L
f : K →+* L
a : L
x y : RatFunc K
hx : Polynomial.eval₂ f a (denom x) ≠ 0
hy : Polynomial.eval₂ f a (denom y) ≠ 0
hxy : Polynomial.eval₂ f a (denom (x * y)) = 0
⊢ Polynomial.eval₂ f a (num (x * y)) / Polynomial.eval₂ f a (denom (x * y)) =
    Polynomial.eval₂ f a (num x) / Polynomial.eval₂ f a (denom x) *
      (Polynomial.eval₂ f a (num y) / Polynomial.eval₂ f a (denom y))

Next tactic:
have := Polynomial.eval₂_eq_zero_of_dvd_of_eval₂_eq_zero f a (denom_mul_dvd x y) hxy
/-- `eval` is a multiplicative homomorphism except when a denominator evaluates to `0`.

Counterexample: `eval _ 0 X * eval _ 0 (1/X) = 0 ≠ 1 = eval _ 0 1 = eval _ 0 (X * 1/X)`.

See also `RatFunc.eval₂_denom_ne_zero` to make the hypotheses simpler but less general.
-/
theorem eval_mul {x y : RatFunc K} (hx : Polynomial.eval₂ f a (denom x) ≠ 0)
    (hy : Polynomial.eval₂ f a (denom y) ≠ 0) : eval f a (x * y) = eval f a x * eval f a y := by
  unfold eval
  by_cases hxy : Polynomial.eval₂ f a (denom (x * y)) = 0
  · have := Polynomial.eval₂_eq_zero_of_dvd_of_eval₂_eq_zero f a (denom_mul_dvd x y) hxy
    

Proof state:
case pos
K : Type u
inst✝¹ : Field K
L : Type u_1
inst✝ : Field L
f : K →+* L
a : L
x y : RatFunc K
hx : Polynomial.eval₂ f a (denom x) ≠ 0
hy : Polynomial.eval₂ f a (denom y) ≠ 0
hxy : Polynomial.eval₂ f a (denom (x * y)) = 0
this : Polynomial.eval₂ f a (denom x * denom y) = 0
⊢ Polynomial.eval₂ f a (num (x * y)) / Polynomial.eval₂ f a (denom (x * y)) =
    Polynomial.eval₂ f a (num x) / Polynomial.eval₂ f a (denom x) *
      (Polynomial.eval₂ f a (num y) / Polynomial.eval₂ f a (denom y))

Next tactic:
rw [Polynomial.eval₂_mul] at this
/-- `eval` is a multiplicative homomorphism except when a denominator evaluates to `0`.

Counterexample: `eval _ 0 X * eval _ 0 (1/X) = 0 ≠ 1 = eval _ 0 1 = eval _ 0 (X * 1/X)`.

See also `RatFunc.eval₂_denom_ne_zero` to make the hypotheses simpler but less general.
-/
theorem eval_mul {x y : RatFunc K} (hx : Polynomial.eval₂ f a (denom x) ≠ 0)
    (hy : Polynomial.eval₂ f a (denom y) ≠ 0) : eval f a (x * y) = eval f a x * eval f a y := by
  unfold eval
  by_cases hxy : Polynomial.eval₂ f a (denom (x * y)) = 0
  · have := Polynomial.eval₂_eq_zero_of_dvd_of_eval₂_eq_zero f a (denom_mul_dvd x y) hxy
    rw [Polynomial.eval₂_mul] at this
    

Proof state:
case pos
K : Type u
inst✝¹ : Field K
L : Type u_1
inst✝ : Field L
f : K →+* L
a : L
x y : RatFunc K
hx : Polynomial.eval₂ f a (denom x) ≠ 0
hy : Polynomial.eval₂ f a (denom y) ≠ 0
hxy : Polynomial.eval₂ f a (denom (x * y)) = 0
this : Polynomial.eval₂ f a (denom x) * Polynomial.eval₂ f a (denom y) = 0
⊢ Polynomial.eval₂ f a (num (x * y)) / Polynomial.eval₂ f a (denom (x * y)) =
    Polynomial.eval₂ f a (num x) / Polynomial.eval₂ f a (denom x) *
      (Polynomial.eval₂ f a (num y) / Polynomial.eval₂ f a (denom y))

Next tactic:
cases mul_eq_zero.mp this
/-- `eval` is a multiplicative homomorphism except when a denominator evaluates to `0`.

Counterexample: `eval _ 0 X * eval _ 0 (1/X) = 0 ≠ 1 = eval _ 0 1 = eval _ 0 (X * 1/X)`.

See also `RatFunc.eval₂_denom_ne_zero` to make the hypotheses simpler but less general.
-/
theorem eval_mul {x y : RatFunc K} (hx : Polynomial.eval₂ f a (denom x) ≠ 0)
    (hy : Polynomial.eval₂ f a (denom y) ≠ 0) : eval f a (x * y) = eval f a x * eval f a y := by
  unfold eval
  by_cases hxy : Polynomial.eval₂ f a (denom (x * y)) = 0
  · have := Polynomial.eval₂_eq_zero_of_dvd_of_eval₂_eq_zero f a (denom_mul_dvd x y) hxy
    rw [Polynomial.eval₂_mul] at this
    cases mul_eq_zero.mp this <;> 

Proof state:
case pos.inl
K : Type u
inst✝¹ : Field K
L : Type u_1
inst✝ : Field L
f : K →+* L
a : L
x y : RatFunc K
hx : Polynomial.eval₂ f a (denom x) ≠ 0
hy : Polynomial.eval₂ f a (denom y) ≠ 0
hxy : Polynomial.eval₂ f a (denom (x * y)) = 0
this : Polynomial.eval₂ f a (denom x) * Polynomial.eval₂ f a (denom y) = 0
h✝ : Polynomial.eval₂ f a (denom x) = 0
⊢ Polynomial.eval₂ f a (num (x * y)) / Polynomial.eval₂ f a (denom (x * y)) =
    Polynomial.eval₂ f a (num x) / Polynomial.eval₂ f a (denom x) *
      (Polynomial.eval₂ f a (num y) / Polynomial.eval₂ f a (denom y))

Next tactic:
contradiction
/-- `eval` is a multiplicative homomorphism except when a denominator evaluates to `0`.

Counterexample: `eval _ 0 X * eval _ 0 (1/X) = 0 ≠ 1 = eval _ 0 1 = eval _ 0 (X * 1/X)`.

See also `RatFunc.eval₂_denom_ne_zero` to make the hypotheses simpler but less general.
-/
theorem eval_mul {x y : RatFunc K} (hx : Polynomial.eval₂ f a (denom x) ≠ 0)
    (hy : Polynomial.eval₂ f a (denom y) ≠ 0) : eval f a (x * y) = eval f a x * eval f a y := by
  unfold eval
  by_cases hxy : Polynomial.eval₂ f a (denom (x * y)) = 0
  · have := Polynomial.eval₂_eq_zero_of_dvd_of_eval₂_eq_zero f a (denom_mul_dvd x y) hxy
    rw [Polynomial.eval₂_mul] at this
    cases mul_eq_zero.mp this <;> 

Proof state:
case pos.inr
K : Type u
inst✝¹ : Field K
L : Type u_1
inst✝ : Field L
f : K →+* L
a : L
x y : RatFunc K
hx : Polynomial.eval₂ f a (denom x) ≠ 0
hy : Polynomial.eval₂ f a (denom y) ≠ 0
hxy : Polynomial.eval₂ f a (denom (x * y)) = 0
this : Polynomial.eval₂ f a (denom x) * Polynomial.eval₂ f a (denom y) = 0
h✝ : Polynomial.eval₂ f a (denom y) = 0
⊢ Polynomial.eval₂ f a (num (x * y)) / Polynomial.eval₂ f a (denom (x * y)) =
    Polynomial.eval₂ f a (num x) / Polynomial.eval₂ f a (denom x) *
      (Polynomial.eval₂ f a (num y) / Polynomial.eval₂ f a (denom y))

Next tactic:
contradiction
/-- `eval` is a multiplicative homomorphism except when a denominator evaluates to `0`.

Counterexample: `eval _ 0 X * eval _ 0 (1/X) = 0 ≠ 1 = eval _ 0 1 = eval _ 0 (X * 1/X)`.

See also `RatFunc.eval₂_denom_ne_zero` to make the hypotheses simpler but less general.
-/
theorem eval_mul {x y : RatFunc K} (hx : Polynomial.eval₂ f a (denom x) ≠ 0)
    (hy : Polynomial.eval₂ f a (denom y) ≠ 0) : eval f a (x * y) = eval f a x * eval f a y := by
  unfold eval
  by_cases hxy : Polynomial.eval₂ f a (denom (x * y)) = 0
  · have := Polynomial.eval₂_eq_zero_of_dvd_of_eval₂_eq_zero f a (denom_mul_dvd x y) hxy
    rw [Polynomial.eval₂_mul] at this
    cases mul_eq_zero.mp this <;> contradiction
  

Proof state:
case neg
K : Type u
inst✝¹ : Field K
L : Type u_1
inst✝ : Field L
f : K →+* L
a : L
x y : RatFunc K
hx : Polynomial.eval₂ f a (denom x) ≠ 0
hy : Polynomial.eval₂ f a (denom y) ≠ 0
hxy : ¬Polynomial.eval₂ f a (denom (x * y)) = 0
⊢ Polynomial.eval₂ f a (num (x * y)) / Polynomial.eval₂ f a (denom (x * y)) =
    Polynomial.eval₂ f a (num x) / Polynomial.eval₂ f a (denom x) *
      (Polynomial.eval₂ f a (num y) / Polynomial.eval₂ f a (denom y))

Next tactic:
rw [div_mul_div_comm, eq_div_iff (mul_ne_zero hx hy), div_eq_mul_inv, mul_right_comm, ←
    div_eq_mul_inv, div_eq_iff hxy]
/-- `eval` is a multiplicative homomorphism except when a denominator evaluates to `0`.

Counterexample: `eval _ 0 X * eval _ 0 (1/X) = 0 ≠ 1 = eval _ 0 1 = eval _ 0 (X * 1/X)`.

See also `RatFunc.eval₂_denom_ne_zero` to make the hypotheses simpler but less general.
-/
theorem eval_mul {x y : RatFunc K} (hx : Polynomial.eval₂ f a (denom x) ≠ 0)
    (hy : Polynomial.eval₂ f a (denom y) ≠ 0) : eval f a (x * y) = eval f a x * eval f a y := by
  unfold eval
  by_cases hxy : Polynomial.eval₂ f a (denom (x * y)) = 0
  · have := Polynomial.eval₂_eq_zero_of_dvd_of_eval₂_eq_zero f a (denom_mul_dvd x y) hxy
    rw [Polynomial.eval₂_mul] at this
    cases mul_eq_zero.mp this <;> contradiction
  rw [div_mul_div_comm, eq_div_iff (mul_ne_zero hx hy), div_eq_mul_inv, mul_right_comm, ←
    div_eq_mul_inv, div_eq_iff hxy]
  

Proof state:
case neg
K : Type u
inst✝¹ : Field K
L : Type u_1
inst✝ : Field L
f : K →+* L
a : L
x y : RatFunc K
hx : Polynomial.eval₂ f a (denom x) ≠ 0
hy : Polynomial.eval₂ f a (denom y) ≠ 0
hxy : ¬Polynomial.eval₂ f a (denom (x * y)) = 0
⊢ Polynomial.eval₂ f a (num (x * y)) * (Polynomial.eval₂ f a (denom x) * Polynomial.eval₂ f a (denom y)) =
    Polynomial.eval₂ f a (num x) * Polynomial.eval₂ f a (num y) * Polynomial.eval₂ f a (denom (x * y))

Next tactic:
simp only [← Polynomial.eval₂_mul]
/-- `eval` is a multiplicative homomorphism except when a denominator evaluates to `0`.

Counterexample: `eval _ 0 X * eval _ 0 (1/X) = 0 ≠ 1 = eval _ 0 1 = eval _ 0 (X * 1/X)`.

See also `RatFunc.eval₂_denom_ne_zero` to make the hypotheses simpler but less general.
-/
theorem eval_mul {x y : RatFunc K} (hx : Polynomial.eval₂ f a (denom x) ≠ 0)
    (hy : Polynomial.eval₂ f a (denom y) ≠ 0) : eval f a (x * y) = eval f a x * eval f a y := by
  unfold eval
  by_cases hxy : Polynomial.eval₂ f a (denom (x * y)) = 0
  · have := Polynomial.eval₂_eq_zero_of_dvd_of_eval₂_eq_zero f a (denom_mul_dvd x y) hxy
    rw [Polynomial.eval₂_mul] at this
    cases mul_eq_zero.mp this <;> contradiction
  rw [div_mul_div_comm, eq_div_iff (mul_ne_zero hx hy), div_eq_mul_inv, mul_right_comm, ←
    div_eq_mul_inv, div_eq_iff hxy]
  simp only [← Polynomial.eval₂_mul]  -- porting note: was `repeat' rw [← Polynomial.eval₂_mul]`
  

Proof state:
case neg
K : Type u
inst✝¹ : Field K
L : Type u_1
inst✝ : Field L
f : K →+* L
a : L
x y : RatFunc K
hx : Polynomial.eval₂ f a (denom x) ≠ 0
hy : Polynomial.eval₂ f a (denom y) ≠ 0
hxy : ¬Polynomial.eval₂ f a (denom (x * y)) = 0
⊢ Polynomial.eval₂ f a (num (x * y) * (denom x * denom y)) = Polynomial.eval₂ f a (num x * num y * denom (x * y))

Next tactic:
congr 1
/-- `eval` is a multiplicative homomorphism except when a denominator evaluates to `0`.

Counterexample: `eval _ 0 X * eval _ 0 (1/X) = 0 ≠ 1 = eval _ 0 1 = eval _ 0 (X * 1/X)`.

See also `RatFunc.eval₂_denom_ne_zero` to make the hypotheses simpler but less general.
-/
theorem eval_mul {x y : RatFunc K} (hx : Polynomial.eval₂ f a (denom x) ≠ 0)
    (hy : Polynomial.eval₂ f a (denom y) ≠ 0) : eval f a (x * y) = eval f a x * eval f a y := by
  unfold eval
  by_cases hxy : Polynomial.eval₂ f a (denom (x * y)) = 0
  · have := Polynomial.eval₂_eq_zero_of_dvd_of_eval₂_eq_zero f a (denom_mul_dvd x y) hxy
    rw [Polynomial.eval₂_mul] at this
    cases mul_eq_zero.mp this <;> contradiction
  rw [div_mul_div_comm, eq_div_iff (mul_ne_zero hx hy), div_eq_mul_inv, mul_right_comm, ←
    div_eq_mul_inv, div_eq_iff hxy]
  simp only [← Polynomial.eval₂_mul]  -- porting note: was `repeat' rw [← Polynomial.eval₂_mul]`
  congr 1
  

Proof state:
case neg.e_p
K : Type u
inst✝¹ : Field K
L : Type u_1
inst✝ : Field L
f : K →+* L
a : L
x y : RatFunc K
hx : Polynomial.eval₂ f a (denom x) ≠ 0
hy : Polynomial.eval₂ f a (denom y) ≠ 0
hxy : ¬Polynomial.eval₂ f a (denom (x * y)) = 0
⊢ num (x * y) * (denom x * denom y) = num x * num y * denom (x * y)

Next tactic:
apply num_denom_mul
@[simp]
theorem intDegree_zero : intDegree (0 : RatFunc K) = 0 := by
  

Proof state:
K : Type u
inst✝ : Field K
⊢ intDegree 0 = 0

Next tactic:
rw [intDegree, num_zero, natDegree_zero, denom_zero, natDegree_one, sub_self]
@[simp]
theorem intDegree_one : intDegree (1 : RatFunc K) = 0 := by
  

Proof state:
K : Type u
inst✝ : Field K
⊢ intDegree 1 = 0

Next tactic:
rw [intDegree, num_one, denom_one, sub_self]
@[simp]
theorem intDegree_C (k : K) : intDegree (RatFunc.C k) = 0 := by
  

Proof state:
K : Type u
inst✝ : Field K
k : K
⊢ intDegree (C k) = 0

Next tactic:
rw [intDegree, num_C, natDegree_C, denom_C, natDegree_one, sub_self]
@[simp]
theorem intDegree_X : intDegree (X : RatFunc K) = 1 := by
  

Proof state:
K : Type u
inst✝ : Field K
⊢ intDegree X = 1

Next tactic:
rw [intDegree, RatFunc.num_X, Polynomial.natDegree_X, RatFunc.denom_X, Polynomial.natDegree_one,
    Int.ofNat_one, Int.ofNat_zero, sub_zero]
@[simp]
theorem intDegree_polynomial {p : K[X]} :
    intDegree (algebraMap K[X] (RatFunc K) p) = natDegree p := by
  

Proof state:
K : Type u
inst✝ : Field K
p : K[X]
⊢ intDegree ((algebraMap K[X] (RatFunc K)) p) = ↑(natDegree p)

Next tactic:
rw [intDegree, RatFunc.num_algebraMap, RatFunc.denom_algebraMap, Polynomial.natDegree_one,
    Int.ofNat_zero, sub_zero]
theorem intDegree_mul {x y : RatFunc K} (hx : x ≠ 0) (hy : y ≠ 0) :
    intDegree (x * y) = intDegree x + intDegree y := by
  

Proof state:
K : Type u
inst✝ : Field K
x y : RatFunc K
hx : x ≠ 0
hy : y ≠ 0
⊢ intDegree (x * y) = intDegree x + intDegree y

Next tactic:
simp only [intDegree, add_sub, sub_add, sub_sub_eq_add_sub, sub_sub, sub_eq_sub_iff_add_eq_add]
theorem intDegree_mul {x y : RatFunc K} (hx : x ≠ 0) (hy : y ≠ 0) :
    intDegree (x * y) = intDegree x + intDegree y := by
  simp only [intDegree, add_sub, sub_add, sub_sub_eq_add_sub, sub_sub, sub_eq_sub_iff_add_eq_add]
  

Proof state:
K : Type u
inst✝ : Field K
x y : RatFunc K
hx : x ≠ 0
hy : y ≠ 0
⊢ ↑(natDegree (num (x * y))) + (↑(natDegree (denom x)) + ↑(natDegree (denom y))) =
    ↑(natDegree (num x)) + ↑(natDegree (num y)) + ↑(natDegree (denom (x * y)))

Next tactic:
norm_cast
theorem intDegree_mul {x y : RatFunc K} (hx : x ≠ 0) (hy : y ≠ 0) :
    intDegree (x * y) = intDegree x + intDegree y := by
  simp only [intDegree, add_sub, sub_add, sub_sub_eq_add_sub, sub_sub, sub_eq_sub_iff_add_eq_add]
  norm_cast
  

Proof state:
K : Type u
inst✝ : Field K
x y : RatFunc K
hx : x ≠ 0
hy : y ≠ 0
⊢ natDegree (num (x * y)) + (natDegree (denom x) + natDegree (denom y)) =
    natDegree (num x) + natDegree (num y) + natDegree (denom (x * y))

Next tactic:
rw [← Polynomial.natDegree_mul x.denom_ne_zero y.denom_ne_zero, ←
    Polynomial.natDegree_mul (RatFunc.num_ne_zero (mul_ne_zero hx hy))
      (mul_ne_zero x.denom_ne_zero y.denom_ne_zero),
    ← Polynomial.natDegree_mul (RatFunc.num_ne_zero hx) (RatFunc.num_ne_zero hy), ←
    Polynomial.natDegree_mul (mul_ne_zero (RatFunc.num_ne_zero hx) (RatFunc.num_ne_zero hy))
      (x * y).denom_ne_zero,
    RatFunc.num_denom_mul]
@[simp]
theorem intDegree_neg (x : RatFunc K) : intDegree (-x) = intDegree x := by
  

Proof state:
K : Type u
inst✝ : Field K
x : RatFunc K
⊢ intDegree (-x) = intDegree x

Next tactic:
by_cases hx : x = 0
@[simp]
theorem intDegree_neg (x : RatFunc K) : intDegree (-x) = intDegree x := by
  by_cases hx : x = 0
  · 

Proof state:
case pos
K : Type u
inst✝ : Field K
x : RatFunc K
hx : x = 0
⊢ intDegree (-x) = intDegree x

Next tactic:
rw [hx, neg_zero]
@[simp]
theorem intDegree_neg (x : RatFunc K) : intDegree (-x) = intDegree x := by
  by_cases hx : x = 0
  · rw [hx, neg_zero]
  · 

Proof state:
case neg
K : Type u
inst✝ : Field K
x : RatFunc K
hx : ¬x = 0
⊢ intDegree (-x) = intDegree x

Next tactic:
rw [intDegree, intDegree, ← natDegree_neg x.num]
@[simp]
theorem intDegree_neg (x : RatFunc K) : intDegree (-x) = intDegree x := by
  by_cases hx : x = 0
  · rw [hx, neg_zero]
  · rw [intDegree, intDegree, ← natDegree_neg x.num]
    

Proof state:
case neg
K : Type u
inst✝ : Field K
x : RatFunc K
hx : ¬x = 0
⊢ ↑(natDegree (num (-x))) - ↑(natDegree (denom (-x))) = ↑(natDegree (-num x)) - ↑(natDegree (denom x))

Next tactic:
exact
      natDegree_sub_eq_of_prod_eq (num_ne_zero (neg_ne_zero.mpr hx)) (denom_ne_zero (-x))
        (neg_ne_zero.mpr (num_ne_zero hx)) (denom_ne_zero x) (num_denom_neg x)
theorem natDegree_num_mul_right_sub_natDegree_denom_mul_left_eq_intDegree {x : RatFunc K}
    (hx : x ≠ 0) {s : K[X]} (hs : s ≠ 0) :
    ((x.num * s).natDegree : ℤ) - (s * x.denom).natDegree = x.intDegree := by
  

Proof state:
K : Type u
inst✝ : Field K
x : RatFunc K
hx : x ≠ 0
s : K[X]
hs : s ≠ 0
⊢ ↑(natDegree (num x * s)) - ↑(natDegree (s * denom x)) = intDegree x

Next tactic:
apply natDegree_sub_eq_of_prod_eq (mul_ne_zero (num_ne_zero hx) hs)
    (mul_ne_zero hs x.denom_ne_zero) (num_ne_zero hx) x.denom_ne_zero
theorem natDegree_num_mul_right_sub_natDegree_denom_mul_left_eq_intDegree {x : RatFunc K}
    (hx : x ≠ 0) {s : K[X]} (hs : s ≠ 0) :
    ((x.num * s).natDegree : ℤ) - (s * x.denom).natDegree = x.intDegree := by
  apply natDegree_sub_eq_of_prod_eq (mul_ne_zero (num_ne_zero hx) hs)
    (mul_ne_zero hs x.denom_ne_zero) (num_ne_zero hx) x.denom_ne_zero
  

Proof state:
K : Type u
inst✝ : Field K
x : RatFunc K
hx : x ≠ 0
s : K[X]
hs : s ≠ 0
⊢ num x * s * denom x = num x * (s * denom x)

Next tactic:
rw [mul_assoc]
theorem intDegree_add_le {x y : RatFunc K} (hy : y ≠ 0) (hxy : x + y ≠ 0) :
    intDegree (x + y) ≤ max (intDegree x) (intDegree y) := by
  

Proof state:
K : Type u
inst✝ : Field K
x y : RatFunc K
hy : y ≠ 0
hxy : x + y ≠ 0
⊢ intDegree (x + y) ≤ max (intDegree x) (intDegree y)

Next tactic:
by_cases hx : x = 0
theorem intDegree_add_le {x y : RatFunc K} (hy : y ≠ 0) (hxy : x + y ≠ 0) :
    intDegree (x + y) ≤ max (intDegree x) (intDegree y) := by
  by_cases hx : x = 0
  · 

Proof state:
case pos
K : Type u
inst✝ : Field K
x y : RatFunc K
hy : y ≠ 0
hxy : x + y ≠ 0
hx : x = 0
⊢ intDegree (x + y) ≤ max (intDegree x) (intDegree y)

Next tactic:
simp only [hx, zero_add, ne_eq] at hxy