[GOAL]
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
⊢ vars (wittPolyProd p n) ⊆ univ ×ˢ range (n + 1)
[PROOFSTEP]
rw [wittPolyProd]
[GOAL]
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
⊢ vars (↑(rename (Prod.mk 0)) (wittPolynomial p ℤ n) * ↑(rename (Prod.mk 1)) (wittPolynomial p ℤ n)) ⊆
    univ ×ˢ range (n + 1)
[PROOFSTEP]
apply Subset.trans (vars_mul _ _)
[GOAL]
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
⊢ vars (↑(rename (Prod.mk 0)) (wittPolynomial p ℤ n)) ∪ vars (↑(rename (Prod.mk 1)) (wittPolynomial p ℤ n)) ⊆
    univ ×ˢ range (n + 1)
[PROOFSTEP]
refine' union_subset _ _
[GOAL]
case refine'_1
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
⊢ vars (↑(rename (Prod.mk 0)) (wittPolynomial p ℤ n)) ⊆ univ ×ˢ range (n + 1)
[PROOFSTEP]
refine' Subset.trans (vars_rename _ _) _
[GOAL]
case refine'_1
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
⊢ image (Prod.mk 0) (vars (wittPolynomial p ℤ n)) ⊆ univ ×ˢ range (n + 1)
[PROOFSTEP]
simp [wittPolynomial_vars, image_subset_iff]
[GOAL]
case refine'_2
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
⊢ vars (↑(rename (Prod.mk 1)) (wittPolynomial p ℤ n)) ⊆ univ ×ˢ range (n + 1)
[PROOFSTEP]
refine' Subset.trans (vars_rename _ _) _
[GOAL]
case refine'_2
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
⊢ image (Prod.mk 1) (vars (wittPolynomial p ℤ n)) ⊆ univ ×ˢ range (n + 1)
[PROOFSTEP]
simp [wittPolynomial_vars, image_subset_iff]
[GOAL]
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
⊢ vars (wittPolyProdRemainder p n) ⊆ univ ×ˢ range n
[PROOFSTEP]
rw [wittPolyProdRemainder]
[GOAL]
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
⊢ vars (∑ i in range n, ↑p ^ i * wittMul p i ^ p ^ (n - i)) ⊆ univ ×ˢ range n
[PROOFSTEP]
refine' Subset.trans (vars_sum_subset _ _) _
[GOAL]
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
⊢ (Finset.biUnion (range n) fun i => vars (↑p ^ i * wittMul p i ^ p ^ (n - i))) ⊆ univ ×ˢ range n
[PROOFSTEP]
rw [biUnion_subset]
[GOAL]
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
⊢ ∀ (x : ℕ), x ∈ range n → vars (↑p ^ x * wittMul p x ^ p ^ (n - x)) ⊆ univ ×ˢ range n
[PROOFSTEP]
intro x hx
[GOAL]
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n x : ℕ
hx : x ∈ range n
⊢ vars (↑p ^ x * wittMul p x ^ p ^ (n - x)) ⊆ univ ×ˢ range n
[PROOFSTEP]
apply Subset.trans (vars_mul _ _)
[GOAL]
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n x : ℕ
hx : x ∈ range n
⊢ vars (↑p ^ x) ∪ vars (wittMul p x ^ p ^ (n - x)) ⊆ univ ×ˢ range n
[PROOFSTEP]
refine' union_subset _ _
[GOAL]
case refine'_1
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n x : ℕ
hx : x ∈ range n
⊢ vars (↑p ^ x) ⊆ univ ×ˢ range n
[PROOFSTEP]
apply Subset.trans (vars_pow _ _)
[GOAL]
case refine'_1
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n x : ℕ
hx : x ∈ range n
⊢ vars ↑p ⊆ univ ×ˢ range n
[PROOFSTEP]
have : (p : 𝕄) = C (p : ℤ) := by simp only [Int.cast_ofNat, eq_intCast]
[GOAL]
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n x : ℕ
hx : x ∈ range n
⊢ ↑p = ↑C ↑p
[PROOFSTEP]
simp only [Int.cast_ofNat, eq_intCast]
[GOAL]
case refine'_1
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n x : ℕ
hx : x ∈ range n
this : ↑p = ↑C ↑p
⊢ vars ↑p ⊆ univ ×ˢ range n
[PROOFSTEP]
rw [this, vars_C]
[GOAL]
case refine'_1
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n x : ℕ
hx : x ∈ range n
this : ↑p = ↑C ↑p
⊢ ∅ ⊆ univ ×ˢ range n
[PROOFSTEP]
apply empty_subset
[GOAL]
case refine'_2
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n x : ℕ
hx : x ∈ range n
⊢ vars (wittMul p x ^ p ^ (n - x)) ⊆ univ ×ˢ range n
[PROOFSTEP]
apply Subset.trans (vars_pow _ _)
[GOAL]
case refine'_2
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n x : ℕ
hx : x ∈ range n
⊢ vars (wittMul p x) ⊆ univ ×ˢ range n
[PROOFSTEP]
apply Subset.trans (wittMul_vars _ _)
[GOAL]
case refine'_2
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n x : ℕ
hx : x ∈ range n
⊢ univ ×ˢ range (x + 1) ⊆ univ ×ˢ range n
[PROOFSTEP]
apply product_subset_product (Subset.refl _)
[GOAL]
case refine'_2
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n x : ℕ
hx : x ∈ range n
⊢ range (x + 1) ⊆ range n
[PROOFSTEP]
simp only [mem_range, range_subset] at hx ⊢
[GOAL]
case refine'_2
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n x : ℕ
hx : x < n
⊢ x + 1 ≤ n
[PROOFSTEP]
exact hx
[GOAL]
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
⊢ vars (remainder p n) ⊆ univ ×ˢ range (n + 1)
[PROOFSTEP]
rw [remainder]
[GOAL]
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
⊢ vars
      ((∑ x in range (n + 1), ↑(rename (Prod.mk 0)) (↑(monomial (Finsupp.single x (p ^ (n + 1 - x)))) (↑p ^ x))) *
        ∑ x in range (n + 1), ↑(rename (Prod.mk 1)) (↑(monomial (Finsupp.single x (p ^ (n + 1 - x)))) (↑p ^ x))) ⊆
    univ ×ˢ range (n + 1)
[PROOFSTEP]
apply Subset.trans (vars_mul _ _)
[GOAL]
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
⊢ vars (∑ x in range (n + 1), ↑(rename (Prod.mk 0)) (↑(monomial (Finsupp.single x (p ^ (n + 1 - x)))) (↑p ^ x))) ∪
      vars (∑ x in range (n + 1), ↑(rename (Prod.mk 1)) (↑(monomial (Finsupp.single x (p ^ (n + 1 - x)))) (↑p ^ x))) ⊆
    univ ×ˢ range (n + 1)
[PROOFSTEP]
refine' union_subset _ _
[GOAL]
case refine'_1
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
⊢ vars (∑ x in range (n + 1), ↑(rename (Prod.mk 0)) (↑(monomial (Finsupp.single x (p ^ (n + 1 - x)))) (↑p ^ x))) ⊆
    univ ×ˢ range (n + 1)
[PROOFSTEP]
refine' Subset.trans (vars_sum_subset _ _) _
[GOAL]
case refine'_1
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
⊢ (Finset.biUnion (range (n + 1)) fun i =>
      vars (↑(rename (Prod.mk 0)) (↑(monomial (Finsupp.single i (p ^ (n + 1 - i)))) (↑p ^ i)))) ⊆
    univ ×ˢ range (n + 1)
[PROOFSTEP]
rw [biUnion_subset]
[GOAL]
case refine'_1
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
⊢ ∀ (x : ℕ),
    x ∈ range (n + 1) →
      vars (↑(rename (Prod.mk 0)) (↑(monomial (Finsupp.single x (p ^ (n + 1 - x)))) (↑p ^ x))) ⊆ univ ×ˢ range (n + 1)
[PROOFSTEP]
intro x hx
[GOAL]
case refine'_1
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n x : ℕ
hx : x ∈ range (n + 1)
⊢ vars (↑(rename (Prod.mk 0)) (↑(monomial (Finsupp.single x (p ^ (n + 1 - x)))) (↑p ^ x))) ⊆ univ ×ˢ range (n + 1)
[PROOFSTEP]
rw [rename_monomial, vars_monomial, Finsupp.mapDomain_single]
[GOAL]
case refine'_1
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n x : ℕ
hx : x ∈ range (n + 1)
⊢ (Finsupp.single (0, x) (p ^ (n + 1 - x))).support ⊆ univ ×ˢ range (n + 1)
[PROOFSTEP]
apply Subset.trans Finsupp.support_single_subset
[GOAL]
case refine'_1
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n x : ℕ
hx : x ∈ range (n + 1)
⊢ {(0, x)} ⊆ univ ×ˢ range (n + 1)
[PROOFSTEP]
simpa using mem_range.mp hx
[GOAL]
case refine'_1
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n x : ℕ
hx : x ∈ range (n + 1)
⊢ ↑p ^ x ≠ 0
[PROOFSTEP]
apply pow_ne_zero
[GOAL]
case refine'_1.h
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n x : ℕ
hx : x ∈ range (n + 1)
⊢ ↑p ≠ 0
[PROOFSTEP]
exact_mod_cast hp.out.ne_zero
[GOAL]
case refine'_2
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
⊢ vars (∑ x in range (n + 1), ↑(rename (Prod.mk 1)) (↑(monomial (Finsupp.single x (p ^ (n + 1 - x)))) (↑p ^ x))) ⊆
    univ ×ˢ range (n + 1)
[PROOFSTEP]
refine' Subset.trans (vars_sum_subset _ _) _
[GOAL]
case refine'_2
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
⊢ (Finset.biUnion (range (n + 1)) fun i =>
      vars (↑(rename (Prod.mk 1)) (↑(monomial (Finsupp.single i (p ^ (n + 1 - i)))) (↑p ^ i)))) ⊆
    univ ×ˢ range (n + 1)
[PROOFSTEP]
rw [biUnion_subset]
[GOAL]
case refine'_2
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
⊢ ∀ (x : ℕ),
    x ∈ range (n + 1) →
      vars (↑(rename (Prod.mk 1)) (↑(monomial (Finsupp.single x (p ^ (n + 1 - x)))) (↑p ^ x))) ⊆ univ ×ˢ range (n + 1)
[PROOFSTEP]
intro x hx
[GOAL]
case refine'_2
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n x : ℕ
hx : x ∈ range (n + 1)
⊢ vars (↑(rename (Prod.mk 1)) (↑(monomial (Finsupp.single x (p ^ (n + 1 - x)))) (↑p ^ x))) ⊆ univ ×ˢ range (n + 1)
[PROOFSTEP]
rw [rename_monomial, vars_monomial, Finsupp.mapDomain_single]
[GOAL]
case refine'_2
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n x : ℕ
hx : x ∈ range (n + 1)
⊢ (Finsupp.single (1, x) (p ^ (n + 1 - x))).support ⊆ univ ×ˢ range (n + 1)
[PROOFSTEP]
apply Subset.trans Finsupp.support_single_subset
[GOAL]
case refine'_2
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n x : ℕ
hx : x ∈ range (n + 1)
⊢ {(1, x)} ⊆ univ ×ˢ range (n + 1)
[PROOFSTEP]
simpa using mem_range.mp hx
[GOAL]
case refine'_2
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n x : ℕ
hx : x ∈ range (n + 1)
⊢ ↑p ^ x ≠ 0
[PROOFSTEP]
apply pow_ne_zero
[GOAL]
case refine'_2.h
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n x : ℕ
hx : x ∈ range (n + 1)
⊢ ↑p ≠ 0
[PROOFSTEP]
exact_mod_cast hp.out.ne_zero
[GOAL]
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
⊢ ∑ i in range (n + 1), ↑p ^ i * wittMul p i ^ p ^ (n - i) = wittPolyProd p n
[PROOFSTEP]
simp only [wittPolyProd]
[GOAL]
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
⊢ ∑ i in range (n + 1), ↑p ^ i * wittMul p i ^ p ^ (n - i) =
    ↑(rename (Prod.mk 0)) (wittPolynomial p ℤ n) * ↑(rename (Prod.mk 1)) (wittPolynomial p ℤ n)
[PROOFSTEP]
convert wittStructureInt_prop p (X (0 : Fin 2) * X 1) n using 1
[GOAL]
case h.e'_2
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
⊢ ∑ i in range (n + 1), ↑p ^ i * wittMul p i ^ p ^ (n - i) =
    ↑(bind₁ (wittStructureInt p (X 0 * X 1))) (wittPolynomial p ℤ n)
[PROOFSTEP]
simp only [wittPolynomial, wittMul]
[GOAL]
case h.e'_2
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
⊢ ∑ x in range (n + 1), ↑p ^ x * wittStructureInt p (X 0 * X 1) x ^ p ^ (n - x) =
    ↑(bind₁ (wittStructureInt p (X 0 * X 1)))
      (∑ x in range (n + 1), ↑(monomial (Finsupp.single x (p ^ (n - x)))) (↑p ^ x))
[PROOFSTEP]
rw [AlgHom.map_sum]
[GOAL]
case h.e'_2
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
⊢ ∑ x in range (n + 1), ↑p ^ x * wittStructureInt p (X 0 * X 1) x ^ p ^ (n - x) =
    ∑ x in range (n + 1),
      ↑(bind₁ (wittStructureInt p (X 0 * X 1))) (↑(monomial (Finsupp.single x (p ^ (n - x)))) (↑p ^ x))
[PROOFSTEP]
congr 1 with i
[GOAL]
case h.e'_2.e_f.h.a
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n i : ℕ
m✝ : Fin 2 × ℕ →₀ ℕ
⊢ MvPolynomial.coeff m✝ (↑p ^ i * wittStructureInt p (X 0 * X 1) i ^ p ^ (n - i)) =
    MvPolynomial.coeff m✝
      (↑(bind₁ (wittStructureInt p (X 0 * X 1))) (↑(monomial (Finsupp.single i (p ^ (n - i)))) (↑p ^ i)))
[PROOFSTEP]
congr 1
[GOAL]
case h.e'_2.e_f.h.a.e_p
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n i : ℕ
m✝ : Fin 2 × ℕ →₀ ℕ
⊢ ↑p ^ i * wittStructureInt p (X 0 * X 1) i ^ p ^ (n - i) =
    ↑(bind₁ (wittStructureInt p (X 0 * X 1))) (↑(monomial (Finsupp.single i (p ^ (n - i)))) (↑p ^ i))
[PROOFSTEP]
have hsupp : (Finsupp.single i (p ^ (n - i))).support = { i } :=
  by
  rw [Finsupp.support_eq_singleton]
  simp only [and_true_iff, Finsupp.single_eq_same, eq_self_iff_true, Ne.def]
  exact pow_ne_zero _ hp.out.ne_zero
[GOAL]
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n i : ℕ
m✝ : Fin 2 × ℕ →₀ ℕ
⊢ (Finsupp.single i (p ^ (n - i))).support = {i}
[PROOFSTEP]
rw [Finsupp.support_eq_singleton]
[GOAL]
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n i : ℕ
m✝ : Fin 2 × ℕ →₀ ℕ
⊢ ↑(Finsupp.single i (p ^ (n - i))) i ≠ 0 ∧
    Finsupp.single i (p ^ (n - i)) = Finsupp.single i (↑(Finsupp.single i (p ^ (n - i))) i)
[PROOFSTEP]
simp only [and_true_iff, Finsupp.single_eq_same, eq_self_iff_true, Ne.def]
[GOAL]
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n i : ℕ
m✝ : Fin 2 × ℕ →₀ ℕ
⊢ ¬p ^ (n - i) = 0
[PROOFSTEP]
exact pow_ne_zero _ hp.out.ne_zero
[GOAL]
case h.e'_2.e_f.h.a.e_p
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n i : ℕ
m✝ : Fin 2 × ℕ →₀ ℕ
hsupp : (Finsupp.single i (p ^ (n - i))).support = {i}
⊢ ↑p ^ i * wittStructureInt p (X 0 * X 1) i ^ p ^ (n - i) =
    ↑(bind₁ (wittStructureInt p (X 0 * X 1))) (↑(monomial (Finsupp.single i (p ^ (n - i)))) (↑p ^ i))
[PROOFSTEP]
simp only [bind₁_monomial, hsupp, Int.cast_ofNat, prod_singleton, eq_intCast, Finsupp.single_eq_same, C_pow,
  mul_eq_mul_left_iff, true_or_iff, eq_self_iff_true, Int.cast_pow]
[GOAL]
case h.e'_3
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
⊢ ↑(rename (Prod.mk 0)) (wittPolynomial p ℤ n) * ↑(rename (Prod.mk 1)) (wittPolynomial p ℤ n) =
    ↑(bind₁ fun i => ↑(rename (Prod.mk i)) (wittPolynomial p ℤ n)) (X 0 * X 1)
[PROOFSTEP]
simp only [map_mul, bind₁_X_right]
[GOAL]
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
⊢ ↑p ^ n * wittMul p n + wittPolyProdRemainder p n = wittPolyProd p n
[PROOFSTEP]
convert mul_polyOfInterest_aux1 p n
[GOAL]
case h.e'_2
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
⊢ ↑p ^ n * wittMul p n + wittPolyProdRemainder p n = ∑ i in range (n + 1), ↑p ^ i * wittMul p i ^ p ^ (n - i)
[PROOFSTEP]
rw [sum_range_succ, add_comm, Nat.sub_self, pow_zero, pow_one]
[GOAL]
case h.e'_2
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
⊢ wittPolyProdRemainder p n + ↑p ^ n * wittMul p n =
    ∑ x in range n, ↑p ^ x * wittMul p x ^ p ^ (n - x) + ↑p ^ n * wittMul p n
[PROOFSTEP]
rfl
[GOAL]
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
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)) (wittPolynomial p ℤ (n + 1)) +
        ↑p ^ (n + 1) * X (1, n + 1) * ↑(rename (Prod.mk 0)) (wittPolynomial p ℤ (n + 1)) +
      remainder p n
[PROOFSTEP]
have mvpz : (p : 𝕄) ^ (n + 1) = MvPolynomial.C ((p : ℤ) ^ (n + 1)) := by simp only;
  norm_cast
    -- Porting note: the original proof applies `sum_range_succ` through a non-`conv` rewrite,
      -- but this does not work in Lean 4; the whole proof also times out very badly. The proof has been
      -- nearly totally rewritten here and now finishes quite fast.
[GOAL]
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
⊢ ↑p ^ (n + 1) = ↑C (↑p ^ (n + 1))
[PROOFSTEP]
simp only
[GOAL]
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
⊢ ↑p ^ (n + 1) = ↑C (↑p ^ (n + 1))
[PROOFSTEP]
norm_cast
  -- Porting note: the original proof applies `sum_range_succ` through a non-`conv` rewrite,
    -- but this does not work in Lean 4; the whole proof also times out very badly. The proof has been
    -- nearly totally rewritten here and now finishes quite fast.
[GOAL]
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
mvpz : ↑p ^ (n + 1) = ↑C (↑p ^ (n + 1))
⊢ 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)) (wittPolynomial p ℤ (n + 1)) +
        ↑p ^ (n + 1) * X (1, n + 1) * ↑(rename (Prod.mk 0)) (wittPolynomial p ℤ (n + 1)) +
      remainder p n
[PROOFSTEP]
rw [wittPolyProd, wittPolynomial, AlgHom.map_sum, AlgHom.map_sum]
[GOAL]
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
mvpz : ↑p ^ (n + 1) = ↑C (↑p ^ (n + 1))
⊢ (∑ x in range (n + 1 + 1), ↑(rename (Prod.mk 0)) (↑(monomial (Finsupp.single x (p ^ (n + 1 - x)))) (↑p ^ x))) *
      ∑ x in range (n + 1 + 1), ↑(rename (Prod.mk 1)) (↑(monomial (Finsupp.single x (p ^ (n + 1 - x)))) (↑p ^ x)) =
    -(↑p ^ (n + 1) * X (0, n + 1)) * (↑p ^ (n + 1) * X (1, n + 1)) +
          ↑p ^ (n + 1) * X (0, n + 1) *
            ∑ x in range (n + 1 + 1),
              ↑(rename (Prod.mk 1)) (↑(monomial (Finsupp.single x (p ^ (n + 1 - x)))) (↑p ^ x)) +
        ↑p ^ (n + 1) * X (1, n + 1) *
          ∑ x in range (n + 1 + 1), ↑(rename (Prod.mk 0)) (↑(monomial (Finsupp.single x (p ^ (n + 1 - x)))) (↑p ^ x)) +
      remainder p n
[PROOFSTEP]
conv_lhs =>
  arg 1
  rw [sum_range_succ, ← C_mul_X_pow_eq_monomial, tsub_self, pow_zero, pow_one, map_mul, rename_C, rename_X, ← mvpz]
[GOAL]
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
mvpz : ↑p ^ (n + 1) = ↑C (↑p ^ (n + 1))
| (∑ x in range (n + 1 + 1), ↑(rename (Prod.mk 0)) (↑(monomial (Finsupp.single x (p ^ (n + 1 - x)))) (↑p ^ x))) *
    ∑ x in range (n + 1 + 1), ↑(rename (Prod.mk 1)) (↑(monomial (Finsupp.single x (p ^ (n + 1 - x)))) (↑p ^ x))
[PROOFSTEP]
  arg 1
  rw [sum_range_succ, ← C_mul_X_pow_eq_monomial, tsub_self, pow_zero, pow_one, map_mul, rename_C, rename_X, ← mvpz]
[GOAL]
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
mvpz : ↑p ^ (n + 1) = ↑C (↑p ^ (n + 1))
| (∑ x in range (n + 1 + 1), ↑(rename (Prod.mk 0)) (↑(monomial (Finsupp.single x (p ^ (n + 1 - x)))) (↑p ^ x))) *
    ∑ x in range (n + 1 + 1), ↑(rename (Prod.mk 1)) (↑(monomial (Finsupp.single x (p ^ (n + 1 - x)))) (↑p ^ x))
[PROOFSTEP]
  arg 1
  rw [sum_range_succ, ← C_mul_X_pow_eq_monomial, tsub_self, pow_zero, pow_one, map_mul, rename_C, rename_X, ← mvpz]
[GOAL]
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
mvpz : ↑p ^ (n + 1) = ↑C (↑p ^ (n + 1))
| (∑ x in range (n + 1 + 1), ↑(rename (Prod.mk 0)) (↑(monomial (Finsupp.single x (p ^ (n + 1 - x)))) (↑p ^ x))) *
    ∑ x in range (n + 1 + 1), ↑(rename (Prod.mk 1)) (↑(monomial (Finsupp.single x (p ^ (n + 1 - x)))) (↑p ^ x))
[PROOFSTEP]
arg 1
[GOAL]
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
mvpz : ↑p ^ (n + 1) = ↑C (↑p ^ (n + 1))
| ∑ x in range (n + 1 + 1), ↑(rename (Prod.mk 0)) (↑(monomial (Finsupp.single x (p ^ (n + 1 - x)))) (↑p ^ x))
[PROOFSTEP]
rw [sum_range_succ, ← C_mul_X_pow_eq_monomial, tsub_self, pow_zero, pow_one, map_mul, rename_C, rename_X, ← mvpz]
[GOAL]
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
mvpz : ↑p ^ (n + 1) = ↑C (↑p ^ (n + 1))
⊢ (∑ x in range (n + 1), ↑(rename (Prod.mk 0)) (↑(monomial (Finsupp.single x (p ^ (n + 1 - x)))) (↑p ^ x)) +
        ↑p ^ (n + 1) * X (0, n + 1)) *
      ∑ x in range (n + 1 + 1), ↑(rename (Prod.mk 1)) (↑(monomial (Finsupp.single x (p ^ (n + 1 - x)))) (↑p ^ x)) =
    -(↑p ^ (n + 1) * X (0, n + 1)) * (↑p ^ (n + 1) * X (1, n + 1)) +
          ↑p ^ (n + 1) * X (0, n + 1) *
            ∑ x in range (n + 1 + 1),
              ↑(rename (Prod.mk 1)) (↑(monomial (Finsupp.single x (p ^ (n + 1 - x)))) (↑p ^ x)) +
        ↑p ^ (n + 1) * X (1, n + 1) *
          ∑ x in range (n + 1 + 1), ↑(rename (Prod.mk 0)) (↑(monomial (Finsupp.single x (p ^ (n + 1 - x)))) (↑p ^ x)) +
      remainder p n
[PROOFSTEP]
conv_lhs =>
  arg 2
  rw [sum_range_succ, ← C_mul_X_pow_eq_monomial, tsub_self, pow_zero, pow_one, map_mul, rename_C, rename_X, ← mvpz]
[GOAL]
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
mvpz : ↑p ^ (n + 1) = ↑C (↑p ^ (n + 1))
| (∑ x in range (n + 1), ↑(rename (Prod.mk 0)) (↑(monomial (Finsupp.single x (p ^ (n + 1 - x)))) (↑p ^ x)) +
      ↑p ^ (n + 1) * X (0, n + 1)) *
    ∑ x in range (n + 1 + 1), ↑(rename (Prod.mk 1)) (↑(monomial (Finsupp.single x (p ^ (n + 1 - x)))) (↑p ^ x))
[PROOFSTEP]
  arg 2
  rw [sum_range_succ, ← C_mul_X_pow_eq_monomial, tsub_self, pow_zero, pow_one, map_mul, rename_C, rename_X, ← mvpz]
[GOAL]
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
mvpz : ↑p ^ (n + 1) = ↑C (↑p ^ (n + 1))
| (∑ x in range (n + 1), ↑(rename (Prod.mk 0)) (↑(monomial (Finsupp.single x (p ^ (n + 1 - x)))) (↑p ^ x)) +
      ↑p ^ (n + 1) * X (0, n + 1)) *
    ∑ x in range (n + 1 + 1), ↑(rename (Prod.mk 1)) (↑(monomial (Finsupp.single x (p ^ (n + 1 - x)))) (↑p ^ x))
[PROOFSTEP]
  arg 2
  rw [sum_range_succ, ← C_mul_X_pow_eq_monomial, tsub_self, pow_zero, pow_one, map_mul, rename_C, rename_X, ← mvpz]
[GOAL]
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
mvpz : ↑p ^ (n + 1) = ↑C (↑p ^ (n + 1))
| (∑ x in range (n + 1), ↑(rename (Prod.mk 0)) (↑(monomial (Finsupp.single x (p ^ (n + 1 - x)))) (↑p ^ x)) +
      ↑p ^ (n + 1) * X (0, n + 1)) *
    ∑ x in range (n + 1 + 1), ↑(rename (Prod.mk 1)) (↑(monomial (Finsupp.single x (p ^ (n + 1 - x)))) (↑p ^ x))
[PROOFSTEP]
arg 2
[GOAL]
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
mvpz : ↑p ^ (n + 1) = ↑C (↑p ^ (n + 1))
| ∑ x in range (n + 1 + 1), ↑(rename (Prod.mk 1)) (↑(monomial (Finsupp.single x (p ^ (n + 1 - x)))) (↑p ^ x))
[PROOFSTEP]
rw [sum_range_succ, ← C_mul_X_pow_eq_monomial, tsub_self, pow_zero, pow_one, map_mul, rename_C, rename_X, ← mvpz]
[GOAL]
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
mvpz : ↑p ^ (n + 1) = ↑C (↑p ^ (n + 1))
⊢ (∑ x in range (n + 1), ↑(rename (Prod.mk 0)) (↑(monomial (Finsupp.single x (p ^ (n + 1 - x)))) (↑p ^ x)) +
        ↑p ^ (n + 1) * X (0, n + 1)) *
      (∑ x in range (n + 1), ↑(rename (Prod.mk 1)) (↑(monomial (Finsupp.single x (p ^ (n + 1 - x)))) (↑p ^ x)) +
        ↑p ^ (n + 1) * X (1, n + 1)) =
    -(↑p ^ (n + 1) * X (0, n + 1)) * (↑p ^ (n + 1) * X (1, n + 1)) +
          ↑p ^ (n + 1) * X (0, n + 1) *
            ∑ x in range (n + 1 + 1),
              ↑(rename (Prod.mk 1)) (↑(monomial (Finsupp.single x (p ^ (n + 1 - x)))) (↑p ^ x)) +
        ↑p ^ (n + 1) * X (1, n + 1) *
          ∑ x in range (n + 1 + 1), ↑(rename (Prod.mk 0)) (↑(monomial (Finsupp.single x (p ^ (n + 1 - x)))) (↑p ^ x)) +
      remainder p n
[PROOFSTEP]
conv_rhs =>
  enter [1, 1, 2, 2]
  rw [sum_range_succ, ← C_mul_X_pow_eq_monomial, tsub_self, pow_zero, pow_one, map_mul, rename_C, rename_X, ← mvpz]
[GOAL]
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
mvpz : ↑p ^ (n + 1) = ↑C (↑p ^ (n + 1))
| -(↑p ^ (n + 1) * X (0, n + 1)) * (↑p ^ (n + 1) * X (1, n + 1)) +
        ↑p ^ (n + 1) * X (0, n + 1) *
          ∑ x in range (n + 1 + 1), ↑(rename (Prod.mk 1)) (↑(monomial (Finsupp.single x (p ^ (n + 1 - x)))) (↑p ^ x)) +
      ↑p ^ (n + 1) * X (1, n + 1) *
        ∑ x in range (n + 1 + 1), ↑(rename (Prod.mk 0)) (↑(monomial (Finsupp.single x (p ^ (n + 1 - x)))) (↑p ^ x)) +
    remainder p n
[PROOFSTEP]
  enter [1, 1, 2, 2]
  rw [sum_range_succ, ← C_mul_X_pow_eq_monomial, tsub_self, pow_zero, pow_one, map_mul, rename_C, rename_X, ← mvpz]
[GOAL]
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
mvpz : ↑p ^ (n + 1) = ↑C (↑p ^ (n + 1))
| -(↑p ^ (n + 1) * X (0, n + 1)) * (↑p ^ (n + 1) * X (1, n + 1)) +
        ↑p ^ (n + 1) * X (0, n + 1) *
          ∑ x in range (n + 1 + 1), ↑(rename (Prod.mk 1)) (↑(monomial (Finsupp.single x (p ^ (n + 1 - x)))) (↑p ^ x)) +
      ↑p ^ (n + 1) * X (1, n + 1) *
        ∑ x in range (n + 1 + 1), ↑(rename (Prod.mk 0)) (↑(monomial (Finsupp.single x (p ^ (n + 1 - x)))) (↑p ^ x)) +
    remainder p n
[PROOFSTEP]
  enter [1, 1, 2, 2]
  rw [sum_range_succ, ← C_mul_X_pow_eq_monomial, tsub_self, pow_zero, pow_one, map_mul, rename_C, rename_X, ← mvpz]
[GOAL]
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
mvpz : ↑p ^ (n + 1) = ↑C (↑p ^ (n + 1))
| -(↑p ^ (n + 1) * X (0, n + 1)) * (↑p ^ (n + 1) * X (1, n + 1)) +
        ↑p ^ (n + 1) * X (0, n + 1) *
          ∑ x in range (n + 1 + 1), ↑(rename (Prod.mk 1)) (↑(monomial (Finsupp.single x (p ^ (n + 1 - x)))) (↑p ^ x)) +
      ↑p ^ (n + 1) * X (1, n + 1) *
        ∑ x in range (n + 1 + 1), ↑(rename (Prod.mk 0)) (↑(monomial (Finsupp.single x (p ^ (n + 1 - x)))) (↑p ^ x)) +
    remainder p n
[PROOFSTEP]
enter [1, 1, 2, 2]
[GOAL]
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
mvpz : ↑p ^ (n + 1) = ↑C (↑p ^ (n + 1))
| ∑ x in range (n + 1 + 1), ↑(rename (Prod.mk 1)) (↑(monomial (Finsupp.single x (p ^ (n + 1 - x)))) (↑p ^ x))
[PROOFSTEP]
rw [sum_range_succ, ← C_mul_X_pow_eq_monomial, tsub_self, pow_zero, pow_one, map_mul, rename_C, rename_X, ← mvpz]
[GOAL]
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
mvpz : ↑p ^ (n + 1) = ↑C (↑p ^ (n + 1))
⊢ (∑ x in range (n + 1), ↑(rename (Prod.mk 0)) (↑(monomial (Finsupp.single x (p ^ (n + 1 - x)))) (↑p ^ x)) +
        ↑p ^ (n + 1) * X (0, n + 1)) *
      (∑ x in range (n + 1), ↑(rename (Prod.mk 1)) (↑(monomial (Finsupp.single x (p ^ (n + 1 - x)))) (↑p ^ x)) +
        ↑p ^ (n + 1) * X (1, n + 1)) =
    -(↑p ^ (n + 1) * X (0, n + 1)) * (↑p ^ (n + 1) * X (1, n + 1)) +
          ↑p ^ (n + 1) * X (0, n + 1) *
            (∑ x in range (n + 1), ↑(rename (Prod.mk 1)) (↑(monomial (Finsupp.single x (p ^ (n + 1 - x)))) (↑p ^ x)) +
              ↑p ^ (n + 1) * X (1, n + 1)) +
        ↑p ^ (n + 1) * X (1, n + 1) *
          ∑ x in range (n + 1 + 1), ↑(rename (Prod.mk 0)) (↑(monomial (Finsupp.single x (p ^ (n + 1 - x)))) (↑p ^ x)) +
      remainder p n
[PROOFSTEP]
conv_rhs =>
  enter [1, 2, 2]
  rw [sum_range_succ, ← C_mul_X_pow_eq_monomial, tsub_self, pow_zero, pow_one, map_mul, rename_C, rename_X, ← mvpz]
[GOAL]
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
mvpz : ↑p ^ (n + 1) = ↑C (↑p ^ (n + 1))
| -(↑p ^ (n + 1) * X (0, n + 1)) * (↑p ^ (n + 1) * X (1, n + 1)) +
        ↑p ^ (n + 1) * X (0, n + 1) *
          (∑ x in range (n + 1), ↑(rename (Prod.mk 1)) (↑(monomial (Finsupp.single x (p ^ (n + 1 - x)))) (↑p ^ x)) +
            ↑p ^ (n + 1) * X (1, n + 1)) +
      ↑p ^ (n + 1) * X (1, n + 1) *
        ∑ x in range (n + 1 + 1), ↑(rename (Prod.mk 0)) (↑(monomial (Finsupp.single x (p ^ (n + 1 - x)))) (↑p ^ x)) +
    remainder p n
[PROOFSTEP]
  enter [1, 2, 2]
  rw [sum_range_succ, ← C_mul_X_pow_eq_monomial, tsub_self, pow_zero, pow_one, map_mul, rename_C, rename_X, ← mvpz]
[GOAL]
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
mvpz : ↑p ^ (n + 1) = ↑C (↑p ^ (n + 1))
| -(↑p ^ (n + 1) * X (0, n + 1)) * (↑p ^ (n + 1) * X (1, n + 1)) +
        ↑p ^ (n + 1) * X (0, n + 1) *
          (∑ x in range (n + 1), ↑(rename (Prod.mk 1)) (↑(monomial (Finsupp.single x (p ^ (n + 1 - x)))) (↑p ^ x)) +
            ↑p ^ (n + 1) * X (1, n + 1)) +
      ↑p ^ (n + 1) * X (1, n + 1) *
        ∑ x in range (n + 1 + 1), ↑(rename (Prod.mk 0)) (↑(monomial (Finsupp.single x (p ^ (n + 1 - x)))) (↑p ^ x)) +
    remainder p n
[PROOFSTEP]
  enter [1, 2, 2]
  rw [sum_range_succ, ← C_mul_X_pow_eq_monomial, tsub_self, pow_zero, pow_one, map_mul, rename_C, rename_X, ← mvpz]
[GOAL]
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
mvpz : ↑p ^ (n + 1) = ↑C (↑p ^ (n + 1))
| -(↑p ^ (n + 1) * X (0, n + 1)) * (↑p ^ (n + 1) * X (1, n + 1)) +
        ↑p ^ (n + 1) * X (0, n + 1) *
          (∑ x in range (n + 1), ↑(rename (Prod.mk 1)) (↑(monomial (Finsupp.single x (p ^ (n + 1 - x)))) (↑p ^ x)) +
            ↑p ^ (n + 1) * X (1, n + 1)) +
      ↑p ^ (n + 1) * X (1, n + 1) *
        ∑ x in range (n + 1 + 1), ↑(rename (Prod.mk 0)) (↑(monomial (Finsupp.single x (p ^ (n + 1 - x)))) (↑p ^ x)) +
    remainder p n
[PROOFSTEP]
enter [1, 2, 2]
[GOAL]
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
mvpz : ↑p ^ (n + 1) = ↑C (↑p ^ (n + 1))
| ∑ x in range (n + 1 + 1), ↑(rename (Prod.mk 0)) (↑(monomial (Finsupp.single x (p ^ (n + 1 - x)))) (↑p ^ x))
[PROOFSTEP]
rw [sum_range_succ, ← C_mul_X_pow_eq_monomial, tsub_self, pow_zero, pow_one, map_mul, rename_C, rename_X, ← mvpz]
[GOAL]
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
mvpz : ↑p ^ (n + 1) = ↑C (↑p ^ (n + 1))
⊢ (∑ x in range (n + 1), ↑(rename (Prod.mk 0)) (↑(monomial (Finsupp.single x (p ^ (n + 1 - x)))) (↑p ^ x)) +
        ↑p ^ (n + 1) * X (0, n + 1)) *
      (∑ x in range (n + 1), ↑(rename (Prod.mk 1)) (↑(monomial (Finsupp.single x (p ^ (n + 1 - x)))) (↑p ^ x)) +
        ↑p ^ (n + 1) * X (1, n + 1)) =
    -(↑p ^ (n + 1) * X (0, n + 1)) * (↑p ^ (n + 1) * X (1, n + 1)) +
          ↑p ^ (n + 1) * X (0, n + 1) *
            (∑ x in range (n + 1), ↑(rename (Prod.mk 1)) (↑(monomial (Finsupp.single x (p ^ (n + 1 - x)))) (↑p ^ x)) +
              ↑p ^ (n + 1) * X (1, n + 1)) +
        ↑p ^ (n + 1) * X (1, n + 1) *
          (∑ x in range (n + 1), ↑(rename (Prod.mk 0)) (↑(monomial (Finsupp.single x (p ^ (n + 1 - x)))) (↑p ^ x)) +
            ↑p ^ (n + 1) * X (0, n + 1)) +
      remainder p n
[PROOFSTEP]
simp only [add_mul, mul_add]
[GOAL]
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
mvpz : ↑p ^ (n + 1) = ↑C (↑p ^ (n + 1))
⊢ (∑ x in range (n + 1), ↑(rename (Prod.mk 0)) (↑(monomial (Finsupp.single x (p ^ (n + 1 - x)))) (↑p ^ x))) *
          ∑ x in range (n + 1), ↑(rename (Prod.mk 1)) (↑(monomial (Finsupp.single x (p ^ (n + 1 - x)))) (↑p ^ x)) +
        ↑p ^ (n + 1) * X (0, n + 1) *
          ∑ x in range (n + 1), ↑(rename (Prod.mk 1)) (↑(monomial (Finsupp.single x (p ^ (n + 1 - x)))) (↑p ^ x)) +
      ((∑ x in range (n + 1), ↑(rename (Prod.mk 0)) (↑(monomial (Finsupp.single x (p ^ (n + 1 - x)))) (↑p ^ x))) *
          (↑p ^ (n + 1) * X (1, n + 1)) +
        ↑p ^ (n + 1) * X (0, n + 1) * (↑p ^ (n + 1) * X (1, n + 1))) =
    -(↑p ^ (n + 1) * X (0, n + 1)) * (↑p ^ (n + 1) * X (1, n + 1)) +
          (↑p ^ (n + 1) * X (0, n + 1) *
              ∑ x in range (n + 1), ↑(rename (Prod.mk 1)) (↑(monomial (Finsupp.single x (p ^ (n + 1 - x)))) (↑p ^ x)) +
            ↑p ^ (n + 1) * X (0, n + 1) * (↑p ^ (n + 1) * X (1, n + 1))) +
        (↑p ^ (n + 1) * X (1, n + 1) *
            ∑ x in range (n + 1), ↑(rename (Prod.mk 0)) (↑(monomial (Finsupp.single x (p ^ (n + 1 - x)))) (↑p ^ x)) +
          ↑p ^ (n + 1) * X (1, n + 1) * (↑p ^ (n + 1) * X (0, n + 1))) +
      remainder p n
[PROOFSTEP]
rw [add_comm _ (remainder p n)]
[GOAL]
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
mvpz : ↑p ^ (n + 1) = ↑C (↑p ^ (n + 1))
⊢ (∑ x in range (n + 1), ↑(rename (Prod.mk 0)) (↑(monomial (Finsupp.single x (p ^ (n + 1 - x)))) (↑p ^ x))) *
          ∑ x in range (n + 1), ↑(rename (Prod.mk 1)) (↑(monomial (Finsupp.single x (p ^ (n + 1 - x)))) (↑p ^ x)) +
        ↑p ^ (n + 1) * X (0, n + 1) *
          ∑ x in range (n + 1), ↑(rename (Prod.mk 1)) (↑(monomial (Finsupp.single x (p ^ (n + 1 - x)))) (↑p ^ x)) +
      ((∑ x in range (n + 1), ↑(rename (Prod.mk 0)) (↑(monomial (Finsupp.single x (p ^ (n + 1 - x)))) (↑p ^ x))) *
          (↑p ^ (n + 1) * X (1, n + 1)) +
        ↑p ^ (n + 1) * X (0, n + 1) * (↑p ^ (n + 1) * X (1, n + 1))) =
    remainder p n +
      (-(↑p ^ (n + 1) * X (0, n + 1)) * (↑p ^ (n + 1) * X (1, n + 1)) +
          (↑p ^ (n + 1) * X (0, n + 1) *
              ∑ x in range (n + 1), ↑(rename (Prod.mk 1)) (↑(monomial (Finsupp.single x (p ^ (n + 1 - x)))) (↑p ^ x)) +
            ↑p ^ (n + 1) * X (0, n + 1) * (↑p ^ (n + 1) * X (1, n + 1))) +
        (↑p ^ (n + 1) * X (1, n + 1) *
            ∑ x in range (n + 1), ↑(rename (Prod.mk 0)) (↑(monomial (Finsupp.single x (p ^ (n + 1 - x)))) (↑p ^ x)) +
          ↑p ^ (n + 1) * X (1, n + 1) * (↑p ^ (n + 1) * X (0, n + 1))))
[PROOFSTEP]
simp only [add_assoc]
[GOAL]
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
mvpz : ↑p ^ (n + 1) = ↑C (↑p ^ (n + 1))
⊢ (∑ x in range (n + 1), ↑(rename (Prod.mk 0)) (↑(monomial (Finsupp.single x (p ^ (n + 1 - x)))) (↑p ^ x))) *
        ∑ x in range (n + 1), ↑(rename (Prod.mk 1)) (↑(monomial (Finsupp.single x (p ^ (n + 1 - x)))) (↑p ^ x)) +
      (↑p ^ (n + 1) * X (0, n + 1) *
          ∑ x in range (n + 1), ↑(rename (Prod.mk 1)) (↑(monomial (Finsupp.single x (p ^ (n + 1 - x)))) (↑p ^ x)) +
        ((∑ x in range (n + 1), ↑(rename (Prod.mk 0)) (↑(monomial (Finsupp.single x (p ^ (n + 1 - x)))) (↑p ^ x))) *
            (↑p ^ (n + 1) * X (1, n + 1)) +
          ↑p ^ (n + 1) * X (0, n + 1) * (↑p ^ (n + 1) * X (1, n + 1)))) =
    remainder p n +
      (-(↑p ^ (n + 1) * X (0, n + 1)) * (↑p ^ (n + 1) * X (1, n + 1)) +
        (↑p ^ (n + 1) * X (0, n + 1) *
            ∑ x in range (n + 1), ↑(rename (Prod.mk 1)) (↑(monomial (Finsupp.single x (p ^ (n + 1 - x)))) (↑p ^ x)) +
          (↑p ^ (n + 1) * X (0, n + 1) * (↑p ^ (n + 1) * X (1, n + 1)) +
            (↑p ^ (n + 1) * X (1, n + 1) *
                ∑ x in range (n + 1),
                  ↑(rename (Prod.mk 0)) (↑(monomial (Finsupp.single x (p ^ (n + 1 - x)))) (↑p ^ x)) +
              ↑p ^ (n + 1) * X (1, n + 1) * (↑p ^ (n + 1) * X (0, n + 1))))))
[PROOFSTEP]
apply congrArg (Add.add _)
[GOAL]
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
mvpz : ↑p ^ (n + 1) = ↑C (↑p ^ (n + 1))
⊢ ↑p ^ (n + 1) * X (0, n + 1) *
        ∑ x in range (n + 1), ↑(rename (Prod.mk 1)) (↑(monomial (Finsupp.single x (p ^ (n + 1 - x)))) (↑p ^ x)) +
      ((∑ x in range (n + 1), ↑(rename (Prod.mk 0)) (↑(monomial (Finsupp.single x (p ^ (n + 1 - x)))) (↑p ^ x))) *
          (↑p ^ (n + 1) * X (1, n + 1)) +
        ↑p ^ (n + 1) * X (0, n + 1) * (↑p ^ (n + 1) * X (1, n + 1))) =
    -(↑p ^ (n + 1) * X (0, n + 1)) * (↑p ^ (n + 1) * X (1, n + 1)) +
      (↑p ^ (n + 1) * X (0, n + 1) *
          ∑ x in range (n + 1), ↑(rename (Prod.mk 1)) (↑(monomial (Finsupp.single x (p ^ (n + 1 - x)))) (↑p ^ x)) +
        (↑p ^ (n + 1) * X (0, n + 1) * (↑p ^ (n + 1) * X (1, n + 1)) +
          (↑p ^ (n + 1) * X (1, n + 1) *
              ∑ x in range (n + 1), ↑(rename (Prod.mk 0)) (↑(monomial (Finsupp.single x (p ^ (n + 1 - x)))) (↑p ^ x)) +
            ↑p ^ (n + 1) * X (1, n + 1) * (↑p ^ (n + 1) * X (0, n + 1)))))
[PROOFSTEP]
ring
[GOAL]
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
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)) (wittPolynomial p ℤ (n + 1)) +
        ↑p ^ (n + 1) * X (1, n + 1) * ↑(rename (Prod.mk 0)) (wittPolynomial p ℤ (n + 1)) +
      (remainder p n - wittPolyProdRemainder p (n + 1))
[PROOFSTEP]
rw [← add_sub_assoc, eq_sub_iff_add_eq, mul_polyOfInterest_aux2]
[GOAL]
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
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)) (wittPolynomial p ℤ (n + 1)) +
        ↑p ^ (n + 1) * X (1, n + 1) * ↑(rename (Prod.mk 0)) (wittPolynomial p ℤ (n + 1)) +
      remainder p n
[PROOFSTEP]
exact mul_polyOfInterest_aux3 _ _
[GOAL]
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
⊢ ↑p ^ (n + 1) * polyOfInterest p n = remainder p n - wittPolyProdRemainder p (n + 1)
[PROOFSTEP]
simp only [polyOfInterest, mul_sub, mul_add, sub_eq_iff_eq_add']
[GOAL]
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
⊢ ↑p ^ (n + 1) * wittMul p (n + 1) + ↑p ^ (n + 1) * (↑p ^ (n + 1) * X (0, n + 1) * X (1, n + 1)) =
    ↑p ^ (n + 1) * (X (0, n + 1) * ↑(rename (Prod.mk 1)) (wittPolynomial p ℤ (n + 1))) +
      (↑p ^ (n + 1) * (X (1, n + 1) * ↑(rename (Prod.mk 0)) (wittPolynomial p ℤ (n + 1))) +
        (remainder p n - wittPolyProdRemainder p (n + 1)))
[PROOFSTEP]
rw [mul_polyOfInterest_aux4 p n]
[GOAL]
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
⊢ -(↑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)) (wittPolynomial p ℤ (n + 1)) +
          ↑p ^ (n + 1) * X (1, n + 1) * ↑(rename (Prod.mk 0)) (wittPolynomial p ℤ (n + 1)) +
        (remainder p n - wittPolyProdRemainder p (n + 1)) +
      ↑p ^ (n + 1) * (↑p ^ (n + 1) * X (0, n + 1) * X (1, n + 1)) =
    ↑p ^ (n + 1) * (X (0, n + 1) * ↑(rename (Prod.mk 1)) (wittPolynomial p ℤ (n + 1))) +
      (↑p ^ (n + 1) * (X (1, n + 1) * ↑(rename (Prod.mk 0)) (wittPolynomial p ℤ (n + 1))) +
        (remainder p n - wittPolyProdRemainder p (n + 1)))
[PROOFSTEP]
ring
[GOAL]
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
⊢ vars (↑p ^ (n + 1) * polyOfInterest p n) ⊆ univ ×ˢ range (n + 1)
[PROOFSTEP]
rw [mul_polyOfInterest_aux5]
[GOAL]
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
⊢ vars (remainder p n - wittPolyProdRemainder p (n + 1)) ⊆ univ ×ˢ range (n + 1)
[PROOFSTEP]
apply Subset.trans (vars_sub_subset _)
[GOAL]
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
⊢ vars (remainder p n) ∪ vars (wittPolyProdRemainder p (n + 1)) ⊆ univ ×ˢ range (n + 1)
[PROOFSTEP]
refine' union_subset _ _
[GOAL]
case refine'_1
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
⊢ vars (remainder p n) ⊆ univ ×ˢ range (n + 1)
[PROOFSTEP]
apply remainder_vars
[GOAL]
case refine'_2
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
⊢ vars (wittPolyProdRemainder p (n + 1)) ⊆ univ ×ˢ range (n + 1)
[PROOFSTEP]
apply wittPolyProdRemainder_vars
[GOAL]
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
⊢ vars (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)) (wittPolynomial p ℤ (n + 1)) -
          X (1, n + 1) * ↑(rename (Prod.mk 0)) (wittPolynomial p ℤ (n + 1))))
[PROOFSTEP]
have : (p : 𝕄) ^ (n + 1) = C ((p : ℤ) ^ (n + 1)) := by simp only; norm_cast
[GOAL]
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
⊢ ↑p ^ (n + 1) = ↑C (↑p ^ (n + 1))
[PROOFSTEP]
simp only
[GOAL]
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
⊢ ↑p ^ (n + 1) = ↑C (↑p ^ (n + 1))
[PROOFSTEP]
norm_cast
[GOAL]
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
this : ↑p ^ (n + 1) = ↑C (↑p ^ (n + 1))
⊢ vars (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)) (wittPolynomial p ℤ (n + 1)) -
          X (1, n + 1) * ↑(rename (Prod.mk 0)) (wittPolynomial p ℤ (n + 1))))
[PROOFSTEP]
rw [polyOfInterest, this, vars_C_mul]
[GOAL]
case ha
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
this : ↑p ^ (n + 1) = ↑C (↑p ^ (n + 1))
⊢ ↑p ^ (n + 1) ≠ 0
[PROOFSTEP]
apply pow_ne_zero
[GOAL]
case ha.h
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
this : ↑p ^ (n + 1) = ↑C (↑p ^ (n + 1))
⊢ ↑p ≠ 0
[PROOFSTEP]
exact_mod_cast hp.out.ne_zero
[GOAL]
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
⊢ vars (polyOfInterest p n) ⊆ univ ×ˢ range (n + 1)
[PROOFSTEP]
rw [polyOfInterest_vars_eq]
[GOAL]
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
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)) (wittPolynomial p ℤ (n + 1)) -
          X (1, n + 1) * ↑(rename (Prod.mk 0)) (wittPolynomial p ℤ (n + 1)))) ⊆
    univ ×ˢ range (n + 1)
[PROOFSTEP]
apply mul_polyOfInterest_vars
[GOAL]
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
x y : 𝕎 k
⊢ peval (polyOfInterest p n) ![fun i => coeff x i, fun i => coeff y i] =
    coeff (x * y) (n + 1) + ↑(p ^ (n + 1)) * coeff x (n + 1) * coeff y (n + 1) -
        coeff y (n + 1) * ∑ i in range (n + 1 + 1), ↑(p ^ i) * coeff x i ^ p ^ (n + 1 - i) -
      coeff x (n + 1) * ∑ i in range (n + 1 + 1), ↑(p ^ i) * coeff y i ^ p ^ (n + 1 - i)
[PROOFSTEP]
simp only [polyOfInterest, peval, map_natCast, Matrix.head_cons, map_pow, Function.uncurry_apply_pair, aeval_X,
  Matrix.cons_val_one, map_mul, Matrix.cons_val_zero, map_sub]
[GOAL]
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
x y : 𝕎 k
⊢ ↑(aeval (Function.uncurry ![fun i => coeff x i, fun i => coeff y i]))
          (wittMul p (n + 1) + ↑p ^ (n + 1) * X (0, n + 1) * X (1, n + 1)) -
        coeff x (n + 1) *
          ↑(aeval (Function.uncurry ![fun i => coeff x i, fun i => coeff y i]))
            (↑(rename (Prod.mk 1)) (wittPolynomial p ℤ (n + 1))) -
      coeff y (n + 1) *
        ↑(aeval (Function.uncurry ![fun i => coeff x i, fun i => coeff y i]))
          (↑(rename (Prod.mk 0)) (wittPolynomial p ℤ (n + 1))) =
    coeff (x * y) (n + 1) + ↑(p ^ (n + 1)) * coeff x (n + 1) * coeff y (n + 1) -
        coeff y (n + 1) * ∑ i in range (n + 1 + 1), ↑(p ^ i) * coeff x i ^ p ^ (n + 1 - i) -
      coeff x (n + 1) * ∑ i in range (n + 1 + 1), ↑(p ^ i) * coeff y i ^ p ^ (n + 1 - i)
[PROOFSTEP]
rw [sub_sub, add_comm (_ * _), ← sub_sub]
[GOAL]
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
x y : 𝕎 k
⊢ ↑(aeval (Function.uncurry ![fun i => coeff x i, fun i => coeff y i]))
          (wittMul p (n + 1) + ↑p ^ (n + 1) * X (0, n + 1) * X (1, n + 1)) -
        coeff y (n + 1) *
          ↑(aeval (Function.uncurry ![fun i => coeff x i, fun i => coeff y i]))
            (↑(rename (Prod.mk 0)) (wittPolynomial p ℤ (n + 1))) -
      coeff x (n + 1) *
        ↑(aeval (Function.uncurry ![fun i => coeff x i, fun i => coeff y i]))
          (↑(rename (Prod.mk 1)) (wittPolynomial p ℤ (n + 1))) =
    coeff (x * y) (n + 1) + ↑(p ^ (n + 1)) * coeff x (n + 1) * coeff y (n + 1) -
        coeff y (n + 1) * ∑ i in range (n + 1 + 1), ↑(p ^ i) * coeff x i ^ p ^ (n + 1 - i) -
      coeff x (n + 1) * ∑ i in range (n + 1 + 1), ↑(p ^ i) * coeff y i ^ p ^ (n + 1 - i)
[PROOFSTEP]
have mvpz : (p : MvPolynomial ℕ ℤ) = MvPolynomial.C ↑p := by rw [eq_intCast, Int.cast_ofNat]
[GOAL]
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
x y : 𝕎 k
⊢ ↑p = ↑C ↑p
[PROOFSTEP]
rw [eq_intCast, Int.cast_ofNat]
[GOAL]
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
x y : 𝕎 k
mvpz : ↑p = ↑C ↑p
⊢ ↑(aeval (Function.uncurry ![fun i => coeff x i, fun i => coeff y i]))
          (wittMul p (n + 1) + ↑p ^ (n + 1) * X (0, n + 1) * X (1, n + 1)) -
        coeff y (n + 1) *
          ↑(aeval (Function.uncurry ![fun i => coeff x i, fun i => coeff y i]))
            (↑(rename (Prod.mk 0)) (wittPolynomial p ℤ (n + 1))) -
      coeff x (n + 1) *
        ↑(aeval (Function.uncurry ![fun i => coeff x i, fun i => coeff y i]))
          (↑(rename (Prod.mk 1)) (wittPolynomial p ℤ (n + 1))) =
    coeff (x * y) (n + 1) + ↑(p ^ (n + 1)) * coeff x (n + 1) * coeff y (n + 1) -
        coeff y (n + 1) * ∑ i in range (n + 1 + 1), ↑(p ^ i) * coeff x i ^ p ^ (n + 1 - i) -
      coeff x (n + 1) * ∑ i in range (n + 1 + 1), ↑(p ^ i) * coeff y i ^ p ^ (n + 1 - i)
[PROOFSTEP]
have : ∀ (f : ℤ →+* k) (g : ℕ → k), eval₂ f g p = f p := by intros; rw [mvpz, MvPolynomial.eval₂_C]
[GOAL]
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
x y : 𝕎 k
mvpz : ↑p = ↑C ↑p
⊢ ∀ (f : ℤ →+* k) (g : ℕ → k), eval₂ f g ↑p = ↑f ↑p
[PROOFSTEP]
intros
[GOAL]
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
x y : 𝕎 k
mvpz : ↑p = ↑C ↑p
f✝ : ℤ →+* k
g✝ : ℕ → k
⊢ eval₂ f✝ g✝ ↑p = ↑f✝ ↑p
[PROOFSTEP]
rw [mvpz, MvPolynomial.eval₂_C]
[GOAL]
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
x y : 𝕎 k
mvpz : ↑p = ↑C ↑p
this : ∀ (f : ℤ →+* k) (g : ℕ → k), eval₂ f g ↑p = ↑f ↑p
⊢ ↑(aeval (Function.uncurry ![fun i => coeff x i, fun i => coeff y i]))
          (wittMul p (n + 1) + ↑p ^ (n + 1) * X (0, n + 1) * X (1, n + 1)) -
        coeff y (n + 1) *
          ↑(aeval (Function.uncurry ![fun i => coeff x i, fun i => coeff y i]))
            (↑(rename (Prod.mk 0)) (wittPolynomial p ℤ (n + 1))) -
      coeff x (n + 1) *
        ↑(aeval (Function.uncurry ![fun i => coeff x i, fun i => coeff y i]))
          (↑(rename (Prod.mk 1)) (wittPolynomial p ℤ (n + 1))) =
    coeff (x * y) (n + 1) + ↑(p ^ (n + 1)) * coeff x (n + 1) * coeff y (n + 1) -
        coeff y (n + 1) * ∑ i in range (n + 1 + 1), ↑(p ^ i) * coeff x i ^ p ^ (n + 1 - i) -
      coeff x (n + 1) * ∑ i in range (n + 1 + 1), ↑(p ^ i) * coeff y i ^ p ^ (n + 1 - i)
[PROOFSTEP]
simp [wittPolynomial_eq_sum_C_mul_X_pow, aeval, eval₂_rename, this, mul_coeff, peval, map_natCast, map_add, map_pow,
  map_mul]
[GOAL]
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝¹ : CommRing k
inst✝ : CharP k p
n : ℕ
x y : 𝕎 k
⊢ peval (polyOfInterest p n) ![fun i => coeff x i, fun i => coeff y i] =
    coeff (x * y) (n + 1) - coeff y (n + 1) * coeff x 0 ^ p ^ (n + 1) - coeff x (n + 1) * coeff y 0 ^ p ^ (n + 1)
[PROOFSTEP]
rw [peval_polyOfInterest]
[GOAL]
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝¹ : CommRing k
inst✝ : CharP k p
n : ℕ
x y : 𝕎 k
⊢ coeff (x * y) (n + 1) + ↑(p ^ (n + 1)) * coeff x (n + 1) * coeff y (n + 1) -
        coeff y (n + 1) * ∑ i in range (n + 1 + 1), ↑(p ^ i) * coeff x i ^ p ^ (n + 1 - i) -
      coeff x (n + 1) * ∑ i in range (n + 1 + 1), ↑(p ^ i) * coeff y i ^ p ^ (n + 1 - i) =
    coeff (x * y) (n + 1) - coeff y (n + 1) * coeff x 0 ^ p ^ (n + 1) - coeff x (n + 1) * coeff y 0 ^ p ^ (n + 1)
[PROOFSTEP]
have : (p : k) = 0 := CharP.cast_eq_zero k p
[GOAL]
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝¹ : CommRing k
inst✝ : CharP k p
n : ℕ
x y : 𝕎 k
this : ↑p = 0
⊢ coeff (x * y) (n + 1) + ↑(p ^ (n + 1)) * coeff x (n + 1) * coeff y (n + 1) -
        coeff y (n + 1) * ∑ i in range (n + 1 + 1), ↑(p ^ i) * coeff x i ^ p ^ (n + 1 - i) -
      coeff x (n + 1) * ∑ i in range (n + 1 + 1), ↑(p ^ i) * coeff y i ^ p ^ (n + 1 - i) =
    coeff (x * y) (n + 1) - coeff y (n + 1) * coeff x 0 ^ p ^ (n + 1) - coeff x (n + 1) * coeff y 0 ^ p ^ (n + 1)
[PROOFSTEP]
simp only [this, Nat.cast_pow, ne_eq, add_eq_zero, and_false, zero_pow', zero_mul, add_zero]
[GOAL]
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝¹ : CommRing k
inst✝ : CharP k p
n : ℕ
x y : 𝕎 k
this : ↑p = 0
⊢ coeff (x * y) (n + 1) - coeff y (n + 1) * ∑ x_1 in range (n + 1 + 1), 0 ^ x_1 * coeff x x_1 ^ p ^ (n + 1 - x_1) -
      coeff x (n + 1) * ∑ x in range (n + 1 + 1), 0 ^ x * coeff y x ^ p ^ (n + 1 - x) =
    coeff (x * y) (n + 1) - coeff y (n + 1) * coeff x 0 ^ p ^ (n + 1) - coeff x (n + 1) * coeff y 0 ^ p ^ (n + 1)
[PROOFSTEP]
have sum_zero_pow_mul_pow_p :
  ∀ y : 𝕎 k, ∑ x : ℕ in range (n + 1 + 1), (0 : k) ^ x * y.coeff x ^ p ^ (n + 1 - x) = y.coeff 0 ^ p ^ (n + 1) :=
  by
  intro y
  rw [Finset.sum_eq_single_of_mem 0]
  · simp
  · simp
  · intro j _ hj
    simp [zero_pow (zero_lt_iff.mpr hj)]
[GOAL]
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝¹ : CommRing k
inst✝ : CharP k p
n : ℕ
x y : 𝕎 k
this : ↑p = 0
⊢ ∀ (y : 𝕎 k), ∑ x in range (n + 1 + 1), 0 ^ x * coeff y x ^ p ^ (n + 1 - x) = coeff y 0 ^ p ^ (n + 1)
[PROOFSTEP]
intro y
[GOAL]
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝¹ : CommRing k
inst✝ : CharP k p
n : ℕ
x y✝ : 𝕎 k
this : ↑p = 0
y : 𝕎 k
⊢ ∑ x in range (n + 1 + 1), 0 ^ x * coeff y x ^ p ^ (n + 1 - x) = coeff y 0 ^ p ^ (n + 1)
[PROOFSTEP]
rw [Finset.sum_eq_single_of_mem 0]
[GOAL]
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝¹ : CommRing k
inst✝ : CharP k p
n : ℕ
x y✝ : 𝕎 k
this : ↑p = 0
y : 𝕎 k
⊢ 0 ^ 0 * coeff y 0 ^ p ^ (n + 1 - 0) = coeff y 0 ^ p ^ (n + 1)
[PROOFSTEP]
simp
[GOAL]
case h
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝¹ : CommRing k
inst✝ : CharP k p
n : ℕ
x y✝ : 𝕎 k
this : ↑p = 0
y : 𝕎 k
⊢ 0 ∈ range (n + 1 + 1)
[PROOFSTEP]
simp
[GOAL]
case h₀
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝¹ : CommRing k
inst✝ : CharP k p
n : ℕ
x y✝ : 𝕎 k
this : ↑p = 0
y : 𝕎 k
⊢ ∀ (b : ℕ), b ∈ range (n + 1 + 1) → b ≠ 0 → 0 ^ b * coeff y b ^ p ^ (n + 1 - b) = 0
[PROOFSTEP]
intro j _ hj
[GOAL]
case h₀
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝¹ : CommRing k
inst✝ : CharP k p
n : ℕ
x y✝ : 𝕎 k
this : ↑p = 0
y : 𝕎 k
j : ℕ
a✝ : j ∈ range (n + 1 + 1)
hj : j ≠ 0
⊢ 0 ^ j * coeff y j ^ p ^ (n + 1 - j) = 0
[PROOFSTEP]
simp [zero_pow (zero_lt_iff.mpr hj)]
[GOAL]
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝¹ : CommRing k
inst✝ : CharP k p
n : ℕ
x y : 𝕎 k
this : ↑p = 0
sum_zero_pow_mul_pow_p :
  ∀ (y : 𝕎 k), ∑ x in range (n + 1 + 1), 0 ^ x * coeff y x ^ p ^ (n + 1 - x) = coeff y 0 ^ p ^ (n + 1)
⊢ coeff (x * y) (n + 1) - coeff y (n + 1) * ∑ x_1 in range (n + 1 + 1), 0 ^ x_1 * coeff x x_1 ^ p ^ (n + 1 - x_1) -
      coeff x (n + 1) * ∑ x in range (n + 1 + 1), 0 ^ x * coeff y x ^ p ^ (n + 1 - x) =
    coeff (x * y) (n + 1) - coeff y (n + 1) * coeff x 0 ^ p ^ (n + 1) - coeff x (n + 1) * coeff y 0 ^ p ^ (n + 1)
[PROOFSTEP]
congr
[GOAL]
case e_a.e_a.e_a
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝¹ : CommRing k
inst✝ : CharP k p
n : ℕ
x y : 𝕎 k
this : ↑p = 0
sum_zero_pow_mul_pow_p :
  ∀ (y : 𝕎 k), ∑ x in range (n + 1 + 1), 0 ^ x * coeff y x ^ p ^ (n + 1 - x) = coeff y 0 ^ p ^ (n + 1)
⊢ ∑ x_1 in range (n + 1 + 1), 0 ^ x_1 * coeff x x_1 ^ p ^ (n + 1 - x_1) = coeff x 0 ^ p ^ (n + 1)
[PROOFSTEP]
apply sum_zero_pow_mul_pow_p
[GOAL]
case e_a.e_a
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝¹ : CommRing k
inst✝ : CharP k p
n : ℕ
x y : 𝕎 k
this : ↑p = 0
sum_zero_pow_mul_pow_p :
  ∀ (y : 𝕎 k), ∑ x in range (n + 1 + 1), 0 ^ x * coeff y x ^ p ^ (n + 1 - x) = coeff y 0 ^ p ^ (n + 1)
⊢ ∑ x in range (n + 1 + 1), 0 ^ x * coeff y x ^ p ^ (n + 1 - x) = coeff y 0 ^ p ^ (n + 1)
[PROOFSTEP]
apply sum_zero_pow_mul_pow_p
[GOAL]
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝¹ : CommRing k
inst✝ : CharP k p
n : ℕ
⊢ ∃ f,
    ∀ (x y : 𝕎 k),
      f (truncateFun (n + 1) x) (truncateFun (n + 1) y) =
        coeff (x * y) (n + 1) - coeff y (n + 1) * coeff x 0 ^ p ^ (n + 1) - coeff x (n + 1) * coeff y 0 ^ p ^ (n + 1)
[PROOFSTEP]
simp only [← peval_polyOfInterest']
[GOAL]
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝¹ : CommRing k
inst✝ : CharP k p
n : ℕ
⊢ ∃ f,
    ∀ (x y : 𝕎 k),
      f (truncateFun (n + 1) x) (truncateFun (n + 1) y) =
        peval (polyOfInterest p n) ![fun i => coeff x i, fun i => coeff y i]
[PROOFSTEP]
obtain ⟨f₀, hf₀⟩ := exists_restrict_to_vars k (polyOfInterest_vars p n)
[GOAL]
case intro
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝¹ : CommRing k
inst✝ : CharP k p
n : ℕ
f₀ : ((↑fun a => a ∈ (univ ×ˢ range (n + 1)).val) → k) → k
hf₀ : ∀ (x : Fin 2 × ℕ → k), f₀ (x ∘ Subtype.val) = ↑(aeval x) (polyOfInterest p n)
⊢ ∃ f,
    ∀ (x y : 𝕎 k),
      f (truncateFun (n + 1) x) (truncateFun (n + 1) y) =
        peval (polyOfInterest p n) ![fun i => coeff x i, fun i => coeff y i]
[PROOFSTEP]
have : ∀ (a : Multiset (Fin 2)) (b : Multiset ℕ), a ×ˢ b = a.product b := fun a b => rfl
[GOAL]
case intro
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝¹ : CommRing k
inst✝ : CharP k p
n : ℕ
f₀ : ((↑fun a => a ∈ (univ ×ˢ range (n + 1)).val) → k) → k
hf₀ : ∀ (x : Fin 2 × ℕ → k), f₀ (x ∘ Subtype.val) = ↑(aeval x) (polyOfInterest p n)
this : ∀ (a : Multiset (Fin 2)) (b : Multiset ℕ), a ×ˢ b = Multiset.product a b
⊢ ∃ f,
    ∀ (x y : 𝕎 k),
      f (truncateFun (n + 1) x) (truncateFun (n + 1) y) =
        peval (polyOfInterest p n) ![fun i => coeff x i, fun i => coeff y i]
[PROOFSTEP]
let f : TruncatedWittVector p (n + 1) k → TruncatedWittVector p (n + 1) k → k :=
  by
  intro x y
  apply f₀
  rintro ⟨a, ha⟩
  apply Function.uncurry ![x, y]
  simp_rw [product_val, this, Multiset.mem_product, mem_univ_val, true_and_iff, range_val, Multiset.range_succ,
    Multiset.mem_cons, Multiset.mem_range] at ha
  refine' ⟨a.fst, ⟨a.snd, _⟩⟩
  cases' ha with ha ha <;> linarith only [ha]
[GOAL]
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝¹ : CommRing k
inst✝ : CharP k p
n : ℕ
f₀ : ((↑fun a => a ∈ (univ ×ˢ range (n + 1)).val) → k) → k
hf₀ : ∀ (x : Fin 2 × ℕ → k), f₀ (x ∘ Subtype.val) = ↑(aeval x) (polyOfInterest p n)
this : ∀ (a : Multiset (Fin 2)) (b : Multiset ℕ), a ×ˢ b = Multiset.product a b
⊢ TruncatedWittVector p (n + 1) k → TruncatedWittVector p (n + 1) k → k
[PROOFSTEP]
intro x y
[GOAL]
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝¹ : CommRing k
inst✝ : CharP k p
n : ℕ
f₀ : ((↑fun a => a ∈ (univ ×ˢ range (n + 1)).val) → k) → k
hf₀ : ∀ (x : Fin 2 × ℕ → k), f₀ (x ∘ Subtype.val) = ↑(aeval x) (polyOfInterest p n)
this : ∀ (a : Multiset (Fin 2)) (b : Multiset ℕ), a ×ˢ b = Multiset.product a b
x y : TruncatedWittVector p (n + 1) k
⊢ k
[PROOFSTEP]
apply f₀
[GOAL]
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝¹ : CommRing k
inst✝ : CharP k p
n : ℕ
f₀ : ((↑fun a => a ∈ (univ ×ˢ range (n + 1)).val) → k) → k
hf₀ : ∀ (x : Fin 2 × ℕ → k), f₀ (x ∘ Subtype.val) = ↑(aeval x) (polyOfInterest p n)
this : ∀ (a : Multiset (Fin 2)) (b : Multiset ℕ), a ×ˢ b = Multiset.product a b
x y : TruncatedWittVector p (n + 1) k
⊢ (↑fun a => a ∈ (univ ×ˢ range (n + 1)).val) → k
[PROOFSTEP]
rintro ⟨a, ha⟩
[GOAL]
case mk
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝¹ : CommRing k
inst✝ : CharP k p
n : ℕ
f₀ : ((↑fun a => a ∈ (univ ×ˢ range (n + 1)).val) → k) → k
hf₀ : ∀ (x : Fin 2 × ℕ → k), f₀ (x ∘ Subtype.val) = ↑(aeval x) (polyOfInterest p n)
this : ∀ (a : Multiset (Fin 2)) (b : Multiset ℕ), a ×ˢ b = Multiset.product a b
x y : TruncatedWittVector p (n + 1) k
a : Fin 2 × ℕ
ha : a ∈ fun a => a ∈ (univ ×ˢ range (n + 1)).val
⊢ k
[PROOFSTEP]
apply Function.uncurry ![x, y]
[GOAL]
case mk
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝¹ : CommRing k
inst✝ : CharP k p
n : ℕ
f₀ : ((↑fun a => a ∈ (univ ×ˢ range (n + 1)).val) → k) → k
hf₀ : ∀ (x : Fin 2 × ℕ → k), f₀ (x ∘ Subtype.val) = ↑(aeval x) (polyOfInterest p n)
this : ∀ (a : Multiset (Fin 2)) (b : Multiset ℕ), a ×ˢ b = Multiset.product a b
x y : TruncatedWittVector p (n + 1) k
a : Fin 2 × ℕ
ha : a ∈ fun a => a ∈ (univ ×ˢ range (n + 1)).val
⊢ Fin (Nat.succ (Nat.succ 0)) × Fin (n + 1)
[PROOFSTEP]
simp_rw [product_val, this, Multiset.mem_product, mem_univ_val, true_and_iff, range_val, Multiset.range_succ,
  Multiset.mem_cons, Multiset.mem_range] at ha
[GOAL]
case mk
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝¹ : CommRing k
inst✝ : CharP k p
n : ℕ
f₀ : ((↑fun a => a ∈ (univ ×ˢ range (n + 1)).val) → k) → k
hf₀ : ∀ (x : Fin 2 × ℕ → k), f₀ (x ∘ Subtype.val) = ↑(aeval x) (polyOfInterest p n)
this : ∀ (a : Multiset (Fin 2)) (b : Multiset ℕ), a ×ˢ b = Multiset.product a b
x y : TruncatedWittVector p (n + 1) k
a : Fin 2 × ℕ
ha : a ∈ fun a => a.snd = n ∨ a.snd < n
⊢ Fin (Nat.succ (Nat.succ 0)) × Fin (n + 1)
[PROOFSTEP]
refine' ⟨a.fst, ⟨a.snd, _⟩⟩
[GOAL]
case mk
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝¹ : CommRing k
inst✝ : CharP k p
n : ℕ
f₀ : ((↑fun a => a ∈ (univ ×ˢ range (n + 1)).val) → k) → k
hf₀ : ∀ (x : Fin 2 × ℕ → k), f₀ (x ∘ Subtype.val) = ↑(aeval x) (polyOfInterest p n)
this : ∀ (a : Multiset (Fin 2)) (b : Multiset ℕ), a ×ˢ b = Multiset.product a b
x y : TruncatedWittVector p (n + 1) k
a : Fin 2 × ℕ
ha : a ∈ fun a => a.snd = n ∨ a.snd < n
⊢ a.snd < n + 1
[PROOFSTEP]
cases' ha with ha ha
[GOAL]
case mk.inl
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝¹ : CommRing k
inst✝ : CharP k p
n : ℕ
f₀ : ((↑fun a => a ∈ (univ ×ˢ range (n + 1)).val) → k) → k
hf₀ : ∀ (x : Fin 2 × ℕ → k), f₀ (x ∘ Subtype.val) = ↑(aeval x) (polyOfInterest p n)
this : ∀ (a : Multiset (Fin 2)) (b : Multiset ℕ), a ×ˢ b = Multiset.product a b
x y : TruncatedWittVector p (n + 1) k
a : Fin 2 × ℕ
ha : a.snd = n
⊢ a.snd < n + 1
[PROOFSTEP]
linarith only [ha]
[GOAL]
case mk.inr
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝¹ : CommRing k
inst✝ : CharP k p
n : ℕ
f₀ : ((↑fun a => a ∈ (univ ×ˢ range (n + 1)).val) → k) → k
hf₀ : ∀ (x : Fin 2 × ℕ → k), f₀ (x ∘ Subtype.val) = ↑(aeval x) (polyOfInterest p n)
this : ∀ (a : Multiset (Fin 2)) (b : Multiset ℕ), a ×ˢ b = Multiset.product a b
x y : TruncatedWittVector p (n + 1) k
a : Fin 2 × ℕ
ha : a.snd < n
⊢ a.snd < n + 1
[PROOFSTEP]
linarith only [ha]
[GOAL]
case intro
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝¹ : CommRing k
inst✝ : CharP k p
n : ℕ
f₀ : ((↑fun a => a ∈ (univ ×ˢ range (n + 1)).val) → k) → k
hf₀ : ∀ (x : Fin 2 × ℕ → k), f₀ (x ∘ Subtype.val) = ↑(aeval x) (polyOfInterest p n)
this : ∀ (a : Multiset (Fin 2)) (b : Multiset ℕ), a ×ˢ b = Multiset.product a b
f : TruncatedWittVector p (n + 1) k → TruncatedWittVector p (n + 1) k → k :=
  fun x y =>
    f₀ fun a =>
      Subtype.casesOn a fun a ha => Function.uncurry ![x, y] (a.fst, { val := a.snd, isLt := (_ : a.snd < n + 1) })
⊢ ∃ f,
    ∀ (x y : 𝕎 k),
      f (truncateFun (n + 1) x) (truncateFun (n + 1) y) =
        peval (polyOfInterest p n) ![fun i => coeff x i, fun i => coeff y i]
[PROOFSTEP]
use f
[GOAL]
case h
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝¹ : CommRing k
inst✝ : CharP k p
n : ℕ
f₀ : ((↑fun a => a ∈ (univ ×ˢ range (n + 1)).val) → k) → k
hf₀ : ∀ (x : Fin 2 × ℕ → k), f₀ (x ∘ Subtype.val) = ↑(aeval x) (polyOfInterest p n)
this : ∀ (a : Multiset (Fin 2)) (b : Multiset ℕ), a ×ˢ b = Multiset.product a b
f : TruncatedWittVector p (n + 1) k → TruncatedWittVector p (n + 1) k → k :=
  fun x y =>
    f₀ fun a =>
      Subtype.casesOn a fun a ha => Function.uncurry ![x, y] (a.fst, { val := a.snd, isLt := (_ : a.snd < n + 1) })
⊢ ∀ (x y : 𝕎 k),
    f (truncateFun (n + 1) x) (truncateFun (n + 1) y) =
      peval (polyOfInterest p n) ![fun i => coeff x i, fun i => coeff y i]
[PROOFSTEP]
intro x y
[GOAL]
case h
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝¹ : CommRing k
inst✝ : CharP k p
n : ℕ
f₀ : ((↑fun a => a ∈ (univ ×ˢ range (n + 1)).val) → k) → k
hf₀ : ∀ (x : Fin 2 × ℕ → k), f₀ (x ∘ Subtype.val) = ↑(aeval x) (polyOfInterest p n)
this : ∀ (a : Multiset (Fin 2)) (b : Multiset ℕ), a ×ˢ b = Multiset.product a b
f : TruncatedWittVector p (n + 1) k → TruncatedWittVector p (n + 1) k → k :=
  fun x y =>
    f₀ fun a =>
      Subtype.casesOn a fun a ha => Function.uncurry ![x, y] (a.fst, { val := a.snd, isLt := (_ : a.snd < n + 1) })
x y : 𝕎 k
⊢ f (truncateFun (n + 1) x) (truncateFun (n + 1) y) =
    peval (polyOfInterest p n) ![fun i => coeff x i, fun i => coeff y i]
[PROOFSTEP]
dsimp [peval]
[GOAL]
case h
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝¹ : CommRing k
inst✝ : CharP k p
n : ℕ
f₀ : ((↑fun a => a ∈ (univ ×ˢ range (n + 1)).val) → k) → k
hf₀ : ∀ (x : Fin 2 × ℕ → k), f₀ (x ∘ Subtype.val) = ↑(aeval x) (polyOfInterest p n)
this : ∀ (a : Multiset (Fin 2)) (b : Multiset ℕ), a ×ˢ b = Multiset.product a b
f : TruncatedWittVector p (n + 1) k → TruncatedWittVector p (n + 1) k → k :=
  fun x y =>
    f₀ fun a =>
      Subtype.casesOn a fun a ha => Function.uncurry ![x, y] (a.fst, { val := a.snd, isLt := (_ : a.snd < n + 1) })
x y : 𝕎 k
⊢ (f₀ fun a =>
      Matrix.vecCons (truncateFun (n + 1) x) ![truncateFun (n + 1) y] (↑a).fst
        { val := (↑a).snd, isLt := (_ : (↑a).snd < n + 1) }) =
    ↑(aeval (Function.uncurry ![fun i => coeff x i, fun i => coeff y i])) (polyOfInterest p n)
[PROOFSTEP]
rw [← hf₀]
[GOAL]
case h
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝¹ : CommRing k
inst✝ : CharP k p
n : ℕ
f₀ : ((↑fun a => a ∈ (univ ×ˢ range (n + 1)).val) → k) → k
hf₀ : ∀ (x : Fin 2 × ℕ → k), f₀ (x ∘ Subtype.val) = ↑(aeval x) (polyOfInterest p n)
this : ∀ (a : Multiset (Fin 2)) (b : Multiset ℕ), a ×ˢ b = Multiset.product a b
f : TruncatedWittVector p (n + 1) k → TruncatedWittVector p (n + 1) k → k :=
  fun x y =>
    f₀ fun a =>
      Subtype.casesOn a fun a ha => Function.uncurry ![x, y] (a.fst, { val := a.snd, isLt := (_ : a.snd < n + 1) })
x y : 𝕎 k
⊢ (f₀ fun a =>
      Matrix.vecCons (truncateFun (n + 1) x) ![truncateFun (n + 1) y] (↑a).fst
        { val := (↑a).snd, isLt := (_ : (↑a).snd < n + 1) }) =
    f₀ (Function.uncurry ![fun i => coeff x i, fun i => coeff y i] ∘ Subtype.val)
[PROOFSTEP]
congr
[GOAL]
case h.e_a
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝¹ : CommRing k
inst✝ : CharP k p
n : ℕ
f₀ : ((↑fun a => a ∈ (univ ×ˢ range (n + 1)).val) → k) → k
hf₀ : ∀ (x : Fin 2 × ℕ → k), f₀ (x ∘ Subtype.val) = ↑(aeval x) (polyOfInterest p n)
this : ∀ (a : Multiset (Fin 2)) (b : Multiset ℕ), a ×ˢ b = Multiset.product a b
f : TruncatedWittVector p (n + 1) k → TruncatedWittVector p (n + 1) k → k :=
  fun x y =>
    f₀ fun a =>
      Subtype.casesOn a fun a ha => Function.uncurry ![x, y] (a.fst, { val := a.snd, isLt := (_ : a.snd < n + 1) })
x y : 𝕎 k
⊢ (fun a =>
      Matrix.vecCons (truncateFun (n + 1) x) ![truncateFun (n + 1) y] (↑a).fst
        { val := (↑a).snd, isLt := (_ : (↑a).snd < n + 1) }) =
    Function.uncurry ![fun i => coeff x i, fun i => coeff y i] ∘ Subtype.val
[PROOFSTEP]
ext a
[GOAL]
case h.e_a.h
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝¹ : CommRing k
inst✝ : CharP k p
n : ℕ
f₀ : ((↑fun a => a ∈ (univ ×ˢ range (n + 1)).val) → k) → k
hf₀ : ∀ (x : Fin 2 × ℕ → k), f₀ (x ∘ Subtype.val) = ↑(aeval x) (polyOfInterest p n)
this : ∀ (a : Multiset (Fin 2)) (b : Multiset ℕ), a ×ˢ b = Multiset.product a b
f : TruncatedWittVector p (n + 1) k → TruncatedWittVector p (n + 1) k → k :=
  fun x y =>
    f₀ fun a =>
      Subtype.casesOn a fun a ha => Function.uncurry ![x, y] (a.fst, { val := a.snd, isLt := (_ : a.snd < n + 1) })
x y : 𝕎 k
a : ↑fun a => a ∈ univ.val ×ˢ Multiset.range (n + 1)
⊢ Matrix.vecCons (truncateFun (n + 1) x) ![truncateFun (n + 1) y] (↑a).fst
      { val := (↑a).snd, isLt := (_ : (↑a).snd < n + 1) } =
    (Function.uncurry ![fun i => coeff x i, fun i => coeff y i] ∘ Subtype.val) a
[PROOFSTEP]
cases' a with a ha
[GOAL]
case h.e_a.h.mk
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝¹ : CommRing k
inst✝ : CharP k p
n : ℕ
f₀ : ((↑fun a => a ∈ (univ ×ˢ range (n + 1)).val) → k) → k
hf₀ : ∀ (x : Fin 2 × ℕ → k), f₀ (x ∘ Subtype.val) = ↑(aeval x) (polyOfInterest p n)
this : ∀ (a : Multiset (Fin 2)) (b : Multiset ℕ), a ×ˢ b = Multiset.product a b
f : TruncatedWittVector p (n + 1) k → TruncatedWittVector p (n + 1) k → k :=
  fun x y =>
    f₀ fun a =>
      Subtype.casesOn a fun a ha => Function.uncurry ![x, y] (a.fst, { val := a.snd, isLt := (_ : a.snd < n + 1) })
x y : 𝕎 k
a : Fin 2 × ℕ
ha : a ∈ fun a => a ∈ univ.val ×ˢ Multiset.range (n + 1)
⊢ Matrix.vecCons (truncateFun (n + 1) x) ![truncateFun (n + 1) y] (↑{ val := a, property := ha }).fst
      { val := (↑{ val := a, property := ha }).snd, isLt := (_ : (↑{ val := a, property := ha }).snd < n + 1) } =
    (Function.uncurry ![fun i => coeff x i, fun i => coeff y i] ∘ Subtype.val) { val := a, property := ha }
[PROOFSTEP]
cases' a with i m
[GOAL]
case h.e_a.h.mk.mk
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝¹ : CommRing k
inst✝ : CharP k p
n : ℕ
f₀ : ((↑fun a => a ∈ (univ ×ˢ range (n + 1)).val) → k) → k
hf₀ : ∀ (x : Fin 2 × ℕ → k), f₀ (x ∘ Subtype.val) = ↑(aeval x) (polyOfInterest p n)
this : ∀ (a : Multiset (Fin 2)) (b : Multiset ℕ), a ×ˢ b = Multiset.product a b
f : TruncatedWittVector p (n + 1) k → TruncatedWittVector p (n + 1) k → k :=
  fun x y =>
    f₀ fun a =>
      Subtype.casesOn a fun a ha => Function.uncurry ![x, y] (a.fst, { val := a.snd, isLt := (_ : a.snd < n + 1) })
x y : 𝕎 k
i : Fin 2
m : ℕ
ha : (i, m) ∈ fun a => a ∈ univ.val ×ˢ Multiset.range (n + 1)
⊢ Matrix.vecCons (truncateFun (n + 1) x) ![truncateFun (n + 1) y] (↑{ val := (i, m), property := ha }).fst
      { val := (↑{ val := (i, m), property := ha }).snd,
        isLt := (_ : (↑{ val := (i, m), property := ha }).snd < n + 1) } =
    (Function.uncurry ![fun i => coeff x i, fun i => coeff y i] ∘ Subtype.val) { val := (i, m), property := ha }
[PROOFSTEP]
fin_cases i
[GOAL]
case h.e_a.h.mk.mk.head
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝¹ : CommRing k
inst✝ : CharP k p
n : ℕ
f₀ : ((↑fun a => a ∈ (univ ×ˢ range (n + 1)).val) → k) → k
hf₀ : ∀ (x : Fin 2 × ℕ → k), f₀ (x ∘ Subtype.val) = ↑(aeval x) (polyOfInterest p n)
this : ∀ (a : Multiset (Fin 2)) (b : Multiset ℕ), a ×ˢ b = Multiset.product a b
f : TruncatedWittVector p (n + 1) k → TruncatedWittVector p (n + 1) k → k :=
  fun x y =>
    f₀ fun a =>
      Subtype.casesOn a fun a ha => Function.uncurry ![x, y] (a.fst, { val := a.snd, isLt := (_ : a.snd < n + 1) })
x y : 𝕎 k
m : ℕ
ha : ({ val := 0, isLt := (_ : 0 < 2) }, m) ∈ fun a => a ∈ univ.val ×ˢ Multiset.range (n + 1)
⊢ Matrix.vecCons (truncateFun (n + 1) x) ![truncateFun (n + 1) y]
      (↑{ val := ({ val := 0, isLt := (_ : 0 < 2) }, m), property := ha }).fst
      { val := (↑{ val := ({ val := 0, isLt := (_ : 0 < 2) }, m), property := ha }).snd,
        isLt := (_ : (↑{ val := ({ val := 0, isLt := (_ : 0 < 2) }, m), property := ha }).snd < n + 1) } =
    (Function.uncurry ![fun i => coeff x i, fun i => coeff y i] ∘ Subtype.val)
      { val := ({ val := 0, isLt := (_ : 0 < 2) }, m), property := ha }
[PROOFSTEP]
rfl
  -- surely this case split is not necessary
[GOAL]
case h.e_a.h.mk.mk.tail.head
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝¹ : CommRing k
inst✝ : CharP k p
n : ℕ
f₀ : ((↑fun a => a ∈ (univ ×ˢ range (n + 1)).val) → k) → k
hf₀ : ∀ (x : Fin 2 × ℕ → k), f₀ (x ∘ Subtype.val) = ↑(aeval x) (polyOfInterest p n)
this : ∀ (a : Multiset (Fin 2)) (b : Multiset ℕ), a ×ˢ b = Multiset.product a b
f : TruncatedWittVector p (n + 1) k → TruncatedWittVector p (n + 1) k → k :=
  fun x y =>
    f₀ fun a =>
      Subtype.casesOn a fun a ha => Function.uncurry ![x, y] (a.fst, { val := a.snd, isLt := (_ : a.snd < n + 1) })
x y : 𝕎 k
m : ℕ
ha : ({ val := 1, isLt := (_ : (fun a => a < 2) 1) }, m) ∈ fun a => a ∈ univ.val ×ˢ Multiset.range (n + 1)
⊢ Matrix.vecCons (truncateFun (n + 1) x) ![truncateFun (n + 1) y]
      (↑{ val := ({ val := 1, isLt := (_ : (fun a => a < 2) 1) }, m), property := ha }).fst
      { val := (↑{ val := ({ val := 1, isLt := (_ : (fun a => a < 2) 1) }, m), property := ha }).snd,
        isLt := (_ : (↑{ val := ({ val := 1, isLt := (_ : (fun a => a < 2) 1) }, m), property := ha }).snd < n + 1) } =
    (Function.uncurry ![fun i => coeff x i, fun i => coeff y i] ∘ Subtype.val)
      { val := ({ val := 1, isLt := (_ : (fun a => a < 2) 1) }, m), property := ha }
[PROOFSTEP]
rfl
  -- surely this case split is not necessary
[GOAL]
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝¹ : CommRing k
inst✝ : CharP k p
n : ℕ
⊢ ∃ f,
    ∀ (x y : 𝕎 k),
      coeff (x * y) (n + 1) =
        coeff x (n + 1) * coeff y 0 ^ p ^ (n + 1) + coeff y (n + 1) * coeff x 0 ^ p ^ (n + 1) +
          f (truncateFun (n + 1) x) (truncateFun (n + 1) y)
[PROOFSTEP]
obtain ⟨f, hf⟩ := nth_mul_coeff' p k n
[GOAL]
case intro
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝¹ : CommRing k
inst✝ : CharP k p
n : ℕ
f : TruncatedWittVector p (n + 1) k → TruncatedWittVector p (n + 1) k → k
hf :
  ∀ (x y : 𝕎 k),
    f (truncateFun (n + 1) x) (truncateFun (n + 1) y) =
      coeff (x * y) (n + 1) - coeff y (n + 1) * coeff x 0 ^ p ^ (n + 1) - coeff x (n + 1) * coeff y 0 ^ p ^ (n + 1)
⊢ ∃ f,
    ∀ (x y : 𝕎 k),
      coeff (x * y) (n + 1) =
        coeff x (n + 1) * coeff y 0 ^ p ^ (n + 1) + coeff y (n + 1) * coeff x 0 ^ p ^ (n + 1) +
          f (truncateFun (n + 1) x) (truncateFun (n + 1) y)
[PROOFSTEP]
use f
[GOAL]
case h
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝¹ : CommRing k
inst✝ : CharP k p
n : ℕ
f : TruncatedWittVector p (n + 1) k → TruncatedWittVector p (n + 1) k → k
hf :
  ∀ (x y : 𝕎 k),
    f (truncateFun (n + 1) x) (truncateFun (n + 1) y) =
      coeff (x * y) (n + 1) - coeff y (n + 1) * coeff x 0 ^ p ^ (n + 1) - coeff x (n + 1) * coeff y 0 ^ p ^ (n + 1)
⊢ ∀ (x y : 𝕎 k),
    coeff (x * y) (n + 1) =
      coeff x (n + 1) * coeff y 0 ^ p ^ (n + 1) + coeff y (n + 1) * coeff x 0 ^ p ^ (n + 1) +
        f (truncateFun (n + 1) x) (truncateFun (n + 1) y)
[PROOFSTEP]
intro x y
[GOAL]
case h
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝¹ : CommRing k
inst✝ : CharP k p
n : ℕ
f : TruncatedWittVector p (n + 1) k → TruncatedWittVector p (n + 1) k → k
hf :
  ∀ (x y : 𝕎 k),
    f (truncateFun (n + 1) x) (truncateFun (n + 1) y) =
      coeff (x * y) (n + 1) - coeff y (n + 1) * coeff x 0 ^ p ^ (n + 1) - coeff x (n + 1) * coeff y 0 ^ p ^ (n + 1)
x y : 𝕎 k
⊢ coeff (x * y) (n + 1) =
    coeff x (n + 1) * coeff y 0 ^ p ^ (n + 1) + coeff y (n + 1) * coeff x 0 ^ p ^ (n + 1) +
      f (truncateFun (n + 1) x) (truncateFun (n + 1) y)
[PROOFSTEP]
rw [hf x y]
[GOAL]
case h
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝¹ : CommRing k
inst✝ : CharP k p
n : ℕ
f : TruncatedWittVector p (n + 1) k → TruncatedWittVector p (n + 1) k → k
hf :
  ∀ (x y : 𝕎 k),
    f (truncateFun (n + 1) x) (truncateFun (n + 1) y) =
      coeff (x * y) (n + 1) - coeff y (n + 1) * coeff x 0 ^ p ^ (n + 1) - coeff x (n + 1) * coeff y 0 ^ p ^ (n + 1)
x y : 𝕎 k
⊢ coeff (x * y) (n + 1) =
    coeff x (n + 1) * coeff y 0 ^ p ^ (n + 1) + coeff y (n + 1) * coeff x 0 ^ p ^ (n + 1) +
      (coeff (x * y) (n + 1) - coeff y (n + 1) * coeff x 0 ^ p ^ (n + 1) - coeff x (n + 1) * coeff y 0 ^ p ^ (n + 1))
[PROOFSTEP]
ring


[GOAL]
β : Type u_1
M : Type ?u.36709
α : Type ?u.36708
inst✝² : SMul M α
inst✝¹ : FaithfulSMul M α
inst✝ : Nontrivial β
c₁ c₂ : Mᵈᵐᵃ
h : ∀ (a : α → β), c₁ • a = c₂ • a
a : α
⊢ ↑mk.symm c₁ • a = ↑mk.symm c₂ • a
[PROOFSTEP]
rcases exists_pair_ne β with ⟨x, y, hne⟩
[GOAL]
case intro.intro
β : Type u_1
M : Type ?u.36709
α : Type ?u.36708
inst✝² : SMul M α
inst✝¹ : FaithfulSMul M α
inst✝ : Nontrivial β
c₁ c₂ : Mᵈᵐᵃ
h : ∀ (a : α → β), c₁ • a = c₂ • a
a : α
x y : β
hne : x ≠ y
⊢ ↑mk.symm c₁ • a = ↑mk.symm c₂ • a
[PROOFSTEP]
contrapose! hne
[GOAL]
case intro.intro
β : Type u_1
M : Type ?u.36709
α : Type ?u.36708
inst✝² : SMul M α
inst✝¹ : FaithfulSMul M α
inst✝ : Nontrivial β
c₁ c₂ : Mᵈᵐᵃ
h : ∀ (a : α → β), c₁ • a = c₂ • a
a : α
x y : β
hne : ↑mk.symm c₁ • a ≠ ↑mk.symm c₂ • a
⊢ x = y
[PROOFSTEP]
haveI := Classical.decEq α
[GOAL]
case intro.intro
β : Type u_1
M : Type ?u.36709
α : Type ?u.36708
inst✝² : SMul M α
inst✝¹ : FaithfulSMul M α
inst✝ : Nontrivial β
c₁ c₂ : Mᵈᵐᵃ
h : ∀ (a : α → β), c₁ • a = c₂ • a
a : α
x y : β
hne : ↑mk.symm c₁ • a ≠ ↑mk.symm c₂ • a
this : DecidableEq α
⊢ x = y
[PROOFSTEP]
replace h := congr_fun (h (update (const α x) (mk.symm c₂ • a) y)) a
[GOAL]
case intro.intro
β : Type u_1
M : Type ?u.36709
α : Type ?u.36708
inst✝² : SMul M α
inst✝¹ : FaithfulSMul M α
inst✝ : Nontrivial β
c₁ c₂ : Mᵈᵐᵃ
a : α
x y : β
hne : ↑mk.symm c₁ • a ≠ ↑mk.symm c₂ • a
this : DecidableEq α
h : (c₁ • update (const α x) (↑mk.symm c₂ • a) y) a = (c₂ • update (const α x) (↑mk.symm c₂ • a) y) a
⊢ x = y
[PROOFSTEP]
simpa [smul_apply, hne] using h


[GOAL]
α : Type u_1
inst✝¹ : OrderedAddCommGroup α
inst✝ : Archimedean α
x y : αᵒᵈ
hy : 0 < y
n : ℕ
hn : -↑ofDual x ≤ n • -y
⊢ x ≤ n • y
[PROOFSTEP]
rwa [neg_nsmul, neg_le_neg_iff] at hn
[GOAL]
α : Type u_1
inst✝¹ : LinearOrderedAddCommGroup α
inst✝ : Archimedean α
a : α
ha : 0 < a
g : α
⊢ ∃! k, k • a ≤ g ∧ g < (k + 1) • a
[PROOFSTEP]
let s : Set ℤ := {n : ℤ | n • a ≤ g}
[GOAL]
α : Type u_1
inst✝¹ : LinearOrderedAddCommGroup α
inst✝ : Archimedean α
a : α
ha : 0 < a
g : α
s : Set ℤ := {n | n • a ≤ g}
⊢ ∃! k, k • a ≤ g ∧ g < (k + 1) • a
[PROOFSTEP]
obtain ⟨k, hk : -g ≤ k • a⟩ := Archimedean.arch (-g) ha
[GOAL]
case intro
α : Type u_1
inst✝¹ : LinearOrderedAddCommGroup α
inst✝ : Archimedean α
a : α
ha : 0 < a
g : α
s : Set ℤ := {n | n • a ≤ g}
k : ℕ
hk : -g ≤ k • a
⊢ ∃! k, k • a ≤ g ∧ g < (k + 1) • a
[PROOFSTEP]
have h_ne : s.Nonempty := ⟨-k, by simpa using neg_le_neg hk⟩
[GOAL]
α : Type u_1
inst✝¹ : LinearOrderedAddCommGroup α
inst✝ : Archimedean α
a : α
ha : 0 < a
g : α
s : Set ℤ := {n | n • a ≤ g}
k : ℕ
hk : -g ≤ k • a
⊢ -↑k ∈ s
[PROOFSTEP]
simpa using neg_le_neg hk
[GOAL]
case intro
α : Type u_1
inst✝¹ : LinearOrderedAddCommGroup α
inst✝ : Archimedean α
a : α
ha : 0 < a
g : α
s : Set ℤ := {n | n • a ≤ g}
k : ℕ
hk : -g ≤ k • a
h_ne : Set.Nonempty s
⊢ ∃! k, k • a ≤ g ∧ g < (k + 1) • a
[PROOFSTEP]
obtain ⟨k, hk⟩ := Archimedean.arch g ha
[GOAL]
case intro.intro
α : Type u_1
inst✝¹ : LinearOrderedAddCommGroup α
inst✝ : Archimedean α
a : α
ha : 0 < a
g : α
s : Set ℤ := {n | n • a ≤ g}
k✝ : ℕ
hk✝ : -g ≤ k✝ • a
h_ne : Set.Nonempty s
k : ℕ
hk : g ≤ k • a
⊢ ∃! k, k • a ≤ g ∧ g < (k + 1) • a
[PROOFSTEP]
have h_bdd : ∀ n ∈ s, n ≤ (k : ℤ) := by
  intro n hn
  apply (zsmul_le_zsmul_iff ha).mp
  rw [← coe_nat_zsmul] at hk
  exact le_trans hn hk
[GOAL]
α : Type u_1
inst✝¹ : LinearOrderedAddCommGroup α
inst✝ : Archimedean α
a : α
ha : 0 < a
g : α
s : Set ℤ := {n | n • a ≤ g}
k✝ : ℕ
hk✝ : -g ≤ k✝ • a
h_ne : Set.Nonempty s
k : ℕ
hk : g ≤ k • a
⊢ ∀ (n : ℤ), n ∈ s → n ≤ ↑k
[PROOFSTEP]
intro n hn
[GOAL]
α : Type u_1
inst✝¹ : LinearOrderedAddCommGroup α
inst✝ : Archimedean α
a : α
ha : 0 < a
g : α
s : Set ℤ := {n | n • a ≤ g}
k✝ : ℕ
hk✝ : -g ≤ k✝ • a
h_ne : Set.Nonempty s
k : ℕ
hk : g ≤ k • a
n : ℤ
hn : n ∈ s
⊢ n ≤ ↑k
[PROOFSTEP]
apply (zsmul_le_zsmul_iff ha).mp
[GOAL]
α : Type u_1
inst✝¹ : LinearOrderedAddCommGroup α
inst✝ : Archimedean α
a : α
ha : 0 < a
g : α
s : Set ℤ := {n | n • a ≤ g}
k✝ : ℕ
hk✝ : -g ≤ k✝ • a
h_ne : Set.Nonempty s
k : ℕ
hk : g ≤ k • a
n : ℤ
hn : n ∈ s
⊢ n • a ≤ ↑k • a
[PROOFSTEP]
rw [← coe_nat_zsmul] at hk
[GOAL]
α : Type u_1
inst✝¹ : LinearOrderedAddCommGroup α
inst✝ : Archimedean α
a : α
ha : 0 < a
g : α
s : Set ℤ := {n | n • a ≤ g}
k✝ : ℕ
hk✝ : -g ≤ k✝ • a
h_ne : Set.Nonempty s
k : ℕ
hk : g ≤ ↑k • a
n : ℤ
hn : n ∈ s
⊢ n • a ≤ ↑k • a
[PROOFSTEP]
exact le_trans hn hk
[GOAL]
case intro.intro
α : Type u_1
inst✝¹ : LinearOrderedAddCommGroup α
inst✝ : Archimedean α
a : α
ha : 0 < a
g : α
s : Set ℤ := {n | n • a ≤ g}
k✝ : ℕ
hk✝ : -g ≤ k✝ • a
h_ne : Set.Nonempty s
k : ℕ
hk : g ≤ k • a
h_bdd : ∀ (n : ℤ), n ∈ s → n ≤ ↑k
⊢ ∃! k, k • a ≤ g ∧ g < (k + 1) • a
[PROOFSTEP]
obtain ⟨m, hm, hm'⟩ := Int.exists_greatest_of_bdd ⟨k, h_bdd⟩ h_ne
[GOAL]
case intro.intro.intro.intro
α : Type u_1
inst✝¹ : LinearOrderedAddCommGroup α
inst✝ : Archimedean α
a : α
ha : 0 < a
g : α
s : Set ℤ := {n | n • a ≤ g}
k✝ : ℕ
hk✝ : -g ≤ k✝ • a
h_ne : Set.Nonempty s
k : ℕ
hk : g ≤ k • a
h_bdd : ∀ (n : ℤ), n ∈ s → n ≤ ↑k
m : ℤ
hm : m ∈ s
hm' : ∀ (z : ℤ), z ∈ s → z ≤ m
⊢ ∃! k, k • a ≤ g ∧ g < (k + 1) • a
[PROOFSTEP]
have hm'' : g < (m + 1) • a := by
  contrapose! hm'
  exact ⟨m + 1, hm', lt_add_one _⟩
[GOAL]
α : Type u_1
inst✝¹ : LinearOrderedAddCommGroup α
inst✝ : Archimedean α
a : α
ha : 0 < a
g : α
s : Set ℤ := {n | n • a ≤ g}
k✝ : ℕ
hk✝ : -g ≤ k✝ • a
h_ne : Set.Nonempty s
k : ℕ
hk : g ≤ k • a
h_bdd : ∀ (n : ℤ), n ∈ s → n ≤ ↑k
m : ℤ
hm : m ∈ s
hm' : ∀ (z : ℤ), z ∈ s → z ≤ m
⊢ g < (m + 1) • a
[PROOFSTEP]
contrapose! hm'
[GOAL]
α : Type u_1
inst✝¹ : LinearOrderedAddCommGroup α
inst✝ : Archimedean α
a : α
ha : 0 < a
g : α
s : Set ℤ := {n | n • a ≤ g}
k✝ : ℕ
hk✝ : -g ≤ k✝ • a
h_ne : Set.Nonempty s
k : ℕ
hk : g ≤ k • a
h_bdd : ∀ (n : ℤ), n ∈ s → n ≤ ↑k
m : ℤ
hm : m ∈ s
hm' : (m + 1) • a ≤ g
⊢ ∃ z, z ∈ {n | n • a ≤ g} ∧ m < z
[PROOFSTEP]
exact ⟨m + 1, hm', lt_add_one _⟩
[GOAL]
case intro.intro.intro.intro
α : Type u_1
inst✝¹ : LinearOrderedAddCommGroup α
inst✝ : Archimedean α
a : α
ha : 0 < a
g : α
s : Set ℤ := {n | n • a ≤ g}
k✝ : ℕ
hk✝ : -g ≤ k✝ • a
h_ne : Set.Nonempty s
k : ℕ
hk : g ≤ k • a
h_bdd : ∀ (n : ℤ), n ∈ s → n ≤ ↑k
m : ℤ
hm : m ∈ s
hm' : ∀ (z : ℤ), z ∈ s → z ≤ m
hm'' : g < (m + 1) • a
⊢ ∃! k, k • a ≤ g ∧ g < (k + 1) • a
[PROOFSTEP]
refine' ⟨m, ⟨hm, hm''⟩, fun n hn => (hm' n hn.1).antisymm <| Int.le_of_lt_add_one _⟩
[GOAL]
case intro.intro.intro.intro
α : Type u_1
inst✝¹ : LinearOrderedAddCommGroup α
inst✝ : Archimedean α
a : α
ha : 0 < a
g : α
s : Set ℤ := {n | n • a ≤ g}
k✝ : ℕ
hk✝ : -g ≤ k✝ • a
h_ne : Set.Nonempty s
k : ℕ
hk : g ≤ k • a
h_bdd : ∀ (n : ℤ), n ∈ s → n ≤ ↑k
m : ℤ
hm : m ∈ s
hm' : ∀ (z : ℤ), z ∈ s → z ≤ m
hm'' : g < (m + 1) • a
n : ℤ
hn : (fun k => k • a ≤ g ∧ g < (k + 1) • a) n
⊢ m < n + 1
[PROOFSTEP]
rw [← zsmul_lt_zsmul_iff ha]
[GOAL]
case intro.intro.intro.intro
α : Type u_1
inst✝¹ : LinearOrderedAddCommGroup α
inst✝ : Archimedean α
a : α
ha : 0 < a
g : α
s : Set ℤ := {n | n • a ≤ g}
k✝ : ℕ
hk✝ : -g ≤ k✝ • a
h_ne : Set.Nonempty s
k : ℕ
hk : g ≤ k • a
h_bdd : ∀ (n : ℤ), n ∈ s → n ≤ ↑k
m : ℤ
hm : m ∈ s
hm' : ∀ (z : ℤ), z ∈ s → z ≤ m
hm'' : g < (m + 1) • a
n : ℤ
hn : (fun k => k • a ≤ g ∧ g < (k + 1) • a) n
⊢ m • a < (n + 1) • a
[PROOFSTEP]
exact lt_of_le_of_lt hm hn.2
[GOAL]
α : Type u_1
inst✝¹ : LinearOrderedAddCommGroup α
inst✝ : Archimedean α
a : α
ha : 0 < a
g : α
⊢ ∃! k, 0 ≤ g - k • a ∧ g - k • a < a
[PROOFSTEP]
simpa only [sub_nonneg, add_zsmul, one_zsmul, sub_lt_iff_lt_add'] using existsUnique_zsmul_near_of_pos ha g
[GOAL]
α : Type u_1
inst✝¹ : LinearOrderedAddCommGroup α
inst✝ : Archimedean α
a : α
ha : 0 < a
b c : α
⊢ ∃! m, b - m • a ∈ Ico c (c + a)
[PROOFSTEP]
simpa only [mem_Ico, le_sub_iff_add_le, zero_add, add_comm c, sub_lt_iff_lt_add', add_assoc] using
  existsUnique_zsmul_near_of_pos' ha (b - c)
[GOAL]
α : Type u_1
inst✝¹ : LinearOrderedAddCommGroup α
inst✝ : Archimedean α
a : α
ha : 0 < a
b c : α
⊢ ∃! x, b + ↑(Equiv.neg ℤ) x • a ∈ Ico c (c + a)
[PROOFSTEP]
simpa only [Equiv.neg_apply, mem_Ico, neg_zsmul, ← sub_eq_add_neg, le_sub_iff_add_le, zero_add, add_comm c,
  sub_lt_iff_lt_add', add_assoc] using existsUnique_zsmul_near_of_pos' ha (b - c)
[GOAL]
α : Type u_1
inst✝¹ : LinearOrderedAddCommGroup α
inst✝ : Archimedean α
a : α
ha : 0 < a
b c : α
⊢ ∃! x, b + ↑(Equiv.addRight 1) x • a ∈ Ioc c (c + a)
[PROOFSTEP]
simpa only [add_zsmul, sub_lt_iff_lt_add', le_sub_iff_add_le', ← add_assoc, and_comm, mem_Ioc, Equiv.coe_addRight,
  one_zsmul, add_le_add_iff_right] using existsUnique_zsmul_near_of_pos ha (c - b)
[GOAL]
α : Type u_1
inst✝¹ : LinearOrderedAddCommGroup α
inst✝ : Archimedean α
a : α
ha : 0 < a
b c : α
⊢ ∃! x, b - ↑(Equiv.neg ℤ) x • a ∈ Ioc c (c + a)
[PROOFSTEP]
simpa only [Equiv.neg_apply, neg_zsmul, sub_neg_eq_add] using existsUnique_add_zsmul_mem_Ioc ha b c
[GOAL]
α : Type u_1
inst✝¹ : StrictOrderedSemiring α
inst✝ : Archimedean α
x : α
n : ℕ
hn : x < n • 1
⊢ x < ↑n
[PROOFSTEP]
rwa [← nsmul_one]
[GOAL]
α : Type u_1
inst✝¹ : OrderedSemiring α
inst✝ : Archimedean α
x : α
⊢ ∃ n, x ≤ ↑n
[PROOFSTEP]
nontriviality α
[GOAL]
α : Type u_1
inst✝¹ : OrderedSemiring α
inst✝ : Archimedean α
x : α
✝ : Nontrivial α
⊢ ∃ n, x ≤ ↑n
[PROOFSTEP]
exact (Archimedean.arch x one_pos).imp fun n h => by rwa [← nsmul_one]
[GOAL]
α : Type u_1
inst✝¹ : OrderedSemiring α
inst✝ : Archimedean α
x : α
✝ : Nontrivial α
n : ℕ
h : x ≤ n • 1
⊢ x ≤ ↑n
[PROOFSTEP]
rwa [← nsmul_one]
[GOAL]
α : Type u_1
inst✝¹ : StrictOrderedSemiring α
inst✝ : Archimedean α
x y : α
hy : 0 < y
this : 0 ≤ 1 + y
n : ℕ
h : x ≤ n • y
⊢ (1 + y) ^ n = (y + 1) ^ n
[PROOFSTEP]
rw [add_comm]
[GOAL]
α : Type u_1
inst✝¹ : StrictOrderedRing α
inst✝ : Archimedean α
x : α
n : ℕ
h : x < ↑n
⊢ x < ↑↑n
[PROOFSTEP]
rwa [Int.cast_ofNat]
[GOAL]
α : Type u_1
inst✝¹ : StrictOrderedRing α
inst✝ : Archimedean α
x : α
n : ℤ
h : -x < ↑n
⊢ ↑(-n) < x
[PROOFSTEP]
rw [Int.cast_neg]
[GOAL]
α : Type u_1
inst✝¹ : StrictOrderedRing α
inst✝ : Archimedean α
x : α
n : ℤ
h : -x < ↑n
⊢ -↑n < x
[PROOFSTEP]
exact neg_lt.1 h
[GOAL]
α : Type u_1
inst✝¹ : StrictOrderedRing α
inst✝ : Archimedean α
x : α
⊢ ∃ fl, ∀ (z : ℤ), z ≤ fl ↔ ↑z ≤ x
[PROOFSTEP]
haveI := Classical.propDecidable
[GOAL]
α : Type u_1
inst✝¹ : StrictOrderedRing α
inst✝ : Archimedean α
x : α
this : (a : Prop) → Decidable a
⊢ ∃ fl, ∀ (z : ℤ), z ≤ fl ↔ ↑z ≤ x
[PROOFSTEP]
have : ∃ ub : ℤ, (ub : α) ≤ x ∧ ∀ z : ℤ, (z : α) ≤ x → z ≤ ub :=
  Int.exists_greatest_of_bdd
    (let ⟨n, hn⟩ := exists_int_gt x
    ⟨n, fun z h' => Int.cast_le.1 <| le_trans h' <| le_of_lt hn⟩)
    (let ⟨n, hn⟩ := exists_int_lt x
    ⟨n, le_of_lt hn⟩)
[GOAL]
α : Type u_1
inst✝¹ : StrictOrderedRing α
inst✝ : Archimedean α
x : α
this✝ : (a : Prop) → Decidable a
this : ∃ ub, ↑ub ≤ x ∧ ∀ (z : ℤ), ↑z ≤ x → z ≤ ub
⊢ ∃ fl, ∀ (z : ℤ), z ≤ fl ↔ ↑z ≤ x
[PROOFSTEP]
refine' this.imp fun fl h z => _
[GOAL]
α : Type u_1
inst✝¹ : StrictOrderedRing α
inst✝ : Archimedean α
x : α
this✝ : (a : Prop) → Decidable a
this : ∃ ub, ↑ub ≤ x ∧ ∀ (z : ℤ), ↑z ≤ x → z ≤ ub
fl : ℤ
h : ↑fl ≤ x ∧ ∀ (z : ℤ), ↑z ≤ x → z ≤ fl
z : ℤ
⊢ z ≤ fl ↔ ↑z ≤ x
[PROOFSTEP]
cases' h with h₁ h₂
[GOAL]
case intro
α : Type u_1
inst✝¹ : StrictOrderedRing α
inst✝ : Archimedean α
x : α
this✝ : (a : Prop) → Decidable a
this : ∃ ub, ↑ub ≤ x ∧ ∀ (z : ℤ), ↑z ≤ x → z ≤ ub
fl z : ℤ
h₁ : ↑fl ≤ x
h₂ : ∀ (z : ℤ), ↑z ≤ x → z ≤ fl
⊢ z ≤ fl ↔ ↑z ≤ x
[PROOFSTEP]
exact ⟨fun h => le_trans (Int.cast_le.2 h) h₁, h₂ z⟩
[GOAL]
α : Type u_1
inst✝¹ : LinearOrderedRing α
inst✝ : Archimedean α
x y : α
hx : 1 ≤ x
hy : 1 < y
⊢ ∃ n, y ^ n ≤ x ∧ x < y ^ (n + 1)
[PROOFSTEP]
have h : ∃ n : ℕ, x < y ^ n := pow_unbounded_of_one_lt _ hy
[GOAL]
α : Type u_1
inst✝¹ : LinearOrderedRing α
inst✝ : Archimedean α
x y : α
hx : 1 ≤ x
hy : 1 < y
h : ∃ n, x < y ^ n
⊢ ∃ n, y ^ n ≤ x ∧ x < y ^ (n + 1)
[PROOFSTEP]
classical exact
  let n := Nat.find h
  have hn : x < y ^ n := Nat.find_spec h
  have hnp : 0 < n := pos_iff_ne_zero.2 fun hn0 => by rw [hn0, pow_zero] at hn ; exact not_le_of_gt hn hx
  have hnsp : Nat.pred n + 1 = n := Nat.succ_pred_eq_of_pos hnp
  have hltn : Nat.pred n < n := Nat.pred_lt (ne_of_gt hnp)
  ⟨Nat.pred n, le_of_not_lt (Nat.find_min h hltn), by rwa [hnsp]⟩
[GOAL]
α : Type u_1
inst✝¹ : LinearOrderedRing α
inst✝ : Archimedean α
x y : α
hx : 1 ≤ x
hy : 1 < y
h : ∃ n, x < y ^ n
⊢ ∃ n, y ^ n ≤ x ∧ x < y ^ (n + 1)
[PROOFSTEP]
exact
  let n := Nat.find h
  have hn : x < y ^ n := Nat.find_spec h
  have hnp : 0 < n := pos_iff_ne_zero.2 fun hn0 => by rw [hn0, pow_zero] at hn ; exact not_le_of_gt hn hx
  have hnsp : Nat.pred n + 1 = n := Nat.succ_pred_eq_of_pos hnp
  have hltn : Nat.pred n < n := Nat.pred_lt (ne_of_gt hnp)
  ⟨Nat.pred n, le_of_not_lt (Nat.find_min h hltn), by rwa [hnsp]⟩
[GOAL]
α : Type u_1
inst✝¹ : LinearOrderedRing α
inst✝ : Archimedean α
x y : α
hx : 1 ≤ x
hy : 1 < y
h : ∃ n, x < y ^ n
n : ℕ := Nat.find h
hn : x < y ^ n
hn0 : n = 0
⊢ False
[PROOFSTEP]
rw [hn0, pow_zero] at hn
[GOAL]
α : Type u_1
inst✝¹ : LinearOrderedRing α
inst✝ : Archimedean α
x y : α
hx : 1 ≤ x
hy : 1 < y
h : ∃ n, x < y ^ n
n : ℕ := Nat.find h
hn : x < 1
hn0 : n = 0
⊢ False
[PROOFSTEP]
exact not_le_of_gt hn hx
[GOAL]
α : Type u_1
inst✝¹ : LinearOrderedRing α
inst✝ : Archimedean α
x y : α
hx : 1 ≤ x
hy : 1 < y
h : ∃ n, x < y ^ n
n : ℕ := Nat.find h
hn : x < y ^ n
hnp : 0 < n
hnsp : Nat.pred n + 1 = n
hltn : Nat.pred n < n
⊢ x < y ^ (Nat.pred n + 1)
[PROOFSTEP]
rwa [hnsp]
[GOAL]
α : Type u_1
inst✝¹ : LinearOrderedField α
inst✝ : Archimedean α
x y ε : α
hx : 0 < x
hy : 1 < y
⊢ ∃ n, x ∈ Ico (y ^ n) (y ^ (n + 1))
[PROOFSTEP]
classical exact
  let ⟨N, hN⟩ := pow_unbounded_of_one_lt x⁻¹ hy
  have he : ∃ m : ℤ, y ^ m ≤ x :=
    ⟨-N,
      le_of_lt
        (by
          rw [zpow_neg y ↑N, zpow_ofNat]
          exact (inv_lt hx (lt_trans (inv_pos.2 hx) hN)).1 hN)⟩
  let ⟨M, hM⟩ := pow_unbounded_of_one_lt x hy
  have hb : ∃ b : ℤ, ∀ m, y ^ m ≤ x → m ≤ b :=
    ⟨M, fun m hm =>
      le_of_not_lt fun hlt =>
        not_lt_of_ge (zpow_le_of_le hy.le hlt.le) (lt_of_le_of_lt hm (by rwa [← zpow_ofNat] at hM ))⟩
  let ⟨n, hn₁, hn₂⟩ := Int.exists_greatest_of_bdd hb he
  ⟨n, hn₁, lt_of_not_ge fun hge => not_le_of_gt (Int.lt_succ _) (hn₂ _ hge)⟩
[GOAL]
α : Type u_1
inst✝¹ : LinearOrderedField α
inst✝ : Archimedean α
x y ε : α
hx : 0 < x
hy : 1 < y
⊢ ∃ n, x ∈ Ico (y ^ n) (y ^ (n + 1))
[PROOFSTEP]
exact
  let ⟨N, hN⟩ := pow_unbounded_of_one_lt x⁻¹ hy
  have he : ∃ m : ℤ, y ^ m ≤ x :=
    ⟨-N,
      le_of_lt
        (by
          rw [zpow_neg y ↑N, zpow_ofNat]
          exact (inv_lt hx (lt_trans (inv_pos.2 hx) hN)).1 hN)⟩
  let ⟨M, hM⟩ := pow_unbounded_of_one_lt x hy
  have hb : ∃ b : ℤ, ∀ m, y ^ m ≤ x → m ≤ b :=
    ⟨M, fun m hm =>
      le_of_not_lt fun hlt =>
        not_lt_of_ge (zpow_le_of_le hy.le hlt.le) (lt_of_le_of_lt hm (by rwa [← zpow_ofNat] at hM ))⟩
  let ⟨n, hn₁, hn₂⟩ := Int.exists_greatest_of_bdd hb he
  ⟨n, hn₁, lt_of_not_ge fun hge => not_le_of_gt (Int.lt_succ _) (hn₂ _ hge)⟩
[GOAL]
α : Type u_1
inst✝¹ : LinearOrderedField α
inst✝ : Archimedean α
x y ε : α
hx : 0 < x
hy : 1 < y
N : ℕ
hN : x⁻¹ < y ^ N
⊢ y ^ (-↑N) < x
[PROOFSTEP]
rw [zpow_neg y ↑N, zpow_ofNat]
[GOAL]
α : Type u_1
inst✝¹ : LinearOrderedField α
inst✝ : Archimedean α
x y ε : α
hx : 0 < x
hy : 1 < y
N : ℕ
hN : x⁻¹ < y ^ N
⊢ (y ^ N)⁻¹ < x
[PROOFSTEP]
exact (inv_lt hx (lt_trans (inv_pos.2 hx) hN)).1 hN
[GOAL]
α : Type u_1
inst✝¹ : LinearOrderedField α
inst✝ : Archimedean α
x y ε : α
hx : 0 < x
hy : 1 < y
N : ℕ
hN : x⁻¹ < y ^ N
he : ∃ m, y ^ m ≤ x
M : ℕ
hM : x < y ^ M
m : ℤ
hm : y ^ m ≤ x
hlt : ↑M < m
⊢ x < y ^ ↑M
[PROOFSTEP]
rwa [← zpow_ofNat] at hM
[GOAL]
α : Type u_1
inst✝¹ : LinearOrderedField α
inst✝ : Archimedean α
x y ε : α
hx : 0 < x
hy : 1 < y
m : ℤ
hle : y ^ m ≤ x⁻¹
hlt : x⁻¹ < y ^ (m + 1)
hyp : 0 < y
⊢ y ^ (-(m + 1)) < x
[PROOFSTEP]
rwa [zpow_neg, inv_lt (zpow_pos_of_pos hyp _) hx]
[GOAL]
α : Type u_1
inst✝¹ : LinearOrderedField α
inst✝ : Archimedean α
x y ε : α
hx : 0 < x
hy : 1 < y
m : ℤ
hle : y ^ m ≤ x⁻¹
hlt : x⁻¹ < y ^ (m + 1)
hyp : 0 < y
⊢ x ≤ y ^ (-(m + 1) + 1)
[PROOFSTEP]
rwa [neg_add, neg_add_cancel_right, zpow_neg, le_inv hx (zpow_pos_of_pos hyp _)]
[GOAL]
α : Type u_1
inst✝¹ : LinearOrderedField α
inst✝ : Archimedean α
x y ε : α
hx : 0 < x
hy : y < 1
⊢ ∃ n, y ^ n < x
[PROOFSTEP]
by_cases y_pos : y ≤ 0
[GOAL]
case pos
α : Type u_1
inst✝¹ : LinearOrderedField α
inst✝ : Archimedean α
x y ε : α
hx : 0 < x
hy : y < 1
y_pos : y ≤ 0
⊢ ∃ n, y ^ n < x
[PROOFSTEP]
use 1
[GOAL]
case h
α : Type u_1
inst✝¹ : LinearOrderedField α
inst✝ : Archimedean α
x y ε : α
hx : 0 < x
hy : y < 1
y_pos : y ≤ 0
⊢ y ^ 1 < x
[PROOFSTEP]
simp only [pow_one]
[GOAL]
case h
α : Type u_1
inst✝¹ : LinearOrderedField α
inst✝ : Archimedean α
x y ε : α
hx : 0 < x
hy : y < 1
y_pos : y ≤ 0
⊢ y < x
[PROOFSTEP]
linarith
[GOAL]
case neg
α : Type u_1
inst✝¹ : LinearOrderedField α
inst✝ : Archimedean α
x y ε : α
hx : 0 < x
hy : y < 1
y_pos : ¬y ≤ 0
⊢ ∃ n, y ^ n < x
[PROOFSTEP]
rw [not_le] at y_pos
[GOAL]
case neg
α : Type u_1
inst✝¹ : LinearOrderedField α
inst✝ : Archimedean α
x y ε : α
hx : 0 < x
hy : y < 1
y_pos : 0 < y
⊢ ∃ n, y ^ n < x
[PROOFSTEP]
rcases pow_unbounded_of_one_lt x⁻¹ (one_lt_inv y_pos hy) with ⟨q, hq⟩
[GOAL]
case neg.intro
α : Type u_1
inst✝¹ : LinearOrderedField α
inst✝ : Archimedean α
x y ε : α
hx : 0 < x
hy : y < 1
y_pos : 0 < y
q : ℕ
hq : x⁻¹ < y⁻¹ ^ q
⊢ ∃ n, y ^ n < x
[PROOFSTEP]
exact ⟨q, by rwa [inv_pow, inv_lt_inv hx (pow_pos y_pos _)] at hq ⟩
[GOAL]
α : Type u_1
inst✝¹ : LinearOrderedField α
inst✝ : Archimedean α
x y ε : α
hx : 0 < x
hy : y < 1
y_pos : 0 < y
q : ℕ
hq : x⁻¹ < y⁻¹ ^ q
⊢ y ^ q < x
[PROOFSTEP]
rwa [inv_pow, inv_lt_inv hx (pow_pos y_pos _)] at hq
[GOAL]
α : Type u_1
inst✝¹ : LinearOrderedField α
inst✝ : Archimedean α
x y ε : α
xpos : 0 < x
hx : x ≤ 1
ypos : 0 < y
hy : y < 1
⊢ ∃ n, y ^ (n + 1) < x ∧ x ≤ y ^ n
[PROOFSTEP]
rcases exists_nat_pow_near (one_le_inv_iff.2 ⟨xpos, hx⟩) (one_lt_inv_iff.2 ⟨ypos, hy⟩) with ⟨n, hn, h'n⟩
[GOAL]
case intro.intro
α : Type u_1
inst✝¹ : LinearOrderedField α
inst✝ : Archimedean α
x y ε : α
xpos : 0 < x
hx : x ≤ 1
ypos : 0 < y
hy : y < 1
n : ℕ
hn : y⁻¹ ^ n ≤ x⁻¹
h'n : x⁻¹ < y⁻¹ ^ (n + 1)
⊢ ∃ n, y ^ (n + 1) < x ∧ x ≤ y ^ n
[PROOFSTEP]
refine' ⟨n, _, _⟩
[GOAL]
case intro.intro.refine'_1
α : Type u_1
inst✝¹ : LinearOrderedField α
inst✝ : Archimedean α
x y ε : α
xpos : 0 < x
hx : x ≤ 1
ypos : 0 < y
hy : y < 1
n : ℕ
hn : y⁻¹ ^ n ≤ x⁻¹
h'n : x⁻¹ < y⁻¹ ^ (n + 1)
⊢ y ^ (n + 1) < x
[PROOFSTEP]
rwa [inv_pow, inv_lt_inv xpos (pow_pos ypos _)] at h'n
[GOAL]
case intro.intro.refine'_2
α : Type u_1
inst✝¹ : LinearOrderedField α
inst✝ : Archimedean α
x y ε : α
xpos : 0 < x
hx : x ≤ 1
ypos : 0 < y
hy : y < 1
n : ℕ
hn : y⁻¹ ^ n ≤ x⁻¹
h'n : x⁻¹ < y⁻¹ ^ (n + 1)
⊢ x ≤ y ^ n
[PROOFSTEP]
rwa [inv_pow, inv_le_inv (pow_pos ypos _) xpos] at hn
[GOAL]
α : Type u_1
inst✝¹ : LinearOrderedField α
inst✝ : Archimedean α
x✝ y ε x : α
n : ℕ
h : x < ↑n
⊢ x < ↑↑n
[PROOFSTEP]
rwa [Rat.cast_coe_nat]
[GOAL]
α : Type u_1
inst✝¹ : LinearOrderedField α
inst✝ : Archimedean α
x✝ y ε x : α
n : ℤ
h : ↑n < x
⊢ ↑↑n < x
[PROOFSTEP]
rwa [Rat.cast_coe_int]
[GOAL]
α : Type u_1
inst✝¹ : LinearOrderedField α
inst✝ : Archimedean α
x✝ y✝ ε x y : α
h : x < y
⊢ ∃ q, x < ↑q ∧ ↑q < y
[PROOFSTEP]
cases' exists_nat_gt (y - x)⁻¹ with n nh
[GOAL]
case intro
α : Type u_1
inst✝¹ : LinearOrderedField α
inst✝ : Archimedean α
x✝ y✝ ε x y : α
h : x < y
n : ℕ
nh : (y - x)⁻¹ < ↑n
⊢ ∃ q, x < ↑q ∧ ↑q < y
[PROOFSTEP]
cases' exists_floor (x * n) with z zh
[GOAL]
case intro.intro
α : Type u_1
inst✝¹ : LinearOrderedField α
inst✝ : Archimedean α
x✝ y✝ ε x y : α
h : x < y
n : ℕ
nh : (y - x)⁻¹ < ↑n
z : ℤ
zh : ∀ (z_1 : ℤ), z_1 ≤ z ↔ ↑z_1 ≤ x * ↑n
⊢ ∃ q, x < ↑q ∧ ↑q < y
[PROOFSTEP]
refine' ⟨(z + 1 : ℤ) / n, _⟩
[GOAL]
case intro.intro
α : Type u_1
inst✝¹ : LinearOrderedField α
inst✝ : Archimedean α
x✝ y✝ ε x y : α
h : x < y
n : ℕ
nh : (y - x)⁻¹ < ↑n
z : ℤ
zh : ∀ (z_1 : ℤ), z_1 ≤ z ↔ ↑z_1 ≤ x * ↑n
⊢ x < ↑(↑(z + 1) / ↑n) ∧ ↑(↑(z + 1) / ↑n) < y
[PROOFSTEP]
have n0' := (inv_pos.2 (sub_pos.2 h)).trans nh
[GOAL]
case intro.intro
α : Type u_1
inst✝¹ : LinearOrderedField α
inst✝ : Archimedean α
x✝ y✝ ε x y : α
h : x < y
n : ℕ
nh : (y - x)⁻¹ < ↑n
z : ℤ
zh : ∀ (z_1 : ℤ), z_1 ≤ z ↔ ↑z_1 ≤ x * ↑n
n0' : 0 < ↑n
⊢ x < ↑(↑(z + 1) / ↑n) ∧ ↑(↑(z + 1) / ↑n) < y
[PROOFSTEP]
have n0 := Nat.cast_pos.1 n0'
[GOAL]
case intro.intro
α : Type u_1
inst✝¹ : LinearOrderedField α
inst✝ : Archimedean α
x✝ y✝ ε x y : α
h : x < y
n : ℕ
nh : (y - x)⁻¹ < ↑n
z : ℤ
zh : ∀ (z_1 : ℤ), z_1 ≤ z ↔ ↑z_1 ≤ x * ↑n
n0' : 0 < ↑n
n0 : 0 < n
⊢ x < ↑(↑(z + 1) / ↑n) ∧ ↑(↑(z + 1) / ↑n) < y
[PROOFSTEP]
rw [Rat.cast_div_of_ne_zero, Rat.cast_coe_nat, Rat.cast_coe_int, div_lt_iff n0']
[GOAL]
case intro.intro
α : Type u_1
inst✝¹ : LinearOrderedField α
inst✝ : Archimedean α
x✝ y✝ ε x y : α
h : x < y
n : ℕ
nh : (y - x)⁻¹ < ↑n
z : ℤ
zh : ∀ (z_1 : ℤ), z_1 ≤ z ↔ ↑z_1 ≤ x * ↑n
n0' : 0 < ↑n
n0 : 0 < n
⊢ x < ↑(z + 1) / ↑n ∧ ↑(z + 1) < y * ↑n
case intro.intro.md
α : Type u_1
inst✝¹ : LinearOrderedField α
inst✝ : Archimedean α
x✝ y✝ ε x y : α
h : x < y
n : ℕ
nh : (y - x)⁻¹ < ↑n
z : ℤ
zh : ∀ (z_1 : ℤ), z_1 ≤ z ↔ ↑z_1 ≤ x * ↑n
n0' : 0 < ↑n
n0 : 0 < n
⊢ ↑(↑(z + 1)).den ≠ 0
case intro.intro.nn
α : Type u_1
inst✝¹ : LinearOrderedField α
inst✝ : Archimedean α
x✝ y✝ ε x y : α
h : x < y
n : ℕ
nh : (y - x)⁻¹ < ↑n
z : ℤ
zh : ∀ (z_1 : ℤ), z_1 ≤ z ↔ ↑z_1 ≤ x * ↑n
n0' : 0 < ↑n
n0 : 0 < n
⊢ ↑(↑n).num ≠ 0
case intro.intro.nd
α : Type u_1
inst✝¹ : LinearOrderedField α
inst✝ : Archimedean α
x✝ y✝ ε x y : α
h : x < y
n : ℕ
nh : (y - x)⁻¹ < ↑n
z : ℤ
zh : ∀ (z_1 : ℤ), z_1 ≤ z ↔ ↑z_1 ≤ x * ↑n
n0' : 0 < ↑n
n0 : 0 < n
⊢ ↑(↑n).den ≠ 0
[PROOFSTEP]
refine' ⟨(lt_div_iff n0').2 <| (lt_iff_lt_of_le_iff_le (zh _)).1 (lt_add_one _), _⟩
[GOAL]
case intro.intro
α : Type u_1
inst✝¹ : LinearOrderedField α
inst✝ : Archimedean α
x✝ y✝ ε x y : α
h : x < y
n : ℕ
nh : (y - x)⁻¹ < ↑n
z : ℤ
zh : ∀ (z_1 : ℤ), z_1 ≤ z ↔ ↑z_1 ≤ x * ↑n
n0' : 0 < ↑n
n0 : 0 < n
⊢ ↑(z + 1) < y * ↑n
case intro.intro.md
α : Type u_1
inst✝¹ : LinearOrderedField α
inst✝ : Archimedean α
x✝ y✝ ε x y : α
h : x < y
n : ℕ
nh : (y - x)⁻¹ < ↑n
z : ℤ
zh : ∀ (z_1 : ℤ), z_1 ≤ z ↔ ↑z_1 ≤ x * ↑n
n0' : 0 < ↑n
n0 : 0 < n
⊢ ↑(↑(z + 1)).den ≠ 0
case intro.intro.nn
α : Type u_1
inst✝¹ : LinearOrderedField α
inst✝ : Archimedean α
x✝ y✝ ε x y : α
h : x < y
n : ℕ
nh : (y - x)⁻¹ < ↑n
z : ℤ
zh : ∀ (z_1 : ℤ), z_1 ≤ z ↔ ↑z_1 ≤ x * ↑n
n0' : 0 < ↑n
n0 : 0 < n
⊢ ↑(↑n).num ≠ 0
case intro.intro.nd
α : Type u_1
inst✝¹ : LinearOrderedField α
inst✝ : Archimedean α
x✝ y✝ ε x y : α
h : x < y
n : ℕ
nh : (y - x)⁻¹ < ↑n
z : ℤ
zh : ∀ (z_1 : ℤ), z_1 ≤ z ↔ ↑z_1 ≤ x * ↑n
n0' : 0 < ↑n
n0 : 0 < n
⊢ ↑(↑n).den ≠ 0
[PROOFSTEP]
rw [Int.cast_add, Int.cast_one]
[GOAL]
case intro.intro
α : Type u_1
inst✝¹ : LinearOrderedField α
inst✝ : Archimedean α
x✝ y✝ ε x y : α
h : x < y
n : ℕ
nh : (y - x)⁻¹ < ↑n
z : ℤ
zh : ∀ (z_1 : ℤ), z_1 ≤ z ↔ ↑z_1 ≤ x * ↑n
n0' : 0 < ↑n
n0 : 0 < n
⊢ ↑z + 1 < y * ↑n
case intro.intro.md
α : Type u_1
inst✝¹ : LinearOrderedField α
inst✝ : Archimedean α
x✝ y✝ ε x y : α
h : x < y
n : ℕ
nh : (y - x)⁻¹ < ↑n
z : ℤ
zh : ∀ (z_1 : ℤ), z_1 ≤ z ↔ ↑z_1 ≤ x * ↑n
n0' : 0 < ↑n
n0 : 0 < n
⊢ ↑(↑(z + 1)).den ≠ 0
case intro.intro.nn
α : Type u_1
inst✝¹ : LinearOrderedField α
inst✝ : Archimedean α
x✝ y✝ ε x y : α
h : x < y
n : ℕ
nh : (y - x)⁻¹ < ↑n
z : ℤ
zh : ∀ (z_1 : ℤ), z_1 ≤ z ↔ ↑z_1 ≤ x * ↑n
n0' : 0 < ↑n
n0 : 0 < n
⊢ ↑(↑n).num ≠ 0
case intro.intro.nd
α : Type u_1
inst✝¹ : LinearOrderedField α
inst✝ : Archimedean α
x✝ y✝ ε x y : α
h : x < y
n : ℕ
nh : (y - x)⁻¹ < ↑n
z : ℤ
zh : ∀ (z_1 : ℤ), z_1 ≤ z ↔ ↑z_1 ≤ x * ↑n
n0' : 0 < ↑n
n0 : 0 < n
⊢ ↑(↑n).den ≠ 0
[PROOFSTEP]
refine' lt_of_le_of_lt (add_le_add_right ((zh _).1 le_rfl) _) _
[GOAL]
case intro.intro
α : Type u_1
inst✝¹ : LinearOrderedField α
inst✝ : Archimedean α
x✝ y✝ ε x y : α
h : x < y
n : ℕ
nh : (y - x)⁻¹ < ↑n
z : ℤ
zh : ∀ (z_1 : ℤ), z_1 ≤ z ↔ ↑z_1 ≤ x * ↑n
n0' : 0 < ↑n
n0 : 0 < n
⊢ x * ↑n + 1 < y * ↑n
case intro.intro.md
α : Type u_1
inst✝¹ : LinearOrderedField α
inst✝ : Archimedean α
x✝ y✝ ε x y : α
h : x < y
n : ℕ
nh : (y - x)⁻¹ < ↑n
z : ℤ
zh : ∀ (z_1 : ℤ), z_1 ≤ z ↔ ↑z_1 ≤ x * ↑n
n0' : 0 < ↑n
n0 : 0 < n
⊢ ↑(↑(z + 1)).den ≠ 0
case intro.intro.nn
α : Type u_1
inst✝¹ : LinearOrderedField α
inst✝ : Archimedean α
x✝ y✝ ε x y : α
h : x < y
n : ℕ
nh : (y - x)⁻¹ < ↑n
z : ℤ
zh : ∀ (z_1 : ℤ), z_1 ≤ z ↔ ↑z_1 ≤ x * ↑n
n0' : 0 < ↑n
n0 : 0 < n
⊢ ↑(↑n).num ≠ 0
case intro.intro.nd
α : Type u_1
inst✝¹ : LinearOrderedField α
inst✝ : Archimedean α
x✝ y✝ ε x y : α
h : x < y
n : ℕ
nh : (y - x)⁻¹ < ↑n
z : ℤ
zh : ∀ (z_1 : ℤ), z_1 ≤ z ↔ ↑z_1 ≤ x * ↑n
n0' : 0 < ↑n
n0 : 0 < n
⊢ ↑(↑n).den ≠ 0
[PROOFSTEP]
rwa [← lt_sub_iff_add_lt', ← sub_mul, ← div_lt_iff' (sub_pos.2 h), one_div]
[GOAL]
case intro.intro.md
α : Type u_1
inst✝¹ : LinearOrderedField α
inst✝ : Archimedean α
x✝ y✝ ε x y : α
h : x < y
n : ℕ
nh : (y - x)⁻¹ < ↑n
z : ℤ
zh : ∀ (z_1 : ℤ), z_1 ≤ z ↔ ↑z_1 ≤ x * ↑n
n0' : 0 < ↑n
n0 : 0 < n
⊢ ↑(↑(z + 1)).den ≠ 0
[PROOFSTEP]
rw [Rat.coe_int_den, Nat.cast_one]
[GOAL]
case intro.intro.md
α : Type u_1
inst✝¹ : LinearOrderedField α
inst✝ : Archimedean α
x✝ y✝ ε x y : α
h : x < y
n : ℕ
nh : (y - x)⁻¹ < ↑n
z : ℤ
zh : ∀ (z_1 : ℤ), z_1 ≤ z ↔ ↑z_1 ≤ x * ↑n
n0' : 0 < ↑n
n0 : 0 < n
⊢ 1 ≠ 0
[PROOFSTEP]
exact one_ne_zero
[GOAL]
case intro.intro.nn
α : Type u_1
inst✝¹ : LinearOrderedField α
inst✝ : Archimedean α
x✝ y✝ ε x y : α
h : x < y
n : ℕ
nh : (y - x)⁻¹ < ↑n
z : ℤ
zh : ∀ (z_1 : ℤ), z_1 ≤ z ↔ ↑z_1 ≤ x * ↑n
n0' : 0 < ↑n
n0 : 0 < n
⊢ ↑(↑n).num ≠ 0
[PROOFSTEP]
intro H
[GOAL]
case intro.intro.nn
α : Type u_1
inst✝¹ : LinearOrderedField α
inst✝ : Archimedean α
x✝ y✝ ε x y : α
h : x < y
n : ℕ
nh : (y - x)⁻¹ < ↑n
z : ℤ
zh : ∀ (z_1 : ℤ), z_1 ≤ z ↔ ↑z_1 ≤ x * ↑n
n0' : 0 < ↑n
n0 : 0 < n
H : ↑(↑n).num = 0
⊢ False
[PROOFSTEP]
rw [Rat.coe_nat_num, Int.cast_ofNat, Nat.cast_eq_zero] at H
[GOAL]
case intro.intro.nn
α : Type u_1
inst✝¹ : LinearOrderedField α
inst✝ : Archimedean α
x✝ y✝ ε x y : α
h : x < y
n : ℕ
nh : (y - x)⁻¹ < ↑n
z : ℤ
zh : ∀ (z_1 : ℤ), z_1 ≤ z ↔ ↑z_1 ≤ x * ↑n
n0' : 0 < ↑n
n0 : 0 < n
H : n = 0
⊢ False
[PROOFSTEP]
subst H
[GOAL]
case intro.intro.nn
α : Type u_1
inst✝¹ : LinearOrderedField α
inst✝ : Archimedean α
x✝ y✝ ε x y : α
h : x < y
z : ℤ
nh : (y - x)⁻¹ < ↑0
zh : ∀ (z_1 : ℤ), z_1 ≤ z ↔ ↑z_1 ≤ x * ↑0
n0' : 0 < ↑0
n0 : 0 < 0
⊢ False
[PROOFSTEP]
cases n0
[GOAL]
case intro.intro.nd
α : Type u_1
inst✝¹ : LinearOrderedField α
inst✝ : Archimedean α
x✝ y✝ ε x y : α
h : x < y
n : ℕ
nh : (y - x)⁻¹ < ↑n
z : ℤ
zh : ∀ (z_1 : ℤ), z_1 ≤ z ↔ ↑z_1 ≤ x * ↑n
n0' : 0 < ↑n
n0 : 0 < n
⊢ ↑(↑n).den ≠ 0
[PROOFSTEP]
rw [Rat.coe_nat_den, Nat.cast_one]
[GOAL]
case intro.intro.nd
α : Type u_1
inst✝¹ : LinearOrderedField α
inst✝ : Archimedean α
x✝ y✝ ε x y : α
h : x < y
n : ℕ
nh : (y - x)⁻¹ < ↑n
z : ℤ
zh : ∀ (z_1 : ℤ), z_1 ≤ z ↔ ↑z_1 ≤ x * ↑n
n0' : 0 < ↑n
n0 : 0 < n
⊢ 1 ≠ 0
[PROOFSTEP]
exact one_ne_zero
[GOAL]
α : Type u_1
inst✝¹ : LinearOrderedField α
inst✝ : Archimedean α
x y ε✝ ε : α
hε : 0 < ε
⊢ ∃ n, 1 / (↑n + 1) < ε
[PROOFSTEP]
cases' exists_nat_gt (1 / ε) with n hn
[GOAL]
case intro
α : Type u_1
inst✝¹ : LinearOrderedField α
inst✝ : Archimedean α
x y ε✝ ε : α
hε : 0 < ε
n : ℕ
hn : 1 / ε < ↑n
⊢ ∃ n, 1 / (↑n + 1) < ε
[PROOFSTEP]
use n
[GOAL]
case h
α : Type u_1
inst✝¹ : LinearOrderedField α
inst✝ : Archimedean α
x y ε✝ ε : α
hε : 0 < ε
n : ℕ
hn : 1 / ε < ↑n
⊢ 1 / (↑n + 1) < ε
[PROOFSTEP]
rw [div_lt_iff, ← div_lt_iff' hε]
[GOAL]
case h
α : Type u_1
inst✝¹ : LinearOrderedField α
inst✝ : Archimedean α
x y ε✝ ε : α
hε : 0 < ε
n : ℕ
hn : 1 / ε < ↑n
⊢ 1 / ε < ↑n + 1
[PROOFSTEP]
apply hn.trans
[GOAL]
case h
α : Type u_1
inst✝¹ : LinearOrderedField α
inst✝ : Archimedean α
x y ε✝ ε : α
hε : 0 < ε
n : ℕ
hn : 1 / ε < ↑n
⊢ ↑n < ↑n + 1
[PROOFSTEP]
simp [zero_lt_one]
[GOAL]
case h
α : Type u_1
inst✝¹ : LinearOrderedField α
inst✝ : Archimedean α
x y ε✝ ε : α
hε : 0 < ε
n : ℕ
hn : 1 / ε < ↑n
⊢ 0 < ↑n + 1
[PROOFSTEP]
exact n.cast_add_one_pos
[GOAL]
α : Type u_1
inst✝¹ : LinearOrderedField α
inst✝ : Archimedean α
x✝ y ε x : α
x0 : 0 < x
⊢ ∃ q, 0 < q ∧ ↑q < x
[PROOFSTEP]
simpa only [Rat.cast_pos] using exists_rat_btwn x0
[GOAL]
α : Type u_1
inst✝ : LinearOrderedField α
H : ∀ (x : α), ∃ n, x < ↑n
x y : α
y0 : 0 < y
n : ℕ
h : x / y < ↑n
⊢ x < n • y
[PROOFSTEP]
rwa [div_lt_iff y0, ← nsmul_eq_mul] at h
[GOAL]
α : Type u_1
inst✝ : LinearOrderedField α
⊢ (∀ (x : α), ∃ n, x < ↑n) → Archimedean α
[PROOFSTEP]
rw [archimedean_iff_nat_lt]
[GOAL]
α : Type u_1
inst✝ : LinearOrderedField α
⊢ (∀ (x : α), ∃ n, x < ↑n) → ∀ (x : α), ∃ n, x < ↑n
[PROOFSTEP]
intro h x
[GOAL]
α : Type u_1
inst✝ : LinearOrderedField α
h : ∀ (x : α), ∃ n, x < ↑n
x : α
⊢ ∃ n, x < ↑n
[PROOFSTEP]
obtain ⟨n, h⟩ := h x
[GOAL]
case intro
α : Type u_1
inst✝ : LinearOrderedField α
h✝ : ∀ (x : α), ∃ n, x < ↑n
x : α
n : ℤ
h : x < ↑n
⊢ ∃ n, x < ↑n
[PROOFSTEP]
refine' ⟨n.toNat, h.trans_le _⟩
[GOAL]
case intro
α : Type u_1
inst✝ : LinearOrderedField α
h✝ : ∀ (x : α), ∃ n, x < ↑n
x : α
n : ℤ
h : x < ↑n
⊢ ↑n ≤ ↑(toNat n)
[PROOFSTEP]
exact_mod_cast Int.self_le_toNat _
[GOAL]
α : Type u_1
inst✝ : LinearOrderedField α
H : ∀ (x : α), ∃ q, x < ↑q
x : α
q : ℚ
h : x < ↑q
⊢ ↑q ≤ ↑⌈q⌉₊
[PROOFSTEP]
simpa only [Rat.cast_coe_nat] using (@Rat.cast_le α _ _ _).2 (Nat.le_ceil _)
[GOAL]
α : Type u_1
n m : ℕ
m0 : 0 < m
⊢ n ≤ n • m
[PROOFSTEP]
rw [← mul_one n, smul_eq_mul, mul_assoc, one_mul m]
[GOAL]
α : Type u_1
n m : ℕ
m0 : 0 < m
⊢ n * 1 ≤ n * m
[PROOFSTEP]
exact Nat.mul_le_mul_left n (by linarith)
[GOAL]
α : Type u_1
n m : ℕ
m0 : 0 < m
⊢ 1 ≤ m
[PROOFSTEP]
linarith
[GOAL]
α : Type u_1
n m : ℤ
m0 : 0 < m
⊢ ↑(toNat n) ≤ toNat n • m
[PROOFSTEP]
simpa only [nsmul_eq_mul, zero_add, mul_one] using
  mul_le_mul_of_nonneg_left (Int.add_one_le_iff.2 m0) (Int.ofNat_zero_le n.toNat)
[GOAL]
α : Type u_1
q : ℚ
⊢ q ≤ ↑q
[PROOFSTEP]
rw [Rat.cast_id]
[GOAL]
α✝ : Type u_1
α : Type ?u.91487
inst✝¹ : LinearOrderedField α
inst✝ : FloorRing α
⊢ Archimedean α
[PROOFSTEP]
rw [archimedean_iff_int_le]
[GOAL]
α✝ : Type u_1
α : Type ?u.91487
inst✝¹ : LinearOrderedField α
inst✝ : FloorRing α
⊢ ∀ (x : α), ∃ n, x ≤ ↑n
[PROOFSTEP]
exact fun x => ⟨⌈x⌉, Int.le_ceil x⟩