data.int.modeq
⟷
Mathlib.Data.Int.ModEq
The following section lists changes to this file in mathlib3 and mathlib4 that occured after the initial port. Most recent changes are shown first. Hovering over a commit will show all commits associated with the same mathlib3 commit.
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(last sync)
a/c ≡ b/c mod m/c → a ≡ b mod m
(#18666)
Also prove -a ≡ -b [ZMOD n] ↔ a ≡ b [ZMOD n]
, a ≡ b [ZMOD -n] ↔ a ≡ b [ZMOD n]
, generalise int.modeq.mul_left'
/int.modeq.mul_right'
, and rename
int.gcd_pos_of_non_zero_left
→ int.gcd_pos_of_ne_zero_left
int.gcd_pos_of_non_zero_right
→ int.gcd_pos_of_ne_zero_right
eq_iff_modeq_int
, char_p.int_coe_eq_int_coe_iff
→ char_p.int_cast_eq_int_cast
(they were duplicates)@@ -45,8 +45,12 @@ instance : is_refl _ (modeq n) := ⟨modeq.refl⟩
@[trans] protected theorem trans : a ≡ b [ZMOD n] → b ≡ c [ZMOD n] → a ≡ c [ZMOD n] := eq.trans
+protected lemma eq : a ≡ b [ZMOD n] → a % n = b % n := id
+
end modeq
+lemma modeq_comm : a ≡ b [ZMOD n] ↔ b ≡ a [ZMOD n] := ⟨modeq.symm, modeq.symm⟩
+
lemma coe_nat_modeq_iff {a b n : ℕ} : a ≡ b [ZMOD n] ↔ a ≡ b [MOD n] :=
by unfold modeq nat.modeq; rw ← int.coe_nat_eq_coe_nat_iff; simp [coe_nat_mod]
@@ -70,19 +74,27 @@ alias modeq_iff_dvd ↔ modeq.dvd modeq_of_dvd
theorem mod_modeq (a n) : a % n ≡ a [ZMOD n] := mod_mod _ _
+@[simp] lemma neg_modeq_neg : -a ≡ -b [ZMOD n] ↔ a ≡ b [ZMOD n] :=
+by simp [modeq_iff_dvd, dvd_sub_comm]
+
+@[simp] lemma modeq_neg : a ≡ b [ZMOD -n] ↔ a ≡ b [ZMOD n] := by simp [modeq_iff_dvd]
+
namespace modeq
protected lemma of_dvd (d : m ∣ n) (h : a ≡ b [ZMOD n]) : a ≡ b [ZMOD m] :=
modeq_of_dvd $ d.trans h.dvd
-protected theorem mul_left' (hc : 0 ≤ c) (h : a ≡ b [ZMOD n]) : c * a ≡ c * b [ZMOD (c * n)] :=
-or.cases_on hc.lt_or_eq (λ hc,
- by unfold modeq;
- simp [mul_mod_mul_of_pos hc, (show _ = _, from h)] )
-(λ hc, by simp [hc.symm])
+protected theorem mul_left' (h : a ≡ b [ZMOD n]) : c * a ≡ c * b [ZMOD (c * n)] :=
+begin
+ obtain hc | rfl | hc := lt_trichotomy c 0,
+ { rw [←neg_modeq_neg, ←modeq_neg, ←neg_mul, ←neg_mul, ←neg_mul],
+ simp only [modeq, mul_mod_mul_of_pos (neg_pos.2 hc), h.eq] },
+ { simp },
+ { simp only [modeq, mul_mod_mul_of_pos hc, h.eq] }
+end
-protected theorem mul_right' (hc : 0 ≤ c) (h : a ≡ b [ZMOD n]) : a * c ≡ b * c [ZMOD (n * c)] :=
-by rw [mul_comm a, mul_comm b, mul_comm n]; exact h.mul_left' hc
+protected theorem mul_right' (h : a ≡ b [ZMOD n]) : a * c ≡ b * c [ZMOD (n * c)] :=
+by rw [mul_comm a, mul_comm b, mul_comm n]; exact h.mul_left'
protected theorem add (h₁ : a ≡ b [ZMOD n]) (h₂ : c ≡ d [ZMOD n]) : a + c ≡ b + d [ZMOD n] :=
modeq_iff_dvd.2 $ by { convert dvd_add h₁.dvd h₂.dvd, ring }
@@ -122,13 +134,10 @@ protected theorem sub_right (c : ℤ) (h : a ≡ b [ZMOD n]) : a - c ≡ b - c [
h.sub modeq.rfl
protected theorem mul_left (c : ℤ) (h : a ≡ b [ZMOD n]) : c * a ≡ c * b [ZMOD n] :=
-or.cases_on (le_total 0 c)
-(λ hc, (h.mul_left' hc).of_dvd (dvd_mul_left _ _) )
-(λ hc, by rw [← neg_neg c, neg_mul, neg_mul _ b];
- exact ((h.mul_left' $ neg_nonneg.2 hc).of_dvd (dvd_mul_left _ _)).neg)
+h.mul_left'.of_dvd $ dvd_mul_left _ _
protected theorem mul_right (c : ℤ) (h : a ≡ b [ZMOD n]) : a * c ≡ b * c [ZMOD n] :=
-by { rw [mul_comm a, mul_comm b], exact h.mul_left c }
+h.mul_right'.of_dvd $ dvd_mul_right _ _
protected theorem mul (h₁ : a ≡ b [ZMOD n]) (h₂ : c ≡ d [ZMOD n]) : a * c ≡ b * d [ZMOD n] :=
(h₂.mul_left _).trans (h₁.mul_right _)
@@ -146,6 +155,28 @@ by rw [modeq_iff_dvd] at *; exact (dvd_mul_left n m).trans h
theorem of_mul_right (m : ℤ) : a ≡ b [ZMOD n * m] → a ≡ b [ZMOD n] :=
mul_comm m n ▸ of_mul_left _
+/-- To cancel a common factor `c` from a `modeq` we must divide the modulus `m` by `gcd m c`. -/
+lemma cancel_right_div_gcd (hm : 0 < m) (h : a * c ≡ b * c [ZMOD m]) : a ≡ b [ZMOD m / gcd m c] :=
+begin
+ let d := gcd m c,
+ have hmd := gcd_dvd_left m c,
+ have hcd := gcd_dvd_right m c,
+ rw modeq_iff_dvd at ⊢ h,
+ refine int.dvd_of_dvd_mul_right_of_gcd_one _ _,
+ show m / d ∣ c / d * (b - a),
+ { rw [mul_comm, ←int.mul_div_assoc (b - a) hcd, sub_mul],
+ exact int.div_dvd_div hmd h },
+ { rw [gcd_div hmd hcd, nat_abs_of_nat, nat.div_self (gcd_pos_of_ne_zero_left c hm.ne')] }
+end
+
+/-- To cancel a common factor `c` from a `modeq` we must divide the modulus `m` by `gcd m c`. -/
+lemma cancel_left_div_gcd (hm : 0 < m) (h : c * a ≡ c * b [ZMOD m]) : a ≡ b [ZMOD m / gcd m c] :=
+cancel_right_div_gcd hm $ by simpa [mul_comm] using h
+
+lemma of_div (h : a / c ≡ b / c [ZMOD m / c]) (ha : c ∣ a) (ha : c ∣ b) (ha : c ∣ m) :
+ a ≡ b [ZMOD m] :=
+by convert h.mul_left'; rwa int.mul_div_cancel'
+
end modeq
theorem modeq_one : a ≡ b [ZMOD 1] := modeq_of_dvd (one_dvd _)
@@ -153,6 +184,11 @@ theorem modeq_one : a ≡ b [ZMOD 1] := modeq_of_dvd (one_dvd _)
lemma modeq_sub (a b : ℤ) : a ≡ b [ZMOD a - b] :=
(modeq_of_dvd dvd_rfl).symm
+@[simp] lemma modeq_zero_iff : a ≡ b [ZMOD 0] ↔ a = b := by rw [modeq, mod_zero, mod_zero]
+
+@[simp] lemma add_modeq_left : n + a ≡ a [ZMOD n] := modeq.symm $ modeq_iff_dvd.2 $ by simp
+@[simp] lemma add_modeq_right : a + n ≡ a [ZMOD n] := modeq.symm $ modeq_iff_dvd.2 $ by simp
+
lemma modeq_and_modeq_iff_modeq_mul {a b m n : ℤ} (hmn : m.nat_abs.coprime n.nat_abs) :
a ≡ b [ZMOD m] ∧ a ≡ b [ZMOD n] ↔ (a ≡ b [ZMOD m * n]) :=
⟨λ h, begin
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
Quite a few modeq
lemmas are still called nat.modeq.modeq_something
or int.modeq.modeq_something
. I'm deleting the duplicated modeq
, so that lemmas (usually) become nat.modeq.something
and int.modeq.something
.
Also add nat.modeq.eq_of_lt_of_lt
as a corollary to nat.modeq.eq_of_abs_lt
.
@@ -66,15 +66,14 @@ begin
exact exists_congr (λ t, sub_eq_iff_eq_add'),
end
-theorem modeq.dvd : a ≡ b [ZMOD n] → n ∣ b - a := modeq_iff_dvd.1
-theorem modeq_of_dvd : n ∣ b - a → a ≡ b [ZMOD n] := modeq_iff_dvd.2
+alias modeq_iff_dvd ↔ modeq.dvd modeq_of_dvd
theorem mod_modeq (a n) : a % n ≡ a [ZMOD n] := mod_mod _ _
namespace modeq
-protected theorem modeq_of_dvd (d : m ∣ n) (h : a ≡ b [ZMOD n]) : a ≡ b [ZMOD m] :=
-modeq_iff_dvd.2 $ d.trans h.dvd
+protected lemma of_dvd (d : m ∣ n) (h : a ≡ b [ZMOD n]) : a ≡ b [ZMOD m] :=
+modeq_of_dvd $ d.trans h.dvd
protected theorem mul_left' (hc : 0 ≤ c) (h : a ≡ b [ZMOD n]) : c * a ≡ c * b [ZMOD (c * n)] :=
or.cases_on hc.lt_or_eq (λ hc,
@@ -124,9 +123,9 @@ h.sub modeq.rfl
protected theorem mul_left (c : ℤ) (h : a ≡ b [ZMOD n]) : c * a ≡ c * b [ZMOD n] :=
or.cases_on (le_total 0 c)
-(λ hc, (h.mul_left' hc).modeq_of_dvd (dvd_mul_left _ _) )
+(λ hc, (h.mul_left' hc).of_dvd (dvd_mul_left _ _) )
(λ hc, by rw [← neg_neg c, neg_mul, neg_mul _ b];
- exact ((h.mul_left' $ neg_nonneg.2 hc).modeq_of_dvd (dvd_mul_left _ _)).neg)
+ exact ((h.mul_left' $ neg_nonneg.2 hc).of_dvd (dvd_mul_left _ _)).neg)
protected theorem mul_right (c : ℤ) (h : a ≡ b [ZMOD n]) : a * c ≡ b * c [ZMOD n] :=
by { rw [mul_comm a, mul_comm b], exact h.mul_left c }
@@ -141,11 +140,11 @@ begin
exact h.mul hd,
end
-theorem of_modeq_mul_left (m : ℤ) (h : a ≡ b [ZMOD m * n]) : a ≡ b [ZMOD n] :=
+theorem of_mul_left (m : ℤ) (h : a ≡ b [ZMOD m * n]) : a ≡ b [ZMOD n] :=
by rw [modeq_iff_dvd] at *; exact (dvd_mul_left n m).trans h
-theorem of_modeq_mul_right (m : ℤ) : a ≡ b [ZMOD n * m] → a ≡ b [ZMOD n] :=
-mul_comm m n ▸ of_modeq_mul_left _
+theorem of_mul_right (m : ℤ) : a ≡ b [ZMOD n * m] → a ≡ b [ZMOD n] :=
+mul_comm m n ▸ of_mul_left _
end modeq
@@ -163,7 +162,7 @@ lemma modeq_and_modeq_iff_modeq_mul {a b m n : ℤ} (hmn : m.nat_abs.coprime n.n
refine hmn.mul_dvd_of_dvd_of_dvd _ _;
rw [← coe_nat_dvd, nat_abs_dvd, dvd_nat_abs]; tauto
end,
-λ h, ⟨h.of_modeq_mul_right _, h.of_modeq_mul_left _⟩⟩
+λ h, ⟨h.of_mul_right _, h.of_mul_left _⟩⟩
lemma gcd_a_modeq (a b : ℕ) : (a : ℤ) * nat.gcd_a a b ≡ nat.gcd a b [ZMOD b] :=
by { rw [← add_zero ((a : ℤ) * _), nat.gcd_eq_gcd_ab],
@@ -197,9 +196,9 @@ let ⟨z, hz1, hz2, hz3⟩ := exists_unique_equiv a hb in
@[simp] lemma mod_mul_right_mod (a b c : ℤ) : a % (b * c) % b = a % b :=
-(mod_modeq _ _).of_modeq_mul_right _
+(mod_modeq _ _).of_mul_right _
@[simp] lemma mod_mul_left_mod (a b c : ℤ) : a % (b * c) % c = a % c :=
-(mod_modeq _ _).of_modeq_mul_left _
+(mod_modeq _ _).of_mul_left _
end int
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(no changes)
(first ported)
mathlib commit https://github.com/leanprover-community/mathlib/commit/65a1391a0106c9204fe45bc73a039f056558cb83
@@ -3,7 +3,7 @@ Copyright (c) 2018 Chris Hughes. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Chris Hughes
-/
-import Data.Nat.Modeq
+import Data.Nat.ModEq
import Tactic.Ring
#align_import data.int.modeq from "leanprover-community/mathlib"@"47a1a73351de8dd6c8d3d32b569c8e434b03ca47"
@@ -86,10 +86,10 @@ theorem modEq_comm : a ≡ b [ZMOD n] ↔ b ≡ a [ZMOD n] :=
#align int.modeq_comm Int.modEq_comm
-/
-#print Int.coe_nat_modEq_iff /-
-theorem coe_nat_modEq_iff {a b n : ℕ} : a ≡ b [ZMOD n] ↔ a ≡ b [MOD n] := by
+#print Int.natCast_modEq_iff /-
+theorem natCast_modEq_iff {a b n : ℕ} : a ≡ b [ZMOD n] ↔ a ≡ b [MOD n] := by
unfold modeq Nat.ModEq <;> rw [← Int.ofNat_inj] <;> simp [coe_nat_mod]
-#align int.coe_nat_modeq_iff Int.coe_nat_modEq_iff
+#align int.coe_nat_modeq_iff Int.natCast_modEq_iff
-/
#print Int.modEq_zero_iff_dvd /-
@@ -260,7 +260,7 @@ protected theorem mul (h₁ : a ≡ b [ZMOD n]) (h₂ : c ≡ d [ZMOD n]) : a *
protected theorem pow (m : ℕ) (h : a ≡ b [ZMOD n]) : a ^ m ≡ b ^ m [ZMOD n] :=
by
induction' m with d hd; · rfl
- rw [pow_succ, pow_succ]
+ rw [pow_succ', pow_succ']
exact h.mul hd
#align int.modeq.pow Int.ModEq.pow
-/
mathlib commit https://github.com/leanprover-community/mathlib/commit/65a1391a0106c9204fe45bc73a039f056558cb83
@@ -204,7 +204,7 @@ protected theorem add_left_cancel' (c : ℤ) (h : c + a ≡ c + b [ZMOD n]) : a
#print Int.ModEq.add_right_cancel /-
protected theorem add_right_cancel (h₁ : c ≡ d [ZMOD n]) (h₂ : a + c ≡ b + d [ZMOD n]) :
- a ≡ b [ZMOD n] := by rw [add_comm a, add_comm b] at h₂ ; exact h₁.add_left_cancel h₂
+ a ≡ b [ZMOD n] := by rw [add_comm a, add_comm b] at h₂; exact h₁.add_left_cancel h₂
#align int.modeq.add_right_cancel Int.ModEq.add_right_cancel
-/
@@ -344,7 +344,7 @@ theorem add_modEq_right : a + n ≡ a [ZMOD n] :=
theorem modEq_and_modEq_iff_modEq_mul {a b m n : ℤ} (hmn : m.natAbs.Coprime n.natAbs) :
a ≡ b [ZMOD m] ∧ a ≡ b [ZMOD n] ↔ a ≡ b [ZMOD m * n] :=
⟨fun h => by
- rw [modeq_iff_dvd, modeq_iff_dvd] at h
+ rw [modeq_iff_dvd, modeq_iff_dvd] at h
rw [modeq_iff_dvd, ← nat_abs_dvd, ← dvd_nat_abs, coe_nat_dvd, nat_abs_mul]
refine' hmn.mul_dvd_of_dvd_of_dvd _ _ <;> rw [← coe_nat_dvd, nat_abs_dvd, dvd_nat_abs] <;>
tauto,
@@ -392,7 +392,7 @@ theorem exists_unique_equiv (a : ℤ) {b : ℤ} (hb : 0 < b) :
⟨a % b, emod_nonneg _ (ne_of_gt hb),
by
have : a % b < |b| := emod_lt _ (ne_of_gt hb)
- rwa [abs_of_pos hb] at this , by simp [modeq]⟩
+ rwa [abs_of_pos hb] at this, by simp [modeq]⟩
#align int.exists_unique_equiv Int.exists_unique_equiv
-/
mathlib commit https://github.com/leanprover-community/mathlib/commit/ce64cd319bb6b3e82f31c2d38e79080d377be451
@@ -3,8 +3,8 @@ Copyright (c) 2018 Chris Hughes. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Chris Hughes
-/
-import Mathbin.Data.Nat.Modeq
-import Mathbin.Tactic.Ring
+import Data.Nat.Modeq
+import Tactic.Ring
#align_import data.int.modeq from "leanprover-community/mathlib"@"47a1a73351de8dd6c8d3d32b569c8e434b03ca47"
mathlib commit https://github.com/leanprover-community/mathlib/commit/ce64cd319bb6b3e82f31c2d38e79080d377be451
@@ -341,7 +341,7 @@ theorem add_modEq_right : a + n ≡ a [ZMOD n] :=
-/
#print Int.modEq_and_modEq_iff_modEq_mul /-
-theorem modEq_and_modEq_iff_modEq_mul {a b m n : ℤ} (hmn : m.natAbs.coprime n.natAbs) :
+theorem modEq_and_modEq_iff_modEq_mul {a b m n : ℤ} (hmn : m.natAbs.Coprime n.natAbs) :
a ≡ b [ZMOD m] ∧ a ≡ b [ZMOD n] ↔ a ≡ b [ZMOD m * n] :=
⟨fun h => by
rw [modeq_iff_dvd, modeq_iff_dvd] at h
@@ -376,9 +376,9 @@ theorem modEq_add_fac_self {a t n : ℤ} : a + n * t ≡ a [ZMOD n] :=
-/
#print Int.mod_coprime /-
-theorem mod_coprime {a b : ℕ} (hab : Nat.coprime a b) : ∃ y : ℤ, a * y ≡ 1 [ZMOD b] :=
+theorem mod_coprime {a b : ℕ} (hab : Nat.Coprime a b) : ∃ y : ℤ, a * y ≡ 1 [ZMOD b] :=
⟨Nat.gcdA a b,
- have hgcd : Nat.gcd a b = 1 := Nat.coprime.gcd_eq_one hab
+ have hgcd : Nat.gcd a b = 1 := Nat.Coprime.gcd_eq_one hab
calc
↑a * Nat.gcdA a b ≡ ↑a * Nat.gcdA a b + ↑b * Nat.gcdB a b [ZMOD ↑b] :=
ModEq.symm <| modEq_add_fac _ <| ModEq.refl _
mathlib commit https://github.com/leanprover-community/mathlib/commit/32a7e535287f9c73f2e4d2aef306a39190f0b504
@@ -123,7 +123,7 @@ theorem modEq_iff_add_fac {a b n : ℤ} : a ≡ b [ZMOD n] ↔ ∃ t, b = a + n
#align int.modeq_iff_add_fac Int.modEq_iff_add_fac
-/
-alias modeq_iff_dvd ↔ modeq.dvd modeq_of_dvd
+alias ⟨modeq.dvd, modeq_of_dvd⟩ := modeq_iff_dvd
#align int.modeq.dvd Int.ModEq.dvd
#align int.modeq_of_dvd Int.modEq_of_dvd
mathlib commit https://github.com/leanprover-community/mathlib/commit/32a7e535287f9c73f2e4d2aef306a39190f0b504
@@ -252,7 +252,7 @@ protected theorem mul_right (c : ℤ) (h : a ≡ b [ZMOD n]) : a * c ≡ b * c [
#print Int.ModEq.mul /-
protected theorem mul (h₁ : a ≡ b [ZMOD n]) (h₂ : c ≡ d [ZMOD n]) : a * c ≡ b * d [ZMOD n] :=
- (h₂.mul_left _).trans (h₁.mul_right _)
+ (h₂.hMul_left _).trans (h₁.hMul_right _)
#align int.modeq.mul Int.ModEq.mul
-/
mathlib commit https://github.com/leanprover-community/mathlib/commit/8ea5598db6caeddde6cb734aa179cc2408dbd345
@@ -2,15 +2,12 @@
Copyright (c) 2018 Chris Hughes. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Chris Hughes
-
-! This file was ported from Lean 3 source module data.int.modeq
-! leanprover-community/mathlib commit 47a1a73351de8dd6c8d3d32b569c8e434b03ca47
-! Please do not edit these lines, except to modify the commit id
-! if you have ported upstream changes.
-/
import Mathbin.Data.Nat.Modeq
import Mathbin.Tactic.Ring
+#align_import data.int.modeq from "leanprover-community/mathlib"@"47a1a73351de8dd6c8d3d32b569c8e434b03ca47"
+
/-!
# Congruences modulo an integer
mathlib commit https://github.com/leanprover-community/mathlib/commit/9fb8964792b4237dac6200193a0d533f1b3f7423
@@ -39,7 +39,6 @@ deriving Decidable
#align int.modeq Int.ModEq
-/
--- mathport name: «expr ≡ [ZMOD ]»
notation:50 a " ≡ " b " [ZMOD " n "]" => ModEq n a b
variable {m n a b c d : ℤ}
@@ -96,20 +95,28 @@ theorem coe_nat_modEq_iff {a b n : ℕ} : a ≡ b [ZMOD n] ↔ a ≡ b [MOD n] :
#align int.coe_nat_modeq_iff Int.coe_nat_modEq_iff
-/
+#print Int.modEq_zero_iff_dvd /-
theorem modEq_zero_iff_dvd : a ≡ 0 [ZMOD n] ↔ n ∣ a := by rw [modeq, zero_mod, dvd_iff_mod_eq_zero]
#align int.modeq_zero_iff_dvd Int.modEq_zero_iff_dvd
+-/
+#print Dvd.dvd.modEq_zero_int /-
theorem Dvd.dvd.modEq_zero_int (h : n ∣ a) : a ≡ 0 [ZMOD n] :=
modEq_zero_iff_dvd.2 h
#align has_dvd.dvd.modeq_zero_int Dvd.dvd.modEq_zero_int
+-/
+#print Dvd.dvd.zero_modEq_int /-
theorem Dvd.dvd.zero_modEq_int (h : n ∣ a) : 0 ≡ a [ZMOD n] :=
h.modEq_zero_int.symm
#align has_dvd.dvd.zero_modeq_int Dvd.dvd.zero_modEq_int
+-/
+#print Int.modEq_iff_dvd /-
theorem modEq_iff_dvd : a ≡ b [ZMOD n] ↔ n ∣ b - a := by
rw [modeq, eq_comm] <;> simp [mod_eq_mod_iff_mod_sub_eq_zero, dvd_iff_mod_eq_zero]
#align int.modeq_iff_dvd Int.modEq_iff_dvd
+-/
#print Int.modEq_iff_add_fac /-
theorem modEq_iff_add_fac {a b n : ℤ} : a ≡ b [ZMOD n] ↔ ∃ t, b = a + n * t :=
@@ -143,9 +150,11 @@ theorem modEq_neg : a ≡ b [ZMOD -n] ↔ a ≡ b [ZMOD n] := by simp [modeq_iff
namespace Modeq
+#print Int.ModEq.of_dvd /-
protected theorem of_dvd (d : m ∣ n) (h : a ≡ b [ZMOD n]) : a ≡ b [ZMOD m] :=
modEq_of_dvd <| d.trans h.Dvd
#align int.modeq.of_dvd Int.ModEq.of_dvd
+-/
#print Int.ModEq.mul_left' /-
protected theorem mul_left' (h : a ≡ b [ZMOD n]) : c * a ≡ c * b [ZMOD c * n] :=
@@ -250,12 +259,14 @@ protected theorem mul (h₁ : a ≡ b [ZMOD n]) (h₂ : c ≡ d [ZMOD n]) : a *
#align int.modeq.mul Int.ModEq.mul
-/
+#print Int.ModEq.pow /-
protected theorem pow (m : ℕ) (h : a ≡ b [ZMOD n]) : a ^ m ≡ b ^ m [ZMOD n] :=
by
induction' m with d hd; · rfl
rw [pow_succ, pow_succ]
exact h.mul hd
#align int.modeq.pow Int.ModEq.pow
+-/
#print Int.ModEq.of_mul_left /-
theorem of_mul_left (m : ℤ) (h : a ≡ b [ZMOD m * n]) : a ≡ b [ZMOD n] := by
@@ -292,9 +303,11 @@ theorem cancel_left_div_gcd (hm : 0 < m) (h : c * a ≡ c * b [ZMOD m]) : a ≡
#align int.modeq.cancel_left_div_gcd Int.ModEq.cancel_left_div_gcd
-/
+#print Int.ModEq.of_div /-
theorem of_div (h : a / c ≡ b / c [ZMOD m / c]) (ha : c ∣ a) (ha : c ∣ b) (ha : c ∣ m) :
a ≡ b [ZMOD m] := by convert h.mul_left' <;> rwa [Int.mul_ediv_cancel']
#align int.modeq.of_div Int.ModEq.of_div
+-/
end Modeq
mathlib commit https://github.com/leanprover-community/mathlib/commit/7e5137f579de09a059a5ce98f364a04e221aabf0
@@ -356,7 +356,6 @@ theorem modEq_add_fac {a b n : ℤ} (c : ℤ) (ha : a ≡ b [ZMOD n]) : a + n *
a + n * c ≡ b + n * c [ZMOD n] := ha.add_right _
_ ≡ b + 0 [ZMOD n] := ((dvd_mul_right _ _).modEq_zero_int.add_left _)
_ ≡ b [ZMOD n] := by rw [add_zero]
-
#align int.modeq_add_fac Int.modEq_add_fac
-/
@@ -373,8 +372,7 @@ theorem mod_coprime {a b : ℕ} (hab : Nat.coprime a b) : ∃ y : ℤ, a * y ≡
calc
↑a * Nat.gcdA a b ≡ ↑a * Nat.gcdA a b + ↑b * Nat.gcdB a b [ZMOD ↑b] :=
ModEq.symm <| modEq_add_fac _ <| ModEq.refl _
- _ ≡ 1 [ZMOD ↑b] := by rw [← Nat.gcd_eq_gcd_ab, hgcd] <;> rfl
- ⟩
+ _ ≡ 1 [ZMOD ↑b] := by rw [← Nat.gcd_eq_gcd_ab, hgcd] <;> rfl⟩
#align int.mod_coprime Int.mod_coprime
-/
mathlib commit https://github.com/leanprover-community/mathlib/commit/cca40788df1b8755d5baf17ab2f27dacc2e17acb
@@ -34,7 +34,8 @@ namespace Int
#print Int.ModEq /-
/-- `a ≡ b [ZMOD n]` when `a % n = b % n`. -/
def ModEq (n a b : ℤ) :=
- a % n = b % n deriving Decidable
+ a % n = b % n
+deriving Decidable
#align int.modeq Int.ModEq
-/
@@ -197,7 +198,7 @@ protected theorem add_left_cancel' (c : ℤ) (h : c + a ≡ c + b [ZMOD n]) : a
#print Int.ModEq.add_right_cancel /-
protected theorem add_right_cancel (h₁ : c ≡ d [ZMOD n]) (h₂ : a + c ≡ b + d [ZMOD n]) :
- a ≡ b [ZMOD n] := by rw [add_comm a, add_comm b] at h₂; exact h₁.add_left_cancel h₂
+ a ≡ b [ZMOD n] := by rw [add_comm a, add_comm b] at h₂ ; exact h₁.add_left_cancel h₂
#align int.modeq.add_right_cancel Int.ModEq.add_right_cancel
-/
@@ -275,7 +276,7 @@ theorem cancel_right_div_gcd (hm : 0 < m) (h : a * c ≡ b * c [ZMOD m]) : a ≡
let d := gcd m c
have hmd := gcd_dvd_left m c
have hcd := gcd_dvd_right m c
- rw [modeq_iff_dvd] at h⊢
+ rw [modeq_iff_dvd] at h ⊢
refine' Int.dvd_of_dvd_mul_right_of_gcd_one _ _
show m / d ∣ c / d * (b - a)
· rw [mul_comm, ← Int.mul_ediv_assoc (b - a) hcd, sub_mul]
@@ -333,7 +334,7 @@ theorem add_modEq_right : a + n ≡ a [ZMOD n] :=
theorem modEq_and_modEq_iff_modEq_mul {a b m n : ℤ} (hmn : m.natAbs.coprime n.natAbs) :
a ≡ b [ZMOD m] ∧ a ≡ b [ZMOD n] ↔ a ≡ b [ZMOD m * n] :=
⟨fun h => by
- rw [modeq_iff_dvd, modeq_iff_dvd] at h
+ rw [modeq_iff_dvd, modeq_iff_dvd] at h
rw [modeq_iff_dvd, ← nat_abs_dvd, ← dvd_nat_abs, coe_nat_dvd, nat_abs_mul]
refine' hmn.mul_dvd_of_dvd_of_dvd _ _ <;> rw [← coe_nat_dvd, nat_abs_dvd, dvd_nat_abs] <;>
tauto,
@@ -383,7 +384,7 @@ theorem exists_unique_equiv (a : ℤ) {b : ℤ} (hb : 0 < b) :
⟨a % b, emod_nonneg _ (ne_of_gt hb),
by
have : a % b < |b| := emod_lt _ (ne_of_gt hb)
- rwa [abs_of_pos hb] at this, by simp [modeq]⟩
+ rwa [abs_of_pos hb] at this , by simp [modeq]⟩
#align int.exists_unique_equiv Int.exists_unique_equiv
-/
mathlib commit https://github.com/leanprover-community/mathlib/commit/917c3c072e487b3cccdbfeff17e75b40e45f66cb
@@ -95,41 +95,17 @@ theorem coe_nat_modEq_iff {a b n : ℕ} : a ≡ b [ZMOD n] ↔ a ≡ b [MOD n] :
#align int.coe_nat_modeq_iff Int.coe_nat_modEq_iff
-/
-/- warning: int.modeq_zero_iff_dvd -> Int.modEq_zero_iff_dvd is a dubious translation:
-lean 3 declaration is
- forall {n : Int} {a : Int}, Iff (Int.ModEq n a (OfNat.ofNat.{0} Int 0 (OfNat.mk.{0} Int 0 (Zero.zero.{0} Int Int.hasZero)))) (Dvd.Dvd.{0} Int (semigroupDvd.{0} Int Int.semigroup) n a)
-but is expected to have type
- forall {n : Int} {a : Int}, Iff (Int.ModEq n a (OfNat.ofNat.{0} Int 0 (instOfNatInt 0))) (Dvd.dvd.{0} Int Int.instDvdInt n a)
-Case conversion may be inaccurate. Consider using '#align int.modeq_zero_iff_dvd Int.modEq_zero_iff_dvdₓ'. -/
theorem modEq_zero_iff_dvd : a ≡ 0 [ZMOD n] ↔ n ∣ a := by rw [modeq, zero_mod, dvd_iff_mod_eq_zero]
#align int.modeq_zero_iff_dvd Int.modEq_zero_iff_dvd
-/- warning: has_dvd.dvd.modeq_zero_int -> Dvd.dvd.modEq_zero_int is a dubious translation:
-lean 3 declaration is
- forall {n : Int} {a : Int}, (Dvd.Dvd.{0} Int (semigroupDvd.{0} Int Int.semigroup) n a) -> (Int.ModEq n a (OfNat.ofNat.{0} Int 0 (OfNat.mk.{0} Int 0 (Zero.zero.{0} Int Int.hasZero))))
-but is expected to have type
- forall {n : Int} {a : Int}, (Dvd.dvd.{0} Int Int.instDvdInt n a) -> (Int.ModEq n a (OfNat.ofNat.{0} Int 0 (instOfNatInt 0)))
-Case conversion may be inaccurate. Consider using '#align has_dvd.dvd.modeq_zero_int Dvd.dvd.modEq_zero_intₓ'. -/
theorem Dvd.dvd.modEq_zero_int (h : n ∣ a) : a ≡ 0 [ZMOD n] :=
modEq_zero_iff_dvd.2 h
#align has_dvd.dvd.modeq_zero_int Dvd.dvd.modEq_zero_int
-/- warning: has_dvd.dvd.zero_modeq_int -> Dvd.dvd.zero_modEq_int is a dubious translation:
-lean 3 declaration is
- forall {n : Int} {a : Int}, (Dvd.Dvd.{0} Int (semigroupDvd.{0} Int Int.semigroup) n a) -> (Int.ModEq n (OfNat.ofNat.{0} Int 0 (OfNat.mk.{0} Int 0 (Zero.zero.{0} Int Int.hasZero))) a)
-but is expected to have type
- forall {n : Int} {a : Int}, (Dvd.dvd.{0} Int Int.instDvdInt n a) -> (Int.ModEq n (OfNat.ofNat.{0} Int 0 (instOfNatInt 0)) a)
-Case conversion may be inaccurate. Consider using '#align has_dvd.dvd.zero_modeq_int Dvd.dvd.zero_modEq_intₓ'. -/
theorem Dvd.dvd.zero_modEq_int (h : n ∣ a) : 0 ≡ a [ZMOD n] :=
h.modEq_zero_int.symm
#align has_dvd.dvd.zero_modeq_int Dvd.dvd.zero_modEq_int
-/- warning: int.modeq_iff_dvd -> Int.modEq_iff_dvd is a dubious translation:
-lean 3 declaration is
- forall {n : Int} {a : Int} {b : Int}, Iff (Int.ModEq n a b) (Dvd.Dvd.{0} Int (semigroupDvd.{0} Int Int.semigroup) n (HSub.hSub.{0, 0, 0} Int Int Int (instHSub.{0} Int Int.hasSub) b a))
-but is expected to have type
- forall {n : Int} {a : Int} {b : Int}, Iff (Int.ModEq n a b) (Dvd.dvd.{0} Int Int.instDvdInt n (HSub.hSub.{0, 0, 0} Int Int Int (instHSub.{0} Int Int.instSubInt) b a))
-Case conversion may be inaccurate. Consider using '#align int.modeq_iff_dvd Int.modEq_iff_dvdₓ'. -/
theorem modEq_iff_dvd : a ≡ b [ZMOD n] ↔ n ∣ b - a := by
rw [modeq, eq_comm] <;> simp [mod_eq_mod_iff_mod_sub_eq_zero, dvd_iff_mod_eq_zero]
#align int.modeq_iff_dvd Int.modEq_iff_dvd
@@ -142,18 +118,6 @@ theorem modEq_iff_add_fac {a b n : ℤ} : a ≡ b [ZMOD n] ↔ ∃ t, b = a + n
#align int.modeq_iff_add_fac Int.modEq_iff_add_fac
-/
-/- warning: int.modeq.dvd -> Int.ModEq.dvd is a dubious translation:
-lean 3 declaration is
- forall {n : Int} {a : Int} {b : Int}, (Int.ModEq n a b) -> (Dvd.Dvd.{0} Int (semigroupDvd.{0} Int Int.semigroup) n (HSub.hSub.{0, 0, 0} Int Int Int (instHSub.{0} Int Int.hasSub) b a))
-but is expected to have type
- forall {n : Int} {a : Int} {b : Int}, (Int.ModEq n a b) -> (Dvd.dvd.{0} Int Int.instDvdInt n (HSub.hSub.{0, 0, 0} Int Int Int (instHSub.{0} Int Int.instSubInt) b a))
-Case conversion may be inaccurate. Consider using '#align int.modeq.dvd Int.ModEq.dvdₓ'. -/
-/- warning: int.modeq_of_dvd -> Int.modEq_of_dvd is a dubious translation:
-lean 3 declaration is
- forall {n : Int} {a : Int} {b : Int}, (Dvd.Dvd.{0} Int (semigroupDvd.{0} Int Int.semigroup) n (HSub.hSub.{0, 0, 0} Int Int Int (instHSub.{0} Int Int.hasSub) b a)) -> (Int.ModEq n a b)
-but is expected to have type
- forall {n : Int} {a : Int} {b : Int}, (Dvd.dvd.{0} Int Int.instDvdInt n (HSub.hSub.{0, 0, 0} Int Int Int (instHSub.{0} Int Int.instSubInt) b a)) -> (Int.ModEq n a b)
-Case conversion may be inaccurate. Consider using '#align int.modeq_of_dvd Int.modEq_of_dvdₓ'. -/
alias modeq_iff_dvd ↔ modeq.dvd modeq_of_dvd
#align int.modeq.dvd Int.ModEq.dvd
#align int.modeq_of_dvd Int.modEq_of_dvd
@@ -178,12 +142,6 @@ theorem modEq_neg : a ≡ b [ZMOD -n] ↔ a ≡ b [ZMOD n] := by simp [modeq_iff
namespace Modeq
-/- warning: int.modeq.of_dvd -> Int.ModEq.of_dvd is a dubious translation:
-lean 3 declaration is
- forall {m : Int} {n : Int} {a : Int} {b : Int}, (Dvd.Dvd.{0} Int (semigroupDvd.{0} Int Int.semigroup) m n) -> (Int.ModEq n a b) -> (Int.ModEq m a b)
-but is expected to have type
- forall {m : Int} {n : Int} {a : Int} {b : Int}, (Dvd.dvd.{0} Int Int.instDvdInt m n) -> (Int.ModEq n a b) -> (Int.ModEq m a b)
-Case conversion may be inaccurate. Consider using '#align int.modeq.of_dvd Int.ModEq.of_dvdₓ'. -/
protected theorem of_dvd (d : m ∣ n) (h : a ≡ b [ZMOD n]) : a ≡ b [ZMOD m] :=
modEq_of_dvd <| d.trans h.Dvd
#align int.modeq.of_dvd Int.ModEq.of_dvd
@@ -291,12 +249,6 @@ protected theorem mul (h₁ : a ≡ b [ZMOD n]) (h₂ : c ≡ d [ZMOD n]) : a *
#align int.modeq.mul Int.ModEq.mul
-/
-/- warning: int.modeq.pow -> Int.ModEq.pow is a dubious translation:
-lean 3 declaration is
- forall {n : Int} {a : Int} {b : Int} (m : Nat), (Int.ModEq n a b) -> (Int.ModEq n (HPow.hPow.{0, 0, 0} Int Nat Int (instHPow.{0, 0} Int Nat (Monoid.Pow.{0} Int Int.monoid)) a m) (HPow.hPow.{0, 0, 0} Int Nat Int (instHPow.{0, 0} Int Nat (Monoid.Pow.{0} Int Int.monoid)) b m))
-but is expected to have type
- forall {n : Int} {a : Int} {b : Int} (m : Nat), (Int.ModEq n a b) -> (Int.ModEq n (HPow.hPow.{0, 0, 0} Int Nat Int Int.instHPowIntNat a m) (HPow.hPow.{0, 0, 0} Int Nat Int Int.instHPowIntNat b m))
-Case conversion may be inaccurate. Consider using '#align int.modeq.pow Int.ModEq.powₓ'. -/
protected theorem pow (m : ℕ) (h : a ≡ b [ZMOD n]) : a ^ m ≡ b ^ m [ZMOD n] :=
by
induction' m with d hd; · rfl
@@ -339,12 +291,6 @@ theorem cancel_left_div_gcd (hm : 0 < m) (h : c * a ≡ c * b [ZMOD m]) : a ≡
#align int.modeq.cancel_left_div_gcd Int.ModEq.cancel_left_div_gcd
-/
-/- warning: int.modeq.of_div -> Int.ModEq.of_div is a dubious translation:
-lean 3 declaration is
- forall {m : Int} {a : Int} {b : Int} {c : Int}, (Int.ModEq (HDiv.hDiv.{0, 0, 0} Int Int Int (instHDiv.{0} Int Int.hasDiv) m c) (HDiv.hDiv.{0, 0, 0} Int Int Int (instHDiv.{0} Int Int.hasDiv) a c) (HDiv.hDiv.{0, 0, 0} Int Int Int (instHDiv.{0} Int Int.hasDiv) b c)) -> (Dvd.Dvd.{0} Int (semigroupDvd.{0} Int Int.semigroup) c a) -> (Dvd.Dvd.{0} Int (semigroupDvd.{0} Int Int.semigroup) c b) -> (Dvd.Dvd.{0} Int (semigroupDvd.{0} Int Int.semigroup) c m) -> (Int.ModEq m a b)
-but is expected to have type
- forall {m : Int} {a : Int} {b : Int} {c : Int}, (Int.ModEq (HDiv.hDiv.{0, 0, 0} Int Int Int (instHDiv.{0} Int Int.instDivInt_1) m c) (HDiv.hDiv.{0, 0, 0} Int Int Int (instHDiv.{0} Int Int.instDivInt_1) a c) (HDiv.hDiv.{0, 0, 0} Int Int Int (instHDiv.{0} Int Int.instDivInt_1) b c)) -> (Dvd.dvd.{0} Int Int.instDvdInt c a) -> (Dvd.dvd.{0} Int Int.instDvdInt c b) -> (Dvd.dvd.{0} Int Int.instDvdInt c m) -> (Int.ModEq m a b)
-Case conversion may be inaccurate. Consider using '#align int.modeq.of_div Int.ModEq.of_divₓ'. -/
theorem of_div (h : a / c ≡ b / c [ZMOD m / c]) (ha : c ∣ a) (ha : c ∣ b) (ha : c ∣ m) :
a ≡ b [ZMOD m] := by convert h.mul_left' <;> rwa [Int.mul_ediv_cancel']
#align int.modeq.of_div Int.ModEq.of_div
mathlib commit https://github.com/leanprover-community/mathlib/commit/917c3c072e487b3cccdbfeff17e75b40e45f66cb
@@ -207,9 +207,7 @@ protected theorem mul_right' (h : a ≡ b [ZMOD n]) : a * c ≡ b * c [ZMOD n *
#print Int.ModEq.add /-
protected theorem add (h₁ : a ≡ b [ZMOD n]) (h₂ : c ≡ d [ZMOD n]) : a + c ≡ b + d [ZMOD n] :=
- modEq_iff_dvd.2 <| by
- convert dvd_add h₁.dvd h₂.dvd
- ring
+ modEq_iff_dvd.2 <| by convert dvd_add h₁.dvd h₂.dvd; ring
#align int.modeq.add Int.ModEq.add
-/
@@ -229,9 +227,7 @@ protected theorem add_right (c : ℤ) (h : a ≡ b [ZMOD n]) : a + c ≡ b + c [
protected theorem add_left_cancel (h₁ : a ≡ b [ZMOD n]) (h₂ : a + c ≡ b + d [ZMOD n]) :
c ≡ d [ZMOD n] :=
have : d - c = b + d - (a + c) - (b - a) := by ring
- modEq_iff_dvd.2 <| by
- rw [this]
- exact dvd_sub h₂.dvd h₁.dvd
+ modEq_iff_dvd.2 <| by rw [this]; exact dvd_sub h₂.dvd h₁.dvd
#align int.modeq.add_left_cancel Int.ModEq.add_left_cancel
-/
@@ -243,9 +239,7 @@ protected theorem add_left_cancel' (c : ℤ) (h : c + a ≡ c + b [ZMOD n]) : a
#print Int.ModEq.add_right_cancel /-
protected theorem add_right_cancel (h₁ : c ≡ d [ZMOD n]) (h₂ : a + c ≡ b + d [ZMOD n]) :
- a ≡ b [ZMOD n] := by
- rw [add_comm a, add_comm b] at h₂
- exact h₁.add_left_cancel h₂
+ a ≡ b [ZMOD n] := by rw [add_comm a, add_comm b] at h₂; exact h₁.add_left_cancel h₂
#align int.modeq.add_right_cancel Int.ModEq.add_right_cancel
-/
@@ -262,10 +256,8 @@ protected theorem neg (h : a ≡ b [ZMOD n]) : -a ≡ -b [ZMOD n] :=
-/
#print Int.ModEq.sub /-
-protected theorem sub (h₁ : a ≡ b [ZMOD n]) (h₂ : c ≡ d [ZMOD n]) : a - c ≡ b - d [ZMOD n] :=
- by
- rw [sub_eq_add_neg, sub_eq_add_neg]
- exact h₁.add h₂.neg
+protected theorem sub (h₁ : a ≡ b [ZMOD n]) (h₂ : c ≡ d [ZMOD n]) : a - c ≡ b - d [ZMOD n] := by
+ rw [sub_eq_add_neg, sub_eq_add_neg]; exact h₁.add h₂.neg
#align int.modeq.sub Int.ModEq.sub
-/
mathlib commit https://github.com/leanprover-community/mathlib/commit/06a655b5fcfbda03502f9158bbf6c0f1400886f9
@@ -75,15 +75,19 @@ protected theorem trans : a ≡ b [ZMOD n] → b ≡ c [ZMOD n] → a ≡ c [ZMO
#align int.modeq.trans Int.ModEq.trans
-/
+#print Int.ModEq.eq /-
protected theorem eq : a ≡ b [ZMOD n] → a % n = b % n :=
id
#align int.modeq.eq Int.ModEq.eq
+-/
end Modeq
+#print Int.modEq_comm /-
theorem modEq_comm : a ≡ b [ZMOD n] ↔ b ≡ a [ZMOD n] :=
⟨ModEq.symm, ModEq.symm⟩
#align int.modeq_comm Int.modEq_comm
+-/
#print Int.coe_nat_modEq_iff /-
theorem coe_nat_modEq_iff {a b n : ℕ} : a ≡ b [ZMOD n] ↔ a ≡ b [MOD n] := by
@@ -160,13 +164,17 @@ theorem mod_modEq (a n) : a % n ≡ a [ZMOD n] :=
#align int.mod_modeq Int.mod_modEq
-/
+#print Int.neg_modEq_neg /-
@[simp]
theorem neg_modEq_neg : -a ≡ -b [ZMOD n] ↔ a ≡ b [ZMOD n] := by simp [modeq_iff_dvd, dvd_sub_comm]
#align int.neg_modeq_neg Int.neg_modEq_neg
+-/
+#print Int.modEq_neg /-
@[simp]
theorem modEq_neg : a ≡ b [ZMOD -n] ↔ a ≡ b [ZMOD n] := by simp [modeq_iff_dvd]
#align int.modeq_neg Int.modEq_neg
+-/
namespace Modeq
@@ -180,12 +188,7 @@ protected theorem of_dvd (d : m ∣ n) (h : a ≡ b [ZMOD n]) : a ≡ b [ZMOD m]
modEq_of_dvd <| d.trans h.Dvd
#align int.modeq.of_dvd Int.ModEq.of_dvd
-/- warning: int.modeq.mul_left' -> Int.ModEq.mul_left' is a dubious translation:
-lean 3 declaration is
- forall {n : Int} {a : Int} {b : Int} {c : Int}, (Int.ModEq n a b) -> (Int.ModEq (HMul.hMul.{0, 0, 0} Int Int Int (instHMul.{0} Int Int.hasMul) c n) (HMul.hMul.{0, 0, 0} Int Int Int (instHMul.{0} Int Int.hasMul) c a) (HMul.hMul.{0, 0, 0} Int Int Int (instHMul.{0} Int Int.hasMul) c b))
-but is expected to have type
- forall {n : Int} {a : Int} {b : Int} {c : Int}, (LE.le.{0} Int Int.instLEInt (OfNat.ofNat.{0} Int 0 (instOfNatInt 0)) c) -> (Int.ModEq n a b) -> (Int.ModEq (HMul.hMul.{0, 0, 0} Int Int Int (instHMul.{0} Int Int.instMulInt) c n) (HMul.hMul.{0, 0, 0} Int Int Int (instHMul.{0} Int Int.instMulInt) c a) (HMul.hMul.{0, 0, 0} Int Int Int (instHMul.{0} Int Int.instMulInt) c b))
-Case conversion may be inaccurate. Consider using '#align int.modeq.mul_left' Int.ModEq.mul_left'ₓ'. -/
+#print Int.ModEq.mul_left' /-
protected theorem mul_left' (h : a ≡ b [ZMOD n]) : c * a ≡ c * b [ZMOD c * n] :=
by
obtain hc | rfl | hc := lt_trichotomy c 0
@@ -194,16 +197,13 @@ protected theorem mul_left' (h : a ≡ b [ZMOD n]) : c * a ≡ c * b [ZMOD c * n
· simp
· simp only [modeq, mul_mod_mul_of_pos hc, h.eq]
#align int.modeq.mul_left' Int.ModEq.mul_left'
+-/
-/- warning: int.modeq.mul_right' -> Int.ModEq.mul_right' is a dubious translation:
-lean 3 declaration is
- forall {n : Int} {a : Int} {b : Int} {c : Int}, (Int.ModEq n a b) -> (Int.ModEq (HMul.hMul.{0, 0, 0} Int Int Int (instHMul.{0} Int Int.hasMul) n c) (HMul.hMul.{0, 0, 0} Int Int Int (instHMul.{0} Int Int.hasMul) a c) (HMul.hMul.{0, 0, 0} Int Int Int (instHMul.{0} Int Int.hasMul) b c))
-but is expected to have type
- forall {n : Int} {a : Int} {b : Int} {c : Int}, (LE.le.{0} Int Int.instLEInt (OfNat.ofNat.{0} Int 0 (instOfNatInt 0)) c) -> (Int.ModEq n a b) -> (Int.ModEq (HMul.hMul.{0, 0, 0} Int Int Int (instHMul.{0} Int Int.instMulInt) n c) (HMul.hMul.{0, 0, 0} Int Int Int (instHMul.{0} Int Int.instMulInt) a c) (HMul.hMul.{0, 0, 0} Int Int Int (instHMul.{0} Int Int.instMulInt) b c))
-Case conversion may be inaccurate. Consider using '#align int.modeq.mul_right' Int.ModEq.mul_right'ₓ'. -/
+#print Int.ModEq.mul_right' /-
protected theorem mul_right' (h : a ≡ b [ZMOD n]) : a * c ≡ b * c [ZMOD n * c] := by
rw [mul_comm a, mul_comm b, mul_comm n] <;> exact h.mul_left'
#align int.modeq.mul_right' Int.ModEq.mul_right'
+-/
#print Int.ModEq.add /-
protected theorem add (h₁ : a ≡ b [ZMOD n]) (h₂ : c ≡ d [ZMOD n]) : a + c ≡ b + d [ZMOD n] :=
@@ -324,6 +324,7 @@ theorem of_mul_right (m : ℤ) : a ≡ b [ZMOD n * m] → a ≡ b [ZMOD n] :=
#align int.modeq.of_mul_right Int.ModEq.of_mul_right
-/
+#print Int.ModEq.cancel_right_div_gcd /-
/-- To cancel a common factor `c` from a `modeq` we must divide the modulus `m` by `gcd m c`. -/
theorem cancel_right_div_gcd (hm : 0 < m) (h : a * c ≡ b * c [ZMOD m]) : a ≡ b [ZMOD m / gcd m c] :=
by
@@ -337,12 +338,21 @@ theorem cancel_right_div_gcd (hm : 0 < m) (h : a * c ≡ b * c [ZMOD m]) : a ≡
exact Int.ediv_dvd_ediv hmd h
· rw [gcd_div hmd hcd, nat_abs_of_nat, Nat.div_self (gcd_pos_of_ne_zero_left c hm.ne')]
#align int.modeq.cancel_right_div_gcd Int.ModEq.cancel_right_div_gcd
+-/
+#print Int.ModEq.cancel_left_div_gcd /-
/-- To cancel a common factor `c` from a `modeq` we must divide the modulus `m` by `gcd m c`. -/
theorem cancel_left_div_gcd (hm : 0 < m) (h : c * a ≡ c * b [ZMOD m]) : a ≡ b [ZMOD m / gcd m c] :=
cancel_right_div_gcd hm <| by simpa [mul_comm] using h
#align int.modeq.cancel_left_div_gcd Int.ModEq.cancel_left_div_gcd
+-/
+/- warning: int.modeq.of_div -> Int.ModEq.of_div is a dubious translation:
+lean 3 declaration is
+ forall {m : Int} {a : Int} {b : Int} {c : Int}, (Int.ModEq (HDiv.hDiv.{0, 0, 0} Int Int Int (instHDiv.{0} Int Int.hasDiv) m c) (HDiv.hDiv.{0, 0, 0} Int Int Int (instHDiv.{0} Int Int.hasDiv) a c) (HDiv.hDiv.{0, 0, 0} Int Int Int (instHDiv.{0} Int Int.hasDiv) b c)) -> (Dvd.Dvd.{0} Int (semigroupDvd.{0} Int Int.semigroup) c a) -> (Dvd.Dvd.{0} Int (semigroupDvd.{0} Int Int.semigroup) c b) -> (Dvd.Dvd.{0} Int (semigroupDvd.{0} Int Int.semigroup) c m) -> (Int.ModEq m a b)
+but is expected to have type
+ forall {m : Int} {a : Int} {b : Int} {c : Int}, (Int.ModEq (HDiv.hDiv.{0, 0, 0} Int Int Int (instHDiv.{0} Int Int.instDivInt_1) m c) (HDiv.hDiv.{0, 0, 0} Int Int Int (instHDiv.{0} Int Int.instDivInt_1) a c) (HDiv.hDiv.{0, 0, 0} Int Int Int (instHDiv.{0} Int Int.instDivInt_1) b c)) -> (Dvd.dvd.{0} Int Int.instDvdInt c a) -> (Dvd.dvd.{0} Int Int.instDvdInt c b) -> (Dvd.dvd.{0} Int Int.instDvdInt c m) -> (Int.ModEq m a b)
+Case conversion may be inaccurate. Consider using '#align int.modeq.of_div Int.ModEq.of_divₓ'. -/
theorem of_div (h : a / c ≡ b / c [ZMOD m / c]) (ha : c ∣ a) (ha : c ∣ b) (ha : c ∣ m) :
a ≡ b [ZMOD m] := by convert h.mul_left' <;> rwa [Int.mul_ediv_cancel']
#align int.modeq.of_div Int.ModEq.of_div
@@ -361,19 +371,25 @@ theorem modEq_sub (a b : ℤ) : a ≡ b [ZMOD a - b] :=
#align int.modeq_sub Int.modEq_sub
-/
+#print Int.modEq_zero_iff /-
@[simp]
theorem modEq_zero_iff : a ≡ b [ZMOD 0] ↔ a = b := by rw [modeq, mod_zero, mod_zero]
#align int.modeq_zero_iff Int.modEq_zero_iff
+-/
+#print Int.add_modEq_left /-
@[simp]
theorem add_modEq_left : n + a ≡ a [ZMOD n] :=
ModEq.symm <| modEq_iff_dvd.2 <| by simp
#align int.add_modeq_left Int.add_modEq_left
+-/
+#print Int.add_modEq_right /-
@[simp]
theorem add_modEq_right : a + n ≡ a [ZMOD n] :=
ModEq.symm <| modEq_iff_dvd.2 <| by simp
#align int.add_modeq_right Int.add_modEq_right
+-/
#print Int.modEq_and_modEq_iff_modEq_mul /-
theorem modEq_and_modEq_iff_modEq_mul {a b m n : ℤ} (hmn : m.natAbs.coprime n.natAbs) :
mathlib commit https://github.com/leanprover-community/mathlib/commit/3cacc945118c8c637d89950af01da78307f59325
@@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE.
Authors: Chris Hughes
! This file was ported from Lean 3 source module data.int.modeq
-! leanprover-community/mathlib commit c0dbeca1a7a7f4959cdf6b2817629bafbf1547a0
+! leanprover-community/mathlib commit 47a1a73351de8dd6c8d3d32b569c8e434b03ca47
! Please do not edit these lines, except to modify the commit id
! if you have ported upstream changes.
-/
@@ -75,8 +75,16 @@ protected theorem trans : a ≡ b [ZMOD n] → b ≡ c [ZMOD n] → a ≡ c [ZMO
#align int.modeq.trans Int.ModEq.trans
-/
+protected theorem eq : a ≡ b [ZMOD n] → a % n = b % n :=
+ id
+#align int.modeq.eq Int.ModEq.eq
+
end Modeq
+theorem modEq_comm : a ≡ b [ZMOD n] ↔ b ≡ a [ZMOD n] :=
+ ⟨ModEq.symm, ModEq.symm⟩
+#align int.modeq_comm Int.modEq_comm
+
#print Int.coe_nat_modEq_iff /-
theorem coe_nat_modEq_iff {a b n : ℕ} : a ≡ b [ZMOD n] ↔ a ≡ b [MOD n] := by
unfold modeq Nat.ModEq <;> rw [← Int.ofNat_inj] <;> simp [coe_nat_mod]
@@ -152,6 +160,14 @@ theorem mod_modEq (a n) : a % n ≡ a [ZMOD n] :=
#align int.mod_modeq Int.mod_modEq
-/
+@[simp]
+theorem neg_modEq_neg : -a ≡ -b [ZMOD n] ↔ a ≡ b [ZMOD n] := by simp [modeq_iff_dvd, dvd_sub_comm]
+#align int.neg_modeq_neg Int.neg_modEq_neg
+
+@[simp]
+theorem modEq_neg : a ≡ b [ZMOD -n] ↔ a ≡ b [ZMOD n] := by simp [modeq_iff_dvd]
+#align int.modeq_neg Int.modEq_neg
+
namespace Modeq
/- warning: int.modeq.of_dvd -> Int.ModEq.of_dvd is a dubious translation:
@@ -164,19 +180,30 @@ protected theorem of_dvd (d : m ∣ n) (h : a ≡ b [ZMOD n]) : a ≡ b [ZMOD m]
modEq_of_dvd <| d.trans h.Dvd
#align int.modeq.of_dvd Int.ModEq.of_dvd
-#print Int.ModEq.mul_left' /-
-protected theorem mul_left' (hc : 0 ≤ c) (h : a ≡ b [ZMOD n]) : c * a ≡ c * b [ZMOD c * n] :=
- Or.cases_on hc.lt_or_eq
- (fun hc => by unfold modeq <;> simp [mul_mod_mul_of_pos hc, show _ = _ from h]) fun hc => by
- simp [hc.symm]
+/- warning: int.modeq.mul_left' -> Int.ModEq.mul_left' is a dubious translation:
+lean 3 declaration is
+ forall {n : Int} {a : Int} {b : Int} {c : Int}, (Int.ModEq n a b) -> (Int.ModEq (HMul.hMul.{0, 0, 0} Int Int Int (instHMul.{0} Int Int.hasMul) c n) (HMul.hMul.{0, 0, 0} Int Int Int (instHMul.{0} Int Int.hasMul) c a) (HMul.hMul.{0, 0, 0} Int Int Int (instHMul.{0} Int Int.hasMul) c b))
+but is expected to have type
+ forall {n : Int} {a : Int} {b : Int} {c : Int}, (LE.le.{0} Int Int.instLEInt (OfNat.ofNat.{0} Int 0 (instOfNatInt 0)) c) -> (Int.ModEq n a b) -> (Int.ModEq (HMul.hMul.{0, 0, 0} Int Int Int (instHMul.{0} Int Int.instMulInt) c n) (HMul.hMul.{0, 0, 0} Int Int Int (instHMul.{0} Int Int.instMulInt) c a) (HMul.hMul.{0, 0, 0} Int Int Int (instHMul.{0} Int Int.instMulInt) c b))
+Case conversion may be inaccurate. Consider using '#align int.modeq.mul_left' Int.ModEq.mul_left'ₓ'. -/
+protected theorem mul_left' (h : a ≡ b [ZMOD n]) : c * a ≡ c * b [ZMOD c * n] :=
+ by
+ obtain hc | rfl | hc := lt_trichotomy c 0
+ · rw [← neg_modeq_neg, ← modeq_neg, ← neg_mul, ← neg_mul, ← neg_mul]
+ simp only [modeq, mul_mod_mul_of_pos (neg_pos.2 hc), h.eq]
+ · simp
+ · simp only [modeq, mul_mod_mul_of_pos hc, h.eq]
#align int.modeq.mul_left' Int.ModEq.mul_left'
--/
-#print Int.ModEq.mul_right' /-
-protected theorem mul_right' (hc : 0 ≤ c) (h : a ≡ b [ZMOD n]) : a * c ≡ b * c [ZMOD n * c] := by
- rw [mul_comm a, mul_comm b, mul_comm n] <;> exact h.mul_left' hc
+/- warning: int.modeq.mul_right' -> Int.ModEq.mul_right' is a dubious translation:
+lean 3 declaration is
+ forall {n : Int} {a : Int} {b : Int} {c : Int}, (Int.ModEq n a b) -> (Int.ModEq (HMul.hMul.{0, 0, 0} Int Int Int (instHMul.{0} Int Int.hasMul) n c) (HMul.hMul.{0, 0, 0} Int Int Int (instHMul.{0} Int Int.hasMul) a c) (HMul.hMul.{0, 0, 0} Int Int Int (instHMul.{0} Int Int.hasMul) b c))
+but is expected to have type
+ forall {n : Int} {a : Int} {b : Int} {c : Int}, (LE.le.{0} Int Int.instLEInt (OfNat.ofNat.{0} Int 0 (instOfNatInt 0)) c) -> (Int.ModEq n a b) -> (Int.ModEq (HMul.hMul.{0, 0, 0} Int Int Int (instHMul.{0} Int Int.instMulInt) n c) (HMul.hMul.{0, 0, 0} Int Int Int (instHMul.{0} Int Int.instMulInt) a c) (HMul.hMul.{0, 0, 0} Int Int Int (instHMul.{0} Int Int.instMulInt) b c))
+Case conversion may be inaccurate. Consider using '#align int.modeq.mul_right' Int.ModEq.mul_right'ₓ'. -/
+protected theorem mul_right' (h : a ≡ b [ZMOD n]) : a * c ≡ b * c [ZMOD n * c] := by
+ rw [mul_comm a, mul_comm b, mul_comm n] <;> exact h.mul_left'
#align int.modeq.mul_right' Int.ModEq.mul_right'
--/
#print Int.ModEq.add /-
protected theorem add (h₁ : a ≡ b [ZMOD n]) (h₂ : c ≡ d [ZMOD n]) : a + c ≡ b + d [ZMOD n] :=
@@ -256,17 +283,13 @@ protected theorem sub_right (c : ℤ) (h : a ≡ b [ZMOD n]) : a - c ≡ b - c [
#print Int.ModEq.mul_left /-
protected theorem mul_left (c : ℤ) (h : a ≡ b [ZMOD n]) : c * a ≡ c * b [ZMOD n] :=
- Or.cases_on (le_total 0 c) (fun hc => (h.mul_left' hc).of_dvd (dvd_mul_left _ _)) fun hc => by
- rw [← neg_neg c, neg_mul, neg_mul _ b] <;>
- exact ((h.mul_left' <| neg_nonneg.2 hc).of_dvd (dvd_mul_left _ _)).neg
+ h.mul_left'.of_dvd <| dvd_mul_left _ _
#align int.modeq.mul_left Int.ModEq.mul_left
-/
#print Int.ModEq.mul_right /-
protected theorem mul_right (c : ℤ) (h : a ≡ b [ZMOD n]) : a * c ≡ b * c [ZMOD n] :=
- by
- rw [mul_comm a, mul_comm b]
- exact h.mul_left c
+ h.mul_right'.of_dvd <| dvd_mul_right _ _
#align int.modeq.mul_right Int.ModEq.mul_right
-/
@@ -301,6 +324,29 @@ theorem of_mul_right (m : ℤ) : a ≡ b [ZMOD n * m] → a ≡ b [ZMOD n] :=
#align int.modeq.of_mul_right Int.ModEq.of_mul_right
-/
+/-- To cancel a common factor `c` from a `modeq` we must divide the modulus `m` by `gcd m c`. -/
+theorem cancel_right_div_gcd (hm : 0 < m) (h : a * c ≡ b * c [ZMOD m]) : a ≡ b [ZMOD m / gcd m c] :=
+ by
+ let d := gcd m c
+ have hmd := gcd_dvd_left m c
+ have hcd := gcd_dvd_right m c
+ rw [modeq_iff_dvd] at h⊢
+ refine' Int.dvd_of_dvd_mul_right_of_gcd_one _ _
+ show m / d ∣ c / d * (b - a)
+ · rw [mul_comm, ← Int.mul_ediv_assoc (b - a) hcd, sub_mul]
+ exact Int.ediv_dvd_ediv hmd h
+ · rw [gcd_div hmd hcd, nat_abs_of_nat, Nat.div_self (gcd_pos_of_ne_zero_left c hm.ne')]
+#align int.modeq.cancel_right_div_gcd Int.ModEq.cancel_right_div_gcd
+
+/-- To cancel a common factor `c` from a `modeq` we must divide the modulus `m` by `gcd m c`. -/
+theorem cancel_left_div_gcd (hm : 0 < m) (h : c * a ≡ c * b [ZMOD m]) : a ≡ b [ZMOD m / gcd m c] :=
+ cancel_right_div_gcd hm <| by simpa [mul_comm] using h
+#align int.modeq.cancel_left_div_gcd Int.ModEq.cancel_left_div_gcd
+
+theorem of_div (h : a / c ≡ b / c [ZMOD m / c]) (ha : c ∣ a) (ha : c ∣ b) (ha : c ∣ m) :
+ a ≡ b [ZMOD m] := by convert h.mul_left' <;> rwa [Int.mul_ediv_cancel']
+#align int.modeq.of_div Int.ModEq.of_div
+
end Modeq
#print Int.modEq_one /-
@@ -315,6 +361,20 @@ theorem modEq_sub (a b : ℤ) : a ≡ b [ZMOD a - b] :=
#align int.modeq_sub Int.modEq_sub
-/
+@[simp]
+theorem modEq_zero_iff : a ≡ b [ZMOD 0] ↔ a = b := by rw [modeq, mod_zero, mod_zero]
+#align int.modeq_zero_iff Int.modEq_zero_iff
+
+@[simp]
+theorem add_modEq_left : n + a ≡ a [ZMOD n] :=
+ ModEq.symm <| modEq_iff_dvd.2 <| by simp
+#align int.add_modeq_left Int.add_modEq_left
+
+@[simp]
+theorem add_modEq_right : a + n ≡ a [ZMOD n] :=
+ ModEq.symm <| modEq_iff_dvd.2 <| by simp
+#align int.add_modeq_right Int.add_modEq_right
+
#print Int.modEq_and_modEq_iff_modEq_mul /-
theorem modEq_and_modEq_iff_modEq_mul {a b m n : ℤ} (hmn : m.natAbs.coprime n.natAbs) :
a ≡ b [ZMOD m] ∧ a ≡ b [ZMOD n] ↔ a ≡ b [ZMOD m * n] :=
mathlib commit https://github.com/leanprover-community/mathlib/commit/4c586d291f189eecb9d00581aeb3dd998ac34442
@@ -339,7 +339,7 @@ theorem gcd_a_modEq (a b : ℕ) : (a : ℤ) * Nat.gcdA a b ≡ Nat.gcd a b [ZMOD
theorem modEq_add_fac {a b n : ℤ} (c : ℤ) (ha : a ≡ b [ZMOD n]) : a + n * c ≡ b [ZMOD n] :=
calc
a + n * c ≡ b + n * c [ZMOD n] := ha.add_right _
- _ ≡ b + 0 [ZMOD n] := (dvd_mul_right _ _).modEq_zero_int.add_left _
+ _ ≡ b + 0 [ZMOD n] := ((dvd_mul_right _ _).modEq_zero_int.add_left _)
_ ≡ b [ZMOD n] := by rw [add_zero]
#align int.modeq_add_fac Int.modEq_add_fac
mathlib commit https://github.com/leanprover-community/mathlib/commit/bd9851ca476957ea4549eb19b40e7b5ade9428cc
deprecated
attributeWhy these changes?
@@ -325,7 +325,6 @@ theorem mod_mul_left_mod (a b c : ℤ) : a % (b * c) % c = a % c :=
(mod_modEq _ _).of_mul_left _
#align int.mod_mul_left_mod Int.mod_mul_left_mod
--- 2024-04-02
-@[deprecated] alias coe_nat_modEq_iff := natCast_modEq_iff
+@[deprecated] alias coe_nat_modEq_iff := natCast_modEq_iff -- 2024-04-02
end Int
coe_nat
to natCast
(#11637)
Reduce the diff of #11499
All in the Int
namespace:
ofNat_eq_cast
→ ofNat_eq_natCast
cast_eq_cast_iff_Nat
→ natCast_inj
natCast_eq_ofNat
→ ofNat_eq_natCast
coe_nat_sub
→ natCast_sub
coe_nat_nonneg
→ natCast_nonneg
sign_coe_add_one
→ sign_natCast_add_one
nat_succ_eq_int_succ
→ natCast_succ
succ_neg_nat_succ
→ succ_neg_natCast_succ
coe_pred_of_pos
→ natCast_pred_of_pos
coe_nat_div
→ natCast_div
coe_nat_ediv
→ natCast_ediv
sign_coe_nat_of_nonzero
→ sign_natCast_of_ne_zero
toNat_coe_nat
→ toNat_natCast
toNat_coe_nat_add_one
→ toNat_natCast_add_one
coe_nat_dvd
→ natCast_dvd_natCast
coe_nat_dvd_left
→ natCast_dvd
coe_nat_dvd_right
→ dvd_natCast
le_coe_nat_sub
→ le_natCast_sub
succ_coe_nat_pos
→ succ_natCast_pos
coe_nat_modEq_iff
→ natCast_modEq_iff
coe_natAbs
→ natCast_natAbs
coe_nat_eq_zero
→ natCast_eq_zero
coe_nat_ne_zero
→ natCast_ne_zero
coe_nat_ne_zero_iff_pos
→ natCast_ne_zero_iff_pos
abs_coe_nat
→ abs_natCast
coe_nat_nonpos_iff
→ natCast_nonpos_iff
Also rename Nat.coe_nat_dvd
to Nat.cast_dvd_cast
@@ -75,9 +75,9 @@ end ModEq
theorem modEq_comm : a ≡ b [ZMOD n] ↔ b ≡ a [ZMOD n] := ⟨ModEq.symm, ModEq.symm⟩
#align int.modeq_comm Int.modEq_comm
-theorem coe_nat_modEq_iff {a b n : ℕ} : a ≡ b [ZMOD n] ↔ a ≡ b [MOD n] := by
- unfold ModEq Nat.ModEq; rw [← Int.ofNat_inj]; simp [coe_nat_mod]
-#align int.coe_nat_modeq_iff Int.coe_nat_modEq_iff
+theorem natCast_modEq_iff {a b n : ℕ} : a ≡ b [ZMOD n] ↔ a ≡ b [MOD n] := by
+ unfold ModEq Nat.ModEq; rw [← Int.ofNat_inj]; simp [natCast_mod]
+#align int.coe_nat_modeq_iff Int.natCast_modEq_iff
theorem modEq_zero_iff_dvd : a ≡ 0 [ZMOD n] ↔ n ∣ a := by
rw [ModEq, zero_emod, dvd_iff_emod_eq_zero]
@@ -267,8 +267,8 @@ theorem modEq_and_modEq_iff_modEq_mul {a b m n : ℤ} (hmn : m.natAbs.Coprime n.
a ≡ b [ZMOD m] ∧ a ≡ b [ZMOD n] ↔ a ≡ b [ZMOD m * n] :=
⟨fun h => by
rw [modEq_iff_dvd, modEq_iff_dvd] at h
- rw [modEq_iff_dvd, ← natAbs_dvd, ← dvd_natAbs, coe_nat_dvd, natAbs_mul]
- refine' hmn.mul_dvd_of_dvd_of_dvd _ _ <;> rw [← coe_nat_dvd, natAbs_dvd, dvd_natAbs] <;>
+ rw [modEq_iff_dvd, ← natAbs_dvd, ← dvd_natAbs, natCast_dvd_natCast, natAbs_mul]
+ refine' hmn.mul_dvd_of_dvd_of_dvd _ _ <;> rw [← natCast_dvd_natCast, natAbs_dvd, dvd_natAbs] <;>
tauto,
fun h => ⟨h.of_mul_right _, h.of_mul_left _⟩⟩
#align int.modeq_and_modeq_iff_modeq_mul Int.modEq_and_modEq_iff_modEq_mul
@@ -325,4 +325,7 @@ theorem mod_mul_left_mod (a b c : ℤ) : a % (b * c) % c = a % c :=
(mod_modEq _ _).of_mul_left _
#align int.mod_mul_left_mod Int.mod_mul_left_mod
+-- 2024-04-02
+@[deprecated] alias coe_nat_modEq_iff := natCast_modEq_iff
+
end Int
We change the following field in the definition of an additive commutative monoid:
nsmul_succ : ∀ (n : ℕ) (x : G),
- AddMonoid.nsmul (n + 1) x = x + AddMonoid.nsmul n x
+ AddMonoid.nsmul (n + 1) x = AddMonoid.nsmul n x + x
where the latter is more natural
We adjust the definitions of ^
in monoids, groups, etc.
Originally there was a warning comment about why this natural order was preferred
use
x * npowRec n x
and notnpowRec n x * x
in the definition to make sure that definitional unfolding ofnpowRec
is blocked, to avoid deep recursion issues.
but it seems to no longer apply.
Remarks on the PR :
pow_succ
and pow_succ'
have switched their meanings.Ideal.IsPrime.mul_mem_pow
which is defined in [Mathlib/RingTheory/DedekindDomain/Ideal.lean]. Changing the order of operation forced me to add the symmetric lemma Ideal.IsPrime.mem_pow_mul
.@@ -208,7 +208,7 @@ protected theorem mul (h₁ : a ≡ b [ZMOD n]) (h₂ : c ≡ d [ZMOD n]) : a *
@[gcongr] protected theorem pow (m : ℕ) (h : a ≡ b [ZMOD n]) : a ^ m ≡ b ^ m [ZMOD n] := by
induction' m with d hd; · rfl
rw [pow_succ, pow_succ]
- exact h.mul hd
+ exact hd.mul h
#align int.modeq.pow Int.ModEq.pow
lemma of_mul_left (m : ℤ) (h : a ≡ b [ZMOD m * n]) : a ≡ b [ZMOD n] := by
Homogenises porting notes via capitalisation and addition of whitespace.
It makes the following changes:
@@ -111,7 +111,7 @@ theorem mod_modEq (a n) : a % n ≡ a [ZMOD n] :=
@[simp]
theorem neg_modEq_neg : -a ≡ -b [ZMOD n] ↔ a ≡ b [ZMOD n] := by
---porting note: Restore old proof once #3309 is through
+-- Porting note: Restore old proof once #3309 is through
simp [-sub_neg_eq_add, neg_sub_neg, modEq_iff_dvd, dvd_sub_comm]
#align int.neg_modeq_neg Int.neg_modEq_neg
@@ -224,7 +224,7 @@ theorem cancel_right_div_gcd (hm : 0 < m) (h : a * c ≡ b * c [ZMOD m]) :
a ≡ b [ZMOD m / gcd m c] := by
letI d := gcd m c
rw [modEq_iff_dvd] at h ⊢
- -- porting note: removed `show` due to leanprover-community/mathlib4#3305
+ -- Porting note: removed `show` due to leanprover-community/mathlib4#3305
refine Int.dvd_of_dvd_mul_right_of_gcd_one (?_ : m / d ∣ c / d * (b - a)) ?_
· rw [mul_comm, ← Int.mul_ediv_assoc (b - a) gcd_dvd_right, sub_mul]
exact Int.ediv_dvd_ediv gcd_dvd_left h
Notable changes: lemmas were added in https://github.com/leanprover/std4/pull/538 about gcd
and lcm
, that now have implicit arguments. Mostly this is a positive change in Mathlib, we can just delete the arguments. The one to consider in review is in ModEq
.
Co-authored-by: Scott Morrison <scott.morrison@gmail.com>
@@ -223,14 +223,13 @@ lemma of_mul_right (m : ℤ) : a ≡ b [ZMOD n * m] → a ≡ b [ZMOD n] :=
theorem cancel_right_div_gcd (hm : 0 < m) (h : a * c ≡ b * c [ZMOD m]) :
a ≡ b [ZMOD m / gcd m c] := by
letI d := gcd m c
- have hmd := gcd_dvd_left m c
- have hcd := gcd_dvd_right m c
rw [modEq_iff_dvd] at h ⊢
-- porting note: removed `show` due to leanprover-community/mathlib4#3305
refine Int.dvd_of_dvd_mul_right_of_gcd_one (?_ : m / d ∣ c / d * (b - a)) ?_
- · rw [mul_comm, ← Int.mul_ediv_assoc (b - a) hcd, sub_mul]
- exact Int.ediv_dvd_ediv hmd h
- · rw [gcd_div hmd hcd, natAbs_ofNat, Nat.div_self (gcd_pos_of_ne_zero_left c hm.ne')]
+ · rw [mul_comm, ← Int.mul_ediv_assoc (b - a) gcd_dvd_right, sub_mul]
+ exact Int.ediv_dvd_ediv gcd_dvd_left h
+ · rw [gcd_div gcd_dvd_left gcd_dvd_right, natAbs_ofNat,
+ Nat.div_self (gcd_pos_of_ne_zero_left c hm.ne')]
#align int.modeq.cancel_right_div_gcd Int.ModEq.cancel_right_div_gcd
/-- To cancel a common factor `c` from a `ModEq` we must divide the modulus `m` by `gcd m c`. -/
This covers these changes in Std: https://github.com/leanprover/std4/compare/6b4cf96c89e53cfcd73350bbcd90333a051ff4f0...[9dd24a34](https://github.com/leanprover-community/mathlib/commit/9dd24a3493cceefa2bede383f21e4ef548990b68)
Int.ofNat_natAbs_eq_of_nonneg
has become Int.natAbs_of_nonneg
(and one argument has become implicit)List.map_id''
and List.map_id'
have exchanged names. (Yay naming things using primes!)Co-authored-by: Scott Morrison <scott.morrison@gmail.com>
@@ -315,7 +315,7 @@ theorem exists_unique_equiv (a : ℤ) {b : ℤ} (hb : 0 < b) :
theorem exists_unique_equiv_nat (a : ℤ) {b : ℤ} (hb : 0 < b) : ∃ z : ℕ, ↑z < b ∧ ↑z ≡ a [ZMOD b] :=
let ⟨z, hz1, hz2, hz3⟩ := exists_unique_equiv a hb
⟨z.natAbs, by
- constructor <;> rw [ofNat_natAbs_eq_of_nonneg z hz1] <;> assumption⟩
+ constructor <;> rw [natAbs_of_nonneg hz1] <;> assumption⟩
#align int.exists_unique_equiv_nat Int.exists_unique_equiv_nat
theorem mod_mul_right_mod (a b c : ℤ) : a % (b * c) % b = a % b :=
@@ -129,7 +129,7 @@ protected theorem mul_left' (h : a ≡ b [ZMOD n]) : c * a ≡ c * b [ZMOD c * n
obtain hc | rfl | hc := lt_trichotomy c 0
· rw [← neg_modEq_neg, ← modEq_neg, ← neg_mul, ← neg_mul, ← neg_mul]
simp only [ModEq, mul_emod_mul_of_pos _ _ (neg_pos.2 hc), h.eq]
- · simp only [zero_mul]; rfl
+ · simp only [zero_mul, ModEq.rfl]
· simp only [ModEq, mul_emod_mul_of_pos _ _ hc, h.eq]
#align int.modeq.mul_left' Int.ModEq.mul_left'
bitwise_of_ne_zero
, since it wasn't used, and could cause loops in an inconsistent context.@@ -42,7 +42,7 @@ instance : Decidable (ModEq n a b) := decEq (a % n) (b % n)
namespace ModEq
-@[refl]
+@[refl, simp]
protected theorem refl (a : ℤ) : a ≡ a [ZMOD n] :=
@rfl _ _
#align int.modeq.refl Int.ModEq.refl
This is the supremum of
along with some minor fixes from failures on nightly-testing as Mathlib master
is merged into it.
Note that some PRs for changes that are already compatible with the current toolchain and will be necessary have already been split out: #8380.
I am hopeful that in future we will be able to progressively merge adaptation PRs into a bump/v4.X.0
branch, so we never end up with a "big merge" like this. However one of these adaptation PRs (#8056) predates my new scheme for combined CI, and it wasn't possible to keep that PR viable in the meantime.
In particular this includes adjustments for the Lean PRs
We can get rid of all the
local macro_rules | `($x ^ $y) => `(HPow.hPow $x $y) -- Porting note: See issue [lean4#2220](https://github.com/leanprover/lean4/pull/2220)
macros across Mathlib (and in any projects that want to write natural number powers of reals).
Changes the default behaviour of simp
to (config := {decide := false})
. This makes simp
(and consequentially norm_num
) less powerful, but also more consistent, and less likely to blow up in long failures. This requires a variety of changes: changing some previously by simp
or norm_num
to decide
or rfl
, or adding (config := {decide := true})
.
This changed the behaviour of simp
so that simp [f]
will only unfold "fully applied" occurrences of f
. The old behaviour can be recovered with simp (config := { unfoldPartialApp := true })
. We may in future add a syntax for this, e.g. simp [!f]
; please provide feedback! In the meantime, we have made the following changes:
(config := { unfoldPartialApp := true })
in some places, to recover the old behaviour@[eqns]
to manually adjust the equation lemmas for a particular definition, recovering the old behaviour just for that definition. See #8371, where we do this for Function.comp
and Function.flip
.This change in Lean may require further changes down the line (e.g. adding the !f
syntax, and/or upstreaming the special treatment for Function.comp
and Function.flip
, and/or removing this special treatment). Please keep an open and skeptical mind about these changes!
Co-authored-by: leanprover-community-mathlib4-bot <leanprover-community-mathlib4-bot@users.noreply.github.com> Co-authored-by: Scott Morrison <scott.morrison@gmail.com> Co-authored-by: Eric Wieser <wieser.eric@gmail.com> Co-authored-by: Mauricio Collares <mauricio@collares.org>
@@ -129,7 +129,7 @@ protected theorem mul_left' (h : a ≡ b [ZMOD n]) : c * a ≡ c * b [ZMOD c * n
obtain hc | rfl | hc := lt_trichotomy c 0
· rw [← neg_modEq_neg, ← modEq_neg, ← neg_mul, ← neg_mul, ← neg_mul]
simp only [ModEq, mul_emod_mul_of_pos _ _ (neg_pos.2 hc), h.eq]
- · simp
+ · simp only [zero_mul]; rfl
· simp only [ModEq, mul_emod_mul_of_pos _ _ hc, h.eq]
#align int.modeq.mul_left' Int.ModEq.mul_left'
@@ -264,7 +264,7 @@ theorem add_modEq_left : n + a ≡ a [ZMOD n] := ModEq.symm <| modEq_iff_dvd.2 <
theorem add_modEq_right : a + n ≡ a [ZMOD n] := ModEq.symm <| modEq_iff_dvd.2 <| by simp
#align int.add_modeq_right Int.add_modEq_right
-theorem modEq_and_modEq_iff_modEq_mul {a b m n : ℤ} (hmn : m.natAbs.coprime n.natAbs) :
+theorem modEq_and_modEq_iff_modEq_mul {a b m n : ℤ} (hmn : m.natAbs.Coprime n.natAbs) :
a ≡ b [ZMOD m] ∧ a ≡ b [ZMOD n] ↔ a ≡ b [ZMOD m * n] :=
⟨fun h => by
rw [modEq_iff_dvd, modEq_iff_dvd] at h
@@ -294,9 +294,9 @@ theorem modEq_add_fac_self {a t n : ℤ} : a + n * t ≡ a [ZMOD n] :=
modEq_add_fac _ ModEq.rfl
#align int.modeq_add_fac_self Int.modEq_add_fac_self
-theorem mod_coprime {a b : ℕ} (hab : Nat.coprime a b) : ∃ y : ℤ, a * y ≡ 1 [ZMOD b] :=
+theorem mod_coprime {a b : ℕ} (hab : Nat.Coprime a b) : ∃ y : ℤ, a * y ≡ 1 [ZMOD b] :=
⟨Nat.gcdA a b,
- have hgcd : Nat.gcd a b = 1 := Nat.coprime.gcd_eq_one hab
+ have hgcd : Nat.gcd a b = 1 := Nat.Coprime.gcd_eq_one hab
calc
↑a * Nat.gcdA a b ≡ ↑a * Nat.gcdA a b + ↑b * Nat.gcdB a b [ZMOD ↑b] :=
ModEq.symm <| modEq_add_fac _ <| ModEq.refl _
@@ -264,7 +264,7 @@ theorem add_modEq_left : n + a ≡ a [ZMOD n] := ModEq.symm <| modEq_iff_dvd.2 <
theorem add_modEq_right : a + n ≡ a [ZMOD n] := ModEq.symm <| modEq_iff_dvd.2 <| by simp
#align int.add_modeq_right Int.add_modEq_right
-theorem modEq_and_modEq_iff_modEq_mul {a b m n : ℤ} (hmn : m.natAbs.Coprime n.natAbs) :
+theorem modEq_and_modEq_iff_modEq_mul {a b m n : ℤ} (hmn : m.natAbs.coprime n.natAbs) :
a ≡ b [ZMOD m] ∧ a ≡ b [ZMOD n] ↔ a ≡ b [ZMOD m * n] :=
⟨fun h => by
rw [modEq_iff_dvd, modEq_iff_dvd] at h
@@ -294,9 +294,9 @@ theorem modEq_add_fac_self {a t n : ℤ} : a + n * t ≡ a [ZMOD n] :=
modEq_add_fac _ ModEq.rfl
#align int.modeq_add_fac_self Int.modEq_add_fac_self
-theorem mod_coprime {a b : ℕ} (hab : Nat.Coprime a b) : ∃ y : ℤ, a * y ≡ 1 [ZMOD b] :=
+theorem mod_coprime {a b : ℕ} (hab : Nat.coprime a b) : ∃ y : ℤ, a * y ≡ 1 [ZMOD b] :=
⟨Nat.gcdA a b,
- have hgcd : Nat.gcd a b = 1 := Nat.Coprime.gcd_eq_one hab
+ have hgcd : Nat.gcd a b = 1 := Nat.coprime.gcd_eq_one hab
calc
↑a * Nat.gcdA a b ≡ ↑a * Nat.gcdA a b + ↑b * Nat.gcdB a b [ZMOD ↑b] :=
ModEq.symm <| modEq_add_fac _ <| ModEq.refl _
Some changes have already been review and delegated in #6910 and #7148.
The diff that needs looking at is https://github.com/leanprover-community/mathlib4/pull/7174/commits/64d6d07ee18163627c8f517eb31455411921c5ac
The std bump PR was insta-merged already!
Co-authored-by: leanprover-community-mathlib4-bot <leanprover-community-mathlib4-bot@users.noreply.github.com> Co-authored-by: Scott Morrison <scott.morrison@gmail.com>
@@ -264,7 +264,7 @@ theorem add_modEq_left : n + a ≡ a [ZMOD n] := ModEq.symm <| modEq_iff_dvd.2 <
theorem add_modEq_right : a + n ≡ a [ZMOD n] := ModEq.symm <| modEq_iff_dvd.2 <| by simp
#align int.add_modeq_right Int.add_modEq_right
-theorem modEq_and_modEq_iff_modEq_mul {a b m n : ℤ} (hmn : m.natAbs.coprime n.natAbs) :
+theorem modEq_and_modEq_iff_modEq_mul {a b m n : ℤ} (hmn : m.natAbs.Coprime n.natAbs) :
a ≡ b [ZMOD m] ∧ a ≡ b [ZMOD n] ↔ a ≡ b [ZMOD m * n] :=
⟨fun h => by
rw [modEq_iff_dvd, modEq_iff_dvd] at h
@@ -294,9 +294,9 @@ theorem modEq_add_fac_self {a t n : ℤ} : a + n * t ≡ a [ZMOD n] :=
modEq_add_fac _ ModEq.rfl
#align int.modeq_add_fac_self Int.modEq_add_fac_self
-theorem mod_coprime {a b : ℕ} (hab : Nat.coprime a b) : ∃ y : ℤ, a * y ≡ 1 [ZMOD b] :=
+theorem mod_coprime {a b : ℕ} (hab : Nat.Coprime a b) : ∃ y : ℤ, a * y ≡ 1 [ZMOD b] :=
⟨Nat.gcdA a b,
- have hgcd : Nat.gcd a b = 1 := Nat.coprime.gcd_eq_one hab
+ have hgcd : Nat.gcd a b = 1 := Nat.Coprime.gcd_eq_one hab
calc
↑a * Nat.gcdA a b ≡ ↑a * Nat.gcdA a b + ↑b * Nat.gcdB a b [ZMOD ↑b] :=
ModEq.symm <| modEq_add_fac _ <| ModEq.refl _
@@ -101,7 +101,7 @@ theorem modEq_iff_add_fac {a b n : ℤ} : a ≡ b [ZMOD n] ↔ ∃ t, b = a + n
exact exists_congr fun t => sub_eq_iff_eq_add'
#align int.modeq_iff_add_fac Int.modEq_iff_add_fac
-alias modEq_iff_dvd ↔ ModEq.dvd modEq_of_dvd
+alias ⟨ModEq.dvd, modEq_of_dvd⟩ := modEq_iff_dvd
#align int.modeq.dvd Int.ModEq.dvd
#align int.modeq_of_dvd Int.modEq_of_dvd
Easy of use function to compliment modEq_add_fac, the statement that :
a = b [ZMOD n] implies a - c * n = b [ZMOD n]
@@ -286,6 +286,10 @@ theorem modEq_add_fac {a b n : ℤ} (c : ℤ) (ha : a ≡ b [ZMOD n]) : a + n *
_ ≡ b [ZMOD n] := by rw [add_zero]
#align int.modeq_add_fac Int.modEq_add_fac
+theorem modEq_sub_fac {a b n : ℤ} (c : ℤ) (ha : a ≡ b [ZMOD n]) : a - n * c ≡ b [ZMOD n] := by
+ convert Int.modEq_add_fac (-c) ha using 1
+ ring
+
theorem modEq_add_fac_self {a t n : ℤ} : a + n * t ≡ a [ZMOD n] :=
modEq_add_fac _ ModEq.rfl
#align int.modeq_add_fac_self Int.modEq_add_fac_self
@@ -2,17 +2,14 @@
Copyright (c) 2018 Chris Hughes. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Chris Hughes
-
-! This file was ported from Lean 3 source module data.int.modeq
-! leanprover-community/mathlib commit 47a1a73351de8dd6c8d3d32b569c8e434b03ca47
-! Please do not edit these lines, except to modify the commit id
-! if you have ported upstream changes.
-/
import Std.Data.Int.DivMod
import Mathlib.Data.Nat.ModEq
import Mathlib.Tactic.GCongr.Core
import Mathlib.Tactic.Ring
+#align_import data.int.modeq from "leanprover-community/mathlib"@"47a1a73351de8dd6c8d3d32b569c8e434b03ca47"
+
/-!
# Congruences modulo an integer
gcongr
for "relational congruence" (#3965)
This PR implements a new tactic, gcongr
, which applies "relational congruence" rules, reducing a relational goal between a LHS and RHS matching the same pattern to relational subgoals between the differing inputs to the pattern. For example,
example {a b x c d : ℝ} (h1 : a + 1 ≤ b + 1) (h2 : c + 2 ≤ d + 2) :
x ^ 4 * a + c ≤ x ^ 4 * b + d := by
gcongr
· linarith
· linarith
This example has the goal of proving the relation ≤
between a LHS and RHS both of the pattern
x ^ 4 * ?_ + ?_
(with inputs a
, c
on the left and b
, d
on the right); after the use of gcongr
, we have the simpler goals a ≤ b
and c ≤ d
.
For a sense of the style of argument facilitated by the tactic, this commit (which will be PR'd separately) gives >100 examples of use cases in the existing library.
The tactic's syntax allows for a pattern to be provided explicitly; this is useful if a non-maximal match is desired:
example {a b c d x : ℝ} (h : a + c + 1 ≤ b + d + 1) :
x ^ 4 * (a + c) + 5 ≤ x ^ 4 * (b + d) + 5 := by
gcongr x ^ 4 * ?_ + 5
linarith
This feature is the analogue for general relations of the mathlib3 congrm
tactic.
The "relational congruence" rules used are the library lemmas which have been tagged with the attribute @[gcongr]
. For example, the first example constructs the proof term
add_le_add (mul_le_mul_of_nonneg_left _ (pow_bit0_nonneg x 2)) _
using the relational congruence lemmas add_le_add
and mul_le_mul_of_nonneg_left
. In this initial implementation, the @[gcongr]
tagging has been set up for arithmetic head functions (+
, *
etc) and the relations ≤
, <
and congruence-mod-n
.
The tactic attempts to discharge side goals to these "relational congruence" lemmas (such as the side goal 0 ≤ x ^ 4
in the above application of mul_le_mul_of_nonneg_left
) using the tactic gcongr_discharger
, which wraps positivity
but can also be extended. Side goals not discharged in this way are left for the user.
Co-authored-by: Mario Carneiro <di.gama@gmail.com>
Co-authored-by: Mario Carneiro <di.gama@gmail.com> Co-authored-by: Moritz Doll <moritz.doll@googlemail.com>
@@ -10,6 +10,7 @@ Authors: Chris Hughes
-/
import Std.Data.Int.DivMod
import Mathlib.Data.Nat.ModEq
+import Mathlib.Tactic.GCongr.Core
import Mathlib.Tactic.Ring
/-!
@@ -139,17 +140,18 @@ protected theorem mul_right' (h : a ≡ b [ZMOD n]) : a * c ≡ b * c [ZMOD n *
rw [mul_comm a, mul_comm b, mul_comm n]; exact h.mul_left'
#align int.modeq.mul_right' Int.ModEq.mul_right'
+@[gcongr]
protected theorem add (h₁ : a ≡ b [ZMOD n]) (h₂ : c ≡ d [ZMOD n]) : a + c ≡ b + d [ZMOD n] :=
modEq_iff_dvd.2 <| by
convert dvd_add h₁.dvd h₂.dvd using 1
ring
#align int.modeq.add Int.ModEq.add
-protected theorem add_left (c : ℤ) (h : a ≡ b [ZMOD n]) : c + a ≡ c + b [ZMOD n] :=
+@[gcongr] protected theorem add_left (c : ℤ) (h : a ≡ b [ZMOD n]) : c + a ≡ c + b [ZMOD n] :=
ModEq.rfl.add h
#align int.modeq.add_left Int.ModEq.add_left
-protected theorem add_right (c : ℤ) (h : a ≡ b [ZMOD n]) : a + c ≡ b + c [ZMOD n] :=
+@[gcongr] protected theorem add_right (c : ℤ) (h : a ≡ b [ZMOD n]) : a + c ≡ b + c [ZMOD n] :=
h.add ModEq.rfl
#align int.modeq.add_right Int.ModEq.add_right
@@ -175,36 +177,38 @@ protected theorem add_right_cancel' (c : ℤ) (h : a + c ≡ b + c [ZMOD n]) : a
ModEq.rfl.add_right_cancel h
#align int.modeq.add_right_cancel' Int.ModEq.add_right_cancel'
-protected theorem neg (h : a ≡ b [ZMOD n]) : -a ≡ -b [ZMOD n] :=
+@[gcongr] protected theorem neg (h : a ≡ b [ZMOD n]) : -a ≡ -b [ZMOD n] :=
h.add_left_cancel (by simp_rw [← sub_eq_add_neg, sub_self]; rfl)
#align int.modeq.neg Int.ModEq.neg
+@[gcongr]
protected theorem sub (h₁ : a ≡ b [ZMOD n]) (h₂ : c ≡ d [ZMOD n]) : a - c ≡ b - d [ZMOD n] := by
rw [sub_eq_add_neg, sub_eq_add_neg]
exact h₁.add h₂.neg
#align int.modeq.sub Int.ModEq.sub
-protected theorem sub_left (c : ℤ) (h : a ≡ b [ZMOD n]) : c - a ≡ c - b [ZMOD n] :=
+@[gcongr] protected theorem sub_left (c : ℤ) (h : a ≡ b [ZMOD n]) : c - a ≡ c - b [ZMOD n] :=
ModEq.rfl.sub h
#align int.modeq.sub_left Int.ModEq.sub_left
-protected theorem sub_right (c : ℤ) (h : a ≡ b [ZMOD n]) : a - c ≡ b - c [ZMOD n] :=
+@[gcongr] protected theorem sub_right (c : ℤ) (h : a ≡ b [ZMOD n]) : a - c ≡ b - c [ZMOD n] :=
h.sub ModEq.rfl
#align int.modeq.sub_right Int.ModEq.sub_right
-protected theorem mul_left (c : ℤ) (h : a ≡ b [ZMOD n]) : c * a ≡ c * b [ZMOD n] :=
+@[gcongr] protected theorem mul_left (c : ℤ) (h : a ≡ b [ZMOD n]) : c * a ≡ c * b [ZMOD n] :=
h.mul_left'.of_dvd <| dvd_mul_left _ _
#align int.modeq.mul_left Int.ModEq.mul_left
-protected theorem mul_right (c : ℤ) (h : a ≡ b [ZMOD n]) : a * c ≡ b * c [ZMOD n] :=
+@[gcongr] protected theorem mul_right (c : ℤ) (h : a ≡ b [ZMOD n]) : a * c ≡ b * c [ZMOD n] :=
h.mul_right'.of_dvd <| dvd_mul_right _ _
#align int.modeq.mul_right Int.ModEq.mul_right
+@[gcongr]
protected theorem mul (h₁ : a ≡ b [ZMOD n]) (h₂ : c ≡ d [ZMOD n]) : a * c ≡ b * d [ZMOD n] :=
(h₂.mul_left _).trans (h₁.mul_right _)
#align int.modeq.mul Int.ModEq.mul
-protected theorem pow (m : ℕ) (h : a ≡ b [ZMOD n]) : a ^ m ≡ b ^ m [ZMOD n] := by
+@[gcongr] protected theorem pow (m : ℕ) (h : a ≡ b [ZMOD n]) : a ^ m ≡ b ^ m [ZMOD n] := by
induction' m with d hd; · rfl
rw [pow_succ, pow_succ]
exact h.mul hd
by
s! (#3825)
This PR puts, with one exception, every single remaining by
that lies all by itself on its own line to the previous line, thus matching the current behaviour of start-port.sh
. The exception is when the by
begins the second or later argument to a tuple or anonymous constructor; see https://github.com/leanprover-community/mathlib4/pull/3825#discussion_r1186702599.
Essentially this is s/\n *by$/ by/g
, but with manual editing to satisfy the linter's max-100-char-line requirement. The Python style linter is also modified to catch these "isolated by
s".
@@ -219,8 +219,8 @@ lemma of_mul_right (m : ℤ) : a ≡ b [ZMOD n * m] → a ≡ b [ZMOD n] :=
#align int.modeq.of_mul_right Int.ModEq.of_mul_right
/-- To cancel a common factor `c` from a `ModEq` we must divide the modulus `m` by `gcd m c`. -/
-theorem cancel_right_div_gcd (hm : 0 < m) (h : a * c ≡ b * c [ZMOD m]) : a ≡ b [ZMOD m / gcd m c] :=
- by
+theorem cancel_right_div_gcd (hm : 0 < m) (h : a * c ≡ b * c [ZMOD m]) :
+ a ≡ b [ZMOD m / gcd m c] := by
letI d := gcd m c
have hmd := gcd_dvd_left m c
have hcd := gcd_dvd_right m c
@@ -303,8 +303,8 @@ theorem exists_unique_equiv (a : ℤ) {b : ℤ} (hb : 0 < b) :
∃ z : ℤ, 0 ≤ z ∧ z < b ∧ z ≡ a [ZMOD b] :=
⟨a % b, emod_nonneg _ (ne_of_gt hb),
by
- have : a % b < |b| := emod_lt _ (ne_of_gt hb)
- rwa [abs_of_pos hb] at this, by simp [ModEq]⟩
+ have : a % b < |b| := emod_lt _ (ne_of_gt hb)
+ rwa [abs_of_pos hb] at this, by simp [ModEq]⟩
#align int.exists_unique_equiv Int.exists_unique_equiv
theorem exists_unique_equiv_nat (a : ℤ) {b : ℤ} (hb : 0 < b) : ∃ z : ℕ, ↑z < b ∧ ↑z ≡ a [ZMOD b] :=
This PR fixes two things:
align
statements for definitions and theorems and instances that are separated by two newlines from the relevant declaration (s/\n\n#align/\n#align
). This is often seen in the mathport output after ending calc
blocks.#align
statements. (This was needed for a script I wrote for #3630.)@@ -96,7 +96,6 @@ theorem _root_.Dvd.dvd.zero_modEq_int (h : n ∣ a) : 0 ≡ a [ZMOD n] :=
theorem modEq_iff_dvd : a ≡ b [ZMOD n] ↔ n ∣ b - a := by
rw [ModEq, eq_comm]
simp [emod_eq_emod_iff_emod_sub_eq_zero, dvd_iff_emod_eq_zero]
-
#align int.modeq_iff_dvd Int.modEq_iff_dvd
theorem modEq_iff_add_fac {a b n : ℤ} : a ≡ b [ZMOD n] ↔ ∃ t, b = a + n * t := by
@@ -284,7 +283,6 @@ theorem modEq_add_fac {a b n : ℤ} (c : ℤ) (ha : a ≡ b [ZMOD n]) : a + n *
a + n * c ≡ b + n * c [ZMOD n] := ha.add_right _
_ ≡ b + 0 [ZMOD n] := (dvd_mul_right _ _).modEq_zero_int.add_left _
_ ≡ b [ZMOD n] := by rw [add_zero]
-
#align int.modeq_add_fac Int.modEq_add_fac
theorem modEq_add_fac_self {a t n : ℤ} : a + n * t ≡ a [ZMOD n] :=
a/c ≡ b/c mod m/c → a ≡ b mod m
(#3259)
https://github.com/leanprover-community/mathlib/pull/18119, https://github.com/leanprover-community/mathlib/pull/18666.
algebra.ring.divisibility
@f1a2caaf51ef593799107fe9a8d5e411599f3996
..47a1a73351de8dd6c8d3d32b569c8e434b03ca47
data.nat.order.lemmas
@2258b40dacd2942571c8ce136215350c702dc78f
..47a1a73351de8dd6c8d3d32b569c8e434b03ca47
data.int.gcd
@d4f69d96f3532729da8ebb763f4bc26fcf640f06
..47a1a73351de8dd6c8d3d32b569c8e434b03ca47
data.nat.modeq
@2ed7e4aec72395b6a7c3ac4ac7873a7a43ead17c
..47a1a73351de8dd6c8d3d32b569c8e434b03ca47
data.int.modeq
@2ed7e4aec72395b6a7c3ac4ac7873a7a43ead17c
..47a1a73351de8dd6c8d3d32b569c8e434b03ca47
algebra.char_p.basic
@ceb887ddf3344dab425292e497fa2af91498437c
..47a1a73351de8dd6c8d3d32b569c8e434b03ca47
data.zmod.basic
@297619ec79dedf23525458b6bf5bf35c736fd2b8
..47a1a73351de8dd6c8d3d32b569c8e434b03ca47
Co-authored-by: Parcly Taxel <reddeloostw@gmail.com> Co-authored-by: Eric Wieser <wieser.eric@gmail.com>
@@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE.
Authors: Chris Hughes
! This file was ported from Lean 3 source module data.int.modeq
-! leanprover-community/mathlib commit 2ed7e4aec72395b6a7c3ac4ac7873a7a43ead17c
+! leanprover-community/mathlib commit 47a1a73351de8dd6c8d3d32b569c8e434b03ca47
! Please do not edit these lines, except to modify the commit id
! if you have ported upstream changes.
-/
@@ -69,8 +69,14 @@ protected theorem trans : a ≡ b [ZMOD n] → b ≡ c [ZMOD n] → a ≡ c [ZMO
instance : IsTrans ℤ (ModEq n) where
trans := @Int.ModEq.trans n
+protected theorem eq : a ≡ b [ZMOD n] → a % n = b % n := id
+#align int.modeq.eq Int.ModEq.eq
+
end ModEq
+theorem modEq_comm : a ≡ b [ZMOD n] ↔ b ≡ a [ZMOD n] := ⟨ModEq.symm, ModEq.symm⟩
+#align int.modeq_comm Int.modEq_comm
+
theorem coe_nat_modEq_iff {a b n : ℕ} : a ≡ b [ZMOD n] ↔ a ≡ b [MOD n] := by
unfold ModEq Nat.ModEq; rw [← Int.ofNat_inj]; simp [coe_nat_mod]
#align int.coe_nat_modeq_iff Int.coe_nat_modEq_iff
@@ -106,23 +112,32 @@ theorem mod_modEq (a n) : a % n ≡ a [ZMOD n] :=
emod_emod _ _
#align int.mod_modeq Int.mod_modEq
+@[simp]
+theorem neg_modEq_neg : -a ≡ -b [ZMOD n] ↔ a ≡ b [ZMOD n] := by
+--porting note: Restore old proof once #3309 is through
+ simp [-sub_neg_eq_add, neg_sub_neg, modEq_iff_dvd, dvd_sub_comm]
+#align int.neg_modeq_neg Int.neg_modEq_neg
+
+@[simp]
+theorem modEq_neg : a ≡ b [ZMOD -n] ↔ a ≡ b [ZMOD n] := by simp [modEq_iff_dvd]
+#align int.modeq_neg Int.modEq_neg
+
namespace ModEq
protected theorem of_dvd (d : m ∣ n) (h : a ≡ b [ZMOD n]) : a ≡ b [ZMOD m] :=
modEq_iff_dvd.2 <| d.trans h.dvd
#align int.modeq.of_dvd Int.ModEq.of_dvd
-protected theorem mul_left' (hc : 0 ≤ c) (h : a ≡ b [ZMOD n]) : c * a ≡ c * b [ZMOD c * n] :=
- match hc.lt_or_eq with
- | .inl hc => by
- unfold ModEq
- simp [mul_emod_mul_of_pos _ _ hc, show _ = _ from h]
- | .inr hc => by
- simp [hc.symm]
+protected theorem mul_left' (h : a ≡ b [ZMOD n]) : c * a ≡ c * b [ZMOD c * n] := by
+ obtain hc | rfl | hc := lt_trichotomy c 0
+ · rw [← neg_modEq_neg, ← modEq_neg, ← neg_mul, ← neg_mul, ← neg_mul]
+ simp only [ModEq, mul_emod_mul_of_pos _ _ (neg_pos.2 hc), h.eq]
+ · simp
+ · simp only [ModEq, mul_emod_mul_of_pos _ _ hc, h.eq]
#align int.modeq.mul_left' Int.ModEq.mul_left'
-protected theorem mul_right' (hc : 0 ≤ c) (h : a ≡ b [ZMOD n]) : a * c ≡ b * c [ZMOD n * c] := by
- rw [mul_comm a, mul_comm b, mul_comm n]; exact h.mul_left' hc
+protected theorem mul_right' (h : a ≡ b [ZMOD n]) : a * c ≡ b * c [ZMOD n * c] := by
+ rw [mul_comm a, mul_comm b, mul_comm n]; exact h.mul_left'
#align int.modeq.mul_right' Int.ModEq.mul_right'
protected theorem add (h₁ : a ≡ b [ZMOD n]) (h₂ : c ≡ d [ZMOD n]) : a + c ≡ b + d [ZMOD n] :=
@@ -179,16 +194,11 @@ protected theorem sub_right (c : ℤ) (h : a ≡ b [ZMOD n]) : a - c ≡ b - c [
#align int.modeq.sub_right Int.ModEq.sub_right
protected theorem mul_left (c : ℤ) (h : a ≡ b [ZMOD n]) : c * a ≡ c * b [ZMOD n] :=
- match (le_total 0 c) with
- | .inl hc => (h.mul_left' hc).of_dvd (dvd_mul_left _ _)
- | .inr hc => by
- rw [← neg_neg c, neg_mul, neg_mul _ b]
- exact ((h.mul_left' <| neg_nonneg.2 hc).of_dvd (dvd_mul_left _ _)).neg
+ h.mul_left'.of_dvd <| dvd_mul_left _ _
#align int.modeq.mul_left Int.ModEq.mul_left
-protected theorem mul_right (c : ℤ) (h : a ≡ b [ZMOD n]) : a * c ≡ b * c [ZMOD n] := by
- rw [mul_comm a, mul_comm b]
- exact h.mul_left c
+protected theorem mul_right (c : ℤ) (h : a ≡ b [ZMOD n]) : a * c ≡ b * c [ZMOD n] :=
+ h.mul_right'.of_dvd <| dvd_mul_right _ _
#align int.modeq.mul_right Int.ModEq.mul_right
protected theorem mul (h₁ : a ≡ b [ZMOD n]) (h₂ : c ≡ d [ZMOD n]) : a * c ≡ b * d [ZMOD n] :=
@@ -209,6 +219,29 @@ lemma of_mul_right (m : ℤ) : a ≡ b [ZMOD n * m] → a ≡ b [ZMOD n] :=
mul_comm m n ▸ of_mul_left _
#align int.modeq.of_mul_right Int.ModEq.of_mul_right
+/-- To cancel a common factor `c` from a `ModEq` we must divide the modulus `m` by `gcd m c`. -/
+theorem cancel_right_div_gcd (hm : 0 < m) (h : a * c ≡ b * c [ZMOD m]) : a ≡ b [ZMOD m / gcd m c] :=
+ by
+ letI d := gcd m c
+ have hmd := gcd_dvd_left m c
+ have hcd := gcd_dvd_right m c
+ rw [modEq_iff_dvd] at h ⊢
+ -- porting note: removed `show` due to leanprover-community/mathlib4#3305
+ refine Int.dvd_of_dvd_mul_right_of_gcd_one (?_ : m / d ∣ c / d * (b - a)) ?_
+ · rw [mul_comm, ← Int.mul_ediv_assoc (b - a) hcd, sub_mul]
+ exact Int.ediv_dvd_ediv hmd h
+ · rw [gcd_div hmd hcd, natAbs_ofNat, Nat.div_self (gcd_pos_of_ne_zero_left c hm.ne')]
+#align int.modeq.cancel_right_div_gcd Int.ModEq.cancel_right_div_gcd
+
+/-- To cancel a common factor `c` from a `ModEq` we must divide the modulus `m` by `gcd m c`. -/
+theorem cancel_left_div_gcd (hm : 0 < m) (h : c * a ≡ c * b [ZMOD m]) : a ≡ b [ZMOD m / gcd m c] :=
+ cancel_right_div_gcd hm <| by simpa [mul_comm] using h
+#align int.modeq.cancel_left_div_gcd Int.ModEq.cancel_left_div_gcd
+
+theorem of_div (h : a / c ≡ b / c [ZMOD m / c]) (ha : c ∣ a) (ha : c ∣ b) (ha : c ∣ m) :
+ a ≡ b [ZMOD m] := by convert h.mul_left' <;> rwa [Int.mul_ediv_cancel']
+#align int.modeq.of_div Int.ModEq.of_div
+
end ModEq
theorem modEq_one : a ≡ b [ZMOD 1] :=
@@ -219,6 +252,18 @@ theorem modEq_sub (a b : ℤ) : a ≡ b [ZMOD a - b] :=
(modEq_of_dvd dvd_rfl).symm
#align int.modeq_sub Int.modEq_sub
+@[simp]
+theorem modEq_zero_iff : a ≡ b [ZMOD 0] ↔ a = b := by rw [ModEq, emod_zero, emod_zero]
+#align int.modeq_zero_iff Int.modEq_zero_iff
+
+@[simp]
+theorem add_modEq_left : n + a ≡ a [ZMOD n] := ModEq.symm <| modEq_iff_dvd.2 <| by simp
+#align int.add_modeq_left Int.add_modEq_left
+
+@[simp]
+theorem add_modEq_right : a + n ≡ a [ZMOD n] := ModEq.symm <| modEq_iff_dvd.2 <| by simp
+#align int.add_modeq_right Int.add_modEq_right
+
theorem modEq_and_modEq_iff_modEq_mul {a b m n : ℤ} (hmn : m.natAbs.coprime n.natAbs) :
a ≡ b [ZMOD m] ∧ a ≡ b [ZMOD n] ↔ a ≡ b [ZMOD m * n] :=
⟨fun h => by
congr!
and convert
(#2606)
congr!
, convert
, and convert_to
to control parts of the congruence algorithm, in particular transparency settings when applying congruence lemmas.congr!
now applies congruence lemmas with reducible transparency by default. This prevents it from unfolding definitions when applying congruence lemmas. It also now tries both the LHS-biased and RHS-biased simp congruence lemmas, with a configuration option to set which it should try first.HEq
congruence lemma generator that gives each hypothesis access to the proofs of previous hypotheses. This means that if you have an equality ⊢ ⟨a, x⟩ = ⟨b, y⟩
of sigma types, congr!
turns this into goals ⊢ a = b
and ⊢ a = b → HEq x y
(note that congr!
will also auto-introduce a = b
for you in the second goal). This congruence lemma generator applies to more cases than the simp congruence lemma generator does.congr!
(and hence convert
) are more careful about applying lemmas that don't force definitions to unfold. There were a number of cases in mathlib where the implementation of congr
was being abused to unfold definitions.set_option trace.congr! true
you can see what congr!
sees when it is deciding on congruence lemmas.convert_to
to do using 1
when there is no using
clause, to match its documentation.Note that congr!
is more capable than congr
at finding a way to equate left-hand sides and right-hand sides, so you will frequently need to limit its depth with a using
clause. However, there is also a new heuristic to prevent considering unlikely-to-be-provable type equalities (controlled by the typeEqs
option), which can help limit the depth automatically.
There is also a predefined configuration that you can invoke with, for example, convert (config := .unfoldSameFun) h
, that causes it to behave more like congr
, including using default transparency when unfolding.
@@ -127,7 +127,7 @@ protected theorem mul_right' (hc : 0 ≤ c) (h : a ≡ b [ZMOD n]) : a * c ≡ b
protected theorem add (h₁ : a ≡ b [ZMOD n]) (h₂ : c ≡ d [ZMOD n]) : a + c ≡ b + d [ZMOD n] :=
modEq_iff_dvd.2 <| by
- convert dvd_add h₁.dvd h₂.dvd
+ convert dvd_add h₁.dvd h₂.dvd using 1
ring
#align int.modeq.add Int.ModEq.add
IsTrans α r → Trans r r r
and Trans r r r → IsTrans α r
(#1522)
Now Trans.trans
conflicts with _root_.trans
.
@@ -66,8 +66,8 @@ protected theorem trans : a ≡ b [ZMOD n] → b ≡ c [ZMOD n] → a ≡ c [ZMO
Eq.trans
#align int.modeq.trans Int.ModEq.trans
-instance : Trans (ModEq n) (ModEq n) (ModEq n) where
- trans := Int.ModEq.trans
+instance : IsTrans ℤ (ModEq n) where
+ trans := @Int.ModEq.trans n
end ModEq
by
line breaks (#1523)
During porting, I usually fix the desired format we seem to want for the line breaks around by
with
awk '{do {{if (match($0, "^ by$") && length(p) < 98) {p=p " by";} else {if (NR!=1) {print p}; p=$0}}} while (getline == 1) if (getline==0) print p}' Mathlib/File/Im/Working/On.lean
I noticed there are some more files that slipped through.
This pull request is the result of running this command:
grep -lr "^ by\$" Mathlib | xargs -n 1 awk -i inplace '{do {{if (match($0, "^ by$") && length(p) < 98 && not (match(p, "^[ \t]*--"))) {p=p " by";} else {if (NR!=1) {print p}; p=$0}}} while (getline == 1) if (getline==0) print p}'
Co-authored-by: Moritz Firsching <firsching@google.com>
@@ -93,8 +93,7 @@ theorem modEq_iff_dvd : a ≡ b [ZMOD n] ↔ n ∣ b - a := by
#align int.modeq_iff_dvd Int.modEq_iff_dvd
-theorem modEq_iff_add_fac {a b n : ℤ} : a ≡ b [ZMOD n] ↔ ∃ t, b = a + n * t :=
- by
+theorem modEq_iff_add_fac {a b n : ℤ} : a ≡ b [ZMOD n] ↔ ∃ t, b = a + n * t := by
rw [modEq_iff_dvd]
exact exists_congr fun t => sub_eq_iff_eq_add'
#align int.modeq_iff_add_fac Int.modEq_iff_add_fac
@@ -166,8 +165,7 @@ protected theorem neg (h : a ≡ b [ZMOD n]) : -a ≡ -b [ZMOD n] :=
h.add_left_cancel (by simp_rw [← sub_eq_add_neg, sub_self]; rfl)
#align int.modeq.neg Int.ModEq.neg
-protected theorem sub (h₁ : a ≡ b [ZMOD n]) (h₂ : c ≡ d [ZMOD n]) : a - c ≡ b - d [ZMOD n] :=
- by
+protected theorem sub (h₁ : a ≡ b [ZMOD n]) (h₂ : c ≡ d [ZMOD n]) : a - c ≡ b - d [ZMOD n] := by
rw [sub_eq_add_neg, sub_eq_add_neg]
exact h₁.add h₂.neg
#align int.modeq.sub Int.ModEq.sub
@@ -188,8 +186,7 @@ protected theorem mul_left (c : ℤ) (h : a ≡ b [ZMOD n]) : c * a ≡ c * b [Z
exact ((h.mul_left' <| neg_nonneg.2 hc).of_dvd (dvd_mul_left _ _)).neg
#align int.modeq.mul_left Int.ModEq.mul_left
-protected theorem mul_right (c : ℤ) (h : a ≡ b [ZMOD n]) : a * c ≡ b * c [ZMOD n] :=
- by
+protected theorem mul_right (c : ℤ) (h : a ≡ b [ZMOD n]) : a * c ≡ b * c [ZMOD n] := by
rw [mul_comm a, mul_comm b]
exact h.mul_left c
#align int.modeq.mul_right Int.ModEq.mul_right
@@ -198,8 +195,7 @@ protected theorem mul (h₁ : a ≡ b [ZMOD n]) (h₂ : c ≡ d [ZMOD n]) : a *
(h₂.mul_left _).trans (h₁.mul_right _)
#align int.modeq.mul Int.ModEq.mul
-protected theorem pow (m : ℕ) (h : a ≡ b [ZMOD n]) : a ^ m ≡ b ^ m [ZMOD n] :=
- by
+protected theorem pow (m : ℕ) (h : a ≡ b [ZMOD n]) : a ^ m ≡ b ^ m [ZMOD n] := by
induction' m with d hd; · rfl
rw [pow_succ, pow_succ]
exact h.mul hd
@@ -233,8 +229,7 @@ theorem modEq_and_modEq_iff_modEq_mul {a b m n : ℤ} (hmn : m.natAbs.coprime n.
fun h => ⟨h.of_mul_right _, h.of_mul_left _⟩⟩
#align int.modeq_and_modeq_iff_modeq_mul Int.modEq_and_modEq_iff_modEq_mul
-theorem gcd_a_modEq (a b : ℕ) : (a : ℤ) * Nat.gcdA a b ≡ Nat.gcd a b [ZMOD b] :=
- by
+theorem gcd_a_modEq (a b : ℕ) : (a : ℤ) * Nat.gcdA a b ≡ Nat.gcd a b [ZMOD b] := by
rw [← add_zero ((a : ℤ) * _), Nat.gcd_eq_gcd_ab]
exact (dvd_mul_right _ _).zero_modEq_int.add_left _
#align int.gcd_a_modeq Int.gcd_a_modEq
ModEq
lemma names (#1384)
Match https://github.com/leanprover-community/mathlib/pull/17902
@@ -4,7 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE.
Authors: Chris Hughes
! This file was ported from Lean 3 source module data.int.modeq
-! leanprover-community/mathlib commit ffc3730d545623aedf5d5bd46a3153cbf41f6c2c
+! leanprover-community/mathlib commit 2ed7e4aec72395b6a7c3ac4ac7873a7a43ead17c
! Please do not edit these lines, except to modify the commit id
! if you have ported upstream changes.
-/
@@ -99,12 +99,8 @@ theorem modEq_iff_add_fac {a b n : ℤ} : a ≡ b [ZMOD n] ↔ ∃ t, b = a + n
exact exists_congr fun t => sub_eq_iff_eq_add'
#align int.modeq_iff_add_fac Int.modEq_iff_add_fac
-theorem ModEq.dvd : a ≡ b [ZMOD n] → n ∣ b - a :=
- modEq_iff_dvd.1
+alias modEq_iff_dvd ↔ ModEq.dvd modEq_of_dvd
#align int.modeq.dvd Int.ModEq.dvd
-
-theorem modEq_of_dvd : n ∣ b - a → a ≡ b [ZMOD n] :=
- modEq_iff_dvd.2
#align int.modeq_of_dvd Int.modEq_of_dvd
theorem mod_modEq (a n) : a % n ≡ a [ZMOD n] :=
@@ -113,9 +109,9 @@ theorem mod_modEq (a n) : a % n ≡ a [ZMOD n] :=
namespace ModEq
-protected theorem modEq_of_dvd (d : m ∣ n) (h : a ≡ b [ZMOD n]) : a ≡ b [ZMOD m] :=
+protected theorem of_dvd (d : m ∣ n) (h : a ≡ b [ZMOD n]) : a ≡ b [ZMOD m] :=
modEq_iff_dvd.2 <| d.trans h.dvd
-#align int.modeq.modeq_of_dvd Int.ModEq.modEq_of_dvd
+#align int.modeq.of_dvd Int.ModEq.of_dvd
protected theorem mul_left' (hc : 0 ≤ c) (h : a ≡ b [ZMOD n]) : c * a ≡ c * b [ZMOD c * n] :=
match hc.lt_or_eq with
@@ -186,10 +182,10 @@ protected theorem sub_right (c : ℤ) (h : a ≡ b [ZMOD n]) : a - c ≡ b - c [
protected theorem mul_left (c : ℤ) (h : a ≡ b [ZMOD n]) : c * a ≡ c * b [ZMOD n] :=
match (le_total 0 c) with
- | .inl hc => (h.mul_left' hc).modEq_of_dvd (dvd_mul_left _ _)
+ | .inl hc => (h.mul_left' hc).of_dvd (dvd_mul_left _ _)
| .inr hc => by
rw [← neg_neg c, neg_mul, neg_mul _ b]
- exact ((h.mul_left' <| neg_nonneg.2 hc).modEq_of_dvd (dvd_mul_left _ _)).neg
+ exact ((h.mul_left' <| neg_nonneg.2 hc).of_dvd (dvd_mul_left _ _)).neg
#align int.modeq.mul_left Int.ModEq.mul_left
protected theorem mul_right (c : ℤ) (h : a ≡ b [ZMOD n]) : a * c ≡ b * c [ZMOD n] :=
@@ -209,13 +205,13 @@ protected theorem pow (m : ℕ) (h : a ≡ b [ZMOD n]) : a ^ m ≡ b ^ m [ZMOD n
exact h.mul hd
#align int.modeq.pow Int.ModEq.pow
-theorem of_modEq_mul_left (m : ℤ) (h : a ≡ b [ZMOD m * n]) : a ≡ b [ZMOD n] := by
+lemma of_mul_left (m : ℤ) (h : a ≡ b [ZMOD m * n]) : a ≡ b [ZMOD n] := by
rw [modEq_iff_dvd] at *; exact (dvd_mul_left n m).trans h
-#align int.modeq.of_modeq_mul_left Int.ModEq.of_modEq_mul_left
+#align int.modeq.of_mul_left Int.ModEq.of_mul_left
-theorem of_modEq_mul_right (m : ℤ) : a ≡ b [ZMOD n * m] → a ≡ b [ZMOD n] :=
- mul_comm m n ▸ of_modEq_mul_left _
-#align int.modeq.of_modeq_mul_right Int.ModEq.of_modEq_mul_right
+lemma of_mul_right (m : ℤ) : a ≡ b [ZMOD n * m] → a ≡ b [ZMOD n] :=
+ mul_comm m n ▸ of_mul_left _
+#align int.modeq.of_mul_right Int.ModEq.of_mul_right
end ModEq
@@ -234,7 +230,7 @@ theorem modEq_and_modEq_iff_modEq_mul {a b m n : ℤ} (hmn : m.natAbs.coprime n.
rw [modEq_iff_dvd, ← natAbs_dvd, ← dvd_natAbs, coe_nat_dvd, natAbs_mul]
refine' hmn.mul_dvd_of_dvd_of_dvd _ _ <;> rw [← coe_nat_dvd, natAbs_dvd, dvd_natAbs] <;>
tauto,
- fun h => ⟨h.of_modEq_mul_right _, h.of_modEq_mul_left _⟩⟩
+ fun h => ⟨h.of_mul_right _, h.of_mul_left _⟩⟩
#align int.modeq_and_modeq_iff_modeq_mul Int.modEq_and_modEq_iff_modEq_mul
theorem gcd_a_modEq (a b : ℕ) : (a : ℤ) * Nat.gcdA a b ≡ Nat.gcd a b [ZMOD b] :=
@@ -248,7 +244,7 @@ theorem modEq_add_fac {a b n : ℤ} (c : ℤ) (ha : a ≡ b [ZMOD n]) : a + n *
a + n * c ≡ b + n * c [ZMOD n] := ha.add_right _
_ ≡ b + 0 [ZMOD n] := (dvd_mul_right _ _).modEq_zero_int.add_left _
_ ≡ b [ZMOD n] := by rw [add_zero]
-
+
#align int.modeq_add_fac Int.modEq_add_fac
theorem modEq_add_fac_self {a t n : ℤ} : a + n * t ≡ a [ZMOD n] :=
@@ -280,11 +276,11 @@ theorem exists_unique_equiv_nat (a : ℤ) {b : ℤ} (hb : 0 < b) : ∃ z : ℕ,
#align int.exists_unique_equiv_nat Int.exists_unique_equiv_nat
theorem mod_mul_right_mod (a b c : ℤ) : a % (b * c) % b = a % b :=
- (mod_modEq _ _).of_modEq_mul_right _
+ (mod_modEq _ _).of_mul_right _
#align int.mod_mul_right_mod Int.mod_mul_right_mod
theorem mod_mul_left_mod (a b c : ℤ) : a % (b * c) % c = a % c :=
- (mod_modEq _ _).of_modEq_mul_left _
+ (mod_modEq _ _).of_mul_left _
#align int.mod_mul_left_mod Int.mod_mul_left_mod
end Int
All dependencies are ported!