|
| 1 | +/- |
| 2 | +Copyright (c) 2022 Michael Stoll. All rights reserved. |
| 3 | +Released under Apache 2.0 license as described in the file LICENSE. |
| 4 | +Authors: Michael Stoll |
| 5 | +
|
| 6 | +! This file was ported from Lean 3 source module number_theory.legendre_symbol.zmod_char |
| 7 | +! leanprover-community/mathlib commit 70fd9563a21e7b963887c9360bd29b2393e6225a |
| 8 | +! Please do not edit these lines, except to modify the commit id |
| 9 | +! if you have ported upstream changes. |
| 10 | +-/ |
| 11 | +import Mathlib.Data.Int.Range |
| 12 | +import Mathlib.Data.ZMod.Basic |
| 13 | +import Mathlib.NumberTheory.LegendreSymbol.MulCharacter |
| 14 | + |
| 15 | +/-! |
| 16 | +# Quadratic characters on ℤ/nℤ |
| 17 | +
|
| 18 | +This file defines some quadratic characters on the rings ℤ/4ℤ and ℤ/8ℤ. |
| 19 | +
|
| 20 | +We set them up to be of type `MulChar (ZMod n) ℤ`, where `n` is `4` or `8`. |
| 21 | +
|
| 22 | +## Tags |
| 23 | +
|
| 24 | +quadratic character, zmod |
| 25 | +-/ |
| 26 | + |
| 27 | + |
| 28 | +/-! |
| 29 | +### Quadratic characters mod 4 and 8 |
| 30 | +
|
| 31 | +We define the primitive quadratic characters `χ₄`on `ZMod 4` |
| 32 | +and `χ₈`, `χ₈'` on `ZMod 8`. |
| 33 | +-/ |
| 34 | + |
| 35 | + |
| 36 | +namespace ZMod |
| 37 | + |
| 38 | +section QuadCharModP |
| 39 | + |
| 40 | +/-- Define the nontrivial quadratic character on `ZMod 4`, `χ₄`. |
| 41 | +It corresponds to the extension `ℚ(√-1)/ℚ`. -/ |
| 42 | +@[simps] |
| 43 | +def χ₄ : MulChar (ZMod 4) ℤ where |
| 44 | + toFun := (![0, 1, 0, -1] : ZMod 4 → ℤ) |
| 45 | + map_one' := rfl |
| 46 | + map_mul' := by decide |
| 47 | + map_nonunit' := by decide |
| 48 | +#align zmod.χ₄ ZMod.χ₄ |
| 49 | + |
| 50 | +/-- `χ₄` takes values in `{0, 1, -1}` -/ |
| 51 | +theorem isQuadratic_χ₄ : χ₄.IsQuadratic := by |
| 52 | + intro a |
| 53 | + -- Porting note: was `decide!` |
| 54 | + fin_cases a |
| 55 | + all_goals decide |
| 56 | +#align zmod.is_quadratic_χ₄ ZMod.isQuadratic_χ₄ |
| 57 | + |
| 58 | +/-- The value of `χ₄ n`, for `n : ℕ`, depends only on `n % 4`. -/ |
| 59 | +theorem χ₄_nat_mod_four (n : ℕ) : χ₄ n = χ₄ (n % 4 : ℕ) := by rw [← ZMod.nat_cast_mod n 4] |
| 60 | +#align zmod.χ₄_nat_mod_four ZMod.χ₄_nat_mod_four |
| 61 | + |
| 62 | +/-- The value of `χ₄ n`, for `n : ℤ`, depends only on `n % 4`. -/ |
| 63 | +theorem χ₄_int_mod_four (n : ℤ) : χ₄ n = χ₄ (n % 4 : ℤ) := by |
| 64 | + rw [← ZMod.int_cast_mod n 4] |
| 65 | + norm_cast |
| 66 | +#align zmod.χ₄_int_mod_four ZMod.χ₄_int_mod_four |
| 67 | + |
| 68 | +/-- An explicit description of `χ₄` on integers / naturals -/ |
| 69 | +theorem χ₄_int_eq_if_mod_four (n : ℤ) : |
| 70 | + χ₄ n = if n % 2 = 0 then 0 else if n % 4 = 1 then 1 else -1 := by |
| 71 | + have help : ∀ m : ℤ, 0 ≤ m → m < 4 → χ₄ m = if m % 2 = 0 then 0 else if m = 1 then 1 else -1 := by |
| 72 | + decide |
| 73 | + rw [← Int.emod_emod_of_dvd n (by norm_num : (2 : ℤ) ∣ 4), ← ZMod.int_cast_mod n 4] |
| 74 | + exact help (n % 4) (Int.emod_nonneg n (by norm_num)) (Int.emod_lt n (by norm_num)) |
| 75 | +#align zmod.χ₄_int_eq_if_mod_four ZMod.χ₄_int_eq_if_mod_four |
| 76 | + |
| 77 | +theorem χ₄_nat_eq_if_mod_four (n : ℕ) : |
| 78 | + χ₄ n = if n % 2 = 0 then 0 else if n % 4 = 1 then 1 else -1 := by |
| 79 | + exact_mod_cast χ₄_int_eq_if_mod_four n |
| 80 | +#align zmod.χ₄_nat_eq_if_mod_four ZMod.χ₄_nat_eq_if_mod_four |
| 81 | + |
| 82 | +/-- Alternative description of `χ₄ n` for odd `n : ℕ` in terms of powers of `-1` -/ |
| 83 | +theorem χ₄_eq_neg_one_pow {n : ℕ} (hn : n % 2 = 1) : χ₄ n = (-1) ^ (n / 2) := by |
| 84 | + rw [χ₄_nat_eq_if_mod_four] |
| 85 | + simp only [hn, Nat.one_ne_zero, if_false] |
| 86 | + --porting note: `nth_rw` didn't work here anymore. artifical workaround |
| 87 | + nth_rw 3 [← Nat.div_add_mod n 4] |
| 88 | + nth_rw 3 [(by norm_num : 4 = 2 * 2)] |
| 89 | + rw [mul_assoc, add_comm, Nat.add_mul_div_left _ _ (by norm_num : 0 < 2), pow_add, pow_mul, |
| 90 | + neg_one_sq, one_pow, mul_one] |
| 91 | + have help : ∀ m : ℕ, m < 4 → m % 2 = 1 → ite (m = 1) (1 : ℤ) (-1) = (-1) ^ (m / 2) := by decide |
| 92 | + exact |
| 93 | + help (n % 4) (Nat.mod_lt n (by norm_num)) |
| 94 | + ((Nat.mod_mod_of_dvd n (by norm_num : 2 ∣ 4)).trans hn) |
| 95 | +#align zmod.χ₄_eq_neg_one_pow ZMod.χ₄_eq_neg_one_pow |
| 96 | + |
| 97 | +/-- If `n % 4 = 1`, then `χ₄ n = 1`. -/ |
| 98 | +theorem χ₄_nat_one_mod_four {n : ℕ} (hn : n % 4 = 1) : χ₄ n = 1 := by |
| 99 | + rw [χ₄_nat_mod_four, hn] |
| 100 | + rfl |
| 101 | +#align zmod.χ₄_nat_one_mod_four ZMod.χ₄_nat_one_mod_four |
| 102 | + |
| 103 | +/-- If `n % 4 = 3`, then `χ₄ n = -1`. -/ |
| 104 | +theorem χ₄_nat_three_mod_four {n : ℕ} (hn : n % 4 = 3) : χ₄ n = -1 := by |
| 105 | + rw [χ₄_nat_mod_four, hn] |
| 106 | + rfl |
| 107 | +#align zmod.χ₄_nat_three_mod_four ZMod.χ₄_nat_three_mod_four |
| 108 | + |
| 109 | +/-- If `n % 4 = 1`, then `χ₄ n = 1`. -/ |
| 110 | +theorem χ₄_int_one_mod_four {n : ℤ} (hn : n % 4 = 1) : χ₄ n = 1 := by |
| 111 | + rw [χ₄_int_mod_four, hn] |
| 112 | + rfl |
| 113 | +#align zmod.χ₄_int_one_mod_four ZMod.χ₄_int_one_mod_four |
| 114 | + |
| 115 | +/-- If `n % 4 = 3`, then `χ₄ n = -1`. -/ |
| 116 | +theorem χ₄_int_three_mod_four {n : ℤ} (hn : n % 4 = 3) : χ₄ n = -1 := by |
| 117 | + rw [χ₄_int_mod_four, hn] |
| 118 | + rfl |
| 119 | +#align zmod.χ₄_int_three_mod_four ZMod.χ₄_int_three_mod_four |
| 120 | + |
| 121 | +/-- If `n % 4 = 1`, then `(-1)^(n/2) = 1`. -/ |
| 122 | +theorem neg_one_pow_div_two_of_one_mod_four {n : ℕ} (hn : n % 4 = 1) : (-1 : ℤ) ^ (n / 2) = 1 := by |
| 123 | + rw [← χ₄_eq_neg_one_pow (Nat.odd_of_mod_four_eq_one hn), ← nat_cast_mod, hn] |
| 124 | + rfl |
| 125 | +#align zmod.neg_one_pow_div_two_of_one_mod_four ZMod.neg_one_pow_div_two_of_one_mod_four |
| 126 | + |
| 127 | +/-- If `n % 4 = 3`, then `(-1)^(n/2) = -1`. -/ |
| 128 | +theorem neg_one_pow_div_two_of_three_mod_four {n : ℕ} (hn : n % 4 = 3) : |
| 129 | + (-1 : ℤ) ^ (n / 2) = -1 := by |
| 130 | + rw [← χ₄_eq_neg_one_pow (Nat.odd_of_mod_four_eq_three hn), ← nat_cast_mod, hn] |
| 131 | + rfl |
| 132 | +#align zmod.neg_one_pow_div_two_of_three_mod_four ZMod.neg_one_pow_div_two_of_three_mod_four |
| 133 | + |
| 134 | +lemma test : IsUnit (7 : ZMod 8) := by |
| 135 | + have : (7 : ZMod 8) * 7 = 1 := by decide |
| 136 | + exact isUnit_of_mul_eq_one (7 : ZMod 8) 7 this |
| 137 | + |
| 138 | +set_option maxHeartbeats 250000 in -- Porting note: otherwise `map_nonunit'` times out |
| 139 | +/-- Define the first primitive quadratic character on `ZMod 8`, `χ₈`. |
| 140 | +It corresponds to the extension `ℚ(√2)/ℚ`. -/ |
| 141 | +@[simps] |
| 142 | +def χ₈ : MulChar (ZMod 8) ℤ where |
| 143 | + toFun := (![0, 1, 0, -1, 0, -1, 0, 1] : ZMod 8 → ℤ) |
| 144 | + map_one' := rfl |
| 145 | + map_mul' := by decide |
| 146 | + map_nonunit' := by decide |
| 147 | +#align zmod.χ₈ ZMod.χ₈ |
| 148 | + |
| 149 | +/-- `χ₈` takes values in `{0, 1, -1}` -/ |
| 150 | +theorem isQuadratic_χ₈ : χ₈.IsQuadratic := by |
| 151 | + intro a |
| 152 | + --porting note: was `decide!` |
| 153 | + fin_cases a |
| 154 | + all_goals decide |
| 155 | +#align zmod.is_quadratic_χ₈ ZMod.isQuadratic_χ₈ |
| 156 | + |
| 157 | +/-- The value of `χ₈ n`, for `n : ℕ`, depends only on `n % 8`. -/ |
| 158 | +theorem χ₈_nat_mod_eight (n : ℕ) : χ₈ n = χ₈ (n % 8 : ℕ) := by rw [← ZMod.nat_cast_mod n 8] |
| 159 | +#align zmod.χ₈_nat_mod_eight ZMod.χ₈_nat_mod_eight |
| 160 | + |
| 161 | +/-- The value of `χ₈ n`, for `n : ℤ`, depends only on `n % 8`. -/ |
| 162 | +theorem χ₈_int_mod_eight (n : ℤ) : χ₈ n = χ₈ (n % 8 : ℤ) := by |
| 163 | + rw [← ZMod.int_cast_mod n 8] |
| 164 | + norm_cast |
| 165 | +#align zmod.χ₈_int_mod_eight ZMod.χ₈_int_mod_eight |
| 166 | + |
| 167 | +/-- An explicit description of `χ₈` on integers / naturals -/ |
| 168 | +theorem χ₈_int_eq_if_mod_eight (n : ℤ) : |
| 169 | + χ₈ n = if n % 2 = 0 then 0 else if n % 8 = 1 ∨ n % 8 = 7 then 1 else -1 := by |
| 170 | + have help : |
| 171 | + ∀ m : ℤ, 0 ≤ m → m < 8 → χ₈ m = if m % 2 = 0 then 0 else if m = 1 ∨ m = 7 then 1 else -1 := by |
| 172 | + decide |
| 173 | + rw [← Int.emod_emod_of_dvd n (by norm_num : (2 : ℤ) ∣ 8), ← ZMod.int_cast_mod n 8] |
| 174 | + exact help (n % 8) (Int.emod_nonneg n (by norm_num)) (Int.emod_lt n (by norm_num)) |
| 175 | +#align zmod.χ₈_int_eq_if_mod_eight ZMod.χ₈_int_eq_if_mod_eight |
| 176 | + |
| 177 | +theorem χ₈_nat_eq_if_mod_eight (n : ℕ) : |
| 178 | + χ₈ n = if n % 2 = 0 then 0 else if n % 8 = 1 ∨ n % 8 = 7 then 1 else -1 := by |
| 179 | + exact_mod_cast χ₈_int_eq_if_mod_eight n |
| 180 | +#align zmod.χ₈_nat_eq_if_mod_eight ZMod.χ₈_nat_eq_if_mod_eight |
| 181 | + |
| 182 | +set_option maxHeartbeats 250000 in -- Porting note: otherwise `map_nonunit'` times out |
| 183 | +/-- Define the second primitive quadratic character on `ZMod 8`, `χ₈'`. |
| 184 | +It corresponds to the extension `ℚ(√-2)/ℚ`. -/ |
| 185 | +@[simps] |
| 186 | +def χ₈' : MulChar (ZMod 8) ℤ where |
| 187 | + toFun := (![0, 1, 0, 1, 0, -1, 0, -1] : ZMod 8 → ℤ) |
| 188 | + map_one' := rfl |
| 189 | + map_mul' := by decide |
| 190 | + map_nonunit' := by decide |
| 191 | +#align zmod.χ₈' ZMod.χ₈' |
| 192 | + |
| 193 | +/-- `χ₈'` takes values in `{0, 1, -1}` -/ |
| 194 | +theorem isQuadratic_χ₈' : χ₈'.IsQuadratic := by |
| 195 | + intro a |
| 196 | + --porting note: was `decide!` |
| 197 | + fin_cases a |
| 198 | + all_goals decide |
| 199 | +#align zmod.is_quadratic_χ₈' ZMod.isQuadratic_χ₈' |
| 200 | + |
| 201 | +/-- An explicit description of `χ₈'` on integers / naturals -/ |
| 202 | +theorem χ₈'_int_eq_if_mod_eight (n : ℤ) : |
| 203 | + χ₈' n = if n % 2 = 0 then 0 else if n % 8 = 1 ∨ n % 8 = 3 then 1 else -1 := by |
| 204 | + have help : |
| 205 | + ∀ m : ℤ, 0 ≤ m → m < 8 → χ₈' m = if m % 2 = 0 then 0 else if m = 1 ∨ m = 3 then 1 else -1 := by |
| 206 | + decide |
| 207 | + rw [← Int.emod_emod_of_dvd n (by norm_num : (2 : ℤ) ∣ 8), ← ZMod.int_cast_mod n 8] |
| 208 | + exact help (n % 8) (Int.emod_nonneg n (by norm_num)) (Int.emod_lt n (by norm_num)) |
| 209 | +#align zmod.χ₈'_int_eq_if_mod_eight ZMod.χ₈'_int_eq_if_mod_eight |
| 210 | + |
| 211 | +theorem χ₈'_nat_eq_if_mod_eight (n : ℕ) : |
| 212 | + χ₈' n = if n % 2 = 0 then 0 else if n % 8 = 1 ∨ n % 8 = 3 then 1 else -1 := by |
| 213 | + exact_mod_cast χ₈'_int_eq_if_mod_eight n |
| 214 | +#align zmod.χ₈'_nat_eq_if_mod_eight ZMod.χ₈'_nat_eq_if_mod_eight |
| 215 | + |
| 216 | +/-- The relation between `χ₄`, `χ₈` and `χ₈'` -/ |
| 217 | +theorem χ₈'_eq_χ₄_mul_χ₈ (a : ZMod 8) : χ₈' a = χ₄ a * χ₈ a := by |
| 218 | + --porting note: was `decide!` |
| 219 | + fin_cases a |
| 220 | + all_goals decide |
| 221 | +#align zmod.χ₈'_eq_χ₄_mul_χ₈ ZMod.χ₈'_eq_χ₄_mul_χ₈ |
| 222 | + |
| 223 | +theorem χ₈'_int_eq_χ₄_mul_χ₈ (a : ℤ) : χ₈' a = χ₄ a * χ₈ a := by |
| 224 | + rw [← @cast_int_cast 8 (ZMod 4) _ 4 _ (by norm_num) a] |
| 225 | + exact χ₈'_eq_χ₄_mul_χ₈ a |
| 226 | +#align zmod.χ₈'_int_eq_χ₄_mul_χ₈ ZMod.χ₈'_int_eq_χ₄_mul_χ₈ |
| 227 | + |
| 228 | +end QuadCharModP |
| 229 | + |
| 230 | +end ZMod |
0 commit comments