Built with
doc-gen4 , running Lean4.
Bubbles (
) indicate interactive fragments: hover for details, tap to reveal contents.
Use
Ctrl+ā Ctrl+ā to navigate,
Ctrl+š±ļø to focus.
On Mac, use
Cmd instead of
Ctrl .
/-
Copyright (c) 2014 Jeremy Avigad. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Jeremy Avigad, Leonardo de Moura, Mario Carneiro
-/
import Std.Data.Nat.Lemmas
/-!
# Definitions and properties of `gcd`, `lcm`, and `coprime`
-/
namespace Nat
theorem gcd_rec ( m n : Nat ) : gcd m n = gcd ( n % m ) m :=
match m with
| 0 => by have := ( mod_zero : ā (a : Nat ), a % 0 = a mod_zero n ). symm : ā {α : Sort ?u.189} {a b : α }, a = b ā b = a symm ; rwa [ gcd_zero_right : ā (n : Nat ), gcd n 0 = n gcd_zero_right]
| _ + 1 => by simp [ gcd_succ ]
@[elab_as_elim] theorem gcd.induction : ā {P : Nat ā Nat ā Prop } (m n : Nat ), (ā (n : Nat ), P 0 n ) ā (ā (m n : Nat ), 0 < m ā P (n % m ) m ā P m n ) ā P m n gcd.induction { P : Nat ā Nat ā Prop } ( m n : Nat )
( H0 : ā n , P 0 n ) ( H1 : ā (m n : Nat ), 0 < m ā P (n % m ) m ā P m n H1 : ā m n , 0 < m ā P ( n % m ) m ā P m n ) : P m n :=
Nat.strongInductionOn : ā {motive : Nat ā Sort ?u.455 } (n : Nat ), (ā (n : Nat ), (ā (m : Nat ), m < n ā motive m ) ā motive n ) ā motive n Nat.strongInductionOn (motive := fun m => ā n , P m n ) m
( fun
| 0 , _ => H0
| _+1, IH : ā (m : Nat ), m < nā + 1 ā (fun m => ā (n : Nat ), P m n ) m IH => fun _ => H1 : ā (m n : Nat ), 0 < m ā P (n % m ) m ā P m n H1 _ _ ( succ_pos _ ) ( IH : ā (m : Nat ), m < nā + 1 ā (fun m => ā (n : Nat ), P m n ) m IH _ ( mod_lt _ ( succ_pos _ )) _ ) )
n
/-- The least common multiple of `m` and `n`, defined using `gcd`. -/
def lcm ( m n : Nat ) : Nat := m * n / gcd m n
/-- `m` and `n` are coprime, or relatively prime, if their `gcd` is 1. -/
@[reducible] def coprime ( m n : Nat ) : Prop := gcd m n = 1
---
theorem gcd_dvd ( m n : Nat ) : ( gcd m n ⣠m ) ⧠( gcd m n ⣠n ) := by
induction m , n using gcd.induction : ā {P : Nat ā Nat ā Prop } (m n : Nat ), (ā (n : Nat ), P 0 n ) ā (ā (m n : Nat ), 0 < m ā P (n % m ) m ā P m n ) ā P m n gcd.induction with
| H0 n => rw [ gcd_zero_left : ā (y : Nat ), gcd 0 y = y gcd_zero_left] ; exact ⨠Nat.dvd_zero : ā (a : Nat ), a ⣠0 Nat.dvd_zero n , Nat.dvd_refl : ā (a : Nat ), a ⣠a Nat.dvd_refl n ā©
| H1 m n _ IH => rw [ ā gcd_rec ] at IH ; exact ⨠IH . 2 , ( dvd_mod_iff IH . 2 ). 1 : ā {a b : Prop }, (a ā b ) ā a ā b 1 IH . 1 ā©
theorem gcd_dvd_left ( m n : Nat ) : gcd m n ⣠m := ( gcd_dvd m n ). left : ā {a b : Prop }, a ā§ b ā a left
theorem gcd_dvd_right : ā (m n : Nat ), gcd m n ⣠n gcd_dvd_right ( m n : Nat ) : gcd m n ⣠n := ( gcd_dvd m n ). right : ā {a b : Prop }, a ā§ b ā b right
theorem gcd_le_left ( n ) ( h : 0 < m ) : gcd m n ⤠m := le_of_dvd h <| gcd_dvd_left m n
theorem gcd_le_right ( n ) ( h : 0 < n ) : gcd m n ⤠n := le_of_dvd h <| gcd_dvd_right : ā (m n : Nat ), gcd m n ⣠n gcd_dvd_right m n
theorem dvd_gcd : k ⣠m ā k ⣠n ā k ⣠gcd m n := by
induction m , n using gcd.induction : ā {P : Nat ā Nat ā Prop } (m n : Nat ), (ā (n : Nat ), P 0 n ) ā (ā (m n : Nat ), 0 < m ā P (n % m ) m ā P m n ) ā P m n gcd.induction with intro km kn
| H0 n => rw [ gcd_zero_left : ā (y : Nat ), gcd 0 y = y gcd_zero_left] ; exact kn
| H1 n m _ IH => rw [ gcd_rec ] ; exact IH (( dvd_mod_iff km ). 2 : ā {a b : Prop }, (a ā b ) ā b ā a 2 kn ) km
theorem dvd_gcd_iff : k ⣠gcd m n ā k ⣠m ā§ k ⣠n :=
⨠fun h => let ⨠hā , hā ā© := gcd_dvd m n ; ⨠Nat.dvd_trans : ā {a b c : Nat }, a ⣠b ā b ⣠c ā a ⣠c Nat.dvd_trans h hā , Nat.dvd_trans : ā {a b c : Nat }, a ⣠b ā b ⣠c ā a ⣠c Nat.dvd_trans h hā ā©,
fun ⨠hā , hā ā© => dvd_gcd hā hā ā©
theorem gcd_comm ( m n : Nat ) : gcd m n = gcd n m :=
dvd_antisymm : ā {m n : Nat }, m ⣠n ā n ⣠m ā m = n dvd_antisymm
( dvd_gcd ( gcd_dvd_right : ā (m n : Nat ), gcd m n ⣠n gcd_dvd_right m n ) ( gcd_dvd_left m n ))
( dvd_gcd ( gcd_dvd_right : ā (m n : Nat ), gcd m n ⣠n gcd_dvd_right n m ) ( gcd_dvd_left n m ))
theorem gcd_eq_left_iff_dvd : m ⣠n ā gcd m n = m :=
⨠fun h => by rw [ gcd_rec , mod_eq_zero_of_dvd : ā {m n : Nat }, m ⣠n ā n % m = 0 mod_eq_zero_of_dvd h , gcd_zero_left : ā (y : Nat ), gcd 0 y = y gcd_zero_left] ,
fun h => h āø gcd_dvd_right : ā (m n : Nat ), gcd m n ⣠n gcd_dvd_right m n ā©
theorem gcd_eq_right_iff_dvd : m ⣠n ā gcd n m = m := by
rw [ gcd_comm ] ; exact gcd_eq_left_iff_dvd
theorem gcd_assoc ( m n k : Nat ) : gcd ( gcd m n ) k = gcd m ( gcd n k ) :=
dvd_antisymm : ā {m n : Nat }, m ⣠n ā n ⣠m ā m = n dvd_antisymm
( dvd_gcd
( Nat.dvd_trans : ā {a b c : Nat }, a ⣠b ā b ⣠c ā a ⣠c Nat.dvd_trans ( gcd_dvd_left ( gcd m n ) k ) ( gcd_dvd_left m n ))
( dvd_gcd ( Nat.dvd_trans : ā {a b c : Nat }, a ⣠b ā b ⣠c ā a ⣠c Nat.dvd_trans ( gcd_dvd_left ( gcd m n ) k ) ( gcd_dvd_right : ā (m n : Nat ), gcd m n ⣠n gcd_dvd_right m n ))
( gcd_dvd_right : ā (m n : Nat ), gcd m n ⣠n gcd_dvd_right ( gcd m n ) k )))
( dvd_gcd
( dvd_gcd ( gcd_dvd_left m ( gcd n k ))
( Nat.dvd_trans : ā {a b c : Nat }, a ⣠b ā b ⣠c ā a ⣠c Nat.dvd_trans ( gcd_dvd_right : ā (m n : Nat ), gcd m n ⣠n gcd_dvd_right m ( gcd n k )) ( gcd_dvd_left n k )))
( Nat.dvd_trans : ā {a b c : Nat }, a ⣠b ā b ⣠c ā a ⣠c Nat.dvd_trans ( gcd_dvd_right : ā (m n : Nat ), gcd m n ⣠n gcd_dvd_right m ( gcd n k )) ( gcd_dvd_right : ā (m n : Nat ), gcd m n ⣠n gcd_dvd_right n k )))
@[ simp ] theorem gcd_one_right : ā (n : Nat ), gcd n 1 = 1 gcd_one_right ( n : Nat ) : gcd n 1 = 1 := ( gcd_comm n 1 ). trans : ā {α : Sort ?u.2308} {a b c : α }, a = b ā b = c ā a = c trans ( gcd_one_left : ā (n : Nat ), gcd 1 n = 1 gcd_one_left n )
theorem gcd_mul_left : ā (m n k : Nat ), gcd (m * n ) (m * k ) = m * gcd n k gcd_mul_left ( m n k : Nat ) : gcd ( m * n ) ( m * k ) = m * gcd n k := by
induction n , k using gcd.induction : ā {P : Nat ā Nat ā Prop } (m n : Nat ), (ā (n : Nat ), P 0 n ) ā (ā (m n : Nat ), 0 < m ā P (n % m ) m ā P m n ) ā P m n gcd.induction with
| H0 k => simp
| H1 n k _ IH => rwa [ ā mul_mod_mul_left : ā (z x y : Nat ), z * x % (z * y ) = z * (x % y ) mul_mod_mul_left, ā gcd_rec , ā gcd_rec ] at IH
theorem gcd_mul_right : ā (m n k : Nat ), gcd (m * n ) (k * n ) = gcd m k * n gcd_mul_right ( m n k : Nat ) : gcd ( m * n ) ( k * n ) = gcd m k * n := by
rw [ Nat.mul_comm : ā (n m : Nat ), n * m = m * n Nat.mul_comm m n , Nat.mul_comm : ā (n m : Nat ), n * m = m * n Nat.mul_comm k n , Nat.mul_comm : ā (n m : Nat ), n * m = m * n Nat.mul_comm ( gcd m k ) n , gcd_mul_left : ā (m n k : Nat ), gcd (m * n ) (m * k ) = m * gcd n k gcd_mul_left]
theorem gcd_pos_of_pos_left { m : Nat } ( n : Nat ) ( mpos : 0 < m ) : 0 < gcd m n :=
pos_of_dvd_of_pos : ā {m n : Nat }, m ⣠n ā 0 < n ā 0 < m pos_of_dvd_of_pos ( gcd_dvd_left m n ) mpos
theorem gcd_pos_of_pos_right ( m : Nat ) { n : Nat } ( npos : 0 < n ) : 0 < gcd m n :=
pos_of_dvd_of_pos : ā {m n : Nat }, m ⣠n ā 0 < n ā 0 < m pos_of_dvd_of_pos ( gcd_dvd_right : ā (m n : Nat ), gcd m n ⣠n gcd_dvd_right m n ) npos
theorem div_gcd_pos_of_pos_left ( b : Nat ) ( h : 0 < a ) : 0 < a / a . gcd b :=
( Nat.le_div_iff_mul_le <| Nat.gcd_pos_of_pos_left : ā {m : Nat } (n : Nat ), 0 < m ā 0 < gcd m n Nat.gcd_pos_of_pos_left _ h ). 2 : ā {a b : Prop }, (a ā b ) ā b ā a 2 ( Nat.one_mul : ā (n : Nat ), 1 * n = n Nat.one_mul _ āø Nat.gcd_le_left _ h )
theorem div_gcd_pos_of_pos_right : ā {b : Nat } (a : Nat ), 0 < b ā 0 < b / gcd a b div_gcd_pos_of_pos_right ( a : Nat ) ( h : 0 < b ) : 0 < b / a . gcd b :=
( Nat.le_div_iff_mul_le <| Nat.gcd_pos_of_pos_right : ā (m : Nat ) {n : Nat }, 0 < n ā 0 < gcd m n Nat.gcd_pos_of_pos_right _ h ). 2 : ā {a b : Prop }, (a ā b ) ā b ā a 2 ( Nat.one_mul : ā (n : Nat ), 1 * n = n Nat.one_mul _ āø Nat.gcd_le_right _ h )
theorem eq_zero_of_gcd_eq_zero_left : ā {m n : Nat }, gcd m n = 0 ā m = 0 eq_zero_of_gcd_eq_zero_left { m n : Nat } ( H : gcd m n = 0 ) : m = 0 :=
match eq_zero_or_pos m with
| .inl : ā {a b : Prop }, a ā a ⨠b .inl H0 => H0
| .inr : ā {a b : Prop }, b ā a ⨠b .inr H1 => absurd : ā {a : Prop } {b : Sort ?u.3408}, a ā ¬ a ā b absurd ( Eq.symm : ā {α : Sort ?u.3411} {a b : α }, a = b ā b = a Eq.symm H ) ( ne_of_lt : ā {a b : Nat }, a < b ā a ā b ne_of_lt ( gcd_pos_of_pos_left _ H1 ))
theorem eq_zero_of_gcd_eq_zero_right : ā {m n : Nat }, gcd m n = 0 ā n = 0 eq_zero_of_gcd_eq_zero_right { m n : Nat } ( H : gcd m n = 0 ) : n = 0 := by
rw [ gcd_comm ] at H
exact eq_zero_of_gcd_eq_zero_left : ā {m n : Nat }, gcd m n = 0 ā m = 0 eq_zero_of_gcd_eq_zero_left H
theorem gcd_ne_zero_left : ā {m n : Nat }, m ā 0 ā gcd m n ā 0 gcd_ne_zero_left : m ā 0 ā gcd m n ā 0 := mt : ā {a b : Prop }, (a ā b ) ā ¬ b ā ¬ a mt eq_zero_of_gcd_eq_zero_left : ā {m n : Nat }, gcd m n = 0 ā m = 0 eq_zero_of_gcd_eq_zero_left
theorem gcd_ne_zero_right : ā {n m : Nat }, n ā 0 ā gcd m n ā 0 gcd_ne_zero_right : n ā 0 ā gcd m n ā 0 := mt : ā {a b : Prop }, (a ā b ) ā ¬ b ā ¬ a mt eq_zero_of_gcd_eq_zero_right : ā {m n : Nat }, gcd m n = 0 ā n = 0 eq_zero_of_gcd_eq_zero_right
theorem gcd_div { m n k : Nat } ( H1 : k ⣠m ) ( H2 : k ⣠n ) :
gcd ( m / k ) ( n / k ) = gcd m n / k :=
match eq_zero_or_pos k with
| .inl : ā {a b : Prop }, a ā a ⨠b .inl H0 => by simp [ H0 ]
| .inr : ā {a b : Prop }, b ā a ⨠b .inr H3 => by
apply Nat.eq_of_mul_eq_mul_right : ā {n m k : Nat }, 0 < m ā n * m = k * m ā n = k Nat.eq_of_mul_eq_mul_right H3
rw [ Nat.div_mul_cancel : ā {n m : Nat }, n ⣠m ā m / n * n = m Nat.div_mul_cancel ( dvd_gcd H1 H2 ), ā gcd_mul_right : ā (m n k : Nat ), gcd (m * n ) (k * n ) = gcd m k * n gcd_mul_right,
Nat.div_mul_cancel : ā {n m : Nat }, n ⣠m ā m / n * n = m Nat.div_mul_cancel H1 , Nat.div_mul_cancel : ā {n m : Nat }, n ⣠m ā m / n * n = m Nat.div_mul_cancel H2 ]
theorem gcd_dvd_gcd_of_dvd_left { m k : Nat } ( n : Nat ) ( H : m ⣠k ) : gcd m n ⣠gcd k n :=
dvd_gcd ( Nat.dvd_trans : ā {a b c : Nat }, a ⣠b ā b ⣠c ā a ⣠c Nat.dvd_trans ( gcd_dvd_left m n ) H ) ( gcd_dvd_right : ā (m n : Nat ), gcd m n ⣠n gcd_dvd_right m n )
theorem gcd_dvd_gcd_of_dvd_right { m k : Nat } ( n : Nat ) ( H : m ⣠k ) : gcd n m ⣠gcd n k :=
dvd_gcd ( gcd_dvd_left n m ) ( Nat.dvd_trans : ā {a b c : Nat }, a ⣠b ā b ⣠c ā a ⣠c Nat.dvd_trans ( gcd_dvd_right : ā (m n : Nat ), gcd m n ⣠n gcd_dvd_right n m ) H )
theorem gcd_dvd_gcd_mul_left : ā (m n k : Nat ), gcd m n ⣠gcd (k * m ) n gcd_dvd_gcd_mul_left ( m n k : Nat ) : gcd m n ⣠gcd ( k * m ) n :=
gcd_dvd_gcd_of_dvd_left _ ( Nat.dvd_mul_left : ā (a b : Nat ), a ⣠b * a Nat.dvd_mul_left _ _ )
theorem gcd_dvd_gcd_mul_right : ā (m n k : Nat ), gcd m n ⣠gcd (m * k ) n gcd_dvd_gcd_mul_right ( m n k : Nat ) : gcd m n ⣠gcd ( m * k ) n :=
gcd_dvd_gcd_of_dvd_left _ ( Nat.dvd_mul_right : ā (a b : Nat ), a ⣠a * b Nat.dvd_mul_right _ _ )
theorem gcd_dvd_gcd_mul_left_right : ā (m n k : Nat ), gcd m n ⣠gcd m (k * n ) gcd_dvd_gcd_mul_left_right ( m n k : Nat ) : gcd m n ⣠gcd m ( k * n ) :=
gcd_dvd_gcd_of_dvd_right _ ( Nat.dvd_mul_left : ā (a b : Nat ), a ⣠b * a Nat.dvd_mul_left _ _ )
theorem gcd_dvd_gcd_mul_right_right : ā (m n k : Nat ), gcd m n ⣠gcd m (n * k ) gcd_dvd_gcd_mul_right_right ( m n k : Nat ) : gcd m n ⣠gcd m ( n * k ) :=
gcd_dvd_gcd_of_dvd_right _ ( Nat.dvd_mul_right : ā (a b : Nat ), a ⣠a * b Nat.dvd_mul_right _ _ )
theorem gcd_eq_left : ā {m n : Nat }, m ⣠n ā gcd m n = m gcd_eq_left { m n : Nat } ( H : m ⣠n ) : gcd m n = m :=
dvd_antisymm : ā {m n : Nat }, m ⣠n ā n ⣠m ā m = n dvd_antisymm ( gcd_dvd_left _ _ ) ( dvd_gcd ( Nat.dvd_refl : ā (a : Nat ), a ⣠a Nat.dvd_refl _ ) H )
theorem gcd_eq_right : ā {m n : Nat }, n ⣠m ā gcd m n = n gcd_eq_right { m n : Nat } ( H : n ⣠m ) : gcd m n = n := by
rw [ gcd_comm , gcd_eq_left : ā {m n : Nat }, m ⣠n ā gcd m n = m gcd_eq_left H ]
@[ simp ] theorem gcd_mul_left_left : ā (m n : Nat ), gcd (m * n ) n = n gcd_mul_left_left ( m n : Nat ) : gcd ( m * n ) n = n :=
dvd_antisymm : ā {m n : Nat }, m ⣠n ā n ⣠m ā m = n dvd_antisymm ( gcd_dvd_right : ā (m n : Nat ), gcd m n ⣠n gcd_dvd_right _ _ ) ( dvd_gcd ( Nat.dvd_mul_left : ā (a b : Nat ), a ⣠b * a Nat.dvd_mul_left _ _ ) ( Nat.dvd_refl : ā (a : Nat ), a ⣠a Nat.dvd_refl _ ))
@[ simp ] theorem gcd_mul_left_right : ā (m n : Nat ), gcd n (m * n ) = n gcd_mul_left_right ( m n : Nat ) : gcd n ( m * n ) = n := by
rw [ gcd_comm , gcd_mul_left_left : ā (m n : Nat ), gcd (m * n ) n = n gcd_mul_left_left]
@[ simp ] theorem gcd_mul_right_left : ā (m n : Nat ), gcd (n * m ) n = n gcd_mul_right_left ( m n : Nat ) : gcd ( n * m ) n = n := by
rw [ Nat.mul_comm : ā (n m : Nat ), n * m = m * n Nat.mul_comm, gcd_mul_left_left : ā (m n : Nat ), gcd (m * n ) n = n gcd_mul_left_left]
@[ simp ] theorem gcd_mul_right_right : ā (m n : Nat ), gcd n (n * m ) = n gcd_mul_right_right ( m n : Nat ) : gcd n ( n * m ) = n := by
rw [ gcd_comm , gcd_mul_right_left : ā (m n : Nat ), gcd (n * m ) n = n gcd_mul_right_left]
@[ simp ] theorem gcd_gcd_self_right_left : ā (m n : Nat ), gcd m (gcd m n ) = gcd m n gcd_gcd_self_right_left ( m n : Nat ) : gcd m ( gcd m n ) = gcd m n :=
dvd_antisymm : ā {m n : Nat }, m ⣠n ā n ⣠m ā m = n dvd_antisymm ( gcd_dvd_right : ā (m n : Nat ), gcd m n ⣠n gcd_dvd_right _ _ ) ( dvd_gcd ( gcd_dvd_left _ _ ) ( Nat.dvd_refl : ā (a : Nat ), a ⣠a Nat.dvd_refl _ ))
@[ simp ] theorem gcd_gcd_self_right_right : ā (m n : Nat ), gcd m (gcd n m ) = gcd n m gcd_gcd_self_right_right ( m n : Nat ) : gcd m ( gcd n m ) = gcd n m := by
rw [ gcd_comm n m , gcd_gcd_self_right_left : ā (m n : Nat ), gcd m (gcd m n ) = gcd m n gcd_gcd_self_right_left]
@[ simp ] theorem gcd_gcd_self_left_right : ā (m n : Nat ), gcd (gcd n m ) m = gcd n m gcd_gcd_self_left_right ( m n : Nat ) : gcd ( gcd n m ) m = gcd n m := by
rw [ gcd_comm , gcd_gcd_self_right_right : ā (m n : Nat ), gcd m (gcd n m ) = gcd n m gcd_gcd_self_right_right]
@[ simp ] theorem gcd_gcd_self_left_left : ā (m n : Nat ), gcd (gcd m n ) m = gcd m n gcd_gcd_self_left_left ( m n : Nat ) : gcd ( gcd m n ) m = gcd m n := by
rw [ gcd_comm m n , gcd_gcd_self_left_right : ā (m n : Nat ), gcd (gcd n m ) m = gcd n m gcd_gcd_self_left_right]
theorem gcd_add_mul_self : ā (m n k : Nat ), gcd m (n + k * m ) = gcd m n gcd_add_mul_self ( m n k : Nat ) : gcd m ( n + k * m ) = gcd m n := by
simp [ gcd_rec m ( n + k * m ), gcd_rec m n ]
theorem gcd_eq_zero_iff { i j : Nat } : gcd i j = 0 ā i = 0 ā§ j = 0 :=
⨠fun h => ⨠eq_zero_of_gcd_eq_zero_left : ā {m n : Nat }, gcd m n = 0 ā m = 0 eq_zero_of_gcd_eq_zero_left h , eq_zero_of_gcd_eq_zero_right : ā {m n : Nat }, gcd m n = 0 ā n = 0 eq_zero_of_gcd_eq_zero_right h ā©,
fun h => by simp [ h ] ā©
/-! ### `lcm` -/
theorem lcm_comm ( m n : Nat ) : lcm m n = lcm n m := by
rw [ lcm , lcm , Nat.mul_comm : ā (n m : Nat ), n * m = m * n Nat.mul_comm n m , gcd_comm n m ]
@[ simp ] theorem lcm_zero_left : ā (m : Nat ), lcm 0 m = 0 lcm_zero_left ( m : Nat ) : lcm 0 m = 0 := by simp [ lcm ]
@[ simp ] theorem lcm_zero_right : ā (m : Nat ), lcm m 0 = 0 lcm_zero_right ( m : Nat ) : lcm m 0 = 0 := by simp [ lcm ]
@[ simp ] theorem lcm_one_left : ā (m : Nat ), lcm 1 m = m lcm_one_left ( m : Nat ) : lcm 1 m = m := by simp [ lcm ]
@[ simp ] theorem lcm_one_right : ā (m : Nat ), lcm m 1 = m lcm_one_right ( m : Nat ) : lcm m 1 = m := by simp [ lcm ]
@[ simp ] theorem lcm_self : ā (m : Nat ), lcm m m = m lcm_self ( m : Nat ) : lcm m m = m := by
match eq_zero_or_pos m with
| .inl : ā {a b : Prop }, a ā a ⨠b .inl h => rw [ h , lcm_zero_left : ā (m : Nat ), lcm 0 m = 0 lcm_zero_left]
| .inr : ā {a b : Prop }, b ā a ⨠b .inr h => simp [ lcm , Nat.mul_div_cancel : ā (m : Nat ) {n : Nat }, 0 < n ā m * n / n = m Nat.mul_div_cancel _ h ]
theorem dvd_lcm_left ( m n : Nat ) : m ⣠lcm m n :=
⨠n / gcd m n , by rw [ ā Nat.mul_div_assoc : ā {k n : Nat } (m : Nat ), k ⣠n ā m * n / k = m * (n / k ) Nat.mul_div_assoc m ( Nat.gcd_dvd_right : ā (m n : Nat ), gcd m n ⣠n Nat.gcd_dvd_right m n ) ] ; rfl ā©
theorem dvd_lcm_right : ā (m n : Nat ), n ⣠lcm m n dvd_lcm_right ( m n : Nat ) : n ⣠lcm m n := lcm_comm n m āø dvd_lcm_left n m
theorem gcd_mul_lcm ( m n : Nat ) : gcd m n * lcm m n = m * n := by
rw [ lcm , Nat.mul_div_cancel' : ā {n m : Nat }, n ⣠m ā n * (m / n ) = m Nat.mul_div_cancel' ( Nat.dvd_trans : ā {a b c : Nat }, a ⣠b ā b ⣠c ā a ⣠c Nat.dvd_trans ( gcd_dvd_left m n ) ( Nat.dvd_mul_right : ā (a b : Nat ), a ⣠a * b Nat.dvd_mul_right m n )) ]
theorem lcm_dvd { m n k : Nat } ( H1 : m ⣠k ) ( H2 : n ⣠k ) : lcm m n ⣠k := by
match eq_zero_or_pos k with
| .inl : ā {a b : Prop }, a ā a ⨠b .inl h => rw [ h ] ; exact Nat.dvd_zero : ā (a : Nat ), a ⣠0 Nat.dvd_zero _
| .inr : ā {a b : Prop }, b ā a ⨠b .inr kpos =>
apply Nat.dvd_of_mul_dvd_mul_left : ā {k m n : Nat }, 0 < k ā k * m ⣠k * n ā m ⣠n Nat.dvd_of_mul_dvd_mul_left ( gcd_pos_of_pos_left n ( pos_of_dvd_of_pos : ā {m n : Nat }, m ⣠n ā 0 < n ā 0 < m pos_of_dvd_of_pos H1 kpos ))
rw [ gcd_mul_lcm , ā gcd_mul_right : ā (m n k : Nat ), gcd (m * n ) (k * n ) = gcd m k * n gcd_mul_right, Nat.mul_comm : ā (n m : Nat ), n * m = m * n Nat.mul_comm n k ]
exact dvd_gcd ( Nat.mul_dvd_mul_left : ā {b c : Nat } (a : Nat ), b ⣠c ā a * b ⣠a * c Nat.mul_dvd_mul_left _ H2 ) ( Nat.mul_dvd_mul_right : ā {a b : Nat }, a ⣠b ā ā (c : Nat ), a * c ⣠b * c Nat.mul_dvd_mul_right H1 _ )
theorem lcm_assoc ( m n k : Nat ) : lcm ( lcm m n ) k = lcm m ( lcm n k ) :=
dvd_antisymm : ā {m n : Nat }, m ⣠n ā n ⣠m ā m = n dvd_antisymm
( lcm_dvd
( lcm_dvd ( dvd_lcm_left m ( lcm n k )) ( Nat.dvd_trans : ā {a b c : Nat }, a ⣠b ā b ⣠c ā a ⣠c Nat.dvd_trans ( dvd_lcm_left n k ) ( dvd_lcm_right : ā (m n : Nat ), n ⣠lcm m n dvd_lcm_right m ( lcm n k ))))
( Nat.dvd_trans : ā {a b c : Nat }, a ⣠b ā b ⣠c ā a ⣠c Nat.dvd_trans ( dvd_lcm_right : ā (m n : Nat ), n ⣠lcm m n dvd_lcm_right n k ) ( dvd_lcm_right : ā (m n : Nat ), n ⣠lcm m n dvd_lcm_right m ( lcm n k ))))
( lcm_dvd
( Nat.dvd_trans : ā {a b c : Nat }, a ⣠b ā b ⣠c ā a ⣠c Nat.dvd_trans ( dvd_lcm_left m n ) ( dvd_lcm_left ( lcm m n ) k ))
( lcm_dvd ( Nat.dvd_trans : ā {a b c : Nat }, a ⣠b ā b ⣠c ā a ⣠c Nat.dvd_trans ( dvd_lcm_right : ā (m n : Nat ), n ⣠lcm m n dvd_lcm_right m n ) ( dvd_lcm_left ( lcm m n ) k ))
( dvd_lcm_right : ā (m n : Nat ), n ⣠lcm m n dvd_lcm_right ( lcm m n ) k )))
theorem lcm_ne_zero : ā {m n : Nat }, m ā 0 ā n ā 0 ā lcm m n ā 0 lcm_ne_zero ( hm : m ā 0 ) ( hn : n ā 0 ) : lcm m n ā 0 := by
intro h
have h1 := gcd_mul_lcm m n
rw [ h , Nat.mul_zero : ā (n : Nat ), n * 0 = 0 Nat.mul_zero] at h1
match mul_eq_zero . 1 : ā {a b : Prop }, (a ā b ) ā a ā b 1 h1 . symm : ā {α : Sort ?u.6884} {a b : α }, a = b ā b = a symm with
| .inl : ā {a b : Prop }, a ā a ⨠b .inl hm1 => exact hm hm1
| .inr : ā {a b : Prop }, b ā a ⨠b .inr hn1 => exact hn hn1
/-!
### `coprime`
See also `nat.coprime_of_dvd` and `nat.coprime_of_dvd'` to prove `nat.coprime m n`.
-/
instance ( m n : Nat ) : Decidable ( coprime m n ) := inferInstanceAs : (α : Sort ?u.7015) ā [i : α ] ā α inferInstanceAs ( Decidable ( _ = 1 ))
theorem coprime_iff_gcd_eq_one : coprime m n ā gcd m n = 1 := .rfl
theorem coprime.gcd_eq_one : coprime m n ā gcd m n = 1 := id : ā {α : Sort ?u.7201}, α ā α id
theorem coprime.symm : coprime n m ā coprime m n := ( gcd_comm m n ). trans : ā {α : Sort ?u.7227} {a b c : α }, a = b ā b = c ā a = c trans
theorem coprime_comm : coprime n m ā coprime m n := ⨠coprime.symm , coprime.symm ā©
theorem coprime.dvd_of_dvd_mul_right : ā {k n m : Nat }, coprime k n ā k ⣠m * n ā k ⣠m coprime.dvd_of_dvd_mul_right ( H1 : coprime k n ) ( H2 : k ⣠m * n ) : k ⣠m := by
let t := dvd_gcd ( Nat.dvd_mul_left : ā (a b : Nat ), a ⣠b * a Nat.dvd_mul_left k m ) H2
rwa [ gcd_mul_left : ā (m n k : Nat ), gcd (m * n ) (m * k ) = m * gcd n k gcd_mul_left, H1 . gcd_eq_one ,