File: Mathlib/RingTheory/WittVector/MulCoeff.lean

full_name: WittVector._aux_Mathlib_RingTheory_WittVector_MulCoeff___macroRules_WittVector_term𝕎_1
code: local notation "𝕎" => WittVector p
goal: Lean.Macro

full_name: WittVector._aux_Mathlib_RingTheory_WittVector_MulCoeff___unexpand_WittVector_1
code: local notation "𝕎" => WittVector p
goal: Lean.PrettyPrinter.Unexpander

full_name: WittVector._aux_Mathlib_RingTheory_WittVector_MulCoeff___macroRules_WittVector_term𝕄_1
code: local notation "𝕄" => MvPolynomial (Fin 2 × ℕ) ℤ
goal: Lean.Macro

full_name: WittVector._aux_Mathlib_RingTheory_WittVector_MulCoeff___unexpand_MvPolynomial_1
code: local notation "𝕄" => MvPolynomial (Fin 2 × ℕ) ℤ
goal: Lean.PrettyPrinter.Unexpander

full_name: WittVector.wittPolyProd
code: /--
```
(∑ i ∈ range n, (y.coeff i)^(p^(n-i)) * p^i.val) *
(∑ i ∈ range n, (y.coeff i)^(p^(n-i)) * p^i.val)
```
-/
def wittPolyProd (n : ℕ) : 𝕄 
goal: MvPolynomial (Fin 2 × ℕ) ℤ

full_name: WittVector.wittPolyProd_vars
code: theorem wittPolyProd_vars (n : ℕ) : (wittPolyProd p n).vars ⊆ univ ×ˢ range (n + 1) 
goal: (WittVector.wittPolyProd p n).vars ⊆ Finset.univ ×ˢ Finset.range (n + 1)

full_name: WittVector.wittPolyProdRemainder
code: /-- The "remainder term" of `WittVector.wittPolyProd`. See `mul_polyOfInterest_aux2`. -/
def wittPolyProdRemainder (n : ℕ) : 𝕄 
goal: MvPolynomial (Fin 2 × ℕ) ℤ

full_name: WittVector.wittPolyProdRemainder_vars
code: theorem wittPolyProdRemainder_vars (n : ℕ) :
    (wittPolyProdRemainder p n).vars ⊆ univ ×ˢ range n 
goal: (WittVector.wittPolyProdRemainder p n).vars ⊆ Finset.univ ×ˢ Finset.range n

full_name: WittVector.remainder
code: /-- `remainder p n` represents the remainder term from `mul_polyOfInterest_aux3`.
`wittPolyProd p (n+1)` will have variables up to `n+1`,
but `remainder` will only have variables up to `n`.
-/
def remainder (n : ℕ) : 𝕄 
goal: MvPolynomial (Fin 2 × ℕ) ℤ

full_name: WittVector.remainder_vars
code: theorem remainder_vars (n : ℕ) : (remainder p n).vars ⊆ univ ×ˢ range (n + 1) 
goal: (WittVector.remainder p n).vars ⊆ Finset.univ ×ˢ Finset.range (n + 1)

full_name: WittVector.polyOfInterest
code: /-- This is the polynomial whose degree we want to get a handle on. -/
def polyOfInterest (n : ℕ) : 𝕄 
goal: MvPolynomial (Fin 2 × ℕ) ℤ

full_name: WittVector.mul_polyOfInterest_aux1
code: theorem mul_polyOfInterest_aux1 (n : ℕ) :
    ∑ i ∈ range (n + 1), (p : 𝕄) ^ i * wittMul p i ^ p ^ (n - i) = wittPolyProd p n 
goal: ∑ i ∈ Finset.range (n + 1), ↑p ^ i * WittVector.wittMul p i ^ p ^ (n - i) = WittVector.wittPolyProd p n

full_name: WittVector.mul_polyOfInterest_aux2
code: theorem mul_polyOfInterest_aux2 (n : ℕ) :
    (p : 𝕄) ^ n * wittMul p n + wittPolyProdRemainder p n = wittPolyProd p n 
goal: ↑p ^ n * WittVector.wittMul p n + WittVector.wittPolyProdRemainder p n = WittVector.wittPolyProd p n

full_name: WittVector.mul_polyOfInterest_aux3
code: theorem mul_polyOfInterest_aux3 (n : ℕ) : wittPolyProd p (n + 1) =
    -((p : 𝕄) ^ (n + 1) * X (0, n + 1)) * ((p : 𝕄) ^ (n + 1) * X (1, n + 1)) +
    (p : 𝕄) ^ (n + 1) * X (0, n + 1) * rename (Prod.mk (1 : Fin 2)) (wittPolynomial p ℤ (n + 1)) +
    (p : 𝕄) ^ (n + 1) * X (1, n + 1) * rename (Prod.mk (0 : Fin 2)) (wittPolynomial p ℤ (n + 1)) +
    remainder p n 
goal: WittVector.wittPolyProd p (n + 1) =
  -(↑p ^ (n + 1) * MvPolynomial.X (0, n + 1)) * (↑p ^ (n + 1) * MvPolynomial.X (1, n + 1)) +
        ↑p ^ (n + 1) * MvPolynomial.X (0, n + 1) * (MvPolynomial.rename (Prod.mk 1)) (wittPolynomial p ℤ (n + 1)) +
      ↑p ^ (n + 1) * MvPolynomial.X (1, n + 1) * (MvPolynomial.rename (Prod.mk 0)) (wittPolynomial p ℤ (n + 1)) +
    WittVector.remainder p n

full_name: WittVector.mul_polyOfInterest_aux4
code: theorem mul_polyOfInterest_aux4 (n : ℕ) :
    (p : 𝕄) ^ (n + 1) * wittMul p (n + 1) =
    -((p : 𝕄) ^ (n + 1) * X (0, n + 1)) * ((p : 𝕄) ^ (n + 1) * X (1, n + 1)) +
    (p : 𝕄) ^ (n + 1) * X (0, n + 1) * rename (Prod.mk (1 : Fin 2)) (wittPolynomial p ℤ (n + 1)) +
    (p : 𝕄) ^ (n + 1) * X (1, n + 1) * rename (Prod.mk (0 : Fin 2)) (wittPolynomial p ℤ (n + 1)) +
    (remainder p n - wittPolyProdRemainder p (n + 1)) 
goal: ↑p ^ (n + 1) * WittVector.wittMul p (n + 1) =
  -(↑p ^ (n + 1) * MvPolynomial.X (0, n + 1)) * (↑p ^ (n + 1) * MvPolynomial.X (1, n + 1)) +
        ↑p ^ (n + 1) * MvPolynomial.X (0, n + 1) * (MvPolynomial.rename (Prod.mk 1)) (wittPolynomial p ℤ (n + 1)) +
      ↑p ^ (n + 1) * MvPolynomial.X (1, n + 1) * (MvPolynomial.rename (Prod.mk 0)) (wittPolynomial p ℤ (n + 1)) +
    (WittVector.remainder p n - WittVector.wittPolyProdRemainder p (n + 1))

full_name: WittVector.mul_polyOfInterest_aux5
code: theorem mul_polyOfInterest_aux5 (n : ℕ) :
    (p : 𝕄) ^ (n + 1) * polyOfInterest p n = remainder p n - wittPolyProdRemainder p (n + 1) 
goal: ↑p ^ (n + 1) * WittVector.polyOfInterest p n = WittVector.remainder p n - WittVector.wittPolyProdRemainder p (n + 1)

full_name: WittVector.mul_polyOfInterest_vars
code: theorem mul_polyOfInterest_vars (n : ℕ) :
    ((p : 𝕄) ^ (n + 1) * polyOfInterest p n).vars ⊆ univ ×ˢ range (n + 1) 
goal: (↑p ^ (n + 1) * WittVector.polyOfInterest p n).vars ⊆ Finset.univ ×ˢ Finset.range (n + 1)

full_name: WittVector.polyOfInterest_vars_eq
code: theorem polyOfInterest_vars_eq (n : ℕ) : (polyOfInterest p n).vars =
    ((p : 𝕄) ^ (n + 1) * (wittMul p (n + 1) + (p : 𝕄) ^ (n + 1) * X (0, n + 1) * X (1, n + 1) -
      X (0, n + 1) * rename (Prod.mk (1 : Fin 2)) (wittPolynomial p ℤ (n + 1)) -
      X (1, n + 1) * rename (Prod.mk (0 : Fin 2)) (wittPolynomial p ℤ (n + 1)))).vars 
goal: (WittVector.polyOfInterest p n).vars =
  (↑p ^ (n + 1) *
      (WittVector.wittMul p (n + 1) + ↑p ^ (n + 1) * MvPolynomial.X (0, n + 1) * MvPolynomial.X (1, n + 1) -
          MvPolynomial.X (0, n + 1) * (MvPolynomial.rename (Prod.mk 1)) (wittPolynomial p ℤ (n + 1)) -
        MvPolynomial.X (1, n + 1) * (MvPolynomial.rename (Prod.mk 0)) (wittPolynomial p ℤ (n + 1)))).vars

full_name: WittVector.polyOfInterest_vars
code: theorem polyOfInterest_vars (n : ℕ) : (polyOfInterest p n).vars ⊆ univ ×ˢ range (n + 1) 
goal: (WittVector.polyOfInterest p n).vars ⊆ Finset.univ ×ˢ Finset.range (n + 1)

full_name: WittVector.peval_polyOfInterest
code: theorem peval_polyOfInterest (n : ℕ) (x y : 𝕎 k) :
    peval (polyOfInterest p n) ![fun i => x.coeff i, fun i => y.coeff i] =
    (x * y).coeff (n + 1) + p ^ (n + 1) * x.coeff (n + 1) * y.coeff (n + 1) -
      y.coeff (n + 1) * ∑ i ∈ range (n + 1 + 1), p ^ i * x.coeff i ^ p ^ (n + 1 - i) -
      x.coeff (n + 1) * ∑ i ∈ range (n + 1 + 1), p ^ i * y.coeff i ^ p ^ (n + 1 - i) 
goal: WittVector.peval (WittVector.polyOfInterest p n) ![fun i => x.coeff i, fun i => y.coeff i] =
  (x * y).coeff (n + 1) + ↑p ^ (n + 1) * x.coeff (n + 1) * y.coeff (n + 1) -
      y.coeff (n + 1) * ∑ i ∈ Finset.range (n + 1 + 1), ↑p ^ i * x.coeff i ^ p ^ (n + 1 - i) -
    x.coeff (n + 1) * ∑ i ∈ Finset.range (n + 1 + 1), ↑p ^ i * y.coeff i ^ p ^ (n + 1 - i)

full_name: WittVector.peval_polyOfInterest'
code: /-- The characteristic `p` version of `peval_polyOfInterest` -/
theorem peval_polyOfInterest' (n : ℕ) (x y : 𝕎 k) :
    peval (polyOfInterest p n) ![fun i => x.coeff i, fun i => y.coeff i] =
      (x * y).coeff (n + 1) - y.coeff (n + 1) * x.coeff 0 ^ p ^ (n + 1) -
        x.coeff (n + 1) * y.coeff 0 ^ p ^ (n + 1) 
goal: WittVector.peval (WittVector.polyOfInterest p n) ![fun i => x.coeff i, fun i => y.coeff i] =
  (x * y).coeff (n + 1) - y.coeff (n + 1) * x.coeff 0 ^ p ^ (n + 1) - x.coeff (n + 1) * y.coeff 0 ^ p ^ (n + 1)

full_name: WittVector.nth_mul_coeff'
code: theorem nth_mul_coeff' (n : ℕ) :
    ∃ f : TruncatedWittVector p (n + 1) k → TruncatedWittVector p (n + 1) k → k,
    ∀ x y : 𝕎 k, f (truncateFun (n + 1) x) (truncateFun (n + 1) y) =
      (x * y).coeff (n + 1) - y.coeff (n + 1) * x.coeff 0 ^ p ^ (n + 1) -
        x.coeff (n + 1) * y.coeff 0 ^ p ^ (n + 1) 
goal: ∃ f,
  ∀ (x y : WittVector p k),
    f (WittVector.truncateFun (n + 1) x) (WittVector.truncateFun (n + 1) y) =
      (x * y).coeff (n + 1) - y.coeff (n + 1) * x.coeff 0 ^ p ^ (n + 1) - x.coeff (n + 1) * y.coeff 0 ^ p ^ (n + 1)

full_name: WittVector.nth_mul_coeff
code: theorem nth_mul_coeff (n : ℕ) :
    ∃ f : TruncatedWittVector p (n + 1) k → TruncatedWittVector p (n + 1) k → k,
    ∀ x y : 𝕎 k, (x * y).coeff (n + 1) =
      x.coeff (n + 1) * y.coeff 0 ^ p ^ (n + 1) + y.coeff (n + 1) * x.coeff 0 ^ p ^ (n + 1) +
      f (truncateFun (n + 1) x) (truncateFun (n + 1) y) 
goal: ∃ f,
  ∀ (x y : WittVector p k),
    (x * y).coeff (n + 1) =
      x.coeff (n + 1) * y.coeff 0 ^ p ^ (n + 1) + y.coeff (n + 1) * x.coeff 0 ^ p ^ (n + 1) +
        f (WittVector.truncateFun (n + 1) x) (WittVector.truncateFun (n + 1) y)

full_name: WittVector.nthRemainder
code: /--
Produces the "remainder function" of the `n+1`st coefficient, which does not depend on the `n+1`st
coefficients of the inputs. -/
def nthRemainder (n : ℕ) : (Fin (n + 1) → k) → (Fin (n + 1) → k) → k 
goal: (Fin (n + 1) → k) → (Fin (n + 1) → k) → k

full_name: WittVector.nthRemainder_spec
code: theorem nthRemainder_spec (n : ℕ) (x y : 𝕎 k) : (x * y).coeff (n + 1) =
    x.coeff (n + 1) * y.coeff 0 ^ p ^ (n + 1) + y.coeff (n + 1) * x.coeff 0 ^ p ^ (n + 1) +
    nthRemainder p n (truncateFun (n + 1) x) (truncateFun (n + 1) y) 
goal: (x * y).coeff (n + 1) =
  x.coeff (n + 1) * y.coeff 0 ^ p ^ (n + 1) + y.coeff (n + 1) * x.coeff 0 ^ p ^ (n + 1) +
    WittVector.nthRemainder p n (WittVector.truncateFun (n + 1) x) (WittVector.truncateFun (n + 1) y)