|
2 | 2 | Copyright (c) 2018 Chris Hughes. All rights reserved.
|
3 | 3 | Released under Apache 2.0 license as described in the file LICENSE.
|
4 | 4 | Author: Chris Hughes
|
| 5 | +
|
| 6 | +# zmod and zmodp |
| 7 | +
|
| 8 | +Definition of the integers mod n, and the field structure on the integers mod p. |
| 9 | +
|
| 10 | +There are two types defined, `zmod n`, which is for integers modulo a positive nat `n : ℕ+`. |
| 11 | +`zmodp` is the type of integers modulo a prime number, for which a field structure is defined. |
| 12 | +
|
| 13 | +## Definitions |
| 14 | +
|
| 15 | +`val` is inherited from `fin` and returns the least natural number in the equivalence class |
| 16 | +
|
| 17 | +`val_min_abs` returns the integer closest to zero in the equivalence class. |
| 18 | +
|
| 19 | +A coercion `cast` is defined from `zmod n` into any semiring. This is a semiring hom if the ring has |
| 20 | +characteristic dividing `n` |
| 21 | +
|
| 22 | +## Implentation notes |
| 23 | +
|
| 24 | +`zmod` and `zmodp` are implemented as different types so that the field instance for `zmodp` can be |
| 25 | +synthesized. This leads to a lot of code duplication and most of the functions and theorems for |
| 26 | +`zmod` are restated for `zmodp` |
| 27 | +
|
5 | 28 | -/
|
6 |
| -import data.int.modeq data.int.gcd data.fintype data.pnat.basic |
| 29 | + |
| 30 | +import data.int.modeq data.int.gcd data.fintype data.pnat.basic tactic.ring |
7 | 31 |
|
8 | 32 | open nat nat.modeq int
|
9 | 33 |
|
@@ -241,6 +265,45 @@ def units_equiv_coprime {n : ℕ+} : units (zmod n) ≃ {x : zmod n // nat.copri
|
241 | 265 | left_inv := λ ⟨_, _, _, _⟩, units.ext rfl,
|
242 | 266 | right_inv := λ ⟨_, _⟩, rfl }
|
243 | 267 |
|
| 268 | +/-- `val_min_abs x` returns the integer in the same equivalence class as `x` that is closest to `0`, |
| 269 | + The result will be in the interval `(-n/2, n/2]` -/ |
| 270 | +def val_min_abs {n : ℕ+} (x : zmod n) : ℤ := |
| 271 | +if x.val ≤ n / 2 then x.val else x.val - n |
| 272 | + |
| 273 | +@[simp] lemma coe_val_min_abs {n : ℕ+} (x : zmod n) : |
| 274 | + (x.val_min_abs : zmod n) = x := |
| 275 | +by simp [zmod.val_min_abs]; split_ifs; simp |
| 276 | + |
| 277 | +lemma nat_abs_val_min_abs_le {n : ℕ+} (x : zmod n) : x.val_min_abs.nat_abs ≤ n / 2 := |
| 278 | +have (x.val - n : ℤ) ≤ 0, from sub_nonpos.2 $ int.coe_nat_le.2 $ le_of_lt x.2, |
| 279 | +begin |
| 280 | + rw zmod.val_min_abs, |
| 281 | + split_ifs with h, |
| 282 | + { exact h }, |
| 283 | + { rw [← int.coe_nat_le, int.of_nat_nat_abs_of_nonpos this, neg_sub], |
| 284 | + conv_lhs { congr, rw [coe_coe, ← nat.mod_add_div n 2, int.coe_nat_add, int.coe_nat_mul, |
| 285 | + int.coe_nat_bit0, int.coe_nat_one] }, |
| 286 | + rw ← sub_nonneg, |
| 287 | + suffices : (0 : ℤ) ≤ x.val - ((n % 2 : ℕ) + (n / 2 : ℕ)), |
| 288 | + { exact le_trans this (le_of_eq $ by ring) }, |
| 289 | + exact sub_nonneg.2 (by rw [← int.coe_nat_add, int.coe_nat_le]; |
| 290 | + exact calc (n : ℕ) % 2 + n / 2 ≤ 1 + n / 2 : |
| 291 | + add_le_add (nat.le_of_lt_succ (nat.mod_lt _ dec_trivial)) (le_refl _) |
| 292 | + ... ≤ x.val : by rw add_comm; exact nat.succ_le_of_lt (lt_of_not_ge h)) } |
| 293 | +end |
| 294 | + |
| 295 | +@[simp] lemma val_min_abs_zero {n : ℕ+} : (0 : zmod n).val_min_abs = 0 := |
| 296 | +by simp [zmod.val_min_abs] |
| 297 | + |
| 298 | +@[simp] lemma val_min_abs_eq_zero {n : ℕ+} (x : zmod n) : |
| 299 | + x.val_min_abs = 0 ↔ x = 0 := |
| 300 | +⟨λ h, begin |
| 301 | + dsimp [zmod.val_min_abs] at h, |
| 302 | + split_ifs at h, |
| 303 | + { exact fin.eq_of_veq (by simp * at *) }, |
| 304 | + { exact absurd h (mt sub_eq_zero.1 (ne_of_lt $ int.coe_nat_lt.2 x.2)) } |
| 305 | +end, λ hx0, hx0.symm ▸ zmod.val_min_abs_zero⟩ |
| 306 | + |
244 | 307 | section
|
245 | 308 | variables {α : Type*} [has_zero α] [has_one α] [has_add α] {n : ℕ+}
|
246 | 309 |
|
@@ -327,6 +390,27 @@ lemma le_div_two_iff_lt_neg {p : ℕ} (hp : prime p) (hp1 : p % 2 = 1)
|
327 | 390 | lemma ne_neg_self (hp1 : p % 2 = 1) {a : zmodp p hp} (ha : a ≠ 0) : a ≠ -a :=
|
328 | 391 | @zmod.ne_neg_self ⟨p, hp.pos⟩ hp1 _ ha
|
329 | 392 |
|
| 393 | +variable {hp} |
| 394 | + |
| 395 | +/-- `val_min_abs x` returns the integer in the same equivalence class as `x` that is closest to `0`, |
| 396 | + The result will be in the interval `(-n/2, n/2]` -/ |
| 397 | +def val_min_abs (x : zmodp p hp) : ℤ := zmod.val_min_abs x |
| 398 | + |
| 399 | +@[simp] lemma coe_val_min_abs (x : zmodp p hp) : |
| 400 | + (x.val_min_abs : zmodp p hp) = x := |
| 401 | +zmod.coe_val_min_abs x |
| 402 | + |
| 403 | +lemma nat_abs_val_min_abs_le (x : zmodp p hp) : x.val_min_abs.nat_abs ≤ p / 2 := |
| 404 | +zmod.nat_abs_val_min_abs_le x |
| 405 | + |
| 406 | +@[simp] lemma val_min_abs_zero : (0 : zmodp p hp).val_min_abs = 0 := |
| 407 | +zmod.val_min_abs_zero |
| 408 | + |
| 409 | +@[simp] lemma val_min_abs_eq_zero (x : zmodp p hp) : x.val_min_abs = 0 ↔ x = 0 := |
| 410 | +zmod.val_min_abs_eq_zero x |
| 411 | + |
| 412 | +variable (hp) |
| 413 | + |
330 | 414 | lemma prime_ne_zero {q : ℕ} (hq : prime q) (hpq : p ≠ q) : (q : zmodp p hp) ≠ 0 :=
|
331 | 415 | by rwa [← nat.cast_zero, ne.def, zmodp.eq_iff_modeq_nat, nat.modeq.modeq_zero_iff,
|
332 | 416 | ← hp.coprime_iff_not_dvd, coprime_primes hp hq]
|
|
0 commit comments