Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Merged by Bors] - feat(algebra/polynomial, data/polynomial): lemmas about monic polynomials #3402

Closed
wants to merge 87 commits into from
Closed
Show file tree
Hide file tree
Changes from 85 commits
Commits
Show all changes
87 commits
Select commit Hold shift + click to select a range
057835f
init
jalex-stark Jul 12, 2020
3e7cdfc
take a simpler typeclass assumption
jalex-stark Jul 12, 2020
40cb3bf
Added some sorried lemmas
awainverse Jul 12, 2020
8d45565
shuffled variables around, error-free now
jalex-stark Jul 12, 2020
3177c74
closed sorries
jalex-stark Jul 12, 2020
5bf0ce2
upgraded a lemma from integral domain to comm_semiring
jalex-stark Jul 12, 2020
0de15c7
monoid_hom.map_prod?
jalex-stark Jul 12, 2020
47383fb
One more sorry closed
awainverse Jul 12, 2020
bbd0c86
Merge branch 'poly_big_ops' of https://github.com/leanprover-communit…
awainverse Jul 12, 2020
72c6191
Monoid homs are good
awainverse Jul 12, 2020
e856a64
Removing an old comment
awainverse Jul 12, 2020
cb4ba5f
tidied docstring
jalex-stark Jul 12, 2020
d07ad32
tidied docstring?
jalex-stark Jul 12, 2020
cfbf6b6
Merge branch 'poly_big_ops' of https://github.com/leanprover-communit…
jalex-stark Jul 12, 2020
9bd57c4
switched a proof to use induciton tactic
jalex-stark Jul 12, 2020
1528caf
another induction conversion
jalex-stark Jul 12, 2020
7f6de18
Even more homs
awainverse Jul 12, 2020
0fc8bc7
Merge branch 'poly_big_ops' of https://github.com/leanprover-communit…
awainverse Jul 12, 2020
a32da0a
Docstrings
awainverse Jul 12, 2020
439068c
Linting [decidable_eq] to classical in proof
awainverse Jul 12, 2020
33409ee
init
jalex-stark Jul 12, 2020
22d54e4
Merge remote-tracking branch 'origin/poly_big_ops' into polynomial_le…
awainverse Jul 12, 2020
2adab74
file move
jalex-stark Jul 12, 2020
4e1ce77
Trimmed some things down
awainverse Jul 12, 2020
5b8b8a4
narrowed scope of module docstring
jalex-stark Jul 12, 2020
8f5486e
file move
jalex-stark Jul 12, 2020
fbbae0b
Merge branch 'poly_big_ops' into polynomial_lemmas_for_freek_83
jalex-stark Jul 12, 2020
8156a81
break into two files
jalex-stark Jul 12, 2020
4594ee7
split out monic.lean
jalex-stark Jul 12, 2020
48372a5
break basic.lean up by level of typeclass assumption
jalex-stark Jul 13, 2020
37d044b
move stuff out of big_operators not matching the module docstring
jalex-stark Jul 13, 2020
ca1bb99
split into two files
jalex-stark Jul 13, 2020
4e94069
added more module docstring
jalex-stark Jul 13, 2020
a5a4f9b
changed a proof to use induction tactic
jalex-stark Jul 13, 2020
2f392aa
Improving documentation
awainverse Jul 13, 2020
639cd08
Noncomputable theory
awainverse Jul 13, 2020
a2ea03a
char_p lemmas
awainverse Jul 13, 2020
1c01f6b
deduped proof of add_pow_char
jalex-stark Jul 13, 2020
f909e25
Update src/algebra/polynomial/basic.lean
jalex-stark Jul 13, 2020
cb66b41
Replaced new alg_homs with aeval
awainverse Jul 13, 2020
cf4cfab
Merge branch 'poly_big_ops' of https://github.com/leanprover-communit…
awainverse Jul 13, 2020
af2d806
coe vs. apply
awainverse Jul 13, 2020
0ea52ee
Answering reviews
awainverse Jul 13, 2020
d380edc
made next_coeff_mul faster at the cost of sorries
jalex-stark Jul 13, 2020
3de1ecf
tweaked documentation for prime lemmas
jalex-stark Jul 13, 2020
4bc378d
remove sorries
jalex-stark Jul 13, 2020
0207446
Update src/algebra/polynomial/basic.lean
jalex-stark Jul 14, 2020
0d3698c
Update src/algebra/polynomial/basic.lean
jalex-stark Jul 14, 2020
0b427ad
Update src/algebra/polynomial/basic.lean
jalex-stark Jul 14, 2020
8613f00
Update src/algebra/polynomial/big_operators.lean
jalex-stark Jul 14, 2020
f662cbf
Update src/algebra/polynomial/big_operators.lean
jalex-stark Jul 14, 2020
df3acb6
tweak documentation per johan's suggestion
jalex-stark Jul 14, 2020
f6ced67
Merge branch 'poly_big_ops' into polynomial_lemmas_for_freek_83
jalex-stark Jul 14, 2020
0f63f11
revert field_theory/finite
jalex-stark Jul 14, 2020
ba3927f
Update src/algebra/polynomial/basic.lean
jalex-stark Jul 14, 2020
cf840c9
Update src/algebra/char_p.lean
jalex-stark Jul 14, 2020
644cb14
golfing
jalex-stark Jul 14, 2020
28911fc
Merge branch 'polynomial_lemmas_for_freek_83' of https://github.com/l…
jalex-stark Jul 14, 2020
4dd84b6
Delete big_operators.lean
jalex-stark Jul 14, 2020
6f79fb7
Update src/algebra/polynomial/basic.lean
jalex-stark Jul 14, 2020
1c19e29
Update src/algebra/polynomial/basic.lean
jalex-stark Jul 14, 2020
4ec8427
Merge branch 'master' into polynomial_lemmas_for_freek_83
jalex-stark Jul 16, 2020
cf92c40
merge algebra/polynomial/basic.lean into data/polynomial/basic.lean
jalex-stark Jul 16, 2020
2300452
...and actually add the code to data, in addition to reomving it from…
jalex-stark Jul 16, 2020
4916f27
simplify proof
jalex-stark Jul 16, 2020
5687211
merge algebra/polynomial/monic into data/polynomial/monic
jalex-stark Jul 16, 2020
6114fa4
resolve a comment
jalex-stark Jul 16, 2020
6226ae1
resolve a comment
jalex-stark Jul 16, 2020
9ea7d32
docs
jalex-stark Jul 16, 2020
7c6ff25
Update src/algebra/char_p.lean
jalex-stark Jul 16, 2020
61eb1c8
formatting
jalex-stark Jul 16, 2020
86d31e5
Merge branch 'polynomial_lemmas_for_freek_83' of https://github.com/l…
jalex-stark Jul 16, 2020
a77bd29
attempt to fix import
jalex-stark Jul 16, 2020
890443c
squeeze import
jalex-stark Jul 17, 2020
3314e11
expand a doc
jalex-stark Jul 17, 2020
78680bf
Update src/algebra/polynomial/big_operators.lean
jalex-stark Jul 17, 2020
d0b1249
name changes
jalex-stark Jul 17, 2020
3179603
swap for bigops notation
jalex-stark Jul 17, 2020
9ac5c60
naming
jalex-stark Jul 17, 2020
9b49e63
i maybe got all of them this time
jalex-stark Jul 17, 2020
9303e57
Merge remote-tracking branch 'origin/master' into polynomial_lemmas_f…
jalex-stark Jul 17, 2020
46b8a10
pow_eq
jalex-stark Jul 17, 2020
5e138a0
restore missing tactic import
jalex-stark Jul 18, 2020
586ee4d
remove zombie file
jalex-stark Jul 18, 2020
e46d267
...and actually remove the file
jalex-stark Jul 18, 2020
4368c1d
two more name changes
jalex-stark Jul 18, 2020
4c3a76d
Merge remote-tracking branch 'origin/master' into polynomial_lemmas_f…
jalex-stark Jul 18, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
28 changes: 18 additions & 10 deletions src/algebra/char_p.lean
Original file line number Diff line number Diff line change
Expand Up @@ -78,19 +78,27 @@ unfold ring_char; exact char_p.cast_eq_zero_iff α (ring_char α)
theorem ring_char.eq (α : Type u) [semiring α] {p : ℕ} (C : char_p α p) : p = ring_char α :=
(classical.some_spec (char_p.exists_unique α)).2 p C

theorem add_pow_char_of_commute (R : Type u) [ring R] {p : ℕ} [fact p.prime]
[char_p R p] (x y : R) (h : commute x y):
(x + y)^p = x^p + y^p :=
begin
rw [commute.add_pow h, finset.sum_range_succ, nat.sub_self, pow_zero, nat.choose_self],
rw [nat.cast_one, mul_one, mul_one, add_right_inj],
convert finset.sum_eq_single 0 _ _, { simp },
swap, { intro h1, contrapose! h1, rw finset.mem_range, apply nat.prime.pos, assumption },
intros b h1 h2,
suffices : (p.choose b : R) = 0, { rw this, simp },
rw char_p.cast_eq_zero_iff R p,
apply nat.prime.dvd_choose_self, assumption', { omega },
rwa ← finset.mem_range
end

theorem add_pow_char (α : Type u) [comm_ring α] {p : ℕ} (hp : nat.prime p)
[char_p α p] (x y : α) : (x + y)^p = x^p + y^p :=
begin
rw [add_pow, finset.sum_range_succ, nat.sub_self, pow_zero, nat.choose_self],
rw [nat.cast_one, mul_one, mul_one, add_right_inj],
transitivity,
{ refine finset.sum_eq_single 0 _ _,
{ intros b h1 h2,
have := nat.prime.dvd_choose_self (nat.pos_of_ne_zero h2) (finset.mem_range.1 h1) hp,
rw [← nat.div_mul_cancel this, nat.cast_mul, char_p.cast_eq_zero α p],
simp only [mul_zero] },
{ intro H, exfalso, apply H, exact finset.mem_range.2 hp.pos } },
rw [pow_zero, nat.sub_zero, one_mul, nat.choose_zero_right, nat.cast_one, mul_one]
haveI : fact p.prime := hp,
apply add_pow_char_of_commute,
apply commute.all,
end

lemma eq_iff_modeq_int (R : Type*) [ring R] (p : ℕ) [char_p R p] (a b : ℤ) :
Expand Down
57 changes: 0 additions & 57 deletions src/algebra/polynomial/basic.lean

This file was deleted.

63 changes: 43 additions & 20 deletions src/algebra/polynomial/big_operators.lean
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ Copyright (c) 2020 Aaron Anderson. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Aaron Anderson, Jalex Stark.
-/
import algebra.polynomial.basic
import data.polynomial.monic
import tactic.linarith

open polynomial finset
Expand All @@ -15,34 +15,36 @@ Lemmas for the interaction between polynomials and ∑ and ∏.

## Main results

- `nat_degree_prod_eq_of_monic` : the degree of a product of monic polynomials is the product of
- `nat_degree_prod_of_monic` : the degree of a product of monic polynomials is the product of
degrees. We prove this only for [comm_semiring R],
but it ought to be true for [semiring R] and list.prod.
- `nat_degree_prod_eq` : for polynomials over an integral domain,
- `nat_degree_prod` : for polynomials over an integral domain,
the degree of the product is the sum of degrees
- `leading_coeff_prod` : for polynomials over an integral domain,
the leading coefficient is the product of leading coefficients
- `card_pred_coeff_prod_X_sub_C` carries most of the content for computing
the second coefficient of the characteristic polynomial.
-/

open_locale big_operators

universes u w

variables {R : Type u} {α : Type w}
variables {R : Type u} {ι : Type w}

namespace polynomial

variable (s : finset α)
variable (s : finset ι)

section comm_semiring
variables [comm_semiring R] (f : α → polynomial R)
variables [comm_semiring R] (f : ι → polynomial R)

lemma nat_degree_prod_le : (∏ i in s, f i).nat_degree ≤ ∑ i in s, (f i).nat_degree :=
begin
classical,
induction s using finset.induction with a s ha hs, { simp },
rw [prod_insert ha, sum_insert ha],
transitivity (f a).nat_degree + (∏ (x : α) in s, (f x)).nat_degree,
transitivity (f a).nat_degree + (∏ x in s, f x).nat_degree,
apply polynomial.nat_degree_mul_le, linarith,
end

Expand All @@ -58,39 +60,60 @@ begin
end

/-- The degree of a product of polynomials is equal to the product of the degrees, provided that the product of leading coefficients is nonzero.
See `nat_degree_prod_eq` (without the `'`) for a version for integral domains, where this condition is automatically satisfied. -/
lemma nat_degree_prod_eq' (h : ∏ i in s, (f i).leading_coeff ≠ 0) :
See `nat_degree_prod` (without the `'`) for a version for integral domains, where this condition is automatically satisfied. -/
lemma nat_degree_prod' (h : ∏ i in s, (f i).leading_coeff ≠ 0) :
(∏ i in s, f i).nat_degree = ∑ i in s, (f i).nat_degree :=
begin
classical,
revert h, induction s using finset.induction with a s ha hs, { simp },
rw [prod_insert ha, prod_insert ha, sum_insert ha],
intro h, rw polynomial.nat_degree_mul_eq', rw hs,
intro h, rw polynomial.nat_degree_mul', rw hs,
apply right_ne_zero_of_mul h,
rwa polynomial.leading_coeff_prod', apply right_ne_zero_of_mul h,
end

lemma monic_prod_of_monic :
(∀ a : α, a ∈ s → monic (f a)) → monic (∏ i in s, f i) :=
by { apply prod_induction, apply monic_mul, apply monic_one }

lemma nat_degree_prod_eq_of_monic [nontrivial R] (h : ∀ i : α, i ∈ s → (f i).monic) :
lemma nat_degree_prod_of_monic [nontrivial R] (h : ∀ i ∈ s, (f i).monic) :
(∏ i in s, f i).nat_degree = ∑ i in s, (f i).nat_degree :=
begin
apply nat_degree_prod_eq',
suffices : ∏ (i : α) in s, (f i).leading_coeff = 1, { rw this, simp },
apply nat_degree_prod',
suffices : ∏ i in s, (f i).leading_coeff = 1, { rw this, simp },
rw prod_eq_one, intros, apply h, assumption,
end

end comm_semiring

section comm_ring
variables [comm_ring R]

open monic
-- Eventually this can be generalized with Vieta's formulas
-- plus the connection between roots and factorization.
lemma next_coeff_prod_X_sub_C [nontrivial R] {s : finset ι} (f : ι → R) :
next_coeff ∏ i in s, (X - C (f i)) = -∑ i in s, f i :=
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe easier to find as prod_X_sub_C_next_coeff? Can you move the next_coeff to use projection notation?

by { rw next_coeff_prod; { simp [monic_X_sub_C] } }

lemma card_pred_coeff_prod_X_sub_C [nontrivial R] (s : finset ι) (f : ι → R) (hs : 0 < s.card) :
(∏ i in s, (X - C (f i))).coeff (s.card - 1) = - ∑ i in s, f i :=
jalex-stark marked this conversation as resolved.
Show resolved Hide resolved
begin
convert next_coeff_prod_X_sub_C (by assumption),
rw next_coeff, split_ifs,
{ rw nat_degree_prod_of_monic at h,
swap, { intros, apply monic_X_sub_C },
rw sum_eq_zero_iff at h,
simp_rw nat_degree_X_sub_C at h, contrapose! h, norm_num,
exact multiset.card_pos_iff_exists_mem.mp hs },
congr, rw nat_degree_prod_of_monic; { simp [nat_degree_X_sub_C, monic_X_sub_C] },
end

end comm_ring

section integral_domain
variables [integral_domain R] (f : α → polynomial R)
variables [integral_domain R] (f : ι → polynomial R)

lemma nat_degree_prod_eq (h : ∀ i ∈ s, f i ≠ 0) :
lemma nat_degree_prod (h : ∀ i ∈ s, f i ≠ 0) :
(∏ i in s, f i).nat_degree = ∑ i in s, (f i).nat_degree :=
begin
apply nat_degree_prod_eq', rw prod_ne_zero_iff,
apply nat_degree_prod', rw prod_ne_zero_iff,
intros x hx, simp [h x hx],
end

Expand Down
9 changes: 9 additions & 0 deletions src/data/polynomial/algebra_map.lean
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,15 @@ alg_hom.ext $ λ p, by rw [eval_unique (f.comp (aeval R A x)), alg_hom.comp_appl
theorem aeval_alg_hom_apply (f : A →ₐ[R] B) (x : A) (p) : aeval R B (f x) p = f (aeval R A x p) :=
alg_hom.ext_iff.1 (aeval_alg_hom f x) p

@[simp] lemma coe_aeval_eq_eval (r : R) :
(aeval R R r : polynomial R → R) = eval r := rfl

lemma coeff_zero_eq_aeval_zero (p : polynomial R) : p.coeff 0 = aeval R R 0 p :=
by simp [coeff_zero_eq_eval_zero]

lemma pow_comp (p q : polynomial R) (k : ℕ) : (p ^ k).comp q = (p.comp q) ^ k :=
by { unfold comp, rw ← coe_eval₂_ring_hom, apply ring_hom.map_pow }

variables [comm_ring S] {f : R →+* S}

lemma is_root_of_eval₂_map_eq_zero
Expand Down
66 changes: 55 additions & 11 deletions src/data/polynomial/degree.lean
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import data.polynomial.eval
# Theory of degrees of polynomials

Some of the main results include
- `degree_mul_eq` : The degree of the product is the sum of degrees
- `degree_mul` : The degree of the product is the sum of degrees
- `leading_coeff_add_of_degree_eq` and `leading_coeff_add_of_degree_lt` :
The leading_coefficient of a sum is determined by the leading coefficients and degrees
- `nat_degree_comp_le` : The degree of the composition is at most the product of degrees
Expand Down Expand Up @@ -207,7 +207,7 @@ calc coeff (p * q) (nat_degree p + nat_degree q) =
{ intro H, exfalso, apply H, rw nat.mem_antidiagonal }
end

lemma degree_mul_eq' (h : leading_coeff p * leading_coeff q ≠ 0) :
lemma degree_mul' (h : leading_coeff p * leading_coeff q ≠ 0) :
degree (p * q) = degree p + degree q :=
have hp : p ≠ 0 := by refine mt _ h; exact λ hp, by rw [hp, leading_coeff_zero, zero_mul],
have hq : q ≠ 0 := by refine mt _ h; exact λ hq, by rw [hq, leading_coeff_zero, mul_zero],
Expand All @@ -218,21 +218,21 @@ begin
rwa coeff_mul_degree_add_degree
end

lemma nat_degree_mul_eq' (h : leading_coeff p * leading_coeff q ≠ 0) :
lemma nat_degree_mul' (h : leading_coeff p * leading_coeff q ≠ 0) :
nat_degree (p * q) = nat_degree p + nat_degree q :=
have hp : p ≠ 0 := mt leading_coeff_eq_zero.2 (λ h₁, h $ by rw [h₁, zero_mul]),
have hq : q ≠ 0 := mt leading_coeff_eq_zero.2 (λ h₁, h $ by rw [h₁, mul_zero]),
have hpq : p * q ≠ 0 := λ hpq, by rw [← coeff_mul_degree_add_degree, hpq, coeff_zero] at h;
exact h rfl,
option.some_inj.1 (show (nat_degree (p * q) : with_bot ℕ) = nat_degree p + nat_degree q,
by rw [← degree_eq_nat_degree hpq, degree_mul_eq' h, degree_eq_nat_degree hp,
by rw [← degree_eq_nat_degree hpq, degree_mul' h, degree_eq_nat_degree hp,
degree_eq_nat_degree hq])

lemma leading_coeff_mul' (h : leading_coeff p * leading_coeff q ≠ 0) :
leading_coeff (p * q) = leading_coeff p * leading_coeff q :=
begin
unfold leading_coeff,
rw [nat_degree_mul_eq' h, coeff_mul_degree_add_degree],
rw [nat_degree_mul' h, coeff_mul_degree_add_degree],
refl
end

Expand All @@ -246,7 +246,7 @@ have h₂ : leading_coeff p * leading_coeff (p ^ n) ≠ 0 :=
by rwa [pow_succ, ← ih h₁] at h,
by rw [pow_succ, pow_succ, leading_coeff_mul' h₂, ih h₁]

lemma degree_pow_eq' : ∀ {n}, leading_coeff p ^ n ≠ 0 →
lemma degree_pow' : ∀ {n}, leading_coeff p ^ n ≠ 0 →
degree (p ^ n) = n •ℕ (degree p)
| 0 := λ h, by rw [pow_zero, ← C_1] at *;
rw [degree_C h, zero_nsmul]
Expand All @@ -255,9 +255,9 @@ have h₁ : leading_coeff p ^ n ≠ 0 := λ h₁, h $
by rw [pow_succ, h₁, mul_zero],
have h₂ : leading_coeff p * leading_coeff (p ^ n) ≠ 0 :=
by rwa [pow_succ, ← leading_coeff_pow' h₁] at h,
by rw [pow_succ, degree_mul_eq' h₂, succ_nsmul, degree_pow_eq' h₁]
by rw [pow_succ, degree_mul' h₂, succ_nsmul, degree_pow' h₁]

lemma nat_degree_pow_eq' {n : ℕ} (h : leading_coeff p ^ n ≠ 0) :
lemma nat_degree_pow' {n : ℕ} (h : leading_coeff p ^ n ≠ 0) :
nat_degree (p ^ n) = n * nat_degree p :=
if hp0 : p = 0 then
if hn0 : n = 0 then by simp *
Expand All @@ -267,7 +267,7 @@ have hpn : p ^ n ≠ 0, from λ hpn0, have h1 : _ := h,
by rw [← leading_coeff_pow' h1, hpn0, leading_coeff_zero] at h;
exact h rfl,
option.some_inj.1 $ show (nat_degree (p ^ n) : with_bot ℕ) = (n * nat_degree p : ℕ),
by rw [← degree_eq_nat_degree hpn, degree_pow_eq' h, degree_eq_nat_degree hp0,
by rw [← degree_eq_nat_degree hpn, degree_pow' h, degree_eq_nat_degree hp0,
← with_bot.coe_nsmul]; simp

@[simp] lemma leading_coeff_X_pow : ∀ n : ℕ, leading_coeff ((X : polynomial R) ^ n) = 1
Expand Down Expand Up @@ -370,7 +370,7 @@ theorem degree_le_iff_coeff_zero (f : polynomial R) (n : with_bot ℕ) :
lemma degree_lt_degree_mul_X (hp : p ≠ 0) : p.degree < (p * X).degree :=
by haveI := nonzero.of_polynomial_ne hp; exact
have leading_coeff p * leading_coeff X ≠ 0, by simpa,
by erw [degree_mul_eq' this, degree_eq_nat_degree hp,
by erw [degree_mul' this, degree_eq_nat_degree hp,
degree_X, ← with_bot.coe_one, ← with_bot.coe_add, with_bot.coe_lt_coe];
exact nat.lt_succ_self _

Expand Down Expand Up @@ -461,7 +461,7 @@ variables [semiring R] [nontrivial R] {p q : polynomial R}
have h : leading_coeff (X : polynomial R) * leading_coeff (X ^ n) ≠ 0,
by rw [leading_coeff_X, leading_coeff_X_pow n, one_mul];
exact zero_ne_one.symm,
by rw [pow_succ, degree_mul_eq' h, degree_X, degree_X_pow, add_comm]; refl
by rw [pow_succ, degree_mul' h, degree_X, degree_X_pow, add_comm]; refl

theorem not_is_unit_X : ¬ is_unit (X : polynomial R) :=
λ ⟨⟨_, g, hfg, hgf⟩, rfl⟩, @zero_ne_one R _ _ $ by erw [← coeff_one_zero, ← hgf, coeff_mul_X_zero]
Expand Down Expand Up @@ -511,6 +511,10 @@ end
@[simp] lemma nat_degree_X_sub_C (x : R) : (X - C x).nat_degree = 1 :=
nat_degree_eq_of_degree_eq_some $ degree_X_sub_C x

@[simp]
lemma next_coeff_X_sub_C (c : R) : next_coeff (X - C c) = - c :=
by simp [next_coeff_of_pos_nat_degree]

lemma degree_X_pow_sub_C {n : ℕ} (hn : 0 < n) (a : R) :
degree ((X : polynomial R) ^ n - C a) = n :=
have degree (-C a) < degree ((X : polynomial R) ^ n),
Expand All @@ -533,4 +537,44 @@ by { apply nat_degree_eq_of_degree_eq_some, simp [degree_X_pow_sub_C hn], }

end nonzero_ring

section integral_domain
variables [integral_domain R] {p q : polynomial R}

@[simp] lemma degree_mul : degree (p * q) = degree p + degree q :=
if hp0 : p = 0 then by simp only [hp0, degree_zero, zero_mul, with_bot.bot_add]
else if hq0 : q = 0 then by simp only [hq0, degree_zero, mul_zero, with_bot.add_bot]
else degree_mul' $ mul_ne_zero (mt leading_coeff_eq_zero.1 hp0)
(mt leading_coeff_eq_zero.1 hq0)

@[simp] lemma degree_pow (p : polynomial R) (n : ℕ) :
degree (p ^ n) = n •ℕ (degree p) :=
by induction n; [simp only [pow_zero, degree_one, zero_nsmul],
simp only [*, pow_succ, succ_nsmul, degree_mul]]

@[simp] lemma leading_coeff_mul (p q : polynomial R) : leading_coeff (p * q) =
leading_coeff p * leading_coeff q :=
begin
by_cases hp : p = 0,
{ simp only [hp, zero_mul, leading_coeff_zero] },
{ by_cases hq : q = 0,
{ simp only [hq, mul_zero, leading_coeff_zero] },
{ rw [leading_coeff_mul'],
exact mul_ne_zero (mt leading_coeff_eq_zero.1 hp) (mt leading_coeff_eq_zero.1 hq) } }
end

/-- `polynomial.leading_coeff` bundled as a `monoid_hom` when `R` is an `integral_domain`, and thus
`leading_coeff` is multiplicative -/
def leading_coeff_hom : polynomial R →* R :=
{ to_fun := leading_coeff,
map_one' := by simp,
map_mul' := leading_coeff_mul }

@[simp] lemma leading_coeff_hom_apply (p : polynomial R) :
leading_coeff_hom p = leading_coeff p := rfl

@[simp] lemma leading_coeff_pow (p : polynomial R) (n : ℕ) :
leading_coeff (p ^ n) = leading_coeff p ^ n :=
leading_coeff_hom.map_pow p n
end integral_domain

end polynomial