l3lab/ntp-mathlib huggingface dataset:
theorem of_div (h : a / c ≡ b / c [MOD m / c]) (ha : c ∣ a) (ha : c ∣ b) (ha : c ∣ m) :
    a ≡ b [MOD m] := by convert h.mul_left' c <;> 

Proof state:
case h.e'_2
m n a b c d : ℕ
h : a / c ≡ b / c [MOD m / c]
ha✝¹ : c ∣ a
ha✝ : c ∣ b
ha : c ∣ m
⊢ a = c * (a / c)

Next tactic:
rwa [Nat.mul_div_cancel']
theorem of_div (h : a / c ≡ b / c [MOD m / c]) (ha : c ∣ a) (ha : c ∣ b) (ha : c ∣ m) :
    a ≡ b [MOD m] := by convert h.mul_left' c <;> 

Proof state:
case h.e'_3
m n a b c d : ℕ
h : a / c ≡ b / c [MOD m / c]
ha✝¹ : c ∣ a
ha✝ : c ∣ b
ha : c ∣ m
⊢ b = c * (b / c)

Next tactic:
rwa [Nat.mul_div_cancel']
lemma modEq_sub (h : b ≤ a) : a ≡ b [MOD a - b] := (modEq_of_dvd $ by 

Proof state:
m n a b c d : ℕ
h : b ≤ a
⊢ ↑(a - b) ∣ ↑a - ↑b

Next tactic:
rw [Int.ofNat_sub h]
@[simp] lemma modEq_zero_iff : a ≡ b [MOD 0] ↔ a = b := by 

Proof state:
m n a b c d : ℕ
⊢ a ≡ b [MOD 0] ↔ a = b

Next tactic:
rw [ModEq, mod_zero, mod_zero]
@[simp] lemma add_modEq_left : n + a ≡ a [MOD n] := by 

Proof state:
m n a b c d : ℕ
⊢ n + a ≡ a [MOD n]

Next tactic:
rw [ModEq, add_mod_left]
@[simp] lemma add_modEq_right : a + n ≡ a [MOD n] := by 

Proof state:
m n a b c d : ℕ
⊢ a + n ≡ a [MOD n]

Next tactic:
rw [ModEq, add_mod_right]
theorem dvd_iff (h : a ≡ b [MOD m]) (hdm : d ∣ m) : d ∣ a ↔ d ∣ b := by
  

Proof state:
m n a b c d : ℕ
h : a ≡ b [MOD m]
hdm : d ∣ m
⊢ d ∣ a ↔ d ∣ b

Next tactic:
simp only [← modEq_zero_iff_dvd]
theorem dvd_iff (h : a ≡ b [MOD m]) (hdm : d ∣ m) : d ∣ a ↔ d ∣ b := by
  simp only [← modEq_zero_iff_dvd]
  

Proof state:
m n a b c d : ℕ
h : a ≡ b [MOD m]
hdm : d ∣ m
⊢ a ≡ 0 [MOD d] ↔ b ≡ 0 [MOD d]

Next tactic:
replace h := h.of_dvd hdm
theorem dvd_iff (h : a ≡ b [MOD m]) (hdm : d ∣ m) : d ∣ a ↔ d ∣ b := by
  simp only [← modEq_zero_iff_dvd]
  replace h := h.of_dvd hdm
  

Proof state:
m n a b c d : ℕ
hdm : d ∣ m
h : a ≡ b [MOD d]
⊢ a ≡ 0 [MOD d] ↔ b ≡ 0 [MOD d]

Next tactic:
exact ⟨h.symm.trans, h.trans⟩
theorem gcd_eq (h : a ≡ b [MOD m]) : gcd a m = gcd b m := by
  

Proof state:
m n a b c d : ℕ
h : a ≡ b [MOD m]
⊢ gcd a m = gcd b m

Next tactic:
have h1 := gcd_dvd_right a m
theorem gcd_eq (h : a ≡ b [MOD m]) : gcd a m = gcd b m := by
  have h1 := gcd_dvd_right a m
  

Proof state:
m n a b c d : ℕ
h : a ≡ b [MOD m]
h1 : gcd a m ∣ m
⊢ gcd a m = gcd b m

Next tactic:
have h2 := gcd_dvd_right b m
theorem gcd_eq (h : a ≡ b [MOD m]) : gcd a m = gcd b m := by
  have h1 := gcd_dvd_right a m
  have h2 := gcd_dvd_right b m
  

Proof state:
m n a b c d : ℕ
h : a ≡ b [MOD m]
h1 : gcd a m ∣ m
h2 : gcd b m ∣ m
⊢ gcd a m = gcd b m

Next tactic:
exact
    dvd_antisymm (dvd_gcd ((h.dvd_iff h1).mp (gcd_dvd_left a m)) h1)
      (dvd_gcd ((h.dvd_iff h2).mpr (gcd_dvd_left b m)) h2)
lemma eq_of_abs_lt (h : a ≡ b [MOD m]) (h2 : |(b : ℤ) - a| < m) : a = b := by
  

Proof state:
m n a b c d : ℕ
h : a ≡ b [MOD m]
h2 : |↑b - ↑a| < ↑m
⊢ a = b

Next tactic:
apply Int.ofNat.inj
lemma eq_of_abs_lt (h : a ≡ b [MOD m]) (h2 : |(b : ℤ) - a| < m) : a = b := by
  apply Int.ofNat.inj
  

Proof state:
case x
m n a b c d : ℕ
h : a ≡ b [MOD m]
h2 : |↑b - ↑a| < ↑m
⊢ Int.ofNat a = Int.ofNat b

Next tactic:
rw [eq_comm, ← sub_eq_zero]
lemma eq_of_abs_lt (h : a ≡ b [MOD m]) (h2 : |(b : ℤ) - a| < m) : a = b := by
  apply Int.ofNat.inj
  rw [eq_comm, ← sub_eq_zero]
  

Proof state:
case x
m n a b c d : ℕ
h : a ≡ b [MOD m]
h2 : |↑b - ↑a| < ↑m
⊢ Int.ofNat b - Int.ofNat a = 0

Next tactic:
exact Int.eq_zero_of_abs_lt_dvd h.dvd h2
/-- 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 [MOD m]) :  a ≡ b [MOD m / gcd m c] := by
  

Proof state:
m n a b c d : ℕ
hm : 0 < m
h : c * a ≡ c * b [MOD m]
⊢ a ≡ b [MOD m / gcd m c]

Next tactic:
let d := gcd m c
/-- 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 [MOD m]) :  a ≡ b [MOD m / gcd m c] := by
  let d := gcd m c
  

Proof state:
m n a b c d✝ : ℕ
hm : 0 < m
h : c * a ≡ c * b [MOD m]
d : ℕ := gcd m c
⊢ a ≡ b [MOD m / gcd m c]

Next tactic:
have hmd := gcd_dvd_left m c
/-- 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 [MOD m]) :  a ≡ b [MOD m / gcd m c] := by
  let d := gcd m c
  have hmd := gcd_dvd_left m c
  

Proof state:
m n a b c d✝ : ℕ
hm : 0 < m
h : c * a ≡ c * b [MOD m]
d : ℕ := gcd m c
hmd : gcd m c ∣ m
⊢ a ≡ b [MOD m / gcd m c]

Next tactic:
have hcd := gcd_dvd_right m c
/-- 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 [MOD m]) :  a ≡ b [MOD m / gcd m c] := by
  let d := gcd m c
  have hmd := gcd_dvd_left m c
  have hcd := gcd_dvd_right m c
  

Proof state:
m n a b c d✝ : ℕ
hm : 0 < m
h : c * a ≡ c * b [MOD m]
d : ℕ := gcd m c
hmd : gcd m c ∣ m
hcd : gcd m c ∣ c
⊢ a ≡ b [MOD m / gcd m c]

Next tactic:
rw [modEq_iff_dvd]
/-- 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 [MOD m]) :  a ≡ b [MOD 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]
  

Proof state:
m n a b c d✝ : ℕ
hm : 0 < m
h : c * a ≡ c * b [MOD m]
d : ℕ := gcd m c
hmd : gcd m c ∣ m
hcd : gcd m c ∣ c
⊢ ↑(m / gcd m c) ∣ ↑b - ↑a

Next tactic:
refine' @Int.dvd_of_dvd_mul_right_of_gcd_one (m / d) (c / d) (b - a) _ _
/-- 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 [MOD m]) :  a ≡ b [MOD 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]
  refine' @Int.dvd_of_dvd_mul_right_of_gcd_one (m / d) (c / d) (b - a) _ _
  

Proof state:
case refine'_1
m n a b c d✝ : ℕ
hm : 0 < m
h : c * a ≡ c * b [MOD m]
d : ℕ := gcd m c
hmd : gcd m c ∣ m
hcd : gcd m c ∣ c
⊢ ↑m / ↑d ∣ ↑c / ↑d * (↑b - ↑a)
case refine'_2
m n a b c d✝ : ℕ
hm : 0 < m
h : c * a ≡ c * b [MOD m]
d : ℕ := gcd m c
hmd : gcd m c ∣ m
hcd : gcd m c ∣ c
⊢ Int.gcd (↑m / ↑d) (↑c / ↑d) = 1

Next tactic:
show (m / d : ℤ) ∣ c / d * (b - a)
/-- 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 [MOD m]) :  a ≡ b [MOD 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]
  refine' @Int.dvd_of_dvd_mul_right_of_gcd_one (m / d) (c / d) (b - a) _ _
  show (m / d : ℤ) ∣ c / d * (b - a)
  · 

Proof state:
case refine'_1
m n a b c d✝ : ℕ
hm : 0 < m
h : c * a ≡ c * b [MOD m]
d : ℕ := gcd m c
hmd : gcd m c ∣ m
hcd : gcd m c ∣ c
⊢ ↑m / ↑d ∣ ↑c / ↑d * (↑b - ↑a)

Next tactic:
rw [mul_comm, ← Int.mul_ediv_assoc (b - a) (Int.coe_nat_dvd.mpr hcd), mul_comm]
/-- 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 [MOD m]) :  a ≡ b [MOD 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]
  refine' @Int.dvd_of_dvd_mul_right_of_gcd_one (m / d) (c / d) (b - a) _ _
  show (m / d : ℤ) ∣ c / d * (b - a)
  · rw [mul_comm, ← Int.mul_ediv_assoc (b - a) (Int.coe_nat_dvd.mpr hcd), mul_comm]
    

Proof state:
case refine'_1
m n a b c d✝ : ℕ
hm : 0 < m
h : c * a ≡ c * b [MOD m]
d : ℕ := gcd m c
hmd : gcd m c ∣ m
hcd : gcd m c ∣ c
⊢ ↑m / ↑d ∣ ↑c * (↑b - ↑a) / ↑(gcd m c)

Next tactic:
apply Int.ediv_dvd_ediv (Int.coe_nat_dvd.mpr hmd)
/-- 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 [MOD m]) :  a ≡ b [MOD 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]
  refine' @Int.dvd_of_dvd_mul_right_of_gcd_one (m / d) (c / d) (b - a) _ _
  show (m / d : ℤ) ∣ c / d * (b - a)
  · rw [mul_comm, ← Int.mul_ediv_assoc (b - a) (Int.coe_nat_dvd.mpr hcd), mul_comm]
    apply Int.ediv_dvd_ediv (Int.coe_nat_dvd.mpr hmd)
    

Proof state:
case refine'_1
m n a b c d✝ : ℕ
hm : 0 < m
h : c * a ≡ c * b [MOD m]
d : ℕ := gcd m c
hmd : gcd m c ∣ m
hcd : gcd m c ∣ c
⊢ ↑m ∣ ↑c * (↑b - ↑a)

Next tactic:
rw [mul_sub]
/-- 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 [MOD m]) :  a ≡ b [MOD 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]
  refine' @Int.dvd_of_dvd_mul_right_of_gcd_one (m / d) (c / d) (b - a) _ _
  show (m / d : ℤ) ∣ c / d * (b - a)
  · rw [mul_comm, ← Int.mul_ediv_assoc (b - a) (Int.coe_nat_dvd.mpr hcd), mul_comm]
    apply Int.ediv_dvd_ediv (Int.coe_nat_dvd.mpr hmd)
    rw [mul_sub]
    

Proof state:
case refine'_1
m n a b c d✝ : ℕ
hm : 0 < m
h : c * a ≡ c * b [MOD m]
d : ℕ := gcd m c
hmd : gcd m c ∣ m
hcd : gcd m c ∣ c
⊢ ↑m ∣ ↑c * ↑b - ↑c * ↑a

Next tactic:
exact modEq_iff_dvd.mp h
/-- 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 [MOD m]) :  a ≡ b [MOD 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]
  refine' @Int.dvd_of_dvd_mul_right_of_gcd_one (m / d) (c / d) (b - a) _ _
  show (m / d : ℤ) ∣ c / d * (b - a)
  · rw [mul_comm, ← Int.mul_ediv_assoc (b - a) (Int.coe_nat_dvd.mpr hcd), mul_comm]
    apply Int.ediv_dvd_ediv (Int.coe_nat_dvd.mpr hmd)
    rw [mul_sub]
    exact modEq_iff_dvd.mp h
  

Proof state:
case refine'_2
m n a b c d✝ : ℕ
hm : 0 < m
h : c * a ≡ c * b [MOD m]
d : ℕ := gcd m c
hmd : gcd m c ∣ m
hcd : gcd m c ∣ c
⊢ Int.gcd (↑m / ↑d) (↑c / ↑d) = 1

Next tactic:
show Int.gcd (m / d) (c / d) = 1
/-- 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 [MOD m]) :  a ≡ b [MOD 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]
  refine' @Int.dvd_of_dvd_mul_right_of_gcd_one (m / d) (c / d) (b - a) _ _
  show (m / d : ℤ) ∣ c / d * (b - a)
  · rw [mul_comm, ← Int.mul_ediv_assoc (b - a) (Int.coe_nat_dvd.mpr hcd), mul_comm]
    apply Int.ediv_dvd_ediv (Int.coe_nat_dvd.mpr hmd)
    rw [mul_sub]
    exact modEq_iff_dvd.mp h
  show Int.gcd (m / d) (c / d) = 1
  · 

Proof state:
case refine'_2
m n a b c d✝ : ℕ
hm : 0 < m
h : c * a ≡ c * b [MOD m]
d : ℕ := gcd m c
hmd : gcd m c ∣ m
hcd : gcd m c ∣ c
⊢ Int.gcd (↑m / ↑d) (↑c / ↑d) = 1

Next tactic:
simp only [← Int.coe_nat_div, Int.coe_nat_gcd (m / d) (c / d), gcd_div hmd hcd,
      Nat.div_self (gcd_pos_of_pos_left c hm)]
/-- 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 [MOD m]) : a ≡ b [MOD m / gcd m c] := by
  

Proof state:
m n a b c d : ℕ
hm : 0 < m
h : a * c ≡ b * c [MOD m]
⊢ a ≡ b [MOD m / gcd m c]

Next tactic:
apply cancel_left_div_gcd hm
/-- 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 [MOD m]) : a ≡ b [MOD m / gcd m c] := by
  apply cancel_left_div_gcd hm
  

Proof state:
m n a b c d : ℕ
hm : 0 < m
h : a * c ≡ b * c [MOD m]
⊢ c * a ≡ c * b [MOD m]

Next tactic:
simpa [mul_comm] using h
/-- A common factor that's coprime with the modulus can be cancelled from a `ModEq` -/
lemma cancel_left_of_coprime (hmc : gcd m c = 1) (h : c * a ≡ c * b [MOD m]) : a ≡ b [MOD m] := by
  

Proof state:
m n a b c d : ℕ
hmc : gcd m c = 1
h : c * a ≡ c * b [MOD m]
⊢ a ≡ b [MOD m]

Next tactic:
rcases m.eq_zero_or_pos with (rfl | hm)
/-- A common factor that's coprime with the modulus can be cancelled from a `ModEq` -/
lemma cancel_left_of_coprime (hmc : gcd m c = 1) (h : c * a ≡ c * b [MOD m]) : a ≡ b [MOD m] := by
  rcases m.eq_zero_or_pos with (rfl | hm)
  · 

Proof state:
case inl
n a b c d : ℕ
hmc : gcd 0 c = 1
h : c * a ≡ c * b [MOD 0]
⊢ a ≡ b [MOD 0]

Next tactic:
simp only [gcd_zero_left] at hmc
/-- A common factor that's coprime with the modulus can be cancelled from a `ModEq` -/
lemma cancel_left_of_coprime (hmc : gcd m c = 1) (h : c * a ≡ c * b [MOD m]) : a ≡ b [MOD m] := by
  rcases m.eq_zero_or_pos with (rfl | hm)
  · simp only [gcd_zero_left] at hmc
    

Proof state:
case inl
n a b c d : ℕ
hmc : c = 1
h : c * a ≡ c * b [MOD 0]
⊢ a ≡ b [MOD 0]

Next tactic:
simp only [gcd_zero_left, hmc, one_mul, modEq_zero_iff] at h
/-- A common factor that's coprime with the modulus can be cancelled from a `ModEq` -/
lemma cancel_left_of_coprime (hmc : gcd m c = 1) (h : c * a ≡ c * b [MOD m]) : a ≡ b [MOD m] := by
  rcases m.eq_zero_or_pos with (rfl | hm)
  · simp only [gcd_zero_left] at hmc
    simp only [gcd_zero_left, hmc, one_mul, modEq_zero_iff] at h
    

Proof state:
case inl
n a b c d : ℕ
hmc : c = 1
h : a = b
⊢ a ≡ b [MOD 0]

Next tactic:
subst h
/-- A common factor that's coprime with the modulus can be cancelled from a `ModEq` -/
lemma cancel_left_of_coprime (hmc : gcd m c = 1) (h : c * a ≡ c * b [MOD m]) : a ≡ b [MOD m] := by
  rcases m.eq_zero_or_pos with (rfl | hm)
  · simp only [gcd_zero_left] at hmc
    simp only [gcd_zero_left, hmc, one_mul, modEq_zero_iff] at h
    subst h
    

Proof state:
case inl
n a c d : ℕ
hmc : c = 1
⊢ a ≡ a [MOD 0]

Next tactic:
rfl
/-- A common factor that's coprime with the modulus can be cancelled from a `ModEq` -/
lemma cancel_left_of_coprime (hmc : gcd m c = 1) (h : c * a ≡ c * b [MOD m]) : a ≡ b [MOD m] := by
  rcases m.eq_zero_or_pos with (rfl | hm)
  · simp only [gcd_zero_left] at hmc
    simp only [gcd_zero_left, hmc, one_mul, modEq_zero_iff] at h
    subst h
    rfl
  

Proof state:
case inr
m n a b c d : ℕ
hmc : gcd m c = 1
h : c * a ≡ c * b [MOD m]
hm : m > 0
⊢ a ≡ b [MOD m]

Next tactic:
simpa [hmc] using h.cancel_left_div_gcd hm
/-- A common factor that's coprime with the modulus can be cancelled from a `ModEq` -/
lemma cancel_right_of_coprime (hmc : gcd m c = 1) (h : a * c ≡ b * c [MOD m]) : a ≡ b [MOD m] :=
  cancel_left_of_coprime hmc $ by 

Proof state:
m n a b c d : ℕ
hmc : gcd m c = 1
h : a * c ≡ b * c [MOD m]
⊢ c * a ≡ c * b [MOD m]

Next tactic:
simpa [mul_comm] using h
/-- The natural number less than `lcm n m` congruent to `a` mod `n` and `b` mod `m` -/
def chineseRemainder' (h : a ≡ b [MOD gcd n m]) : { k // k ≡ a [MOD n] ∧ k ≡ b [MOD m] } :=
  if hn : n = 0 then ⟨a, by 

Proof state:
m n a b c d : ℕ
h : a ≡ b [MOD gcd n m]
hn : n = 0
⊢ a ≡ a [MOD n] ∧ a ≡ b [MOD m]

Next tactic:
rw [hn, gcd_zero_left] at h
/-- The natural number less than `lcm n m` congruent to `a` mod `n` and `b` mod `m` -/
def chineseRemainder' (h : a ≡ b [MOD gcd n m]) : { k // k ≡ a [MOD n] ∧ k ≡ b [MOD m] } :=
  if hn : n = 0 then ⟨a, by rw [hn, gcd_zero_left] at h; 

Proof state:
m n a b c d : ℕ
h : a ≡ b [MOD m]
hn : n = 0
⊢ a ≡ a [MOD n] ∧ a ≡ b [MOD m]

Next tactic:
constructor
/-- The natural number less than `lcm n m` congruent to `a` mod `n` and `b` mod `m` -/
def chineseRemainder' (h : a ≡ b [MOD gcd n m]) : { k // k ≡ a [MOD n] ∧ k ≡ b [MOD m] } :=
  if hn : n = 0 then ⟨a, by rw [hn, gcd_zero_left] at h; constructor; 

Proof state:
case left
m n a b c d : ℕ
h : a ≡ b [MOD m]
hn : n = 0
⊢ a ≡ a [MOD n]
case right m n a b c d : ℕ h : a ≡ b [MOD m] hn : n = 0 ⊢ a ≡ b [MOD m]

Next tactic:
rfl
/-- The natural number less than `lcm n m` congruent to `a` mod `n` and `b` mod `m` -/
def chineseRemainder' (h : a ≡ b [MOD gcd n m]) : { k // k ≡ a [MOD n] ∧ k ≡ b [MOD m] } :=
  if hn : n = 0 then ⟨a, by rw [hn, gcd_zero_left] at h; constructor; rfl; 

Proof state:
case right
m n a b c d : ℕ
h : a ≡ b [MOD m]
hn : n = 0
⊢ a ≡ b [MOD m]

Next tactic:
exact h
/-- The natural number less than `lcm n m` congruent to `a` mod `n` and `b` mod `m` -/
def chineseRemainder' (h : a ≡ b [MOD gcd n m]) : { k // k ≡ a [MOD n] ∧ k ≡ b [MOD m] } :=
  if hn : n = 0 then ⟨a, by rw [hn, gcd_zero_left] at h; constructor; rfl; exact h⟩
  else
    if hm : m = 0 then ⟨b, by 

Proof state:
m n a b c d : ℕ
h : a ≡ b [MOD gcd n m]
hn : ¬n = 0
hm : m = 0
⊢ b ≡ a [MOD n] ∧ b ≡ b [MOD m]

Next tactic:
rw [hm, gcd_zero_right] at h
/-- The natural number less than `lcm n m` congruent to `a` mod `n` and `b` mod `m` -/
def chineseRemainder' (h : a ≡ b [MOD gcd n m]) : { k // k ≡ a [MOD n] ∧ k ≡ b [MOD m] } :=
  if hn : n = 0 then ⟨a, by rw [hn, gcd_zero_left] at h; constructor; rfl; exact h⟩
  else
    if hm : m = 0 then ⟨b, by rw [hm, gcd_zero_right] at h; 

Proof state:
m n a b c d : ℕ
h : a ≡ b [MOD n]
hn : ¬n = 0
hm : m = 0
⊢ b ≡ a [MOD n] ∧ b ≡ b [MOD m]

Next tactic:
constructor
/-- The natural number less than `lcm n m` congruent to `a` mod `n` and `b` mod `m` -/
def chineseRemainder' (h : a ≡ b [MOD gcd n m]) : { k // k ≡ a [MOD n] ∧ k ≡ b [MOD m] } :=
  if hn : n = 0 then ⟨a, by rw [hn, gcd_zero_left] at h; constructor; rfl; exact h⟩
  else
    if hm : m = 0 then ⟨b, by rw [hm, gcd_zero_right] at h; constructor; 

Proof state:
case left
m n a b c d : ℕ
h : a ≡ b [MOD n]
hn : ¬n = 0
hm : m = 0
⊢ b ≡ a [MOD n]
case right m n a b c d : ℕ h : a ≡ b [MOD n] hn : ¬n = 0 hm : m = 0 ⊢ b ≡ b [MOD m]

Next tactic:
exact h.symm
/-- The natural number less than `lcm n m` congruent to `a` mod `n` and `b` mod `m` -/
def chineseRemainder' (h : a ≡ b [MOD gcd n m]) : { k // k ≡ a [MOD n] ∧ k ≡ b [MOD m] } :=
  if hn : n = 0 then ⟨a, by rw [hn, gcd_zero_left] at h; constructor; rfl; exact h⟩
  else
    if hm : m = 0 then ⟨b, by rw [hm, gcd_zero_right] at h; constructor; exact h.symm; 

Proof state:
case right
m n a b c d : ℕ
h : a ≡ b [MOD n]
hn : ¬n = 0
hm : m = 0
⊢ b ≡ b [MOD m]

Next tactic:
rfl
/-- The natural number less than `lcm n m` congruent to `a` mod `n` and `b` mod `m` -/
def chineseRemainder' (h : a ≡ b [MOD gcd n m]) : { k // k ≡ a [MOD n] ∧ k ≡ b [MOD m] } :=
  if hn : n = 0 then ⟨a, by rw [hn, gcd_zero_left] at h; constructor; rfl; exact h⟩
  else
    if hm : m = 0 then ⟨b, by rw [hm, gcd_zero_right] at h; constructor; exact h.symm; rfl⟩
    else
      ⟨let (c, d) := xgcd n m; Int.toNat ((n * c * b + m * d * a) / gcd n m % lcm n m), by
        

Proof state:
m n a b c d : ℕ
h : a ≡ b [MOD gcd n m]
hn : ¬n = 0
hm : ¬m = 0
⊢ (match xgcd n m with
      | (c, d) => Int.toNat ((↑n * c * ↑b + ↑m * d * ↑a) / ↑(gcd n m) % ↑(lcm n m))) ≡
      a [MOD n] ∧
    (match xgcd n m with
      | (c, d) => Int.toNat ((↑n * c * ↑b + ↑m * d * ↑a) / ↑(gcd n m) % ↑(lcm n m))) ≡
      b [MOD m]

Next tactic:
rw [xgcd_val]
/-- The natural number less than `lcm n m` congruent to `a` mod `n` and `b` mod `m` -/
def chineseRemainder' (h : a ≡ b [MOD gcd n m]) : { k // k ≡ a [MOD n] ∧ k ≡ b [MOD m] } :=
  if hn : n = 0 then ⟨a, by rw [hn, gcd_zero_left] at h; constructor; rfl; exact h⟩
  else
    if hm : m = 0 then ⟨b, by rw [hm, gcd_zero_right] at h; constructor; exact h.symm; rfl⟩
    else
      ⟨let (c, d) := xgcd n m; Int.toNat ((n * c * b + m * d * a) / gcd n m % lcm n m), by
        rw [xgcd_val]
        

Proof state:
m n a b c d : ℕ
h : a ≡ b [MOD gcd n m]
hn : ¬n = 0
hm : ¬m = 0
⊢ (match (gcdA n m, gcdB n m) with
      | (c, d) => Int.toNat ((↑n * c * ↑b + ↑m * d * ↑a) / ↑(gcd n m) % ↑(lcm n m))) ≡
      a [MOD n] ∧
    (match (gcdA n m, gcdB n m) with
      | (c, d) => Int.toNat ((↑n * c * ↑b + ↑m * d * ↑a) / ↑(gcd n m) % ↑(lcm n m))) ≡
      b [MOD m]

Next tactic:
dsimp
/-- The natural number less than `lcm n m` congruent to `a` mod `n` and `b` mod `m` -/
def chineseRemainder' (h : a ≡ b [MOD gcd n m]) : { k // k ≡ a [MOD n] ∧ k ≡ b [MOD m] } :=
  if hn : n = 0 then ⟨a, by rw [hn, gcd_zero_left] at h; constructor; rfl; exact h⟩
  else
    if hm : m = 0 then ⟨b, by rw [hm, gcd_zero_right] at h; constructor; exact h.symm; rfl⟩
    else
      ⟨let (c, d) := xgcd n m; Int.toNat ((n * c * b + m * d * a) / gcd n m % lcm n m), by
        rw [xgcd_val]
        dsimp
        

Proof state:
m n a b c d : ℕ
h : a ≡ b [MOD gcd n m]
hn : ¬n = 0
hm : ¬m = 0
⊢ Int.toNat ((↑n * gcdA n m * ↑b + ↑m * gcdB n m * ↑a) / ↑(gcd n m) % ↑(lcm n m)) ≡ a [MOD n] ∧
    Int.toNat ((↑n * gcdA n m * ↑b + ↑m * gcdB n m * ↑a) / ↑(gcd n m) % ↑(lcm n m)) ≡ b [MOD m]

Next tactic:
rw [modEq_iff_dvd, modEq_iff_dvd,
          Int.toNat_of_nonneg (Int.emod_nonneg _ (Int.coe_nat_ne_zero.2 (lcm_ne_zero hn hm)))]
/-- The natural number less than `lcm n m` congruent to `a` mod `n` and `b` mod `m` -/
def chineseRemainder' (h : a ≡ b [MOD gcd n m]) : { k // k ≡ a [MOD n] ∧ k ≡ b [MOD m] } :=
  if hn : n = 0 then ⟨a, by rw [hn, gcd_zero_left] at h; constructor; rfl; exact h⟩
  else
    if hm : m = 0 then ⟨b, by rw [hm, gcd_zero_right] at h; constructor; exact h.symm; rfl⟩
    else
      ⟨let (c, d) := xgcd n m; Int.toNat ((n * c * b + m * d * a) / gcd n m % lcm n m), by
        rw [xgcd_val]
        dsimp
        rw [modEq_iff_dvd, modEq_iff_dvd,
          Int.toNat_of_nonneg (Int.emod_nonneg _ (Int.coe_nat_ne_zero.2 (lcm_ne_zero hn hm)))]
        

Proof state:
m n a b c d : ℕ
h : a ≡ b [MOD gcd n m]
hn : ¬n = 0
hm : ¬m = 0
⊢ ↑n ∣ ↑a - (↑n * gcdA n m * ↑b + ↑m * gcdB n m * ↑a) / ↑(gcd n m) % ↑(lcm n m) ∧
    ↑m ∣ ↑b - (↑n * gcdA n m * ↑b + ↑m * gcdB n m * ↑a) / ↑(gcd n m) % ↑(lcm n m)

Next tactic:
have hnonzero : (gcd n m : ℤ) ≠ 0 := by
          norm_cast
          rw [Nat.gcd_eq_zero_iff, not_and]
          exact fun _ => hm
/-- The natural number less than `lcm n m` congruent to `a` mod `n` and `b` mod `m` -/
def chineseRemainder' (h : a ≡ b [MOD gcd n m]) : { k // k ≡ a [MOD n] ∧ k ≡ b [MOD m] } :=
  if hn : n = 0 then ⟨a, by rw [hn, gcd_zero_left] at h; constructor; rfl; exact h⟩
  else
    if hm : m = 0 then ⟨b, by rw [hm, gcd_zero_right] at h; constructor; exact h.symm; rfl⟩
    else
      ⟨let (c, d) := xgcd n m; Int.toNat ((n * c * b + m * d * a) / gcd n m % lcm n m), by
        rw [xgcd_val]
        dsimp
        rw [modEq_iff_dvd, modEq_iff_dvd,
          Int.toNat_of_nonneg (Int.emod_nonneg _ (Int.coe_nat_ne_zero.2 (lcm_ne_zero hn hm)))]
        have hnonzero : (gcd n m : ℤ) ≠ 0 := by
          

Proof state:
m n a b c d : ℕ
h : a ≡ b [MOD gcd n m]
hn : ¬n = 0
hm : ¬m = 0
⊢ ↑(gcd n m) ≠ 0

Next tactic:
norm_cast
/-- The natural number less than `lcm n m` congruent to `a` mod `n` and `b` mod `m` -/
def chineseRemainder' (h : a ≡ b [MOD gcd n m]) : { k // k ≡ a [MOD n] ∧ k ≡ b [MOD m] } :=
  if hn : n = 0 then ⟨a, by rw [hn, gcd_zero_left] at h; constructor; rfl; exact h⟩
  else
    if hm : m = 0 then ⟨b, by rw [hm, gcd_zero_right] at h; constructor; exact h.symm; rfl⟩
    else
      ⟨let (c, d) := xgcd n m; Int.toNat ((n * c * b + m * d * a) / gcd n m % lcm n m), by
        rw [xgcd_val]
        dsimp
        rw [modEq_iff_dvd, modEq_iff_dvd,
          Int.toNat_of_nonneg (Int.emod_nonneg _ (Int.coe_nat_ne_zero.2 (lcm_ne_zero hn hm)))]
        have hnonzero : (gcd n m : ℤ) ≠ 0 := by
          norm_cast
          

Proof state:
m n a b c d : ℕ
h : a ≡ b [MOD gcd n m]
hn : ¬n = 0
hm : ¬m = 0
⊢ ¬gcd n m = 0

Next tactic:
rw [Nat.gcd_eq_zero_iff, not_and]
/-- The natural number less than `lcm n m` congruent to `a` mod `n` and `b` mod `m` -/
def chineseRemainder' (h : a ≡ b [MOD gcd n m]) : { k // k ≡ a [MOD n] ∧ k ≡ b [MOD m] } :=
  if hn : n = 0 then ⟨a, by rw [hn, gcd_zero_left] at h; constructor; rfl; exact h⟩
  else
    if hm : m = 0 then ⟨b, by rw [hm, gcd_zero_right] at h; constructor; exact h.symm; rfl⟩
    else
      ⟨let (c, d) := xgcd n m; Int.toNat ((n * c * b + m * d * a) / gcd n m % lcm n m), by
        rw [xgcd_val]
        dsimp
        rw [modEq_iff_dvd, modEq_iff_dvd,
          Int.toNat_of_nonneg (Int.emod_nonneg _ (Int.coe_nat_ne_zero.2 (lcm_ne_zero hn hm)))]
        have hnonzero : (gcd n m : ℤ) ≠ 0 := by
          norm_cast
          rw [Nat.gcd_eq_zero_iff, not_and]
          

Proof state:
m n a b c d : ℕ
h : a ≡ b [MOD gcd n m]
hn : ¬n = 0
hm : ¬m = 0
⊢ n = 0 → ¬m = 0

Next tactic:
exact fun _ => hm