[GOAL]
b n : ℕ
⊢ log b n = 0 ↔ n < b ∨ b ≤ 1
[PROOFSTEP]
rw [log, dite_eq_right_iff]
[GOAL]
b n : ℕ
⊢ (∀ (h : b ≤ n ∧ 1 < b),
      (let_fun this := (_ : n / b < n);
        log b (n / b) + 1) =
        0) ↔
    n < b ∨ b ≤ 1
[PROOFSTEP]
simp only [Nat.succ_ne_zero, imp_false, not_and_or, not_le, not_lt]
[GOAL]
b n : ℕ
⊢ 0 < log b n ↔ b ≤ n ∧ 1 < b
[PROOFSTEP]
rw [pos_iff_ne_zero, Ne.def, log_eq_zero_iff, not_or, not_lt, not_le]
[GOAL]
b n : ℕ
h : 1 < b
hn : b ≤ n
⊢ log b n = log b (n / b) + 1
[PROOFSTEP]
rw [log]
[GOAL]
b n : ℕ
h : 1 < b
hn : b ≤ n
⊢ (if h : b ≤ n ∧ 1 < b then
      let_fun this := (_ : n / b < n);
      log b (n / b) + 1
    else 0) =
    log b (n / b) + 1
[PROOFSTEP]
exact if_pos ⟨hn, h⟩
[GOAL]
b : ℕ
hb : 1 < b
x y : ℕ
hy : y ≠ 0
⊢ b ^ x ≤ y ↔ x ≤ log b y
[PROOFSTEP]
induction' y using Nat.strong_induction_on with y ih generalizing x
[GOAL]
case h
b : ℕ
hb : 1 < b
x✝ y✝ : ℕ
hy✝ : y✝ ≠ 0
y : ℕ
ih : ∀ (m : ℕ), m < y → ∀ {x : ℕ}, m ≠ 0 → (b ^ x ≤ m ↔ x ≤ log b m)
x : ℕ
hy : y ≠ 0
⊢ b ^ x ≤ y ↔ x ≤ log b y
[PROOFSTEP]
cases x with
| zero => exact iff_of_true hy.bot_lt (zero_le _)
| succ x =>
  rw [log]; split_ifs with h
  · have b_pos : 0 < b := zero_le_one.trans_lt hb
    rw [succ_eq_add_one, add_le_add_iff_right, ← ih (y / b) (div_lt_self hy.bot_lt hb) (Nat.div_pos h.1 b_pos).ne',
      le_div_iff_mul_le b_pos, pow_succ', mul_comm]
  · exact iff_of_false (fun hby => h ⟨(le_self_pow x.succ_ne_zero _).trans hby, hb⟩) (not_succ_le_zero _)
[GOAL]
case h
b : ℕ
hb : 1 < b
x✝ y✝ : ℕ
hy✝ : y✝ ≠ 0
y : ℕ
ih : ∀ (m : ℕ), m < y → ∀ {x : ℕ}, m ≠ 0 → (b ^ x ≤ m ↔ x ≤ log b m)
x : ℕ
hy : y ≠ 0
⊢ b ^ x ≤ y ↔ x ≤ log b y
[PROOFSTEP]
cases x with
| zero => exact iff_of_true hy.bot_lt (zero_le _)
| succ x =>
  rw [log]; split_ifs with h
  · have b_pos : 0 < b := zero_le_one.trans_lt hb
    rw [succ_eq_add_one, add_le_add_iff_right, ← ih (y / b) (div_lt_self hy.bot_lt hb) (Nat.div_pos h.1 b_pos).ne',
      le_div_iff_mul_le b_pos, pow_succ', mul_comm]
  · exact iff_of_false (fun hby => h ⟨(le_self_pow x.succ_ne_zero _).trans hby, hb⟩) (not_succ_le_zero _)
[GOAL]
case h.zero
b : ℕ
hb : 1 < b
x y✝ : ℕ
hy✝ : y✝ ≠ 0
y : ℕ
ih : ∀ (m : ℕ), m < y → ∀ {x : ℕ}, m ≠ 0 → (b ^ x ≤ m ↔ x ≤ log b m)
hy : y ≠ 0
⊢ b ^ zero ≤ y ↔ zero ≤ log b y
[PROOFSTEP]

| zero => exact iff_of_true hy.bot_lt (zero_le _)
[GOAL]
case h.zero
b : ℕ
hb : 1 < b
x y✝ : ℕ
hy✝ : y✝ ≠ 0
y : ℕ
ih : ∀ (m : ℕ), m < y → ∀ {x : ℕ}, m ≠ 0 → (b ^ x ≤ m ↔ x ≤ log b m)
hy : y ≠ 0
⊢ b ^ zero ≤ y ↔ zero ≤ log b y
[PROOFSTEP]
exact iff_of_true hy.bot_lt (zero_le _)
[GOAL]
case h.succ
b : ℕ
hb : 1 < b
x✝ y✝ : ℕ
hy✝ : y✝ ≠ 0
y : ℕ
ih : ∀ (m : ℕ), m < y → ∀ {x : ℕ}, m ≠ 0 → (b ^ x ≤ m ↔ x ≤ log b m)
hy : y ≠ 0
x : ℕ
⊢ b ^ succ x ≤ y ↔ succ x ≤ log b y
[PROOFSTEP]

| succ x =>
  rw [log]; split_ifs with h
  · have b_pos : 0 < b := zero_le_one.trans_lt hb
    rw [succ_eq_add_one, add_le_add_iff_right, ← ih (y / b) (div_lt_self hy.bot_lt hb) (Nat.div_pos h.1 b_pos).ne',
      le_div_iff_mul_le b_pos, pow_succ', mul_comm]
  · exact iff_of_false (fun hby => h ⟨(le_self_pow x.succ_ne_zero _).trans hby, hb⟩) (not_succ_le_zero _)
[GOAL]
case h.succ
b : ℕ
hb : 1 < b
x✝ y✝ : ℕ
hy✝ : y✝ ≠ 0
y : ℕ
ih : ∀ (m : ℕ), m < y → ∀ {x : ℕ}, m ≠ 0 → (b ^ x ≤ m ↔ x ≤ log b m)
hy : y ≠ 0
x : ℕ
⊢ b ^ succ x ≤ y ↔ succ x ≤ log b y
[PROOFSTEP]
rw [log]
[GOAL]
case h.succ
b : ℕ
hb : 1 < b
x✝ y✝ : ℕ
hy✝ : y✝ ≠ 0
y : ℕ
ih : ∀ (m : ℕ), m < y → ∀ {x : ℕ}, m ≠ 0 → (b ^ x ≤ m ↔ x ≤ log b m)
hy : y ≠ 0
x : ℕ
⊢ b ^ succ x ≤ y ↔
    succ x ≤
      if h : b ≤ y ∧ 1 < b then
        let_fun this := (_ : y / b < y);
        log b (y / b) + 1
      else 0
[PROOFSTEP]
split_ifs with h
[GOAL]
case pos
b : ℕ
hb : 1 < b
x✝ y✝ : ℕ
hy✝ : y✝ ≠ 0
y : ℕ
ih : ∀ (m : ℕ), m < y → ∀ {x : ℕ}, m ≠ 0 → (b ^ x ≤ m ↔ x ≤ log b m)
hy : y ≠ 0
x : ℕ
h : b ≤ y ∧ 1 < b
⊢ b ^ succ x ≤ y ↔
    succ x ≤
      let_fun this := (_ : y / b < y);
      log b (y / b) + 1
[PROOFSTEP]
have b_pos : 0 < b := zero_le_one.trans_lt hb
[GOAL]
case pos
b : ℕ
hb : 1 < b
x✝ y✝ : ℕ
hy✝ : y✝ ≠ 0
y : ℕ
ih : ∀ (m : ℕ), m < y → ∀ {x : ℕ}, m ≠ 0 → (b ^ x ≤ m ↔ x ≤ log b m)
hy : y ≠ 0
x : ℕ
h : b ≤ y ∧ 1 < b
b_pos : 0 < b
⊢ b ^ succ x ≤ y ↔
    succ x ≤
      let_fun this := (_ : y / b < y);
      log b (y / b) + 1
[PROOFSTEP]
rw [succ_eq_add_one, add_le_add_iff_right, ← ih (y / b) (div_lt_self hy.bot_lt hb) (Nat.div_pos h.1 b_pos).ne',
  le_div_iff_mul_le b_pos, pow_succ', mul_comm]
[GOAL]
case neg
b : ℕ
hb : 1 < b
x✝ y✝ : ℕ
hy✝ : y✝ ≠ 0
y : ℕ
ih : ∀ (m : ℕ), m < y → ∀ {x : ℕ}, m ≠ 0 → (b ^ x ≤ m ↔ x ≤ log b m)
hy : y ≠ 0
x : ℕ
h : ¬(b ≤ y ∧ 1 < b)
⊢ b ^ succ x ≤ y ↔ succ x ≤ 0
[PROOFSTEP]
exact iff_of_false (fun hby => h ⟨(le_self_pow x.succ_ne_zero _).trans hby, hb⟩) (not_succ_le_zero _)
[GOAL]
b x y : ℕ
hy : y ≠ 0
h : x ≤ log b y
⊢ b ^ x ≤ y
[PROOFSTEP]
refine' (le_or_lt b 1).elim (fun hb => _) fun hb => (pow_le_iff_le_log hb hy).2 h
[GOAL]
b x y : ℕ
hy : y ≠ 0
h : x ≤ log b y
hb : b ≤ 1
⊢ b ^ x ≤ y
[PROOFSTEP]
rw [log_of_left_le_one hb, nonpos_iff_eq_zero] at h
[GOAL]
b x y : ℕ
hy : y ≠ 0
h : x = 0
hb : b ≤ 1
⊢ b ^ x ≤ y
[PROOFSTEP]
rwa [h, pow_zero, one_le_iff_ne_zero]
[GOAL]
b x y : ℕ
hb : 1 < b
h : b ^ x ≤ y
⊢ x ≤ log b y
[PROOFSTEP]
rcases ne_or_eq y 0 with (hy | rfl)
[GOAL]
case inl
b x y : ℕ
hb : 1 < b
h : b ^ x ≤ y
hy : y ≠ 0
⊢ x ≤ log b y
case inr b x : ℕ hb : 1 < b h : b ^ x ≤ 0 ⊢ x ≤ log b 0
[PROOFSTEP]
exacts [(pow_le_iff_le_log hb hy).1 h, (h.not_lt (pow_pos (zero_lt_one.trans hb) _)).elim]
[GOAL]
b m n : ℕ
h : m ≠ 0 ∨ 1 < b ∧ n ≠ 0
⊢ log b n = m ↔ b ^ m ≤ n ∧ n < b ^ (m + 1)
[PROOFSTEP]
rcases em (1 < b ∧ n ≠ 0) with (⟨hb, hn⟩ | hbn)
[GOAL]
case inl.intro
b m n : ℕ
h : m ≠ 0 ∨ 1 < b ∧ n ≠ 0
hb : 1 < b
hn : n ≠ 0
⊢ log b n = m ↔ b ^ m ≤ n ∧ n < b ^ (m + 1)
[PROOFSTEP]
rw [le_antisymm_iff, ← lt_succ_iff, ← pow_le_iff_le_log, ← lt_pow_iff_log_lt, and_comm]
[GOAL]
case inl.intro.hb
b m n : ℕ
h : m ≠ 0 ∨ 1 < b ∧ n ≠ 0
hb : 1 < b
hn : n ≠ 0
⊢ 1 < b
[PROOFSTEP]
assumption
[GOAL]
case inl.intro.hy
b m n : ℕ
h : m ≠ 0 ∨ 1 < b ∧ n ≠ 0
hb : 1 < b
hn : n ≠ 0
⊢ n ≠ 0
[PROOFSTEP]
assumption
[GOAL]
case inl.intro.hb
b m n : ℕ
h : m ≠ 0 ∨ 1 < b ∧ n ≠ 0
hb : 1 < b
hn : n ≠ 0
⊢ 1 < b
[PROOFSTEP]
assumption
[GOAL]
case inl.intro.hy
b m n : ℕ
h : m ≠ 0 ∨ 1 < b ∧ n ≠ 0
hb : 1 < b
hn : n ≠ 0
⊢ n ≠ 0
[PROOFSTEP]
assumption
[GOAL]
case inr
b m n : ℕ
h : m ≠ 0 ∨ 1 < b ∧ n ≠ 0
hbn : ¬(1 < b ∧ n ≠ 0)
⊢ log b n = m ↔ b ^ m ≤ n ∧ n < b ^ (m + 1)
[PROOFSTEP]
have hm : m ≠ 0 := h.resolve_right hbn
[GOAL]
case inr
b m n : ℕ
h : m ≠ 0 ∨ 1 < b ∧ n ≠ 0
hbn : ¬(1 < b ∧ n ≠ 0)
hm : m ≠ 0
⊢ log b n = m ↔ b ^ m ≤ n ∧ n < b ^ (m + 1)
[PROOFSTEP]
rw [not_and_or, not_lt, Ne.def, not_not] at hbn
[GOAL]
case inr
b m n : ℕ
h : m ≠ 0 ∨ 1 < b ∧ n ≠ 0
hbn : b ≤ 1 ∨ n = 0
hm : m ≠ 0
⊢ log b n = m ↔ b ^ m ≤ n ∧ n < b ^ (m + 1)
[PROOFSTEP]
rcases hbn with (hb | rfl)
[GOAL]
case inr.inl
b m n : ℕ
h : m ≠ 0 ∨ 1 < b ∧ n ≠ 0
hm : m ≠ 0
hb : b ≤ 1
⊢ log b n = m ↔ b ^ m ≤ n ∧ n < b ^ (m + 1)
[PROOFSTEP]
simpa only [log_of_left_le_one hb, hm.symm, false_iff_iff, not_and, not_lt] using
  le_trans (pow_le_pow_of_le_one' hb m.le_succ)
[GOAL]
case inr.inr
b m : ℕ
hm : m ≠ 0
h : m ≠ 0 ∨ 1 < b ∧ 0 ≠ 0
⊢ log b 0 = m ↔ b ^ m ≤ 0 ∧ 0 < b ^ (m + 1)
[PROOFSTEP]
simpa only [log_zero_right, hm.symm, nonpos_iff_eq_zero, false_iff, not_and, not_lt, add_pos_iff, or_true,
  pow_eq_zero_iff] using pow_eq_zero
[GOAL]
b m n : ℕ
h₁ : b ^ m ≤ n
h₂ : n < b ^ (m + 1)
⊢ log b n = m
[PROOFSTEP]
rcases eq_or_ne m 0 with (rfl | hm)
[GOAL]
case inl
b n : ℕ
h₁ : b ^ 0 ≤ n
h₂ : n < b ^ (0 + 1)
⊢ log b n = 0
[PROOFSTEP]
rw [pow_one] at h₂
[GOAL]
case inl
b n : ℕ
h₁ : b ^ 0 ≤ n
h₂ : n < b
⊢ log b n = 0
[PROOFSTEP]
exact log_of_lt h₂
[GOAL]
case inr
b m n : ℕ
h₁ : b ^ m ≤ n
h₂ : n < b ^ (m + 1)
hm : m ≠ 0
⊢ log b n = m
[PROOFSTEP]
exact (log_eq_iff (Or.inl hm)).2 ⟨h₁, h₂⟩
[GOAL]
b n : ℕ
⊢ log b n = 1 ↔ b ≤ n ∧ n < b * b
[PROOFSTEP]
rw [log_eq_iff (Or.inl one_ne_zero), pow_add, pow_one]
[GOAL]
b n : ℕ
hb : 1 < b
hn : n ≠ 0
⊢ log b (n * b) = log b n + 1
[PROOFSTEP]
apply log_eq_of_pow_le_of_lt_pow
[GOAL]
case h₁
b n : ℕ
hb : 1 < b
hn : n ≠ 0
⊢ b ^ (log b n + 1) ≤ n * b
[PROOFSTEP]
rw [pow_succ', mul_comm b]
[GOAL]
case h₂
b n : ℕ
hb : 1 < b
hn : n ≠ 0
⊢ n * b < b ^ (log b n + 1 + 1)
[PROOFSTEP]
rw [pow_succ', mul_comm b]
[GOAL]
case h₁
b n : ℕ
hb : 1 < b
hn : n ≠ 0
⊢ b ^ log b n * b ≤ n * b
case h₂ b n : ℕ hb : 1 < b hn : n ≠ 0 ⊢ n * b < b ^ (log b n + 1) * b
[PROOFSTEP]
exacts [mul_le_mul_right' (pow_log_le_self _ hn) _,
  (mul_lt_mul_right (zero_lt_one.trans hb)).2 (lt_pow_succ_log_self hb _)]
[GOAL]
b : ℕ
⊢ b ^ log b 0 ≤ 0 + 1
[PROOFSTEP]
rw [log_zero_right, pow_zero]
[GOAL]
b : ℕ
⊢ Monotone (log b)
[PROOFSTEP]
refine' monotone_nat_of_le_succ fun n => _
[GOAL]
b n : ℕ
⊢ log b n ≤ log b (n + 1)
[PROOFSTEP]
cases' le_or_lt b 1 with hb hb
[GOAL]
case inl
b n : ℕ
hb : b ≤ 1
⊢ log b n ≤ log b (n + 1)
[PROOFSTEP]
rw [log_of_left_le_one hb]
[GOAL]
case inl
b n : ℕ
hb : b ≤ 1
⊢ 0 ≤ log b (n + 1)
[PROOFSTEP]
exact zero_le _
[GOAL]
case inr
b n : ℕ
hb : 1 < b
⊢ log b n ≤ log b (n + 1)
[PROOFSTEP]
exact le_log_of_pow_le hb (pow_log_le_add_one _ _)
[GOAL]
b c n : ℕ
hc : 1 < c
hb : c ≤ b
⊢ log b n ≤ log c n
[PROOFSTEP]
rcases eq_or_ne n 0 with (rfl | hn)
[GOAL]
case inl
b c : ℕ
hc : 1 < c
hb : c ≤ b
⊢ log b 0 ≤ log c 0
[PROOFSTEP]
rw [log_zero_right, log_zero_right]
[GOAL]
case inr
b c n : ℕ
hc : 1 < c
hb : c ≤ b
hn : n ≠ 0
⊢ log b n ≤ log c n
[PROOFSTEP]
apply le_log_of_pow_le hc
[GOAL]
case inr
b c n : ℕ
hc : 1 < c
hb : c ≤ b
hn : n ≠ 0
⊢ c ^ log b n ≤ n
[PROOFSTEP]
calc
  c ^ log b n ≤ b ^ log b n := pow_le_pow_of_le_left' hb _
  _ ≤ n := pow_log_le_self _ hn
[GOAL]
b n : ℕ
⊢ log b (n / b) = log b n - 1
[PROOFSTEP]
cases' le_or_lt b 1 with hb hb
[GOAL]
case inl
b n : ℕ
hb : b ≤ 1
⊢ log b (n / b) = log b n - 1
[PROOFSTEP]
rw [log_of_left_le_one hb, log_of_left_le_one hb, Nat.zero_sub]
[GOAL]
case inr
b n : ℕ
hb : 1 < b
⊢ log b (n / b) = log b n - 1
[PROOFSTEP]
cases' lt_or_le n b with h h
[GOAL]
case inr.inl
b n : ℕ
hb : 1 < b
h : n < b
⊢ log b (n / b) = log b n - 1
[PROOFSTEP]
rw [div_eq_of_lt h, log_of_lt h, log_zero_right]
[GOAL]
case inr.inr
b n : ℕ
hb : 1 < b
h : b ≤ n
⊢ log b (n / b) = log b n - 1
[PROOFSTEP]
rw [log_of_one_lt_of_le hb h, add_tsub_cancel_right]
[GOAL]
b n : ℕ
⊢ log b (n / b * b) = log b n
[PROOFSTEP]
cases' le_or_lt b 1 with hb hb
[GOAL]
case inl
b n : ℕ
hb : b ≤ 1
⊢ log b (n / b * b) = log b n
[PROOFSTEP]
rw [log_of_left_le_one hb, log_of_left_le_one hb]
[GOAL]
case inr
b n : ℕ
hb : 1 < b
⊢ log b (n / b * b) = log b n
[PROOFSTEP]
cases' lt_or_le n b with h h
[GOAL]
case inr.inl
b n : ℕ
hb : 1 < b
h : n < b
⊢ log b (n / b * b) = log b n
[PROOFSTEP]
rw [div_eq_of_lt h, zero_mul, log_zero_right, log_of_lt h]
[GOAL]
case inr.inr
b n : ℕ
hb : 1 < b
h : b ≤ n
⊢ log b (n / b * b) = log b n
[PROOFSTEP]
rw [log_mul_base hb (Nat.div_pos h (zero_le_one.trans_lt hb)).ne', log_div_base,
  tsub_add_cancel_of_le (succ_le_iff.2 <| log_pos hb h)]
[GOAL]
b n : ℕ
hb : 1 < b
hn : 2 ≤ n
⊢ (n + b - 1) / b < n
[PROOFSTEP]
rw [div_lt_iff_lt_mul (zero_lt_one.trans hb), ← succ_le_iff, ← pred_eq_sub_one,
  succ_pred_eq_of_pos (add_pos (zero_lt_one.trans hn) (zero_lt_one.trans hb))]
[GOAL]
b n : ℕ
hb : 1 < b
hn : 2 ≤ n
⊢ n + b ≤ n * b
[PROOFSTEP]
exact add_le_mul hn hb
[GOAL]
b : ℕ
hb : b ≤ 1
n : ℕ
⊢ clog b n = 0
[PROOFSTEP]
rw [clog, dif_neg fun h : 1 < b ∧ 1 < n => h.1.not_le hb]
[GOAL]
n : ℕ
hn : n ≤ 1
b : ℕ
⊢ clog b n = 0
[PROOFSTEP]
rw [clog, dif_neg fun h : 1 < b ∧ 1 < n => h.2.not_le hn]
[GOAL]
b n : ℕ
hb : 1 < b
hn : 2 ≤ n
⊢ clog b n = clog b ((n + b - 1) / b) + 1
[PROOFSTEP]
rw [clog, dif_pos (⟨hb, hn⟩ : 1 < b ∧ 1 < n)]
[GOAL]
b n : ℕ
hb : 1 < b
hn : 2 ≤ n
⊢ 0 < clog b n
[PROOFSTEP]
rw [clog_of_two_le hb hn]
[GOAL]
b n : ℕ
hb : 1 < b
hn : 2 ≤ n
⊢ 0 < clog b ((n + b - 1) / b) + 1
[PROOFSTEP]
exact zero_lt_succ _
[GOAL]
b n : ℕ
hn : 2 ≤ n
h : n ≤ b
⊢ clog b n = 1
[PROOFSTEP]
rw [clog_of_two_le (hn.trans h) hn, clog_of_right_le_one]
[GOAL]
case hn
b n : ℕ
hn : 2 ≤ n
h : n ≤ b
⊢ (n + b - 1) / b ≤ 1
[PROOFSTEP]
have n_pos : 0 < n := (zero_lt_two' ℕ).trans_le hn
[GOAL]
case hn
b n : ℕ
hn : 2 ≤ n
h : n ≤ b
n_pos : 0 < n
⊢ (n + b - 1) / b ≤ 1
[PROOFSTEP]
rw [← lt_succ_iff, Nat.div_lt_iff_lt_mul (n_pos.trans_le h), ← succ_le_iff, ← pred_eq_sub_one,
  succ_pred_eq_of_pos (add_pos n_pos (n_pos.trans_le h)), succ_mul, one_mul]
[GOAL]
case hn
b n : ℕ
hn : 2 ≤ n
h : n ≤ b
n_pos : 0 < n
⊢ n + b ≤ b + b
[PROOFSTEP]
exact add_le_add_right h _
[GOAL]
b : ℕ
hb : 1 < b
x y : ℕ
⊢ x ≤ b ^ y ↔ clog b x ≤ y
[PROOFSTEP]
induction' x using Nat.strong_induction_on with x ih generalizing y
[GOAL]
case h
b : ℕ
hb : 1 < b
y✝ x : ℕ
ih : ∀ (m : ℕ), m < x → ∀ {y : ℕ}, m ≤ b ^ y ↔ clog b m ≤ y
y : ℕ
⊢ x ≤ b ^ y ↔ clog b x ≤ y
[PROOFSTEP]
cases y
[GOAL]
case h.zero
b : ℕ
hb : 1 < b
y x : ℕ
ih : ∀ (m : ℕ), m < x → ∀ {y : ℕ}, m ≤ b ^ y ↔ clog b m ≤ y
⊢ x ≤ b ^ zero ↔ clog b x ≤ zero
[PROOFSTEP]
rw [pow_zero]
[GOAL]
case h.zero
b : ℕ
hb : 1 < b
y x : ℕ
ih : ∀ (m : ℕ), m < x → ∀ {y : ℕ}, m ≤ b ^ y ↔ clog b m ≤ y
⊢ x ≤ 1 ↔ clog b x ≤ zero
[PROOFSTEP]
refine' ⟨fun h => (clog_of_right_le_one h b).le, _⟩
[GOAL]
case h.zero
b : ℕ
hb : 1 < b
y x : ℕ
ih : ∀ (m : ℕ), m < x → ∀ {y : ℕ}, m ≤ b ^ y ↔ clog b m ≤ y
⊢ clog b x ≤ zero → x ≤ 1
[PROOFSTEP]
simp_rw [← not_lt]
[GOAL]
case h.zero
b : ℕ
hb : 1 < b
y x : ℕ
ih : ∀ (m : ℕ), m < x → ∀ {y : ℕ}, m ≤ b ^ y ↔ clog b m ≤ y
⊢ ¬zero < clog b x → ¬1 < x
[PROOFSTEP]
contrapose!
[GOAL]
case h.zero
b : ℕ
hb : 1 < b
y x : ℕ
ih : ∀ (m : ℕ), m < x → ∀ {y : ℕ}, m ≤ b ^ y ↔ clog b m ≤ y
⊢ 1 < x → zero < clog b x
[PROOFSTEP]
exact clog_pos hb
[GOAL]
case h.succ
b : ℕ
hb : 1 < b
y x : ℕ
ih : ∀ (m : ℕ), m < x → ∀ {y : ℕ}, m ≤ b ^ y ↔ clog b m ≤ y
n✝ : ℕ
⊢ x ≤ b ^ succ n✝ ↔ clog b x ≤ succ n✝
[PROOFSTEP]
have b_pos : 0 < b := (zero_lt_one' ℕ).trans hb
[GOAL]
case h.succ
b : ℕ
hb : 1 < b
y x : ℕ
ih : ∀ (m : ℕ), m < x → ∀ {y : ℕ}, m ≤ b ^ y ↔ clog b m ≤ y
n✝ : ℕ
b_pos : 0 < b
⊢ x ≤ b ^ succ n✝ ↔ clog b x ≤ succ n✝
[PROOFSTEP]
rw [clog]
[GOAL]
case h.succ
b : ℕ
hb : 1 < b
y x : ℕ
ih : ∀ (m : ℕ), m < x → ∀ {y : ℕ}, m ≤ b ^ y ↔ clog b m ≤ y
n✝ : ℕ
b_pos : 0 < b
⊢ x ≤ b ^ succ n✝ ↔
    (if h : 1 < b ∧ 1 < x then
        let_fun this := (_ : (x + b - 1) / b < x);
        clog b ((x + b - 1) / b) + 1
      else 0) ≤
      succ n✝
[PROOFSTEP]
split_ifs with h
[GOAL]
case pos
b : ℕ
hb : 1 < b
y x : ℕ
ih : ∀ (m : ℕ), m < x → ∀ {y : ℕ}, m ≤ b ^ y ↔ clog b m ≤ y
n✝ : ℕ
b_pos : 0 < b
h : 1 < b ∧ 1 < x
⊢ x ≤ b ^ succ n✝ ↔
    (let_fun this := (_ : (x + b - 1) / b < x);
      clog b ((x + b - 1) / b) + 1) ≤
      succ n✝
[PROOFSTEP]
rw [succ_eq_add_one, add_le_add_iff_right, ← ih ((x + b - 1) / b) (add_pred_div_lt hb h.2),
  Nat.div_le_iff_le_mul_add_pred b_pos, mul_comm b, ← pow_succ, add_tsub_assoc_of_le (Nat.succ_le_of_lt b_pos),
  add_le_add_iff_right]
[GOAL]
case neg
b : ℕ
hb : 1 < b
y x : ℕ
ih : ∀ (m : ℕ), m < x → ∀ {y : ℕ}, m ≤ b ^ y ↔ clog b m ≤ y
n✝ : ℕ
b_pos : 0 < b
h : ¬(1 < b ∧ 1 < x)
⊢ x ≤ b ^ succ n✝ ↔ 0 ≤ succ n✝
[PROOFSTEP]
exact iff_of_true ((not_lt.1 (not_and.1 h hb)).trans <| succ_le_of_lt <| pow_pos b_pos _) (zero_le _)
[GOAL]
b x : ℕ
hb : 1 < b
z : ℕ
⊢ clog b (b ^ x) ≤ z ↔ x ≤ z
[PROOFSTEP]
rw [← le_pow_iff_clog_le hb]
[GOAL]
b x : ℕ
hb : 1 < b
z : ℕ
⊢ b ^ x ≤ b ^ z ↔ x ≤ z
[PROOFSTEP]
exact (pow_right_strictMono hb).le_iff_le
[GOAL]
b : ℕ
hb : 1 < b
x : ℕ
hx : 1 < x
⊢ b ^ pred (clog b x) < x
[PROOFSTEP]
rw [← not_le, le_pow_iff_clog_le hb, not_le]
[GOAL]
b : ℕ
hb : 1 < b
x : ℕ
hx : 1 < x
⊢ pred (clog b x) < clog b x
[PROOFSTEP]
exact pred_lt (clog_pos hb hx).ne'
[GOAL]
b n m : ℕ
h : n ≤ m
⊢ clog b n ≤ clog b m
[PROOFSTEP]
cases' le_or_lt b 1 with hb hb
[GOAL]
case inl
b n m : ℕ
h : n ≤ m
hb : b ≤ 1
⊢ clog b n ≤ clog b m
[PROOFSTEP]
rw [clog_of_left_le_one hb]
[GOAL]
case inl
b n m : ℕ
h : n ≤ m
hb : b ≤ 1
⊢ 0 ≤ clog b m
[PROOFSTEP]
exact zero_le _
[GOAL]
case inr
b n m : ℕ
h : n ≤ m
hb : 1 < b
⊢ clog b n ≤ clog b m
[PROOFSTEP]
rw [← le_pow_iff_clog_le hb]
[GOAL]
case inr
b n m : ℕ
h : n ≤ m
hb : 1 < b
⊢ n ≤ b ^ clog b m
[PROOFSTEP]
exact h.trans (le_pow_clog hb _)
[GOAL]
b c n : ℕ
hc : 1 < c
hb : c ≤ b
⊢ clog b n ≤ clog c n
[PROOFSTEP]
rw [← le_pow_iff_clog_le (lt_of_lt_of_le hc hb)]
[GOAL]
b c n : ℕ
hc : 1 < c
hb : c ≤ b
⊢ n ≤ b ^ clog c n
[PROOFSTEP]
calc
  n ≤ c ^ clog c n := le_pow_clog hc _
  _ ≤ b ^ clog c n := pow_le_pow_of_le_left hb _
[GOAL]
b n : ℕ
⊢ log b n ≤ clog b n
[PROOFSTEP]
obtain hb | hb := le_or_lt b 1
[GOAL]
case inl
b n : ℕ
hb : b ≤ 1
⊢ log b n ≤ clog b n
[PROOFSTEP]
rw [log_of_left_le_one hb]
[GOAL]
case inl
b n : ℕ
hb : b ≤ 1
⊢ 0 ≤ clog b n
[PROOFSTEP]
exact zero_le _
[GOAL]
case inr
b n : ℕ
hb : 1 < b
⊢ log b n ≤ clog b n
[PROOFSTEP]
cases n with
| zero =>
  rw [log_zero_right]
  exact zero_le _
| succ n => exact (pow_right_strictMono hb).le_iff_le.1 ((pow_log_le_self b n.succ_ne_zero).trans <| le_pow_clog hb _)
[GOAL]
case inr
b n : ℕ
hb : 1 < b
⊢ log b n ≤ clog b n
[PROOFSTEP]
cases n with
| zero =>
  rw [log_zero_right]
  exact zero_le _
| succ n => exact (pow_right_strictMono hb).le_iff_le.1 ((pow_log_le_self b n.succ_ne_zero).trans <| le_pow_clog hb _)
[GOAL]
case inr.zero
b : ℕ
hb : 1 < b
⊢ log b zero ≤ clog b zero
[PROOFSTEP]

| zero =>
  rw [log_zero_right]
  exact zero_le _
[GOAL]
case inr.zero
b : ℕ
hb : 1 < b
⊢ log b zero ≤ clog b zero
[PROOFSTEP]
rw [log_zero_right]
[GOAL]
case inr.zero
b : ℕ
hb : 1 < b
⊢ 0 ≤ clog b zero
[PROOFSTEP]
exact zero_le _
[GOAL]
case inr.succ
b : ℕ
hb : 1 < b
n : ℕ
⊢ log b (succ n) ≤ clog b (succ n)
[PROOFSTEP]

| succ n => exact (pow_right_strictMono hb).le_iff_le.1 ((pow_log_le_self b n.succ_ne_zero).trans <| le_pow_clog hb _)
[GOAL]
case inr.succ
b : ℕ
hb : 1 < b
n : ℕ
⊢ log b (succ n) ≤ clog b (succ n)
[PROOFSTEP]
exact (pow_right_strictMono hb).le_iff_le.1 ((pow_log_le_self b n.succ_ne_zero).trans <| le_pow_clog hb _)


[GOAL]
p : ℕ
R : Type u_1
inst✝¹ : CommRing R
inst✝ : DecidableEq R
n : ℕ
⊢ wittPolynomial p R n = ∑ i in range (n + 1), ↑C (↑p ^ i) * X i ^ p ^ (n - i)
[PROOFSTEP]
apply sum_congr rfl
[GOAL]
p : ℕ
R : Type u_1
inst✝¹ : CommRing R
inst✝ : DecidableEq R
n : ℕ
⊢ ∀ (x : ℕ), x ∈ range (n + 1) → ↑(monomial (single x (p ^ (n - x)))) (↑p ^ x) = ↑C (↑p ^ x) * X x ^ p ^ (n - x)
[PROOFSTEP]
rintro i -
[GOAL]
p : ℕ
R : Type u_1
inst✝¹ : CommRing R
inst✝ : DecidableEq R
n i : ℕ
⊢ ↑(monomial (single i (p ^ (n - i)))) (↑p ^ i) = ↑C (↑p ^ i) * X i ^ p ^ (n - i)
[PROOFSTEP]
rw [monomial_eq, Finsupp.prod_single_index]
[GOAL]
p : ℕ
R : Type u_1
inst✝¹ : CommRing R
inst✝ : DecidableEq R
n i : ℕ
⊢ X i ^ 0 = 1
[PROOFSTEP]
rw [pow_zero]
[GOAL]
p : ℕ
R : Type u_1
inst✝² : CommRing R
inst✝¹ : DecidableEq R
S : Type u_2
inst✝ : CommRing S
f : R →+* S
n : ℕ
⊢ ↑(map f) (W_ R n) = W_ S n
[PROOFSTEP]
rw [wittPolynomial, map_sum, wittPolynomial]
[GOAL]
p : ℕ
R : Type u_1
inst✝² : CommRing R
inst✝¹ : DecidableEq R
S : Type u_2
inst✝ : CommRing S
f : R →+* S
n : ℕ
⊢ ∑ x in range (n + 1), ↑(map f) (↑(monomial (single x (p ^ (n - x)))) (↑p ^ x)) =
    ∑ i in range (n + 1), ↑(monomial (single i (p ^ (n - i)))) (↑p ^ i)
[PROOFSTEP]
refine sum_congr rfl fun i _ => ?_
[GOAL]
p : ℕ
R : Type u_1
inst✝² : CommRing R
inst✝¹ : DecidableEq R
S : Type u_2
inst✝ : CommRing S
f : R →+* S
n i : ℕ
x✝ : i ∈ range (n + 1)
⊢ ↑(map f) (↑(monomial (single i (p ^ (n - i)))) (↑p ^ i)) = ↑(monomial (single i (p ^ (n - i)))) (↑p ^ i)
[PROOFSTEP]
rw [map_monomial, RingHom.map_pow, map_natCast]
[GOAL]
p : ℕ
R : Type u_1
inst✝² : CommRing R
inst✝¹ : DecidableEq R
S : Type u_2
inst✝ : CommRing S
hp : Fact (Nat.Prime p)
n : ℕ
⊢ ↑constantCoeff (W_ R n) = 0
[PROOFSTEP]
simp only [wittPolynomial, map_sum, constantCoeff_monomial]
[GOAL]
p : ℕ
R : Type u_1
inst✝² : CommRing R
inst✝¹ : DecidableEq R
S : Type u_2
inst✝ : CommRing S
hp : Fact (Nat.Prime p)
n : ℕ
⊢ (∑ x in range (n + 1), if single x (p ^ (n - x)) = 0 then ↑p ^ x else 0) = 0
[PROOFSTEP]
rw [sum_eq_zero]
[GOAL]
p : ℕ
R : Type u_1
inst✝² : CommRing R
inst✝¹ : DecidableEq R
S : Type u_2
inst✝ : CommRing S
hp : Fact (Nat.Prime p)
n : ℕ
⊢ ∀ (x : ℕ), x ∈ range (n + 1) → (if single x (p ^ (n - x)) = 0 then ↑p ^ x else 0) = 0
[PROOFSTEP]
rintro i _
[GOAL]
p : ℕ
R : Type u_1
inst✝² : CommRing R
inst✝¹ : DecidableEq R
S : Type u_2
inst✝ : CommRing S
hp : Fact (Nat.Prime p)
n i : ℕ
a✝ : i ∈ range (n + 1)
⊢ (if single i (p ^ (n - i)) = 0 then ↑p ^ i else 0) = 0
[PROOFSTEP]
rw [if_neg]
[GOAL]
case hnc
p : ℕ
R : Type u_1
inst✝² : CommRing R
inst✝¹ : DecidableEq R
S : Type u_2
inst✝ : CommRing S
hp : Fact (Nat.Prime p)
n i : ℕ
a✝ : i ∈ range (n + 1)
⊢ ¬single i (p ^ (n - i)) = 0
[PROOFSTEP]
rw [Finsupp.single_eq_zero]
[GOAL]
case hnc
p : ℕ
R : Type u_1
inst✝² : CommRing R
inst✝¹ : DecidableEq R
S : Type u_2
inst✝ : CommRing S
hp : Fact (Nat.Prime p)
n i : ℕ
a✝ : i ∈ range (n + 1)
⊢ ¬p ^ (n - i) = 0
[PROOFSTEP]
exact ne_of_gt (pow_pos hp.1.pos _)
[GOAL]
p : ℕ
R : Type u_1
inst✝² : CommRing R
inst✝¹ : DecidableEq R
S : Type u_2
inst✝ : CommRing S
⊢ W_ R 0 = X 0
[PROOFSTEP]
simp only [wittPolynomial, X, sum_singleton, range_one, pow_zero, zero_add, tsub_self]
[GOAL]
p : ℕ
R : Type u_1
inst✝² : CommRing R
inst✝¹ : DecidableEq R
S : Type u_2
inst✝ : CommRing S
⊢ W_ R 1 = ↑C ↑p * X 1 + X 0 ^ p
[PROOFSTEP]
simp only [wittPolynomial_eq_sum_C_mul_X_pow, sum_range_succ_comm, range_one, sum_singleton, one_mul, pow_one, C_1,
  pow_zero, tsub_self, tsub_zero]
[GOAL]
p : ℕ
R : Type u_1
inst✝⁴ : CommRing R
inst✝³ : DecidableEq R
S : Type u_2
inst✝² : CommRing S
A : Type u_3
inst✝¹ : CommRing A
inst✝ : Algebra R A
f : ℕ → A
n : ℕ
⊢ ↑(aeval f) (W_ R n) = ∑ i in range (n + 1), ↑p ^ i * f i ^ p ^ (n - i)
[PROOFSTEP]
simp [wittPolynomial, AlgHom.map_sum, aeval_monomial, Finsupp.prod_single_index]
[GOAL]
p : ℕ
R : Type u_1
inst✝² : CommRing R
inst✝¹ : DecidableEq R
S : Type u_2
inst✝ : CommRing S
n : ℕ
⊢ W_ (ZMod (p ^ (n + 1))) (n + 1) = ↑(expand p) (W_ (ZMod (p ^ (n + 1))) n)
[PROOFSTEP]
simp only [wittPolynomial_eq_sum_C_mul_X_pow]
[GOAL]
p : ℕ
R : Type u_1
inst✝² : CommRing R
inst✝¹ : DecidableEq R
S : Type u_2
inst✝ : CommRing S
n : ℕ
⊢ ∑ x in range (n + 1 + 1), ↑C (↑p ^ x) * X x ^ p ^ (n + 1 - x) =
    ↑(expand p) (∑ x in range (n + 1), ↑C (↑p ^ x) * X x ^ p ^ (n - x))
[PROOFSTEP]
rw [sum_range_succ, ← Nat.cast_pow, CharP.cast_eq_zero (ZMod (p ^ (n + 1))) (p ^ (n + 1)), C_0, zero_mul, add_zero,
  AlgHom.map_sum, sum_congr rfl]
[GOAL]
p : ℕ
R : Type u_1
inst✝² : CommRing R
inst✝¹ : DecidableEq R
S : Type u_2
inst✝ : CommRing S
n : ℕ
⊢ ∀ (x : ℕ), x ∈ range (n + 1) → ↑C (↑p ^ x) * X x ^ p ^ (n + 1 - x) = ↑(expand p) (↑C (↑p ^ x) * X x ^ p ^ (n - x))
[PROOFSTEP]
intro k hk
[GOAL]
p : ℕ
R : Type u_1
inst✝² : CommRing R
inst✝¹ : DecidableEq R
S : Type u_2
inst✝ : CommRing S
n k : ℕ
hk : k ∈ range (n + 1)
⊢ ↑C (↑p ^ k) * X k ^ p ^ (n + 1 - k) = ↑(expand p) (↑C (↑p ^ k) * X k ^ p ^ (n - k))
[PROOFSTEP]
rw [AlgHom.map_mul, AlgHom.map_pow, expand_X, algHom_C, ← pow_mul, ← pow_succ]
[GOAL]
p : ℕ
R : Type u_1
inst✝² : CommRing R
inst✝¹ : DecidableEq R
S : Type u_2
inst✝ : CommRing S
n k : ℕ
hk : k ∈ range (n + 1)
⊢ ↑C (↑p ^ k) * X k ^ p ^ (n + 1 - k) = ↑C (↑p ^ k) * X k ^ p ^ (n - k + 1)
[PROOFSTEP]
congr
[GOAL]
case e_a.e_a.e_a
p : ℕ
R : Type u_1
inst✝² : CommRing R
inst✝¹ : DecidableEq R
S : Type u_2
inst✝ : CommRing S
n k : ℕ
hk : k ∈ range (n + 1)
⊢ n + 1 - k = n - k + 1
[PROOFSTEP]
rw [mem_range] at hk
[GOAL]
case e_a.e_a.e_a
p : ℕ
R : Type u_1
inst✝² : CommRing R
inst✝¹ : DecidableEq R
S : Type u_2
inst✝ : CommRing S
n k : ℕ
hk : k < n + 1
⊢ n + 1 - k = n - k + 1
[PROOFSTEP]
rw [add_comm, add_tsub_assoc_of_le (Nat.lt_succ_iff.mp hk), ← add_comm]
[GOAL]
p : ℕ
R : Type u_1
inst✝³ : CommRing R
inst✝² : DecidableEq R
S : Type u_2
inst✝¹ : CommRing S
hp : NeZero p
inst✝ : CharZero R
n : ℕ
⊢ vars (W_ R n) = range (n + 1)
[PROOFSTEP]
have : ∀ i, (monomial (Finsupp.single i (p ^ (n - i))) ((p : R) ^ i)).vars = { i } :=
  by
  intro i
  refine' vars_monomial_single i (pow_ne_zero _ hp.1) _
  rw [← Nat.cast_pow, Nat.cast_ne_zero]
  exact pow_ne_zero i hp.1
[GOAL]
p : ℕ
R : Type u_1
inst✝³ : CommRing R
inst✝² : DecidableEq R
S : Type u_2
inst✝¹ : CommRing S
hp : NeZero p
inst✝ : CharZero R
n : ℕ
⊢ ∀ (i : ℕ), vars (↑(monomial (single i (p ^ (n - i)))) (↑p ^ i)) = {i}
[PROOFSTEP]
intro i
[GOAL]
p : ℕ
R : Type u_1
inst✝³ : CommRing R
inst✝² : DecidableEq R
S : Type u_2
inst✝¹ : CommRing S
hp : NeZero p
inst✝ : CharZero R
n i : ℕ
⊢ vars (↑(monomial (single i (p ^ (n - i)))) (↑p ^ i)) = {i}
[PROOFSTEP]
refine' vars_monomial_single i (pow_ne_zero _ hp.1) _
[GOAL]
p : ℕ
R : Type u_1
inst✝³ : CommRing R
inst✝² : DecidableEq R
S : Type u_2
inst✝¹ : CommRing S
hp : NeZero p
inst✝ : CharZero R
n i : ℕ
⊢ ↑p ^ i ≠ 0
[PROOFSTEP]
rw [← Nat.cast_pow, Nat.cast_ne_zero]
[GOAL]
p : ℕ
R : Type u_1
inst✝³ : CommRing R
inst✝² : DecidableEq R
S : Type u_2
inst✝¹ : CommRing S
hp : NeZero p
inst✝ : CharZero R
n i : ℕ
⊢ p ^ i ≠ 0
[PROOFSTEP]
exact pow_ne_zero i hp.1
[GOAL]
p : ℕ
R : Type u_1
inst✝³ : CommRing R
inst✝² : DecidableEq R
S : Type u_2
inst✝¹ : CommRing S
hp : NeZero p
inst✝ : CharZero R
n : ℕ
this : ∀ (i : ℕ), vars (↑(monomial (single i (p ^ (n - i)))) (↑p ^ i)) = {i}
⊢ vars (W_ R n) = range (n + 1)
[PROOFSTEP]
rw [wittPolynomial, vars_sum_of_disjoint]
[GOAL]
p : ℕ
R : Type u_1
inst✝³ : CommRing R
inst✝² : DecidableEq R
S : Type u_2
inst✝¹ : CommRing S
hp : NeZero p
inst✝ : CharZero R
n : ℕ
this : ∀ (i : ℕ), vars (↑(monomial (single i (p ^ (n - i)))) (↑p ^ i)) = {i}
⊢ (Finset.biUnion (range (n + 1)) fun i => vars (↑(monomial (single i (p ^ (n - i)))) (↑p ^ i))) = range (n + 1)
[PROOFSTEP]
simp only [this, biUnion_singleton_eq_self]
[GOAL]
case h
p : ℕ
R : Type u_1
inst✝³ : CommRing R
inst✝² : DecidableEq R
S : Type u_2
inst✝¹ : CommRing S
hp : NeZero p
inst✝ : CharZero R
n : ℕ
this : ∀ (i : ℕ), vars (↑(monomial (single i (p ^ (n - i)))) (↑p ^ i)) = {i}
⊢ Pairwise (Disjoint on fun i => vars (↑(monomial (single i (p ^ (n - i)))) (↑p ^ i)))
[PROOFSTEP]
simp only [this]
[GOAL]
case h
p : ℕ
R : Type u_1
inst✝³ : CommRing R
inst✝² : DecidableEq R
S : Type u_2
inst✝¹ : CommRing S
hp : NeZero p
inst✝ : CharZero R
n : ℕ
this : ∀ (i : ℕ), vars (↑(monomial (single i (p ^ (n - i)))) (↑p ^ i)) = {i}
⊢ Pairwise (Disjoint on fun i => {i})
[PROOFSTEP]
intro a b h
[GOAL]
case h
p : ℕ
R : Type u_1
inst✝³ : CommRing R
inst✝² : DecidableEq R
S : Type u_2
inst✝¹ : CommRing S
hp : NeZero p
inst✝ : CharZero R
n : ℕ
this : ∀ (i : ℕ), vars (↑(monomial (single i (p ^ (n - i)))) (↑p ^ i)) = {i}
a b : ℕ
h : a ≠ b
⊢ (Disjoint on fun i => {i}) a b
[PROOFSTEP]
apply disjoint_singleton_left.mpr
[GOAL]
case h
p : ℕ
R : Type u_1
inst✝³ : CommRing R
inst✝² : DecidableEq R
S : Type u_2
inst✝¹ : CommRing S
hp : NeZero p
inst✝ : CharZero R
n : ℕ
this : ∀ (i : ℕ), vars (↑(monomial (single i (p ^ (n - i)))) (↑p ^ i)) = {i}
a b : ℕ
h : a ≠ b
⊢ ¬a ∈ (fun i => {i}) b
[PROOFSTEP]
rwa [mem_singleton]
[GOAL]
p : ℕ
R : Type u_1
inst✝² : CommRing R
inst✝¹ : DecidableEq R
S : Type u_2
inst✝ : CommRing S
hp : NeZero p
n : ℕ
⊢ vars (W_ R n) ⊆ range (n + 1)
[PROOFSTEP]
rw [← map_wittPolynomial p (Int.castRingHom R), ← wittPolynomial_vars p ℤ]
[GOAL]
p : ℕ
R : Type u_1
inst✝² : CommRing R
inst✝¹ : DecidableEq R
S : Type u_2
inst✝ : CommRing S
hp : NeZero p
n : ℕ
⊢ vars (↑(map (Int.castRingHom R)) (W_ ℤ n)) ⊆ vars (W_ ℤ n)
[PROOFSTEP]
apply vars_map
[GOAL]
p : ℕ
R : Type u_1
inst✝² : CommRing R
inst✝¹ : DecidableEq R
inst✝ : Invertible ↑p
n : ℕ
⊢ xInTermsOfW p R n = (X n - ∑ i in range n, ↑C (↑p ^ i) * xInTermsOfW p R i ^ p ^ (n - i)) * ↑C (⅟↑p ^ n)
[PROOFSTEP]
rw [xInTermsOfW, ← Fin.sum_univ_eq_sum_range]
[GOAL]
p : ℕ
R : Type u_1
inst✝² : CommRing R
inst✝¹ : DecidableEq R
hp : Fact (Nat.Prime p)
inst✝ : Invertible ↑p
n : ℕ
⊢ ↑constantCoeff (xInTermsOfW p R n) = 0
[PROOFSTEP]
apply Nat.strongInductionOn n
[GOAL]
p : ℕ
R : Type u_1
inst✝² : CommRing R
inst✝¹ : DecidableEq R
hp : Fact (Nat.Prime p)
inst✝ : Invertible ↑p
n : ℕ
⊢ ∀ (n : ℕ), (∀ (m : ℕ), m < n → ↑constantCoeff (xInTermsOfW p R m) = 0) → ↑constantCoeff (xInTermsOfW p R n) = 0
[PROOFSTEP]
clear n
[GOAL]
p : ℕ
R : Type u_1
inst✝² : CommRing R
inst✝¹ : DecidableEq R
hp : Fact (Nat.Prime p)
inst✝ : Invertible ↑p
⊢ ∀ (n : ℕ), (∀ (m : ℕ), m < n → ↑constantCoeff (xInTermsOfW p R m) = 0) → ↑constantCoeff (xInTermsOfW p R n) = 0
[PROOFSTEP]
intro n IH
[GOAL]
p : ℕ
R : Type u_1
inst✝² : CommRing R
inst✝¹ : DecidableEq R
hp : Fact (Nat.Prime p)
inst✝ : Invertible ↑p
n : ℕ
IH : ∀ (m : ℕ), m < n → ↑constantCoeff (xInTermsOfW p R m) = 0
⊢ ↑constantCoeff (xInTermsOfW p R n) = 0
[PROOFSTEP]
rw [xInTermsOfW_eq, mul_comm, RingHom.map_mul, RingHom.map_sub, map_sum, constantCoeff_C, constantCoeff_X, zero_sub,
  mul_neg, neg_eq_zero]
  -- porting note: here, we should be able to do `rw [sum_eq_zero]`, but the goal that
    -- is created is not what we expect, and the sum is not replaced by zero...
    -- is it a bug in `rw` tactic?
[GOAL]
p : ℕ
R : Type u_1
inst✝² : CommRing R
inst✝¹ : DecidableEq R
hp : Fact (Nat.Prime p)
inst✝ : Invertible ↑p
n : ℕ
IH : ∀ (m : ℕ), m < n → ↑constantCoeff (xInTermsOfW p R m) = 0
⊢ ⅟↑p ^ n * ∑ x in range n, ↑constantCoeff (↑C (↑p ^ x) * xInTermsOfW p R x ^ p ^ (n - x)) = 0
[PROOFSTEP]
refine' Eq.trans (_ : _ = ((⅟↑p : R) ^ n) * 0) (mul_zero _)
[GOAL]
p : ℕ
R : Type u_1
inst✝² : CommRing R
inst✝¹ : DecidableEq R
hp : Fact (Nat.Prime p)
inst✝ : Invertible ↑p
n : ℕ
IH : ∀ (m : ℕ), m < n → ↑constantCoeff (xInTermsOfW p R m) = 0
⊢ ⅟↑p ^ n * ∑ x in range n, ↑constantCoeff (↑C (↑p ^ x) * xInTermsOfW p R x ^ p ^ (n - x)) = ⅟↑p ^ n * 0
[PROOFSTEP]
congr 1
[GOAL]
case e_a
p : ℕ
R : Type u_1
inst✝² : CommRing R
inst✝¹ : DecidableEq R
hp : Fact (Nat.Prime p)
inst✝ : Invertible ↑p
n : ℕ
IH : ∀ (m : ℕ), m < n → ↑constantCoeff (xInTermsOfW p R m) = 0
⊢ ∑ x in range n, ↑constantCoeff (↑C (↑p ^ x) * xInTermsOfW p R x ^ p ^ (n - x)) = 0
[PROOFSTEP]
rw [sum_eq_zero]
[GOAL]
case e_a
p : ℕ
R : Type u_1
inst✝² : CommRing R
inst✝¹ : DecidableEq R
hp : Fact (Nat.Prime p)
inst✝ : Invertible ↑p
n : ℕ
IH : ∀ (m : ℕ), m < n → ↑constantCoeff (xInTermsOfW p R m) = 0
⊢ ∀ (x : ℕ), x ∈ range n → ↑constantCoeff (↑C (↑p ^ x) * xInTermsOfW p R x ^ p ^ (n - x)) = 0
[PROOFSTEP]
intro m H
[GOAL]
case e_a
p : ℕ
R : Type u_1
inst✝² : CommRing R
inst✝¹ : DecidableEq R
hp : Fact (Nat.Prime p)
inst✝ : Invertible ↑p
n : ℕ
IH : ∀ (m : ℕ), m < n → ↑constantCoeff (xInTermsOfW p R m) = 0
m : ℕ
H : m ∈ range n
⊢ ↑constantCoeff (↑C (↑p ^ m) * xInTermsOfW p R m ^ p ^ (n - m)) = 0
[PROOFSTEP]
rw [mem_range] at H
[GOAL]
case e_a
p : ℕ
R : Type u_1
inst✝² : CommRing R
inst✝¹ : DecidableEq R
hp : Fact (Nat.Prime p)
inst✝ : Invertible ↑p
n : ℕ
IH : ∀ (m : ℕ), m < n → ↑constantCoeff (xInTermsOfW p R m) = 0
m : ℕ
H : m < n
⊢ ↑constantCoeff (↑C (↑p ^ m) * xInTermsOfW p R m ^ p ^ (n - m)) = 0
[PROOFSTEP]
simp only [RingHom.map_mul, RingHom.map_pow, map_natCast, IH m H]
[GOAL]
case e_a
p : ℕ
R : Type u_1
inst✝² : CommRing R
inst✝¹ : DecidableEq R
hp : Fact (Nat.Prime p)
inst✝ : Invertible ↑p
n : ℕ
IH : ∀ (m : ℕ), m < n → ↑constantCoeff (xInTermsOfW p R m) = 0
m : ℕ
H : m < n
⊢ ↑p ^ m * 0 ^ p ^ (n - m) = 0
[PROOFSTEP]
rw [zero_pow, mul_zero]
[GOAL]
case e_a
p : ℕ
R : Type u_1
inst✝² : CommRing R
inst✝¹ : DecidableEq R
hp : Fact (Nat.Prime p)
inst✝ : Invertible ↑p
n : ℕ
IH : ∀ (m : ℕ), m < n → ↑constantCoeff (xInTermsOfW p R m) = 0
m : ℕ
H : m < n
⊢ 0 < p ^ (n - m)
[PROOFSTEP]
apply pow_pos hp.1.pos
[GOAL]
p : ℕ
R : Type u_1
inst✝² : CommRing R
inst✝¹ : DecidableEq R
inst✝ : Invertible ↑p
⊢ xInTermsOfW p R 0 = X 0
[PROOFSTEP]
rw [xInTermsOfW_eq, range_zero, sum_empty, pow_zero, C_1, mul_one, sub_zero]
[GOAL]
p : ℕ
R : Type u_1
inst✝¹ : CommRing R
inst✝ : DecidableEq R
hp : Fact (Nat.Prime p)
n : ℕ
⊢ n ∈ vars (xInTermsOfW p ℚ n) ∧ vars (xInTermsOfW p ℚ n) ⊆ range (n + 1)
[PROOFSTEP]
apply Nat.strongInductionOn n
[GOAL]
p : ℕ
R : Type u_1
inst✝¹ : CommRing R
inst✝ : DecidableEq R
hp : Fact (Nat.Prime p)
n : ℕ
⊢ ∀ (n : ℕ),
    (∀ (m : ℕ), m < n → m ∈ vars (xInTermsOfW p ℚ m) ∧ vars (xInTermsOfW p ℚ m) ⊆ range (m + 1)) →
      n ∈ vars (xInTermsOfW p ℚ n) ∧ vars (xInTermsOfW p ℚ n) ⊆ range (n + 1)
[PROOFSTEP]
clear n
[GOAL]
p : ℕ
R : Type u_1
inst✝¹ : CommRing R
inst✝ : DecidableEq R
hp : Fact (Nat.Prime p)
⊢ ∀ (n : ℕ),
    (∀ (m : ℕ), m < n → m ∈ vars (xInTermsOfW p ℚ m) ∧ vars (xInTermsOfW p ℚ m) ⊆ range (m + 1)) →
      n ∈ vars (xInTermsOfW p ℚ n) ∧ vars (xInTermsOfW p ℚ n) ⊆ range (n + 1)
[PROOFSTEP]
intro n ih
[GOAL]
p : ℕ
R : Type u_1
inst✝¹ : CommRing R
inst✝ : DecidableEq R
hp : Fact (Nat.Prime p)
n : ℕ
ih : ∀ (m : ℕ), m < n → m ∈ vars (xInTermsOfW p ℚ m) ∧ vars (xInTermsOfW p ℚ m) ⊆ range (m + 1)
⊢ n ∈ vars (xInTermsOfW p ℚ n) ∧ vars (xInTermsOfW p ℚ n) ⊆ range (n + 1)
[PROOFSTEP]
rw [xInTermsOfW_eq, mul_comm, vars_C_mul _ (nonzero_of_invertible _), vars_sub_of_disjoint, vars_X, range_succ,
  insert_eq]
[GOAL]
p : ℕ
R : Type u_1
inst✝¹ : CommRing R
inst✝ : DecidableEq R
hp : Fact (Nat.Prime p)
n : ℕ
ih : ∀ (m : ℕ), m < n → m ∈ vars (xInTermsOfW p ℚ m) ∧ vars (xInTermsOfW p ℚ m) ⊆ range (m + 1)
⊢ n ∈ {n} ∪ vars (∑ i in range n, ↑C (↑p ^ i) * xInTermsOfW p ℚ i ^ p ^ (n - i)) ∧
    {n} ∪ vars (∑ i in range n, ↑C (↑p ^ i) * xInTermsOfW p ℚ i ^ p ^ (n - i)) ⊆ {n} ∪ range n
case hpq
p : ℕ
R : Type u_1
inst✝¹ : CommRing R
inst✝ : DecidableEq R
hp : Fact (Nat.Prime p)
n : ℕ
ih : ∀ (m : ℕ), m < n → m ∈ vars (xInTermsOfW p ℚ m) ∧ vars (xInTermsOfW p ℚ m) ⊆ range (m + 1)
⊢ Disjoint (vars (X n)) (vars (∑ i in range n, ↑C (↑p ^ i) * xInTermsOfW p ℚ i ^ p ^ (n - i)))
[PROOFSTEP]
on_goal 1 =>
  simp only [true_and_iff, true_or_iff, eq_self_iff_true, mem_union, mem_singleton]
  intro i
  rw [mem_union, mem_union]
  apply Or.imp id
[GOAL]
p : ℕ
R : Type u_1
inst✝¹ : CommRing R
inst✝ : DecidableEq R
hp : Fact (Nat.Prime p)
n : ℕ
ih : ∀ (m : ℕ), m < n → m ∈ vars (xInTermsOfW p ℚ m) ∧ vars (xInTermsOfW p ℚ m) ⊆ range (m + 1)
⊢ n ∈ {n} ∪ vars (∑ i in range n, ↑C (↑p ^ i) * xInTermsOfW p ℚ i ^ p ^ (n - i)) ∧
    {n} ∪ vars (∑ i in range n, ↑C (↑p ^ i) * xInTermsOfW p ℚ i ^ p ^ (n - i)) ⊆ {n} ∪ range n
case hpq
p : ℕ
R : Type u_1
inst✝¹ : CommRing R
inst✝ : DecidableEq R
hp : Fact (Nat.Prime p)
n : ℕ
ih : ∀ (m : ℕ), m < n → m ∈ vars (xInTermsOfW p ℚ m) ∧ vars (xInTermsOfW p ℚ m) ⊆ range (m + 1)
⊢ Disjoint (vars (X n)) (vars (∑ i in range n, ↑C (↑p ^ i) * xInTermsOfW p ℚ i ^ p ^ (n - i)))
[PROOFSTEP]
on_goal 1 =>
  simp only [true_and_iff, true_or_iff, eq_self_iff_true, mem_union, mem_singleton]
  intro i
  rw [mem_union, mem_union]
  apply Or.imp id
[GOAL]
p : ℕ
R : Type u_1
inst✝¹ : CommRing R
inst✝ : DecidableEq R
hp : Fact (Nat.Prime p)
n : ℕ
ih : ∀ (m : ℕ), m < n → m ∈ vars (xInTermsOfW p ℚ m) ∧ vars (xInTermsOfW p ℚ m) ⊆ range (m + 1)
⊢ n ∈ {n} ∪ vars (∑ i in range n, ↑C (↑p ^ i) * xInTermsOfW p ℚ i ^ p ^ (n - i)) ∧
    {n} ∪ vars (∑ i in range n, ↑C (↑p ^ i) * xInTermsOfW p ℚ i ^ p ^ (n - i)) ⊆ {n} ∪ range n
[PROOFSTEP]
simp only [true_and_iff, true_or_iff, eq_self_iff_true, mem_union, mem_singleton]
[GOAL]
p : ℕ
R : Type u_1
inst✝¹ : CommRing R
inst✝ : DecidableEq R
hp : Fact (Nat.Prime p)
n : ℕ
ih : ∀ (m : ℕ), m < n → m ∈ vars (xInTermsOfW p ℚ m) ∧ vars (xInTermsOfW p ℚ m) ⊆ range (m + 1)
⊢ {n} ∪ vars (∑ x in range n, ↑C (↑p ^ x) * xInTermsOfW p ℚ x ^ p ^ (n - x)) ⊆ {n} ∪ range n
[PROOFSTEP]
intro i
[GOAL]
p : ℕ
R : Type u_1
inst✝¹ : CommRing R
inst✝ : DecidableEq R
hp : Fact (Nat.Prime p)
n : ℕ
ih : ∀ (m : ℕ), m < n → m ∈ vars (xInTermsOfW p ℚ m) ∧ vars (xInTermsOfW p ℚ m) ⊆ range (m + 1)
i : ℕ
⊢ i ∈ {n} ∪ vars (∑ x in range n, ↑C (↑p ^ x) * xInTermsOfW p ℚ x ^ p ^ (n - x)) → i ∈ {n} ∪ range n
[PROOFSTEP]
rw [mem_union, mem_union]
[GOAL]
p : ℕ
R : Type u_1
inst✝¹ : CommRing R
inst✝ : DecidableEq R
hp : Fact (Nat.Prime p)
n : ℕ
ih : ∀ (m : ℕ), m < n → m ∈ vars (xInTermsOfW p ℚ m) ∧ vars (xInTermsOfW p ℚ m) ⊆ range (m + 1)
i : ℕ
⊢ i ∈ {n} ∨ i ∈ vars (∑ x in range n, ↑C (↑p ^ x) * xInTermsOfW p ℚ x ^ p ^ (n - x)) → i ∈ {n} ∨ i ∈ range n
[PROOFSTEP]
apply Or.imp id
[GOAL]
p : ℕ
R : Type u_1
inst✝¹ : CommRing R
inst✝ : DecidableEq R
hp : Fact (Nat.Prime p)
n : ℕ
ih : ∀ (m : ℕ), m < n → m ∈ vars (xInTermsOfW p ℚ m) ∧ vars (xInTermsOfW p ℚ m) ⊆ range (m + 1)
i : ℕ
⊢ i ∈ vars (∑ x in range n, ↑C (↑p ^ x) * xInTermsOfW p ℚ x ^ p ^ (n - x)) → i ∈ range n
case hpq
p : ℕ
R : Type u_1
inst✝¹ : CommRing R
inst✝ : DecidableEq R
hp : Fact (Nat.Prime p)
n : ℕ
ih : ∀ (m : ℕ), m < n → m ∈ vars (xInTermsOfW p ℚ m) ∧ vars (xInTermsOfW p ℚ m) ⊆ range (m + 1)
⊢ Disjoint (vars (X n)) (vars (∑ i in range n, ↑C (↑p ^ i) * xInTermsOfW p ℚ i ^ p ^ (n - i)))
[PROOFSTEP]
on_goal 2 => rw [vars_X, disjoint_singleton_left]
[GOAL]
p : ℕ
R : Type u_1
inst✝¹ : CommRing R
inst✝ : DecidableEq R
hp : Fact (Nat.Prime p)
n : ℕ
ih : ∀ (m : ℕ), m < n → m ∈ vars (xInTermsOfW p ℚ m) ∧ vars (xInTermsOfW p ℚ m) ⊆ range (m + 1)
i : ℕ
⊢ i ∈ vars (∑ x in range n, ↑C (↑p ^ x) * xInTermsOfW p ℚ x ^ p ^ (n - x)) → i ∈ range n
case hpq
p : ℕ
R : Type u_1
inst✝¹ : CommRing R
inst✝ : DecidableEq R
hp : Fact (Nat.Prime p)
n : ℕ
ih : ∀ (m : ℕ), m < n → m ∈ vars (xInTermsOfW p ℚ m) ∧ vars (xInTermsOfW p ℚ m) ⊆ range (m + 1)
⊢ Disjoint (vars (X n)) (vars (∑ i in range n, ↑C (↑p ^ i) * xInTermsOfW p ℚ i ^ p ^ (n - i)))
[PROOFSTEP]
on_goal 2 => rw [vars_X, disjoint_singleton_left]
[GOAL]
case hpq
p : ℕ
R : Type u_1
inst✝¹ : CommRing R
inst✝ : DecidableEq R
hp : Fact (Nat.Prime p)
n : ℕ
ih : ∀ (m : ℕ), m < n → m ∈ vars (xInTermsOfW p ℚ m) ∧ vars (xInTermsOfW p ℚ m) ⊆ range (m + 1)
⊢ Disjoint (vars (X n)) (vars (∑ i in range n, ↑C (↑p ^ i) * xInTermsOfW p ℚ i ^ p ^ (n - i)))
[PROOFSTEP]
rw [vars_X, disjoint_singleton_left]
[GOAL]
p : ℕ
R : Type u_1
inst✝¹ : CommRing R
inst✝ : DecidableEq R
hp : Fact (Nat.Prime p)
n : ℕ
ih : ∀ (m : ℕ), m < n → m ∈ vars (xInTermsOfW p ℚ m) ∧ vars (xInTermsOfW p ℚ m) ⊆ range (m + 1)
i : ℕ
⊢ i ∈ vars (∑ x in range n, ↑C (↑p ^ x) * xInTermsOfW p ℚ x ^ p ^ (n - x)) → i ∈ range n
case hpq
p : ℕ
R : Type u_1
inst✝¹ : CommRing R
inst✝ : DecidableEq R
hp : Fact (Nat.Prime p)
n : ℕ
ih : ∀ (m : ℕ), m < n → m ∈ vars (xInTermsOfW p ℚ m) ∧ vars (xInTermsOfW p ℚ m) ⊆ range (m + 1)
⊢ ¬n ∈ vars (∑ i in range n, ↑C (↑p ^ i) * xInTermsOfW p ℚ i ^ p ^ (n - i))
[PROOFSTEP]
all_goals
  intro H
  replace H := vars_sum_subset _ _ H
  rw [mem_biUnion] at H
  rcases H with ⟨j, hj, H⟩
  rw [vars_C_mul] at H
  swap
  · apply pow_ne_zero
    exact_mod_cast hp.1.ne_zero
  rw [mem_range] at hj
  replace H := (ih j hj).2 (vars_pow _ _ H)
  rw [mem_range] at H
[GOAL]
p : ℕ
R : Type u_1
inst✝¹ : CommRing R
inst✝ : DecidableEq R
hp : Fact (Nat.Prime p)
n : ℕ
ih : ∀ (m : ℕ), m < n → m ∈ vars (xInTermsOfW p ℚ m) ∧ vars (xInTermsOfW p ℚ m) ⊆ range (m + 1)
i : ℕ
⊢ i ∈ vars (∑ x in range n, ↑C (↑p ^ x) * xInTermsOfW p ℚ x ^ p ^ (n - x)) → i ∈ range n
[PROOFSTEP]
intro H
[GOAL]
p : ℕ
R : Type u_1
inst✝¹ : CommRing R
inst✝ : DecidableEq R
hp : Fact (Nat.Prime p)
n : ℕ
ih : ∀ (m : ℕ), m < n → m ∈ vars (xInTermsOfW p ℚ m) ∧ vars (xInTermsOfW p ℚ m) ⊆ range (m + 1)
i : ℕ
H : i ∈ vars (∑ x in range n, ↑C (↑p ^ x) * xInTermsOfW p ℚ x ^ p ^ (n - x))
⊢ i ∈ range n
[PROOFSTEP]
replace H := vars_sum_subset _ _ H
[GOAL]
p : ℕ
R : Type u_1
inst✝¹ : CommRing R
inst✝ : DecidableEq R
hp : Fact (Nat.Prime p)
n : ℕ
ih : ∀ (m : ℕ), m < n → m ∈ vars (xInTermsOfW p ℚ m) ∧ vars (xInTermsOfW p ℚ m) ⊆ range (m + 1)
i : ℕ
H : i ∈ Finset.biUnion (range n) fun i => vars (↑C (↑p ^ i) * xInTermsOfW p ℚ i ^ p ^ (n - i))
⊢ i ∈ range n
[PROOFSTEP]
rw [mem_biUnion] at H
[GOAL]
p : ℕ
R : Type u_1
inst✝¹ : CommRing R
inst✝ : DecidableEq R
hp : Fact (Nat.Prime p)
n : ℕ
ih : ∀ (m : ℕ), m < n → m ∈ vars (xInTermsOfW p ℚ m) ∧ vars (xInTermsOfW p ℚ m) ⊆ range (m + 1)
i : ℕ
H : ∃ a, a ∈ range n ∧ i ∈ vars (↑C (↑p ^ a) * xInTermsOfW p ℚ a ^ p ^ (n - a))
⊢ i ∈ range n
[PROOFSTEP]
rcases H with ⟨j, hj, H⟩
[GOAL]
case intro.intro
p : ℕ
R : Type u_1
inst✝¹ : CommRing R
inst✝ : DecidableEq R
hp : Fact (Nat.Prime p)
n : ℕ
ih : ∀ (m : ℕ), m < n → m ∈ vars (xInTermsOfW p ℚ m) ∧ vars (xInTermsOfW p ℚ m) ⊆ range (m + 1)
i j : ℕ
hj : j ∈ range n
H : i ∈ vars (↑C (↑p ^ j) * xInTermsOfW p ℚ j ^ p ^ (n - j))
⊢ i ∈ range n
[PROOFSTEP]
rw [vars_C_mul] at H
[GOAL]
case intro.intro
p : ℕ
R : Type u_1
inst✝¹ : CommRing R
inst✝ : DecidableEq R
hp : Fact (Nat.Prime p)
n : ℕ
ih : ∀ (m : ℕ), m < n → m ∈ vars (xInTermsOfW p ℚ m) ∧ vars (xInTermsOfW p ℚ m) ⊆ range (m + 1)
i j : ℕ
hj : j ∈ range n
H : i ∈ vars (xInTermsOfW p ℚ j ^ p ^ (n - j))
⊢ i ∈ range n
case intro.intro.ha
p : ℕ
R : Type u_1
inst✝¹ : CommRing R
inst✝ : DecidableEq R
hp : Fact (Nat.Prime p)
n : ℕ
ih : ∀ (m : ℕ), m < n → m ∈ vars (xInTermsOfW p ℚ m) ∧ vars (xInTermsOfW p ℚ m) ⊆ range (m + 1)
i j : ℕ
hj : j ∈ range n
H : i ∈ vars (↑C (↑p ^ j) * xInTermsOfW p ℚ j ^ p ^ (n - j))
⊢ ↑p ^ j ≠ 0
[PROOFSTEP]
swap
[GOAL]
case intro.intro.ha
p : ℕ
R : Type u_1
inst✝¹ : CommRing R
inst✝ : DecidableEq R
hp : Fact (Nat.Prime p)
n : ℕ
ih : ∀ (m : ℕ), m < n → m ∈ vars (xInTermsOfW p ℚ m) ∧ vars (xInTermsOfW p ℚ m) ⊆ range (m + 1)
i j : ℕ
hj : j ∈ range n
H : i ∈ vars (↑C (↑p ^ j) * xInTermsOfW p ℚ j ^ p ^ (n - j))
⊢ ↑p ^ j ≠ 0
[PROOFSTEP]
apply pow_ne_zero
[GOAL]
case intro.intro.ha.h
p : ℕ
R : Type u_1
inst✝¹ : CommRing R
inst✝ : DecidableEq R
hp : Fact (Nat.Prime p)
n : ℕ
ih : ∀ (m : ℕ), m < n → m ∈ vars (xInTermsOfW p ℚ m) ∧ vars (xInTermsOfW p ℚ m) ⊆ range (m + 1)
i j : ℕ
hj : j ∈ range n
H : i ∈ vars (↑C (↑p ^ j) * xInTermsOfW p ℚ j ^ p ^ (n - j))
⊢ ↑p ≠ 0
[PROOFSTEP]
exact_mod_cast hp.1.ne_zero
[GOAL]
case intro.intro
p : ℕ
R : Type u_1
inst✝¹ : CommRing R
inst✝ : DecidableEq R
hp : Fact (Nat.Prime p)
n : ℕ
ih : ∀ (m : ℕ), m < n → m ∈ vars (xInTermsOfW p ℚ m) ∧ vars (xInTermsOfW p ℚ m) ⊆ range (m + 1)
i j : ℕ
hj : j ∈ range n
H : i ∈ vars (xInTermsOfW p ℚ j ^ p ^ (n - j))
⊢ i ∈ range n
[PROOFSTEP]
rw [mem_range] at hj
[GOAL]
case intro.intro
p : ℕ
R : Type u_1
inst✝¹ : CommRing R
inst✝ : DecidableEq R
hp : Fact (Nat.Prime p)
n : ℕ
ih : ∀ (m : ℕ), m < n → m ∈ vars (xInTermsOfW p ℚ m) ∧ vars (xInTermsOfW p ℚ m) ⊆ range (m + 1)
i j : ℕ
hj : j < n
H : i ∈ vars (xInTermsOfW p ℚ j ^ p ^ (n - j))
⊢ i ∈ range n
[PROOFSTEP]
replace H := (ih j hj).2 (vars_pow _ _ H)
[GOAL]
case intro.intro
p : ℕ
R : Type u_1
inst✝¹ : CommRing R
inst✝ : DecidableEq R
hp : Fact (Nat.Prime p)
n : ℕ
ih : ∀ (m : ℕ), m < n → m ∈ vars (xInTermsOfW p ℚ m) ∧ vars (xInTermsOfW p ℚ m) ⊆ range (m + 1)
i j : ℕ
hj : j < n
H : i ∈ range (j + 1)
⊢ i ∈ range n
[PROOFSTEP]
rw [mem_range] at H
[GOAL]
case hpq
p : ℕ
R : Type u_1
inst✝¹ : CommRing R
inst✝ : DecidableEq R
hp : Fact (Nat.Prime p)
n : ℕ
ih : ∀ (m : ℕ), m < n → m ∈ vars (xInTermsOfW p ℚ m) ∧ vars (xInTermsOfW p ℚ m) ⊆ range (m + 1)
⊢ ¬n ∈ vars (∑ i in range n, ↑C (↑p ^ i) * xInTermsOfW p ℚ i ^ p ^ (n - i))
[PROOFSTEP]
intro H
[GOAL]
case hpq
p : ℕ
R : Type u_1
inst✝¹ : CommRing R
inst✝ : DecidableEq R
hp : Fact (Nat.Prime p)
n : ℕ
ih : ∀ (m : ℕ), m < n → m ∈ vars (xInTermsOfW p ℚ m) ∧ vars (xInTermsOfW p ℚ m) ⊆ range (m + 1)
H : n ∈ vars (∑ i in range n, ↑C (↑p ^ i) * xInTermsOfW p ℚ i ^ p ^ (n - i))
⊢ False
[PROOFSTEP]
replace H := vars_sum_subset _ _ H
[GOAL]
case hpq
p : ℕ
R : Type u_1
inst✝¹ : CommRing R
inst✝ : DecidableEq R
hp : Fact (Nat.Prime p)
n : ℕ
ih : ∀ (m : ℕ), m < n → m ∈ vars (xInTermsOfW p ℚ m) ∧ vars (xInTermsOfW p ℚ m) ⊆ range (m + 1)
H : n ∈ Finset.biUnion (range n) fun i => vars (↑C (↑p ^ i) * xInTermsOfW p ℚ i ^ p ^ (n - i))
⊢ False
[PROOFSTEP]
rw [mem_biUnion] at H
[GOAL]
case hpq
p : ℕ
R : Type u_1
inst✝¹ : CommRing R
inst✝ : DecidableEq R
hp : Fact (Nat.Prime p)
n : ℕ
ih : ∀ (m : ℕ), m < n → m ∈ vars (xInTermsOfW p ℚ m) ∧ vars (xInTermsOfW p ℚ m) ⊆ range (m + 1)
H : ∃ a, a ∈ range n ∧ n ∈ vars (↑C (↑p ^ a) * xInTermsOfW p ℚ a ^ p ^ (n - a))
⊢ False
[PROOFSTEP]
rcases H with ⟨j, hj, H⟩
[GOAL]
case hpq.intro.intro
p : ℕ
R : Type u_1
inst✝¹ : CommRing R
inst✝ : DecidableEq R
hp : Fact (Nat.Prime p)
n : ℕ
ih : ∀ (m : ℕ), m < n → m ∈ vars (xInTermsOfW p ℚ m) ∧ vars (xInTermsOfW p ℚ m) ⊆ range (m + 1)
j : ℕ
hj : j ∈ range n
H : n ∈ vars (↑C (↑p ^ j) * xInTermsOfW p ℚ j ^ p ^ (n - j))
⊢ False
[PROOFSTEP]
rw [vars_C_mul] at H
[GOAL]
case hpq.intro.intro
p : ℕ
R : Type u_1
inst✝¹ : CommRing R
inst✝ : DecidableEq R
hp : Fact (Nat.Prime p)
n : ℕ
ih : ∀ (m : ℕ), m < n → m ∈ vars (xInTermsOfW p ℚ m) ∧ vars (xInTermsOfW p ℚ m) ⊆ range (m + 1)
j : ℕ
hj : j ∈ range n
H : n ∈ vars (xInTermsOfW p ℚ j ^ p ^ (n - j))
⊢ False
case hpq.intro.intro.ha
p : ℕ
R : Type u_1
inst✝¹ : CommRing R
inst✝ : DecidableEq R
hp : Fact (Nat.Prime p)
n : ℕ
ih : ∀ (m : ℕ), m < n → m ∈ vars (xInTermsOfW p ℚ m) ∧ vars (xInTermsOfW p ℚ m) ⊆ range (m + 1)
j : ℕ
hj : j ∈ range n
H : n ∈ vars (↑C (↑p ^ j) * xInTermsOfW p ℚ j ^ p ^ (n - j))
⊢ ↑p ^ j ≠ 0
[PROOFSTEP]
swap
[GOAL]
case hpq.intro.intro.ha
p : ℕ
R : Type u_1
inst✝¹ : CommRing R
inst✝ : DecidableEq R
hp : Fact (Nat.Prime p)
n : ℕ
ih : ∀ (m : ℕ), m < n → m ∈ vars (xInTermsOfW p ℚ m) ∧ vars (xInTermsOfW p ℚ m) ⊆ range (m + 1)
j : ℕ
hj : j ∈ range n
H : n ∈ vars (↑C (↑p ^ j) * xInTermsOfW p ℚ j ^ p ^ (n - j))
⊢ ↑p ^ j ≠ 0
[PROOFSTEP]
apply pow_ne_zero
[GOAL]
case hpq.intro.intro.ha.h
p : ℕ
R : Type u_1
inst✝¹ : CommRing R
inst✝ : DecidableEq R
hp : Fact (Nat.Prime p)
n : ℕ
ih : ∀ (m : ℕ), m < n → m ∈ vars (xInTermsOfW p ℚ m) ∧ vars (xInTermsOfW p ℚ m) ⊆ range (m + 1)
j : ℕ
hj : j ∈ range n
H : n ∈ vars (↑C (↑p ^ j) * xInTermsOfW p ℚ j ^ p ^ (n - j))
⊢ ↑p ≠ 0
[PROOFSTEP]
exact_mod_cast hp.1.ne_zero
[GOAL]
case hpq.intro.intro
p : ℕ
R : Type u_1
inst✝¹ : CommRing R
inst✝ : DecidableEq R
hp : Fact (Nat.Prime p)
n : ℕ
ih : ∀ (m : ℕ), m < n → m ∈ vars (xInTermsOfW p ℚ m) ∧ vars (xInTermsOfW p ℚ m) ⊆ range (m + 1)
j : ℕ
hj : j ∈ range n
H : n ∈ vars (xInTermsOfW p ℚ j ^ p ^ (n - j))
⊢ False
[PROOFSTEP]
rw [mem_range] at hj
[GOAL]
case hpq.intro.intro
p : ℕ
R : Type u_1
inst✝¹ : CommRing R
inst✝ : DecidableEq R
hp : Fact (Nat.Prime p)
n : ℕ
ih : ∀ (m : ℕ), m < n → m ∈ vars (xInTermsOfW p ℚ m) ∧ vars (xInTermsOfW p ℚ m) ⊆ range (m + 1)
j : ℕ
hj : j < n
H : n ∈ vars (xInTermsOfW p ℚ j ^ p ^ (n - j))
⊢ False
[PROOFSTEP]
replace H := (ih j hj).2 (vars_pow _ _ H)
[GOAL]
case hpq.intro.intro
p : ℕ
R : Type u_1
inst✝¹ : CommRing R
inst✝ : DecidableEq R
hp : Fact (Nat.Prime p)
n : ℕ
ih : ∀ (m : ℕ), m < n → m ∈ vars (xInTermsOfW p ℚ m) ∧ vars (xInTermsOfW p ℚ m) ⊆ range (m + 1)
j : ℕ
hj : j < n
H : n ∈ range (j + 1)
⊢ False
[PROOFSTEP]
rw [mem_range] at H
[GOAL]
case intro.intro
p : ℕ
R : Type u_1
inst✝¹ : CommRing R
inst✝ : DecidableEq R
hp : Fact (Nat.Prime p)
n : ℕ
ih : ∀ (m : ℕ), m < n → m ∈ vars (xInTermsOfW p ℚ m) ∧ vars (xInTermsOfW p ℚ m) ⊆ range (m + 1)
i j : ℕ
hj : j < n
H : i < j + 1
⊢ i ∈ range n
[PROOFSTEP]
rw [mem_range]
[GOAL]
case intro.intro
p : ℕ
R : Type u_1
inst✝¹ : CommRing R
inst✝ : DecidableEq R
hp : Fact (Nat.Prime p)
n : ℕ
ih : ∀ (m : ℕ), m < n → m ∈ vars (xInTermsOfW p ℚ m) ∧ vars (xInTermsOfW p ℚ m) ⊆ range (m + 1)
i j : ℕ
hj : j < n
H : i < j + 1
⊢ i < n
[PROOFSTEP]
linarith
[GOAL]
case hpq.intro.intro
p : ℕ
R : Type u_1
inst✝¹ : CommRing R
inst✝ : DecidableEq R
hp : Fact (Nat.Prime p)
n : ℕ
ih : ∀ (m : ℕ), m < n → m ∈ vars (xInTermsOfW p ℚ m) ∧ vars (xInTermsOfW p ℚ m) ⊆ range (m + 1)
j : ℕ
hj : j < n
H : n < j + 1
⊢ False
[PROOFSTEP]
linarith
[GOAL]
p : ℕ
R : Type u_1
inst✝² : CommRing R
inst✝¹ : DecidableEq R
inst✝ : Invertible ↑p
n : ℕ
⊢ xInTermsOfW p R n * ↑C (↑p ^ n) = X n - ∑ i in range n, ↑C (↑p ^ i) * xInTermsOfW p R i ^ p ^ (n - i)
[PROOFSTEP]
rw [xInTermsOfW_eq, mul_assoc, ← C_mul, ← mul_pow, invOf_mul_self, one_pow, C_1, mul_one]
[GOAL]
p : ℕ
R : Type u_1
inst✝² : CommRing R
inst✝¹ : DecidableEq R
inst✝ : Invertible ↑p
k : ℕ
⊢ ↑(bind₁ (xInTermsOfW p R)) (W_ R k) = X k
[PROOFSTEP]
rw [wittPolynomial_eq_sum_C_mul_X_pow, AlgHom.map_sum]
[GOAL]
p : ℕ
R : Type u_1
inst✝² : CommRing R
inst✝¹ : DecidableEq R
inst✝ : Invertible ↑p
k : ℕ
⊢ ∑ x in range (k + 1), ↑(bind₁ (xInTermsOfW p R)) (↑C (↑p ^ x) * X x ^ p ^ (k - x)) = X k
[PROOFSTEP]
simp only [Nat.cast_pow, AlgHom.map_pow, C_pow, AlgHom.map_mul, algHom_C]
[GOAL]
p : ℕ
R : Type u_1
inst✝² : CommRing R
inst✝¹ : DecidableEq R
inst✝ : Invertible ↑p
k : ℕ
⊢ ∑ x in range (k + 1), ↑C ↑p ^ x * ↑(bind₁ (xInTermsOfW p R)) (X x) ^ p ^ (k - x) = X k
[PROOFSTEP]
rw [sum_range_succ_comm, tsub_self, pow_zero, pow_one, bind₁_X_right, mul_comm, ← C_pow, xInTermsOfW_aux]
[GOAL]
p : ℕ
R : Type u_1
inst✝² : CommRing R
inst✝¹ : DecidableEq R
inst✝ : Invertible ↑p
k : ℕ
⊢ X k - ∑ i in range k, ↑C (↑p ^ i) * xInTermsOfW p R i ^ p ^ (k - i) +
      ∑ x in range k, ↑C ↑p ^ x * ↑(bind₁ (xInTermsOfW p R)) (X x) ^ p ^ (k - x) =
    X k
[PROOFSTEP]
simp only [Nat.cast_pow, C_pow, bind₁_X_right, sub_add_cancel]
[GOAL]
p : ℕ
R : Type u_1
inst✝² : CommRing R
inst✝¹ : DecidableEq R
inst✝ : Invertible ↑p
n : ℕ
⊢ ↑(bind₁ (W_ R)) (xInTermsOfW p R n) = X n
[PROOFSTEP]
apply Nat.strongInductionOn n
[GOAL]
p : ℕ
R : Type u_1
inst✝² : CommRing R
inst✝¹ : DecidableEq R
inst✝ : Invertible ↑p
n : ℕ
⊢ ∀ (n : ℕ), (∀ (m : ℕ), m < n → ↑(bind₁ (W_ R)) (xInTermsOfW p R m) = X m) → ↑(bind₁ (W_ R)) (xInTermsOfW p R n) = X n
[PROOFSTEP]
clear n
[GOAL]
p : ℕ
R : Type u_1
inst✝² : CommRing R
inst✝¹ : DecidableEq R
inst✝ : Invertible ↑p
⊢ ∀ (n : ℕ), (∀ (m : ℕ), m < n → ↑(bind₁ (W_ R)) (xInTermsOfW p R m) = X m) → ↑(bind₁ (W_ R)) (xInTermsOfW p R n) = X n
[PROOFSTEP]
intro n H
[GOAL]
p : ℕ
R : Type u_1
inst✝² : CommRing R
inst✝¹ : DecidableEq R
inst✝ : Invertible ↑p
n : ℕ
H : ∀ (m : ℕ), m < n → ↑(bind₁ (W_ R)) (xInTermsOfW p R m) = X m
⊢ ↑(bind₁ (W_ R)) (xInTermsOfW p R n) = X n
[PROOFSTEP]
rw [xInTermsOfW_eq, AlgHom.map_mul, AlgHom.map_sub, bind₁_X_right, algHom_C, AlgHom.map_sum,
  show X n = (X n * C ((p : R) ^ n)) * C ((⅟p : R) ^ n) by
    rw [mul_assoc, ← C_mul, ← mul_pow, mul_invOf_self, one_pow, map_one, mul_one]]
[GOAL]
p : ℕ
R : Type u_1
inst✝² : CommRing R
inst✝¹ : DecidableEq R
inst✝ : Invertible ↑p
n : ℕ
H : ∀ (m : ℕ), m < n → ↑(bind₁ (W_ R)) (xInTermsOfW p R m) = X m
⊢ X n = X n * ↑C (↑p ^ n) * ↑C (⅟↑p ^ n)
[PROOFSTEP]
rw [mul_assoc, ← C_mul, ← mul_pow, mul_invOf_self, one_pow, map_one, mul_one]
[GOAL]
p : ℕ
R : Type u_1
inst✝² : CommRing R
inst✝¹ : DecidableEq R
inst✝ : Invertible ↑p
n : ℕ
H : ∀ (m : ℕ), m < n → ↑(bind₁ (W_ R)) (xInTermsOfW p R m) = X m
⊢ (W_ R n - ∑ x in range n, ↑(bind₁ (W_ R)) (↑C (↑p ^ x) * xInTermsOfW p R x ^ p ^ (n - x))) * ↑C (⅟↑p ^ n) =
    X n * ↑C (↑p ^ n) * ↑C (⅟↑p ^ n)
[PROOFSTEP]
congr 1
[GOAL]
case e_a
p : ℕ
R : Type u_1
inst✝² : CommRing R
inst✝¹ : DecidableEq R
inst✝ : Invertible ↑p
n : ℕ
H : ∀ (m : ℕ), m < n → ↑(bind₁ (W_ R)) (xInTermsOfW p R m) = X m
⊢ W_ R n - ∑ x in range n, ↑(bind₁ (W_ R)) (↑C (↑p ^ x) * xInTermsOfW p R x ^ p ^ (n - x)) = X n * ↑C (↑p ^ n)
[PROOFSTEP]
rw [wittPolynomial_eq_sum_C_mul_X_pow, sum_range_succ_comm, tsub_self, pow_zero, pow_one, mul_comm (X n), add_sub_assoc,
  add_right_eq_self, sub_eq_zero]
[GOAL]
case e_a
p : ℕ
R : Type u_1
inst✝² : CommRing R
inst✝¹ : DecidableEq R
inst✝ : Invertible ↑p
n : ℕ
H : ∀ (m : ℕ), m < n → ↑(bind₁ (W_ R)) (xInTermsOfW p R m) = X m
⊢ ∑ x in range n, ↑C (↑p ^ x) * X x ^ p ^ (n - x) =
    ∑ x in range n, ↑(bind₁ (W_ R)) (↑C (↑p ^ x) * xInTermsOfW p R x ^ p ^ (n - x))
[PROOFSTEP]
apply sum_congr rfl
[GOAL]
case e_a
p : ℕ
R : Type u_1
inst✝² : CommRing R
inst✝¹ : DecidableEq R
inst✝ : Invertible ↑p
n : ℕ
H : ∀ (m : ℕ), m < n → ↑(bind₁ (W_ R)) (xInTermsOfW p R m) = X m
⊢ ∀ (x : ℕ),
    x ∈ range n → ↑C (↑p ^ x) * X x ^ p ^ (n - x) = ↑(bind₁ (W_ R)) (↑C (↑p ^ x) * xInTermsOfW p R x ^ p ^ (n - x))
[PROOFSTEP]
intro i h
[GOAL]
case e_a
p : ℕ
R : Type u_1
inst✝² : CommRing R
inst✝¹ : DecidableEq R
inst✝ : Invertible ↑p
n : ℕ
H : ∀ (m : ℕ), m < n → ↑(bind₁ (W_ R)) (xInTermsOfW p R m) = X m
i : ℕ
h : i ∈ range n
⊢ ↑C (↑p ^ i) * X i ^ p ^ (n - i) = ↑(bind₁ (W_ R)) (↑C (↑p ^ i) * xInTermsOfW p R i ^ p ^ (n - i))
[PROOFSTEP]
rw [mem_range] at h
[GOAL]
case e_a
p : ℕ
R : Type u_1
inst✝² : CommRing R
inst✝¹ : DecidableEq R
inst✝ : Invertible ↑p
n : ℕ
H : ∀ (m : ℕ), m < n → ↑(bind₁ (W_ R)) (xInTermsOfW p R m) = X m
i : ℕ
h : i < n
⊢ ↑C (↑p ^ i) * X i ^ p ^ (n - i) = ↑(bind₁ (W_ R)) (↑C (↑p ^ i) * xInTermsOfW p R i ^ p ^ (n - i))
[PROOFSTEP]
rw [AlgHom.map_mul, AlgHom.map_pow, algHom_C, H i h]


[GOAL]
p : ℕ
inst✝ : Fact (Nat.Prime p)
hp : p ≠ 2
⊢ legendreSym p 2 = ↑χ₈ ↑p
[PROOFSTEP]
have : (2 : ZMod p) = (2 : ℤ) := by norm_cast
[GOAL]
p : ℕ
inst✝ : Fact (Nat.Prime p)
hp : p ≠ 2
⊢ 2 = ↑2
[PROOFSTEP]
norm_cast
[GOAL]
p : ℕ
inst✝ : Fact (Nat.Prime p)
hp : p ≠ 2
this : 2 = ↑2
⊢ legendreSym p 2 = ↑χ₈ ↑p
[PROOFSTEP]
rw [legendreSym, ← this, quadraticChar_two ((ringChar_zmod_n p).substr hp), card p]
[GOAL]
p : ℕ
inst✝ : Fact (Nat.Prime p)
hp : p ≠ 2
⊢ legendreSym p (-2) = ↑χ₈' ↑p
[PROOFSTEP]
have : (-2 : ZMod p) = (-2 : ℤ) := by norm_cast
[GOAL]
p : ℕ
inst✝ : Fact (Nat.Prime p)
hp : p ≠ 2
⊢ -2 = ↑(-2)
[PROOFSTEP]
norm_cast
[GOAL]
p : ℕ
inst✝ : Fact (Nat.Prime p)
hp : p ≠ 2
this : -2 = ↑(-2)
⊢ legendreSym p (-2) = ↑χ₈' ↑p
[PROOFSTEP]
rw [legendreSym, ← this, quadraticChar_neg_two ((ringChar_zmod_n p).substr hp), card p]
[GOAL]
p : ℕ
inst✝ : Fact (Nat.Prime p)
hp : p ≠ 2
⊢ IsSquare 2 ↔ p % 8 = 1 ∨ p % 8 = 7
[PROOFSTEP]
rw [FiniteField.isSquare_two_iff, card p]
[GOAL]
p : ℕ
inst✝ : Fact (Nat.Prime p)
hp : p ≠ 2
⊢ p % 8 ≠ 3 ∧ p % 8 ≠ 5 ↔ p % 8 = 1 ∨ p % 8 = 7
[PROOFSTEP]
have h₁ := Prime.mod_two_eq_one_iff_ne_two.mpr hp
[GOAL]
p : ℕ
inst✝ : Fact (Nat.Prime p)
hp : p ≠ 2
h₁ : p % 2 = 1
⊢ p % 8 ≠ 3 ∧ p % 8 ≠ 5 ↔ p % 8 = 1 ∨ p % 8 = 7
[PROOFSTEP]
rw [← mod_mod_of_dvd p (by norm_num : 2 ∣ 8)] at h₁
[GOAL]
p : ℕ
inst✝ : Fact (Nat.Prime p)
hp : p ≠ 2
h₁ : p % 2 = 1
⊢ 2 ∣ 8
[PROOFSTEP]
norm_num
[GOAL]
p : ℕ
inst✝ : Fact (Nat.Prime p)
hp : p ≠ 2
h₁ : p % 8 % 2 = 1
⊢ p % 8 ≠ 3 ∧ p % 8 ≠ 5 ↔ p % 8 = 1 ∨ p % 8 = 7
[PROOFSTEP]
have h₂ := mod_lt p (by norm_num : 0 < 8)
[GOAL]
p : ℕ
inst✝ : Fact (Nat.Prime p)
hp : p ≠ 2
h₁ : p % 8 % 2 = 1
⊢ 0 < 8
[PROOFSTEP]
norm_num
[GOAL]
p : ℕ
inst✝ : Fact (Nat.Prime p)
hp : p ≠ 2
h₁ : p % 8 % 2 = 1
h₂ : p % 8 < 8
⊢ p % 8 ≠ 3 ∧ p % 8 ≠ 5 ↔ p % 8 = 1 ∨ p % 8 = 7
[PROOFSTEP]
revert h₂ h₁
[GOAL]
p : ℕ
inst✝ : Fact (Nat.Prime p)
hp : p ≠ 2
⊢ p % 8 % 2 = 1 → p % 8 < 8 → (p % 8 ≠ 3 ∧ p % 8 ≠ 5 ↔ p % 8 = 1 ∨ p % 8 = 7)
[PROOFSTEP]
generalize p % 8 = m
[GOAL]
p : ℕ
inst✝ : Fact (Nat.Prime p)
hp : p ≠ 2
m : ℕ
⊢ m % 2 = 1 → m < 8 → (m ≠ 3 ∧ m ≠ 5 ↔ m = 1 ∨ m = 7)
[PROOFSTEP]
clear! p
[GOAL]
m : ℕ
⊢ m % 2 = 1 → m < 8 → (m ≠ 3 ∧ m ≠ 5 ↔ m = 1 ∨ m = 7)
[PROOFSTEP]
intros
[GOAL]
m : ℕ
h₁✝ : m % 2 = 1
h₂✝ : m < 8
⊢ m ≠ 3 ∧ m ≠ 5 ↔ m = 1 ∨ m = 7
[PROOFSTEP]
interval_cases m
[GOAL]
case «0»
m : ℕ
h₁✝ : 0 % 2 = 1
h₂✝ : 0 < 8
⊢ 0 ≠ 3 ∧ 0 ≠ 5 ↔ 0 = 1 ∨ 0 = 7
[PROOFSTEP]
simp_all
  -- Porting note: was `decide!`
[GOAL]
case «1»
m : ℕ
h₁✝ : 1 % 2 = 1
h₂✝ : 1 < 8
⊢ 1 ≠ 3 ∧ 1 ≠ 5 ↔ 1 = 1 ∨ 1 = 7
[PROOFSTEP]
simp_all
  -- Porting note: was `decide!`
[GOAL]
case «2»
m : ℕ
h₁✝ : 2 % 2 = 1
h₂✝ : 2 < 8
⊢ 2 ≠ 3 ∧ 2 ≠ 5 ↔ 2 = 1 ∨ 2 = 7
[PROOFSTEP]
simp_all
  -- Porting note: was `decide!`
[GOAL]
case «3»
m : ℕ
h₁✝ : 3 % 2 = 1
h₂✝ : 3 < 8
⊢ 3 ≠ 3 ∧ 3 ≠ 5 ↔ 3 = 1 ∨ 3 = 7
[PROOFSTEP]
simp_all
  -- Porting note: was `decide!`
[GOAL]
case «4»
m : ℕ
h₁✝ : 4 % 2 = 1
h₂✝ : 4 < 8
⊢ 4 ≠ 3 ∧ 4 ≠ 5 ↔ 4 = 1 ∨ 4 = 7
[PROOFSTEP]
simp_all
  -- Porting note: was `decide!`
[GOAL]
case «5»
m : ℕ
h₁✝ : 5 % 2 = 1
h₂✝ : 5 < 8
⊢ 5 ≠ 3 ∧ 5 ≠ 5 ↔ 5 = 1 ∨ 5 = 7
[PROOFSTEP]
simp_all
  -- Porting note: was `decide!`
[GOAL]
case «6»
m : ℕ
h₁✝ : 6 % 2 = 1
h₂✝ : 6 < 8
⊢ 6 ≠ 3 ∧ 6 ≠ 5 ↔ 6 = 1 ∨ 6 = 7
[PROOFSTEP]
simp_all
  -- Porting note: was `decide!`
[GOAL]
case «7»
m : ℕ
h₁✝ : 7 % 2 = 1
h₂✝ : 7 < 8
⊢ 7 ≠ 3 ∧ 7 ≠ 5 ↔ 7 = 1 ∨ 7 = 7
[PROOFSTEP]
simp_all
  -- Porting note: was `decide!`
[GOAL]
p : ℕ
inst✝ : Fact (Nat.Prime p)
hp : p ≠ 2
⊢ IsSquare (-2) ↔ p % 8 = 1 ∨ p % 8 = 3
[PROOFSTEP]
rw [FiniteField.isSquare_neg_two_iff, card p]
[GOAL]
p : ℕ
inst✝ : Fact (Nat.Prime p)
hp : p ≠ 2
⊢ p % 8 ≠ 5 ∧ p % 8 ≠ 7 ↔ p % 8 = 1 ∨ p % 8 = 3
[PROOFSTEP]
have h₁ := Prime.mod_two_eq_one_iff_ne_two.mpr hp
[GOAL]
p : ℕ
inst✝ : Fact (Nat.Prime p)
hp : p ≠ 2
h₁ : p % 2 = 1
⊢ p % 8 ≠ 5 ∧ p % 8 ≠ 7 ↔ p % 8 = 1 ∨ p % 8 = 3
[PROOFSTEP]
rw [← mod_mod_of_dvd p (by norm_num : 2 ∣ 8)] at h₁
[GOAL]
p : ℕ
inst✝ : Fact (Nat.Prime p)
hp : p ≠ 2
h₁ : p % 2 = 1
⊢ 2 ∣ 8
[PROOFSTEP]
norm_num
[GOAL]
p : ℕ
inst✝ : Fact (Nat.Prime p)
hp : p ≠ 2
h₁ : p % 8 % 2 = 1
⊢ p % 8 ≠ 5 ∧ p % 8 ≠ 7 ↔ p % 8 = 1 ∨ p % 8 = 3
[PROOFSTEP]
have h₂ := mod_lt p (by norm_num : 0 < 8)
[GOAL]
p : ℕ
inst✝ : Fact (Nat.Prime p)
hp : p ≠ 2
h₁ : p % 8 % 2 = 1
⊢ 0 < 8
[PROOFSTEP]
norm_num
[GOAL]
p : ℕ
inst✝ : Fact (Nat.Prime p)
hp : p ≠ 2
h₁ : p % 8 % 2 = 1
h₂ : p % 8 < 8
⊢ p % 8 ≠ 5 ∧ p % 8 ≠ 7 ↔ p % 8 = 1 ∨ p % 8 = 3
[PROOFSTEP]
revert h₂ h₁
[GOAL]
p : ℕ
inst✝ : Fact (Nat.Prime p)
hp : p ≠ 2
⊢ p % 8 % 2 = 1 → p % 8 < 8 → (p % 8 ≠ 5 ∧ p % 8 ≠ 7 ↔ p % 8 = 1 ∨ p % 8 = 3)
[PROOFSTEP]
generalize p % 8 = m
[GOAL]
p : ℕ
inst✝ : Fact (Nat.Prime p)
hp : p ≠ 2
m : ℕ
⊢ m % 2 = 1 → m < 8 → (m ≠ 5 ∧ m ≠ 7 ↔ m = 1 ∨ m = 3)
[PROOFSTEP]
clear! p
[GOAL]
m : ℕ
⊢ m % 2 = 1 → m < 8 → (m ≠ 5 ∧ m ≠ 7 ↔ m = 1 ∨ m = 3)
[PROOFSTEP]
intros
[GOAL]
m : ℕ
h₁✝ : m % 2 = 1
h₂✝ : m < 8
⊢ m ≠ 5 ∧ m ≠ 7 ↔ m = 1 ∨ m = 3
[PROOFSTEP]
interval_cases m
[GOAL]
case «0»
m : ℕ
h₁✝ : 0 % 2 = 1
h₂✝ : 0 < 8
⊢ 0 ≠ 5 ∧ 0 ≠ 7 ↔ 0 = 1 ∨ 0 = 3
[PROOFSTEP]
simp_all
  -- Porting note: was `decide!`
[GOAL]
case «1»
m : ℕ
h₁✝ : 1 % 2 = 1
h₂✝ : 1 < 8
⊢ 1 ≠ 5 ∧ 1 ≠ 7 ↔ 1 = 1 ∨ 1 = 3
[PROOFSTEP]
simp_all
  -- Porting note: was `decide!`
[GOAL]
case «2»
m : ℕ
h₁✝ : 2 % 2 = 1
h₂✝ : 2 < 8
⊢ 2 ≠ 5 ∧ 2 ≠ 7 ↔ 2 = 1 ∨ 2 = 3
[PROOFSTEP]
simp_all
  -- Porting note: was `decide!`
[GOAL]
case «3»
m : ℕ
h₁✝ : 3 % 2 = 1
h₂✝ : 3 < 8
⊢ 3 ≠ 5 ∧ 3 ≠ 7 ↔ 3 = 1 ∨ 3 = 3
[PROOFSTEP]
simp_all
  -- Porting note: was `decide!`
[GOAL]
case «4»
m : ℕ
h₁✝ : 4 % 2 = 1
h₂✝ : 4 < 8
⊢ 4 ≠ 5 ∧ 4 ≠ 7 ↔ 4 = 1 ∨ 4 = 3
[PROOFSTEP]
simp_all
  -- Porting note: was `decide!`
[GOAL]
case «5»
m : ℕ
h₁✝ : 5 % 2 = 1
h₂✝ : 5 < 8
⊢ 5 ≠ 5 ∧ 5 ≠ 7 ↔ 5 = 1 ∨ 5 = 3
[PROOFSTEP]
simp_all
  -- Porting note: was `decide!`
[GOAL]
case «6»
m : ℕ
h₁✝ : 6 % 2 = 1
h₂✝ : 6 < 8
⊢ 6 ≠ 5 ∧ 6 ≠ 7 ↔ 6 = 1 ∨ 6 = 3
[PROOFSTEP]
simp_all
  -- Porting note: was `decide!`
[GOAL]
case «7»
m : ℕ
h₁✝ : 7 % 2 = 1
h₂✝ : 7 < 8
⊢ 7 ≠ 5 ∧ 7 ≠ 7 ↔ 7 = 1 ∨ 7 = 3
[PROOFSTEP]
simp_all
  -- Porting note: was `decide!`
[GOAL]
p q : ℕ
inst✝¹ : Fact (Nat.Prime p)
inst✝ : Fact (Nat.Prime q)
hp : p ≠ 2
hq : q ≠ 2
hpq : p ≠ q
⊢ legendreSym q ↑p * legendreSym p ↑q = (-1) ^ (p / 2 * (q / 2))
[PROOFSTEP]
have hp₁ := (Prime.eq_two_or_odd <| @Fact.out p.Prime _).resolve_left hp
[GOAL]
p q : ℕ
inst✝¹ : Fact (Nat.Prime p)
inst✝ : Fact (Nat.Prime q)
hp : p ≠ 2
hq : q ≠ 2
hpq : p ≠ q
hp₁ : p % 2 = 1
⊢ legendreSym q ↑p * legendreSym p ↑q = (-1) ^ (p / 2 * (q / 2))
[PROOFSTEP]
have hq₁ := (Prime.eq_two_or_odd <| @Fact.out q.Prime _).resolve_left hq
[GOAL]
p q : ℕ
inst✝¹ : Fact (Nat.Prime p)
inst✝ : Fact (Nat.Prime q)
hp : p ≠ 2
hq : q ≠ 2
hpq : p ≠ q
hp₁ : p % 2 = 1
hq₁ : q % 2 = 1
⊢ legendreSym q ↑p * legendreSym p ↑q = (-1) ^ (p / 2 * (q / 2))
[PROOFSTEP]
have hq₂ : ringChar (ZMod q) ≠ 2 := (ringChar_zmod_n q).substr hq
[GOAL]
p q : ℕ
inst✝¹ : Fact (Nat.Prime p)
inst✝ : Fact (Nat.Prime q)
hp : p ≠ 2
hq : q ≠ 2
hpq : p ≠ q
hp₁ : p % 2 = 1
hq₁ : q % 2 = 1
hq₂ : ringChar (ZMod q) ≠ 2
⊢ legendreSym q ↑p * legendreSym p ↑q = (-1) ^ (p / 2 * (q / 2))
[PROOFSTEP]
have h := quadraticChar_odd_prime ((ringChar_zmod_n p).substr hp) hq ((ringChar_zmod_n p).substr hpq)
[GOAL]
p q : ℕ
inst✝¹ : Fact (Nat.Prime p)
inst✝ : Fact (Nat.Prime q)
hp : p ≠ 2
hq : q ≠ 2
hpq : p ≠ q
hp₁ : p % 2 = 1
hq₁ : q % 2 = 1
hq₂ : ringChar (ZMod q) ≠ 2
h :
  ↑(quadraticChar (ZMod p)) ↑q = ↑(quadraticChar (ZMod q)) (↑(↑χ₄ ↑(Fintype.card (ZMod p))) * ↑(Fintype.card (ZMod p)))
⊢ legendreSym q ↑p * legendreSym p ↑q = (-1) ^ (p / 2 * (q / 2))
[PROOFSTEP]
rw [card p] at h
[GOAL]
p q : ℕ
inst✝¹ : Fact (Nat.Prime p)
inst✝ : Fact (Nat.Prime q)
hp : p ≠ 2
hq : q ≠ 2
hpq : p ≠ q
hp₁ : p % 2 = 1
hq₁ : q % 2 = 1
hq₂ : ringChar (ZMod q) ≠ 2
h : ↑(quadraticChar (ZMod p)) ↑q = ↑(quadraticChar (ZMod q)) (↑(↑χ₄ ↑p) * ↑p)
⊢ legendreSym q ↑p * legendreSym p ↑q = (-1) ^ (p / 2 * (q / 2))
[PROOFSTEP]
have nc : ∀ n r : ℕ, ((n : ℤ) : ZMod r) = n := fun n r => by norm_cast
[GOAL]
p q : ℕ
inst✝¹ : Fact (Nat.Prime p)
inst✝ : Fact (Nat.Prime q)
hp : p ≠ 2
hq : q ≠ 2
hpq : p ≠ q
hp₁ : p % 2 = 1
hq₁ : q % 2 = 1
hq₂ : ringChar (ZMod q) ≠ 2
h : ↑(quadraticChar (ZMod p)) ↑q = ↑(quadraticChar (ZMod q)) (↑(↑χ₄ ↑p) * ↑p)
n r : ℕ
⊢ ↑↑n = ↑n
[PROOFSTEP]
norm_cast
[GOAL]
p q : ℕ
inst✝¹ : Fact (Nat.Prime p)
inst✝ : Fact (Nat.Prime q)
hp : p ≠ 2
hq : q ≠ 2
hpq : p ≠ q
hp₁ : p % 2 = 1
hq₁ : q % 2 = 1
hq₂ : ringChar (ZMod q) ≠ 2
h : ↑(quadraticChar (ZMod p)) ↑q = ↑(quadraticChar (ZMod q)) (↑(↑χ₄ ↑p) * ↑p)
nc : ∀ (n r : ℕ), ↑↑n = ↑n
⊢ legendreSym q ↑p * legendreSym p ↑q = (-1) ^ (p / 2 * (q / 2))
[PROOFSTEP]
have nc' : (((-1) ^ (p / 2) : ℤ) : ZMod q) = (-1) ^ (p / 2) := by norm_cast
[GOAL]
p q : ℕ
inst✝¹ : Fact (Nat.Prime p)
inst✝ : Fact (Nat.Prime q)
hp : p ≠ 2
hq : q ≠ 2
hpq : p ≠ q
hp₁ : p % 2 = 1
hq₁ : q % 2 = 1
hq₂ : ringChar (ZMod q) ≠ 2
h : ↑(quadraticChar (ZMod p)) ↑q = ↑(quadraticChar (ZMod q)) (↑(↑χ₄ ↑p) * ↑p)
nc : ∀ (n r : ℕ), ↑↑n = ↑n
⊢ ↑((-1) ^ (p / 2)) = (-1) ^ (p / 2)
[PROOFSTEP]
norm_cast
[GOAL]
p q : ℕ
inst✝¹ : Fact (Nat.Prime p)
inst✝ : Fact (Nat.Prime q)
hp : p ≠ 2
hq : q ≠ 2
hpq : p ≠ q
hp₁ : p % 2 = 1
hq₁ : q % 2 = 1
hq₂ : ringChar (ZMod q) ≠ 2
h : ↑(quadraticChar (ZMod p)) ↑q = ↑(quadraticChar (ZMod q)) (↑(↑χ₄ ↑p) * ↑p)
nc : ∀ (n r : ℕ), ↑↑n = ↑n
nc' : ↑((-1) ^ (p / 2)) = (-1) ^ (p / 2)
⊢ legendreSym q ↑p * legendreSym p ↑q = (-1) ^ (p / 2 * (q / 2))
[PROOFSTEP]
rw [legendreSym, legendreSym, nc, nc, h, map_mul, mul_rotate', mul_comm (p / 2), ← pow_two,
  quadraticChar_sq_one (prime_ne_zero q p hpq.symm), mul_one, pow_mul, χ₄_eq_neg_one_pow hp₁, nc', map_pow,
  quadraticChar_neg_one hq₂, card q, χ₄_eq_neg_one_pow hq₁]
[GOAL]
p q : ℕ
inst✝¹ : Fact (Nat.Prime p)
inst✝ : Fact (Nat.Prime q)
hp : p ≠ 2
hq : q ≠ 2
⊢ legendreSym q ↑p = (-1) ^ (p / 2 * (q / 2)) * legendreSym p ↑q
[PROOFSTEP]
cases' eq_or_ne p q with h h
[GOAL]
case inl
p q : ℕ
inst✝¹ : Fact (Nat.Prime p)
inst✝ : Fact (Nat.Prime q)
hp : p ≠ 2
hq : q ≠ 2
h : p = q
⊢ legendreSym q ↑p = (-1) ^ (p / 2 * (q / 2)) * legendreSym p ↑q
[PROOFSTEP]
subst p
[GOAL]
case inl
q : ℕ
inst✝¹ : Fact (Nat.Prime q)
hq : q ≠ 2
inst✝ : Fact (Nat.Prime q)
hp : q ≠ 2
⊢ legendreSym q ↑q = (-1) ^ (q / 2 * (q / 2)) * legendreSym q ↑q
[PROOFSTEP]
rw [(eq_zero_iff q q).mpr (by exact_mod_cast nat_cast_self q), mul_zero]
[GOAL]
q : ℕ
inst✝¹ : Fact (Nat.Prime q)
hq : q ≠ 2
inst✝ : Fact (Nat.Prime q)
hp : q ≠ 2
⊢ ↑↑q = 0
[PROOFSTEP]
exact_mod_cast nat_cast_self q
[GOAL]
case inr
p q : ℕ
inst✝¹ : Fact (Nat.Prime p)
inst✝ : Fact (Nat.Prime q)
hp : p ≠ 2
hq : q ≠ 2
h : p ≠ q
⊢ legendreSym q ↑p = (-1) ^ (p / 2 * (q / 2)) * legendreSym p ↑q
[PROOFSTEP]
have qr := congr_arg (· * legendreSym p q) (quadratic_reciprocity hp hq h)
[GOAL]
case inr
p q : ℕ
inst✝¹ : Fact (Nat.Prime p)
inst✝ : Fact (Nat.Prime q)
hp : p ≠ 2
hq : q ≠ 2
h : p ≠ q
qr :
  (fun x => x * legendreSym p ↑q) (legendreSym q ↑p * legendreSym p ↑q) =
    (fun x => x * legendreSym p ↑q) ((-1) ^ (p / 2 * (q / 2)))
⊢ legendreSym q ↑p = (-1) ^ (p / 2 * (q / 2)) * legendreSym p ↑q
[PROOFSTEP]
have : ((q : ℤ) : ZMod p) ≠ 0 := by exact_mod_cast prime_ne_zero p q h
[GOAL]
p q : ℕ
inst✝¹ : Fact (Nat.Prime p)
inst✝ : Fact (Nat.Prime q)
hp : p ≠ 2
hq : q ≠ 2
h : p ≠ q
qr :
  (fun x => x * legendreSym p ↑q) (legendreSym q ↑p * legendreSym p ↑q) =
    (fun x => x * legendreSym p ↑q) ((-1) ^ (p / 2 * (q / 2)))
⊢ ↑↑q ≠ 0
[PROOFSTEP]
exact_mod_cast prime_ne_zero p q h
[GOAL]
case inr
p q : ℕ
inst✝¹ : Fact (Nat.Prime p)
inst✝ : Fact (Nat.Prime q)
hp : p ≠ 2
hq : q ≠ 2
h : p ≠ q
qr :
  (fun x => x * legendreSym p ↑q) (legendreSym q ↑p * legendreSym p ↑q) =
    (fun x => x * legendreSym p ↑q) ((-1) ^ (p / 2 * (q / 2)))
this : ↑↑q ≠ 0
⊢ legendreSym q ↑p = (-1) ^ (p / 2 * (q / 2)) * legendreSym p ↑q
[PROOFSTEP]
simpa only [mul_assoc, ← pow_two, sq_one p this, mul_one] using qr
[GOAL]
p q : ℕ
inst✝¹ : Fact (Nat.Prime p)
inst✝ : Fact (Nat.Prime q)
hp : p % 4 = 1
hq : q ≠ 2
⊢ legendreSym q ↑p = legendreSym p ↑q
[PROOFSTEP]
rw [quadratic_reciprocity' (Prime.mod_two_eq_one_iff_ne_two.mp (odd_of_mod_four_eq_one hp)) hq, pow_mul,
  neg_one_pow_div_two_of_one_mod_four hp, one_pow, one_mul]
[GOAL]
p q : ℕ
inst✝¹ : Fact (Nat.Prime p)
inst✝ : Fact (Nat.Prime q)
hp : p % 4 = 3
hq : q % 4 = 3
⊢ legendreSym q ↑p = -legendreSym p ↑q
[PROOFSTEP]
let nop := @neg_one_pow_div_two_of_three_mod_four
[GOAL]
p q : ℕ
inst✝¹ : Fact (Nat.Prime p)
inst✝ : Fact (Nat.Prime q)
hp : p % 4 = 3
hq : q % 4 = 3
nop : ∀ {n : ℕ}, n % 4 = 3 → (-1) ^ (n / 2) = -1 := @neg_one_pow_div_two_of_three_mod_four
⊢ legendreSym q ↑p = -legendreSym p ↑q
[PROOFSTEP]
rw [quadratic_reciprocity', pow_mul, nop hp, nop hq, neg_one_mul]
[GOAL]
case hp
p q : ℕ
inst✝¹ : Fact (Nat.Prime p)
inst✝ : Fact (Nat.Prime q)
hp : p % 4 = 3
hq : q % 4 = 3
nop : ∀ {n : ℕ}, n % 4 = 3 → (-1) ^ (n / 2) = -1 := @neg_one_pow_div_two_of_three_mod_four
⊢ p ≠ 2
[PROOFSTEP]
rwa [← Prime.mod_two_eq_one_iff_ne_two, odd_of_mod_four_eq_three]
[GOAL]
case hq
p q : ℕ
inst✝¹ : Fact (Nat.Prime p)
inst✝ : Fact (Nat.Prime q)
hp : p % 4 = 3
hq : q % 4 = 3
nop : ∀ {n : ℕ}, n % 4 = 3 → (-1) ^ (n / 2) = -1 := @neg_one_pow_div_two_of_three_mod_four
⊢ q ≠ 2
[PROOFSTEP]
rwa [← Prime.mod_two_eq_one_iff_ne_two, odd_of_mod_four_eq_three]
[GOAL]
p q : ℕ
inst✝¹ : Fact (Nat.Prime p)
inst✝ : Fact (Nat.Prime q)
hp1 : p % 4 = 1
hq1 : q ≠ 2
⊢ IsSquare ↑q ↔ IsSquare ↑p
[PROOFSTEP]
cases' eq_or_ne p q with h h
[GOAL]
case inl
p q : ℕ
inst✝¹ : Fact (Nat.Prime p)
inst✝ : Fact (Nat.Prime q)
hp1 : p % 4 = 1
hq1 : q ≠ 2
h : p = q
⊢ IsSquare ↑q ↔ IsSquare ↑p
[PROOFSTEP]
subst p
[GOAL]
case inl
q : ℕ
inst✝¹ : Fact (Nat.Prime q)
hq1 : q ≠ 2
inst✝ : Fact (Nat.Prime q)
hp1 : q % 4 = 1
⊢ IsSquare ↑q ↔ IsSquare ↑q
[PROOFSTEP]
rfl
[GOAL]
case inr
p q : ℕ
inst✝¹ : Fact (Nat.Prime p)
inst✝ : Fact (Nat.Prime q)
hp1 : p % 4 = 1
hq1 : q ≠ 2
h : p ≠ q
⊢ IsSquare ↑q ↔ IsSquare ↑p
[PROOFSTEP]
rw [← eq_one_iff' p (prime_ne_zero p q h), ← eq_one_iff' q (prime_ne_zero q p h.symm),
  quadratic_reciprocity_one_mod_four hp1 hq1]
[GOAL]
p q : ℕ
inst✝¹ : Fact (Nat.Prime p)
inst✝ : Fact (Nat.Prime q)
hp3 : p % 4 = 3
hq3 : q % 4 = 3
hpq : p ≠ q
⊢ IsSquare ↑q ↔ ¬IsSquare ↑p
[PROOFSTEP]
rw [← eq_one_iff' p (prime_ne_zero p q hpq), ← eq_neg_one_iff' q, quadratic_reciprocity_three_mod_four hp3 hq3, neg_inj]