@@ -105,31 +105,45 @@ by rw [modeq_iff_dvd] at *; exact dvd.trans (dvd_mul_left (n : ℤ) (m : ℤ)) h
105
105
theorem modeq_of_modeq_mul_right (m : ℕ) : a ≡ b [MOD n * m] → a ≡ b [MOD n] :=
106
106
mul_comm m n ▸ modeq_of_modeq_mul_left _
107
107
108
+ theorem modeq_one : a ≡ b [MOD 1 ] := modeq_of_dvd $ one_dvd _
109
+
108
110
local attribute [semireducible] int.nonneg
109
111
112
+ /-- The natural number less than `lcm n m` congruent to `a` mod `n` and `b` mod `m` -/
113
+ def chinese_remainder' (h : a ≡ b [MOD gcd n m]) : {k // k ≡ a [MOD n] ∧ k ≡ b [MOD m]} :=
114
+ if hn : n = 0 then ⟨a, begin rw [hn, gcd_zero_left] at h, split, refl, exact h end ⟩ else
115
+ if hm : m = 0 then ⟨b, begin rw [hm, gcd_zero_right] at h, split, exact h.symm, refl end ⟩ else
116
+ ⟨let (c, d) := xgcd n m in int.to_nat (((n * c * b + m * d * a) / gcd n m) % lcm n m), begin
117
+ rw xgcd_val,
118
+ dsimp [chinese_remainder'._match_1],
119
+ rw [modeq_iff_dvd, modeq_iff_dvd,
120
+ int.to_nat_of_nonneg (int.mod_nonneg _ (int.coe_nat_ne_zero.2 (lcm_ne_zero hn hm)))],
121
+ have hnonzero : (gcd n m : ℤ) ≠ 0 := begin
122
+ norm_cast,
123
+ rw [nat.gcd_eq_zero_iff, not_and],
124
+ exact λ _, hm,
125
+ end ,
126
+ have hcoedvd : ∀ t, (gcd n m : ℤ) ∣ t * (b - a) := λ t, dvd_mul_of_dvd_right h.dvd_of_modeq _,
127
+ have := gcd_eq_gcd_ab n m,
128
+ split; rw [int.mod_def, ← sub_add]; refine dvd_add _ (dvd_mul_of_dvd_left _ _); try {norm_cast},
129
+ { rw ← sub_eq_iff_eq_add' at this ,
130
+ rw [← this , sub_mul, ← add_sub_assoc, add_comm, add_sub_assoc, ← mul_sub,
131
+ int.add_div_of_dvd_left, int.mul_div_cancel_left _ hnonzero, int.mul_div_assoc _ h.dvd_of_modeq,
132
+ ← sub_sub, sub_self, zero_sub, dvd_neg, mul_assoc],
133
+ exact dvd_mul_right _ _,
134
+ norm_cast, exact dvd_mul_right _ _, },
135
+ { exact dvd_lcm_left n m, },
136
+ { rw ← sub_eq_iff_eq_add at this ,
137
+ rw [← this , sub_mul, sub_add, ← mul_sub, int.sub_div_of_dvd, int.mul_div_cancel_left _ hnonzero,
138
+ int.mul_div_assoc _ h.dvd_of_modeq, ← sub_add, sub_self, zero_add, mul_assoc],
139
+ exact dvd_mul_right _ _,
140
+ exact hcoedvd _ },
141
+ { exact dvd_lcm_right n m, },
142
+ end ⟩
143
+
110
144
/-- The natural number less than `n*m` congruent to `a` mod `n` and `b` mod `m` -/
111
145
def chinese_remainder (co : coprime n m) (a b : ℕ) : {k // k ≡ a [MOD n] ∧ k ≡ b [MOD m]} :=
112
- ⟨let (c, d) := xgcd n m in int.to_nat ((b * c * n + a * d * m) % (n * m)), begin
113
- rw xgcd_val, dsimp [chinese_remainder._match_1],
114
- rw [modeq_iff_dvd, modeq_iff_dvd],
115
- rw [int.to_nat_of_nonneg], swap,
116
- { by_cases h₁ : n = 0 , {simp [coprime, h₁] at co, substs m n, simp},
117
- by_cases h₂ : m = 0 , {simp [coprime, h₂] at co, substs m n, simp},
118
- exact int.mod_nonneg _
119
- (mul_ne_zero (int.coe_nat_ne_zero.2 h₁) (int.coe_nat_ne_zero.2 h₂)) },
120
- have := gcd_eq_gcd_ab n m, simp [co.gcd_eq_one, mul_comm] at this ,
121
- rw [int.mod_def, ← sub_add, ← sub_add]; split,
122
- { refine dvd_add _ (dvd_trans (dvd_mul_right _ _) (dvd_mul_right _ _)),
123
- rw [add_comm, ← sub_sub], refine _root_.dvd_sub _ (dvd_mul_left _ _),
124
- have := congr_arg ((*) ↑a) this ,
125
- exact ⟨_, by rwa [mul_add, ← mul_assoc, ← mul_assoc, mul_one, mul_comm,
126
- ← sub_eq_iff_eq_add] at this ⟩ },
127
- { refine dvd_add _ (dvd_trans (dvd_mul_left _ _) (dvd_mul_right _ _)),
128
- rw [← sub_sub], refine _root_.dvd_sub _ (dvd_mul_left _ _),
129
- have := congr_arg ((*) ↑b) this ,
130
- exact ⟨_, by rwa [mul_add, ← mul_assoc, ← mul_assoc, mul_one, mul_comm _ ↑m,
131
- ← sub_eq_iff_eq_add'] at this ⟩ }
132
- end ⟩
146
+ chinese_remainder' (by convert modeq_one)
133
147
134
148
lemma modeq_and_modeq_iff_modeq_mul {a b m n : ℕ} (hmn : coprime m n) :
135
149
a ≡ b [MOD m] ∧ a ≡ b [MOD n] ↔ (a ≡ b [MOD m * n]) :=
0 commit comments