File: Mathlib/Algebra/Polynomial/Laurent.lean

full_name: LaurentPolynomial
code: /-- The semiring of Laurent polynomials with coefficients in the semiring `R`.
We denote it by `R[T;T⁻¹]`.
The ring homomorphism `C : R →+* R[T;T⁻¹]` includes `R` as the constant polynomials. -/
abbrev LaurentPolynomial (R : Type*) [Semiring R] 
goal: Type u_2

full_name: LaurentPolynomial._aux_Mathlib_Algebra_Polynomial_Laurent___unexpand_LaurentPolynomial_1
code: @[nolint docBlame]
scoped[LaurentPolynomial] notation:9000 R "[T;T⁻¹]" => LaurentPolynomial R
goal: Lean.PrettyPrinter.Unexpander

full_name: LaurentPolynomial.«_aux_Mathlib_Algebra_Polynomial_Laurent___macroRules_LaurentPolynomial_term_[T;T⁻¹]_1»
code: @[nolint docBlame]
scoped[LaurentPolynomial] notation:9000 R "[T;T⁻¹]" => LaurentPolynomial R
goal: Lean.Macro

full_name: LaurentPolynomial.ext
code: @[ext]
theorem LaurentPolynomial.ext [Semiring R] {p q : R[T;T⁻¹]} (h : ∀ a, p a = q a) : p = q 
goal: p = q

full_name: Polynomial.toLaurent
code: /-- The ring homomorphism, taking a polynomial with coefficients in `R` to a Laurent polynomial
with coefficients in `R`. -/
def Polynomial.toLaurent [Semiring R] : R[X] →+* R[T;T⁻¹] 
goal: R[X] →+* R[T;T⁻¹]

full_name: Polynomial.toLaurent_apply
code: /-- This is not a simp lemma, as it is usually preferable to use the lemmas about `C` and `X`
instead. -/
theorem Polynomial.toLaurent_apply [Semiring R] (p : R[X]) :
    toLaurent p = p.toFinsupp.mapDomain (↑) 
goal: Polynomial.toLaurent p = AddMonoidAlgebra.mapDomain Nat.cast p.toFinsupp

full_name: Polynomial.toLaurentAlg
code: /-- The `R`-algebra map, taking a polynomial with coefficients in `R` to a Laurent polynomial
with coefficients in `R`. -/
def Polynomial.toLaurentAlg [CommSemiring R] : R[X] →ₐ[R] R[T;T⁻¹] 
goal: R[X] →ₐ[R] R[T;T⁻¹]

full_name: Polynomial.coe_toLaurentAlg
code: @[simp] lemma Polynomial.coe_toLaurentAlg [CommSemiring R] :
    (toLaurentAlg : R[X] → R[T;T⁻¹]) = toLaurent 
goal: ⇑Polynomial.toLaurentAlg = ⇑Polynomial.toLaurent

full_name: Polynomial.toLaurentAlg_apply
code: theorem Polynomial.toLaurentAlg_apply [CommSemiring R] (f : R[X]) : toLaurentAlg f = toLaurent f 
goal: Polynomial.toLaurentAlg f = Polynomial.toLaurent f

full_name: LaurentPolynomial.single_zero_one_eq_one
code: theorem single_zero_one_eq_one : (Finsupp.single 0 1 : R[T;T⁻¹]) = (1 : R[T;T⁻¹]) 
goal: Finsupp.single 0 1 = 1

full_name: LaurentPolynomial.C
code: /-- The ring homomorphism `C`, including `R` into the ring of Laurent polynomials over `R` as
the constant Laurent polynomials. -/
def C : R →+* R[T;T⁻¹] 
goal: R →+* R[T;T⁻¹]

full_name: LaurentPolynomial.algebraMap_apply
code: theorem algebraMap_apply {R A : Type*} [CommSemiring R] [Semiring A] [Algebra R A] (r : R) :
    algebraMap R (LaurentPolynomial A) r = C (algebraMap R A r) 
goal: (algebraMap R A[T;T⁻¹]) r = LaurentPolynomial.C ((algebraMap R A) r)

full_name: LaurentPolynomial.C_eq_algebraMap
code: /-- When we have `[CommSemiring R]`, the function `C` is the same as `algebraMap R R[T;T⁻¹]`.
(But note that `C` is defined when `R` is not necessarily commutative, in which case
`algebraMap` is not available.)
-/
theorem C_eq_algebraMap {R : Type*} [CommSemiring R] (r : R) : C r = algebraMap R R[T;T⁻¹] r 
goal: LaurentPolynomial.C r = (algebraMap R R[T;T⁻¹]) r

full_name: LaurentPolynomial.single_eq_C
code: theorem single_eq_C (r : R) : Finsupp.single 0 r = C r 
goal: Finsupp.single 0 r = LaurentPolynomial.C r

full_name: LaurentPolynomial.C_apply
code: @[simp] lemma C_apply (t : R) (n : ℤ) : C t n = if n = 0 then t else 0 
goal: (LaurentPolynomial.C t) n = if n = 0 then t else 0

full_name: LaurentPolynomial.T
code: /-- The function `n ↦ T ^ n`, implemented as a sequence `ℤ → R[T;T⁻¹]`.

Using directly `T ^ n` does not work, since we want the exponents to be of Type `ℤ` and there
is no `ℤ`-power defined on `R[T;T⁻¹]`.  Using that `T` is a unit introduces extra coercions.
For these reasons, the definition of `T` is as a sequence. -/
def T (n : ℤ) : R[T;T⁻¹] 
goal: R[T;T⁻¹]

full_name: LaurentPolynomial.T_apply
code: @[simp] lemma T_apply (m n : ℤ) : (T n : R[T;T⁻¹]) m = if n = m then 1 else 0 
goal: (LaurentPolynomial.T n) m = if n = m then 1 else 0

full_name: LaurentPolynomial.T_zero
code: @[simp]
theorem T_zero : (T 0 : R[T;T⁻¹]) = 1 
goal: LaurentPolynomial.T 0 = 1

full_name: LaurentPolynomial.T_add
code: theorem T_add (m n : ℤ) : (T (m + n) : R[T;T⁻¹]) = T m * T n 
goal: LaurentPolynomial.T (m + n) = LaurentPolynomial.T m * LaurentPolynomial.T n

full_name: LaurentPolynomial.T_sub
code: theorem T_sub (m n : ℤ) : (T (m - n) : R[T;T⁻¹]) = T m * T (-n) 
goal: LaurentPolynomial.T (m - n) = LaurentPolynomial.T m * LaurentPolynomial.T (-n)

full_name: LaurentPolynomial.T_pow
code: @[simp]
theorem T_pow (m : ℤ) (n : ℕ) : (T m ^ n : R[T;T⁻¹]) = T (n * m) 
goal: LaurentPolynomial.T m ^ n = LaurentPolynomial.T (↑n * m)

full_name: LaurentPolynomial.mul_T_assoc
code: /-- The `simp` version of `mul_assoc`, in the presence of `T`'s. -/
@[simp]
theorem mul_T_assoc (f : R[T;T⁻¹]) (m n : ℤ) : f * T m * T n = f * T (m + n) 
goal: f * LaurentPolynomial.T m * LaurentPolynomial.T n = f * LaurentPolynomial.T (m + n)

full_name: LaurentPolynomial.single_eq_C_mul_T
code: @[simp]
theorem single_eq_C_mul_T (r : R) (n : ℤ) :
    (Finsupp.single n r : R[T;T⁻¹]) = (C r * T n : R[T;T⁻¹]) 
goal: Finsupp.single n r = LaurentPolynomial.C r * LaurentPolynomial.T n

full_name: Polynomial.toLaurent_C_mul_T
code: @[simp]
theorem _root_.Polynomial.toLaurent_C_mul_T (n : ℕ) (r : R) :
    (toLaurent (Polynomial.monomial n r) : R[T;T⁻¹]) = C r * T n 
goal: Polynomial.toLaurent ((Polynomial.monomial n) r) = LaurentPolynomial.C r * LaurentPolynomial.T ↑n

full_name: Polynomial.toLaurent_C
code: @[simp]
theorem _root_.Polynomial.toLaurent_C (r : R) : toLaurent (Polynomial.C r) = C r 
goal: Polynomial.toLaurent (Polynomial.C r) = LaurentPolynomial.C r

full_name: Polynomial.toLaurent_comp_C
code: @[simp]
theorem _root_.Polynomial.toLaurent_comp_C : toLaurent (R := R) ∘ Polynomial.C = C 
goal: ⇑Polynomial.toLaurent ∘ ⇑Polynomial.C = ⇑LaurentPolynomial.C

full_name: Polynomial.toLaurent_X
code: @[simp]
theorem _root_.Polynomial.toLaurent_X : (toLaurent Polynomial.X : R[T;T⁻¹]) = T 1 
goal: Polynomial.toLaurent Polynomial.X = LaurentPolynomial.T 1

full_name: Polynomial.toLaurent_one
code: theorem _root_.Polynomial.toLaurent_one : (Polynomial.toLaurent : R[X] → R[T;T⁻¹]) 1 = 1 
goal: Polynomial.toLaurent 1 = 1

full_name: Polynomial.toLaurent_C_mul_eq
code: theorem _root_.Polynomial.toLaurent_C_mul_eq (r : R) (f : R[X]) :
    toLaurent (Polynomial.C r * f) = C r * toLaurent f 
goal: Polynomial.toLaurent (Polynomial.C r * f) = LaurentPolynomial.C r * Polynomial.toLaurent f

full_name: Polynomial.toLaurent_X_pow
code: theorem _root_.Polynomial.toLaurent_X_pow (n : ℕ) : toLaurent (X ^ n : R[X]) = T n 
goal: Polynomial.toLaurent (Polynomial.X ^ n) = LaurentPolynomial.T ↑n

full_name: Polynomial.toLaurent_C_mul_X_pow
code: theorem _root_.Polynomial.toLaurent_C_mul_X_pow (n : ℕ) (r : R) :
    toLaurent (Polynomial.C r * X ^ n) = C r * T n 
goal: Polynomial.toLaurent (Polynomial.C r * Polynomial.X ^ n) = LaurentPolynomial.C r * LaurentPolynomial.T ↑n

full_name: LaurentPolynomial.invertibleT
code: instance invertibleT (n : ℤ) : Invertible (T n : R[T;T⁻¹]) 
goal: Invertible (LaurentPolynomial.T n)

full_name: LaurentPolynomial.invOf_T
code: @[simp]
theorem invOf_T (n : ℤ) : ⅟ (T n : R[T;T⁻¹]) = T (-n) 
goal: ⅟(LaurentPolynomial.T n) = LaurentPolynomial.T (-n)

full_name: LaurentPolynomial.isUnit_T
code: theorem isUnit_T (n : ℤ) : IsUnit (T n : R[T;T⁻¹]) 
goal: IsUnit (LaurentPolynomial.T n)

full_name: LaurentPolynomial.induction_on
code: @[elab_as_elim]
protected theorem induction_on {M : R[T;T⁻¹] → Prop} (p : R[T;T⁻¹]) (h_C : ∀ a, M (C a))
    (h_add : ∀ {p q}, M p → M q → M (p + q))
    (h_C_mul_T : ∀ (n : ℕ) (a : R), M (C a * T n) → M (C a * T (n + 1)))
    (h_C_mul_T_Z : ∀ (n : ℕ) (a : R), M (C a * T (-n)) → M (C a * T (-n - 1))) : M p 
goal: M p

full_name: LaurentPolynomial.induction_on'
code: /-- To prove something about Laurent polynomials, it suffices to show that
* the condition is closed under taking sums, and
* it holds for monomials.
-/
@[elab_as_elim]
protected theorem induction_on' {M : R[T;T⁻¹] → Prop} (p : R[T;T⁻¹])
    (h_add : ∀ p q, M p → M q → M (p + q)) (h_C_mul_T : ∀ (n : ℤ) (a : R), M (C a * T n)) :
    M p 
goal: M p

full_name: LaurentPolynomial.commute_T
code: theorem commute_T (n : ℤ) (f : R[T;T⁻¹]) : Commute (T n) f 
goal: Commute (LaurentPolynomial.T n) f

full_name: LaurentPolynomial.T_mul
code: @[simp]
theorem T_mul (n : ℤ) (f : R[T;T⁻¹]) : T n * f = f * T n 
goal: LaurentPolynomial.T n * f = f * LaurentPolynomial.T n

full_name: LaurentPolynomial.trunc
code: /-- `trunc : R[T;T⁻¹] →+ R[X]` maps a Laurent polynomial `f` to the polynomial whose terms of
nonnegative degree coincide with the ones of `f`.  The terms of negative degree of `f` "vanish".
`trunc` is a left-inverse to `Polynomial.toLaurent`. -/
def trunc : R[T;T⁻¹] →+ R[X] 
goal: R[T;T⁻¹] →+ R[X]

full_name: LaurentPolynomial.trunc_C_mul_T
code: @[simp]
theorem trunc_C_mul_T (n : ℤ) (r : R) : trunc (C r * T n) = ite (0 ≤ n) (monomial n.toNat r) 0 
goal: LaurentPolynomial.trunc (LaurentPolynomial.C r * LaurentPolynomial.T n) =
  if 0 ≤ n then (Polynomial.monomial n.toNat) r else 0

full_name: LaurentPolynomial.leftInverse_trunc_toLaurent
code: @[simp]
theorem leftInverse_trunc_toLaurent :
    Function.LeftInverse (trunc : R[T;T⁻¹] → R[X]) Polynomial.toLaurent 
goal: Function.LeftInverse ⇑LaurentPolynomial.trunc ⇑Polynomial.toLaurent

full_name: Polynomial.trunc_toLaurent
code: @[simp]
theorem _root_.Polynomial.trunc_toLaurent (f : R[X]) : trunc (toLaurent f) = f 
goal: LaurentPolynomial.trunc (Polynomial.toLaurent f) = f

full_name: Polynomial.toLaurent_injective
code: theorem _root_.Polynomial.toLaurent_injective :
    Function.Injective (Polynomial.toLaurent : R[X] → R[T;T⁻¹]) 
goal: Function.Injective ⇑Polynomial.toLaurent

full_name: Polynomial.toLaurent_inj
code: @[simp]
theorem _root_.Polynomial.toLaurent_inj (f g : R[X]) : toLaurent f = toLaurent g ↔ f = g 
goal: Polynomial.toLaurent f = Polynomial.toLaurent g ↔ f = g

full_name: Polynomial.toLaurent_ne_zero
code: theorem _root_.Polynomial.toLaurent_ne_zero {f : R[X]} : f ≠ 0 ↔ toLaurent f ≠ 0 
goal: f ≠ 0 ↔ Polynomial.toLaurent f ≠ 0

full_name: LaurentPolynomial.exists_T_pow
code: theorem exists_T_pow (f : R[T;T⁻¹]) : ∃ (n : ℕ) (f' : R[X]), toLaurent f' = f * T n 
goal: ∃ n f', Polynomial.toLaurent f' = f * LaurentPolynomial.T ↑n

full_name: LaurentPolynomial.induction_on_mul_T
code: /-- This is a version of `exists_T_pow` stated as an induction principle. -/
@[elab_as_elim]
theorem induction_on_mul_T {Q : R[T;T⁻¹] → Prop} (f : R[T;T⁻¹])
    (Qf : ∀ {f : R[X]} {n : ℕ}, Q (toLaurent f * T (-n))) : Q f 
goal: Q f

full_name: LaurentPolynomial.reduce_to_polynomial_of_mul_T
code: /-- Suppose that `Q` is a statement about Laurent polynomials such that
* `Q` is true on *ordinary* polynomials;
* `Q (f * T)` implies `Q f`;
it follow that `Q` is true on all Laurent polynomials. -/
theorem reduce_to_polynomial_of_mul_T (f : R[T;T⁻¹]) {Q : R[T;T⁻¹] → Prop}
    (Qf : ∀ f : R[X], Q (toLaurent f)) (QT : ∀ f, Q (f * T 1) → Q f) : Q f 
goal: Q f

full_name: LaurentPolynomial.support_C_mul_T
code: theorem support_C_mul_T (a : R) (n : ℤ) : Finsupp.support (C a * T n) ⊆ {n} 
goal: (LaurentPolynomial.C a * LaurentPolynomial.T n).support ⊆ {n}

full_name: LaurentPolynomial.support_C_mul_T_of_ne_zero
code: theorem support_C_mul_T_of_ne_zero {a : R} (a0 : a ≠ 0) (n : ℤ) :
    Finsupp.support (C a * T n) = {n} 
goal: (LaurentPolynomial.C a * LaurentPolynomial.T n).support = {n}

full_name: LaurentPolynomial.toLaurent_support
code: /-- The support of a polynomial `f` is a finset in `ℕ`.  The lemma `toLaurent_support f`
shows that the support of `f.toLaurent` is the same finset, but viewed in `ℤ` under the natural
inclusion `ℕ ↪ ℤ`. -/
theorem toLaurent_support (f : R[X]) : f.toLaurent.support = f.support.map Nat.castEmbedding 
goal: (Polynomial.toLaurent f).support = Finset.map Nat.castEmbedding f.support

full_name: LaurentPolynomial.degree
code: /-- The degree of a Laurent polynomial takes values in `WithBot ℤ`.
If `f : R[T;T⁻¹]` is a Laurent polynomial, then `f.degree` is the maximum of its support of `f`,
or `⊥`, if `f = 0`. -/
def degree (f : R[T;T⁻¹]) : WithBot ℤ 
goal: WithBot ℤ

full_name: LaurentPolynomial.degree_zero
code: @[simp]
theorem degree_zero : degree (0 : R[T;T⁻¹]) = ⊥ 
goal: LaurentPolynomial.degree 0 = ⊥

full_name: LaurentPolynomial.degree_eq_bot_iff
code: @[simp]
theorem degree_eq_bot_iff {f : R[T;T⁻¹]} : f.degree = ⊥ ↔ f = 0 
goal: f.degree = ⊥ ↔ f = 0

full_name: LaurentPolynomial.degree_C_mul_T
code: @[simp]
theorem degree_C_mul_T (n : ℤ) (a : R) (a0 : a ≠ 0) : degree (C a * T n) = n 
goal: (LaurentPolynomial.C a * LaurentPolynomial.T n).degree = ↑n

full_name: LaurentPolynomial.degree_C_mul_T_ite
code: theorem degree_C_mul_T_ite [DecidableEq R] (n : ℤ) (a : R) :
    degree (C a * T n) = if a = 0 then ⊥ else ↑n 
goal: (LaurentPolynomial.C a * LaurentPolynomial.T n).degree = if a = 0 then ⊥ else ↑n

full_name: LaurentPolynomial.degree_T
code: @[simp]
theorem degree_T [Nontrivial R] (n : ℤ) : (T n : R[T;T⁻¹]).degree = n 
goal: (LaurentPolynomial.T n).degree = ↑n

full_name: LaurentPolynomial.degree_C
code: theorem degree_C {a : R} (a0 : a ≠ 0) : (C a).degree = 0 
goal: (LaurentPolynomial.C a).degree = 0

full_name: LaurentPolynomial.degree_C_ite
code: theorem degree_C_ite [DecidableEq R] (a : R) : (C a).degree = if a = 0 then ⊥ else 0 
goal: (LaurentPolynomial.C a).degree = if a = 0 then ⊥ else 0

full_name: LaurentPolynomial.degree_C_mul_T_le
code: theorem degree_C_mul_T_le (n : ℤ) (a : R) : degree (C a * T n) ≤ n 
goal: (LaurentPolynomial.C a * LaurentPolynomial.T n).degree ≤ ↑n

full_name: LaurentPolynomial.degree_T_le
code: theorem degree_T_le (n : ℤ) : (T n : R[T;T⁻¹]).degree ≤ n 
goal: (LaurentPolynomial.T n).degree ≤ ↑n

full_name: LaurentPolynomial.degree_C_le
code: theorem degree_C_le (a : R) : (C a).degree ≤ 0 
goal: (LaurentPolynomial.C a).degree ≤ 0

full_name: LaurentPolynomial.instModulePolynomial
code: instance : Module R[X] R[T;T⁻¹] 
goal: Module R[X] R[T;T⁻¹]

full_name: LaurentPolynomial.instIsScalarTowerPolynomial
code: instance (R : Type*) [Semiring R] : IsScalarTower R[X] R[X] R[T;T⁻¹] 
goal: IsScalarTower R[X] R[X] R[T;T⁻¹]

full_name: LaurentPolynomial.algebraPolynomial
code: instance algebraPolynomial (R : Type*) [CommSemiring R] : Algebra R[X] R[T;T⁻¹] 
goal: Algebra R[X] R[T;T⁻¹]

full_name: LaurentPolynomial.algebraMap_X_pow
code: theorem algebraMap_X_pow (n : ℕ) : algebraMap R[X] R[T;T⁻¹] (X ^ n) = T n 
goal: (algebraMap R[X] R[T;T⁻¹]) (Polynomial.X ^ n) = LaurentPolynomial.T ↑n

full_name: LaurentPolynomial.algebraMap_eq_toLaurent
code: @[simp]
theorem algebraMap_eq_toLaurent (f : R[X]) : algebraMap R[X] R[T;T⁻¹] f = toLaurent f 
goal: (algebraMap R[X] R[T;T⁻¹]) f = Polynomial.toLaurent f

full_name: LaurentPolynomial.isLocalization
code: theorem isLocalization : IsLocalization (Submonoid.closure ({X} : Set R[X])) R[T;T⁻¹] 
goal: IsLocalization (Submonoid.closure {Polynomial.X}) R[T;T⁻¹]

full_name: LaurentPolynomial.invert
code: /-- The map which substitutes `T ↦ T⁻¹` into a Laurent polynomial. -/
def invert : R[T;T⁻¹] ≃ₐ[R] R[T;T⁻¹] 
goal: R[T;T⁻¹] ≃ₐ[R] R[T;T⁻¹]

full_name: LaurentPolynomial.invert_T
code: @[simp] lemma invert_T (n : ℤ) : invert (T n : R[T;T⁻¹]) = T (-n) 
goal: LaurentPolynomial.invert (LaurentPolynomial.T n) = LaurentPolynomial.T (-n)

full_name: LaurentPolynomial.invert_apply
code: @[simp] lemma invert_apply (f : R[T;T⁻¹]) (n : ℤ) : invert f n = f (-n) 
goal: (LaurentPolynomial.invert f) n = f (-n)

full_name: LaurentPolynomial.invert_comp_C
code: @[simp] lemma invert_comp_C : invert ∘ (@C R _) = C 
goal: ⇑LaurentPolynomial.invert ∘ ⇑LaurentPolynomial.C = ⇑LaurentPolynomial.C

full_name: LaurentPolynomial.invert_C
code: @[simp] lemma invert_C (t : R) : invert (C t) = C t 
goal: LaurentPolynomial.invert (LaurentPolynomial.C t) = LaurentPolynomial.C t

full_name: LaurentPolynomial.involutive_invert
code: lemma involutive_invert : Involutive (invert (R := R)) 
goal: Function.Involutive ⇑LaurentPolynomial.invert

full_name: LaurentPolynomial.invert_symm
code: @[simp] lemma invert_symm : (invert (R := R)).symm = invert 
goal: LaurentPolynomial.invert.symm = LaurentPolynomial.invert

full_name: LaurentPolynomial.toLaurent_reverse
code: lemma toLaurent_reverse (p : R[X]) :
    toLaurent p.reverse = invert (toLaurent p) * (T p.natDegree) 
goal: Polynomial.toLaurent p.reverse = LaurentPolynomial.invert (Polynomial.toLaurent p) * LaurentPolynomial.T ↑p.natDegree