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) 2018 Guy Leroy. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Sangwoo Jo (aka Jason), Guy Leroy, Johannes HΓΆlzl, Mario Carneiro
! This file was ported from Lean 3 source module data.int.gcd
! leanprover-community/mathlib commit 47a1a73351de8dd6c8d3d32b569c8e434b03ca47
! Please do not edit these lines, except to modify the commit id
! if you have ported upstream changes.
-/
import Mathlib.Data.Nat.GCD.Basic
import Mathlib.Algebra.GroupPower.Lemmas
import Mathlib.Algebra.Ring.Regular
import Mathlib.Data.Int.Dvd.Basic
import Mathlib.Order.Bounds.Basic
/-!
# Extended GCD and divisibility over β€
## Main definitions
* Given `x y : β`, `xgcd x y` computes the pair of integers `(a, b)` such that
`gcd x y = x * a + y * b`. `gcd_a x y` and `gcd_b x y` are defined to be `a` and `b`,
respectively.
## Main statements
* `gcd_eq_gcd_ab`: BΓ©zout's lemma, given `x y : β`, `gcd x y = x * gcd_a x y + y * gcd_b x y`.
## Tags
BΓ©zout's lemma, Bezout's lemma
-/
/-! ### Extended Euclidean algorithm -/
namespace Nat
/-- Helper function for the extended GCD algorithm (`Nat.xgcd`). -/
def xgcdAux : β β β€ β β€ β β β β€ β β€ β β Γ β€ Γ β€
| 0 , _, _, r' , s' , t' => ( r' , s' , t' )
| succ k , s , t , r' , s' , t' =>
have : r' % succ k < succ k := mod_lt _ <| ( succ_pos _ ). gt : β {Ξ± : Type ?u.212} [inst : LT Ξ± ] {x y : Ξ± }, x < y β y > x gt
let q := r' / succ k
xgcdAux ( r' % succ k ) ( s' - q * s ) ( t' - q * t ) ( succ k ) s t
#align nat.xgcd_aux Nat.xgcdAux
-- porting note: these are not in mathlib3; these equation lemmas are to fix
-- complaints by the Lean 4 `unusedHavesSuffices` linter obtained when `simp [xgcdAux]` is used.
theorem xgcdAux_zero : β {s t : β€ } {r' : β } {s' t' : β€ }, xgcdAux 0 s t r' s' t' = (r' , s' , t' ) xgcdAux_zero : xgcdAux 0 s t r' s' t' = ( r' , s' , t' ) := rfl : β {Ξ± : Sort ?u.12495} {a : Ξ± }, a = a rfl
theorem xgcdAux_succ : xgcdAux ( succ k ) s t r' s' t' =
xgcdAux ( r' % succ k ) ( s' - ( r' / succ k ) * s ) ( t' - ( r' / succ k ) * t ) ( succ k ) s t := rfl : β {Ξ± : Sort ?u.13002} {a : Ξ± }, a = a rfl
@[ simp ]
theorem xgcd_zero_left : β {s t : β€ } {r' : β } {s' t' : β€ }, xgcdAux 0 s t r' s' t' = (r' , s' , t' ) xgcd_zero_left { s t r' s' t' } : xgcdAux 0 s t r' s' t' = ( r' , s' , t' ) := by simp [ xgcdAux ]
#align nat.xgcd_zero_left Nat.xgcd_zero_left : β {s t : β€ } {r' : β } {s' t' : β€ }, xgcdAux 0 s t r' s' t' = (r' , s' , t' ) Nat.xgcd_zero_left
theorem xgcd_aux_rec { r s t r' s' t' } ( h : 0 < r ) :
xgcdAux r s t r' s' t' = xgcdAux ( r' % r ) ( s' - r' / r * s ) ( t' - r' / r * t ) r s t := by
obtain β¨r, rflβ© : β k , r = succ k β¨r β¨r, rflβ© : β k , r = succ k , rfl β¨r, rflβ© : β k , r = succ k β© := Nat.exists_eq_succ_of_ne_zero : β {n : β }, n β 0 β β k , n = succ k Nat.exists_eq_succ_of_ne_zero h . ne'
rfl
#align nat.xgcd_aux_rec Nat.xgcd_aux_rec
/-- Use the extended GCD algorithm to generate the `a` and `b` values
satisfying `gcd x y = x * a + y * b`. -/
def xgcd ( x y : β ) : β€ Γ β€ :=
( xgcdAux x 1 0 y 0 1 ). 2 : {Ξ± : Type ?u.15014} β {Ξ² : Type ?u.15013} β Ξ± Γ Ξ² β Ξ² 2
#align nat.xgcd Nat.xgcd
/-- The extended GCD `a` value in the equation `gcd x y = x * a + y * b`. -/
def gcdA ( x y : β ) : β€ :=
( xgcd x y ). 1 : {Ξ± : Type ?u.15082} β {Ξ² : Type ?u.15081} β Ξ± Γ Ξ² β Ξ± 1
#align nat.gcd_a Nat.gcdA
/-- The extended GCD `b` value in the equation `gcd x y = x * a + y * b`. -/
def gcdB ( x y : β ) : β€ :=
( xgcd x y ). 2 : {Ξ± : Type ?u.15125} β {Ξ² : Type ?u.15124} β Ξ± Γ Ξ² β Ξ² 2
#align nat.gcd_b Nat.gcdB
@[ simp ]
theorem gcdA_zero_left : β {s : β }, gcdA 0 s = 0 gcdA_zero_left { s : β } : gcdA 0 s = 0 := by
unfold gcdA
rw [ xgcd , xgcd_zero_left : β {s t : β€ } {r' : β } {s' t' : β€ }, xgcdAux 0 s t r' s' t' = (r' , s' , t' ) xgcd_zero_left]
#align nat.gcd_a_zero_left Nat.gcdA_zero_left : β {s : β }, gcdA 0 s = 0 Nat.gcdA_zero_left
@[ simp ]
theorem gcdB_zero_left : β {s : β }, gcdB 0 s = 1 gcdB_zero_left { s : β } : gcdB 0 s = 1 := by
unfold gcdB
rw [ xgcd , xgcd_zero_left : β {s t : β€ } {r' : β } {s' t' : β€ }, xgcdAux 0 s t r' s' t' = (r' , s' , t' ) xgcd_zero_left]
#align nat.gcd_b_zero_left Nat.gcdB_zero_left : β {s : β }, gcdB 0 s = 1 Nat.gcdB_zero_left
@[ simp ]
theorem gcdA_zero_right : β {s : β }, s β 0 β gcdA s 0 = 1 gcdA_zero_right { s : β } ( h : s β 0 ) : gcdA s 0 = 1 := by
unfold gcdA xgcd
obtain β¨s, rflβ© : β k , s = succ k β¨s β¨s, rflβ© : β k , s = succ k , rfl β¨s, rflβ© : β k , s = succ k β© := Nat.exists_eq_succ_of_ne_zero : β {n : β }, n β 0 β β k , n = succ k Nat.exists_eq_succ_of_ne_zero h
-- Porting note: `simp [xgcdAux_succ]` crashes Lean here
rw [ xgcdAux_succ ]
rfl
#align nat.gcd_a_zero_right Nat.gcdA_zero_right : β {s : β }, s β 0 β gcdA s 0 = 1 Nat.gcdA_zero_right
@[ simp ]
theorem gcdB_zero_right : β {s : β }, s β 0 β gcdB s 0 = 0 gcdB_zero_right { s : β } ( h : s β 0 ) : gcdB s 0 = 0 := by
unfold gcdB xgcd
obtain β¨s, rflβ© : β k , s = succ k β¨s β¨s, rflβ© : β k , s = succ k , rfl β¨s, rflβ© : β k , s = succ k β© := Nat.exists_eq_succ_of_ne_zero : β {n : β }, n β 0 β β k , n = succ k Nat.exists_eq_succ_of_ne_zero h
-- Porting note: `simp [xgcdAux_succ]` crashes Lean here
rw [ xgcdAux_succ ]
rfl
#align nat.gcd_b_zero_right Nat.gcdB_zero_right : β {s : β }, s β 0 β gcdB s 0 = 0 Nat.gcdB_zero_right
@[ simp ]
theorem xgcd_aux_fst : β (x y : β ) (s t s' t' : β€ ), (xgcdAux x s t y s' t' ).fst = gcd x y xgcd_aux_fst ( x y ) : β s t s' t' , ( xgcdAux x s t y s' t' ). 1 : {Ξ± : Type ?u.15679} β {Ξ² : Type ?u.15678} β Ξ± Γ Ξ² β Ξ± 1 = gcd x y :=
gcd.induction : β {P : β β β β Prop } (m n : β ), (β (n : β ), P 0 n ) β (β (m n : β ), 0 < m β P (n % m ) m β P m n ) β P m n gcd.induction x y ( by simp ) fun x y h IH s t s' t' => by
simp [ xgcd_aux_rec , h , IH ]
rw [ β gcd_rec ]
#align nat.xgcd_aux_fst Nat.xgcd_aux_fst : β (x y : β ) (s t s' t' : β€ ), (xgcdAux x s t y s' t' ).fst = gcd x y Nat.xgcd_aux_fst
theorem xgcd_aux_val ( x y ) : xgcdAux x 1 0 y 0 1 = ( gcd x y , xgcd x y ) := by
rw [ xgcd , β xgcd_aux_fst : β (x y : β ) (s t s' t' : β€ ), (xgcdAux x s t y s' t' ).fst = gcd x y xgcd_aux_fst x y 1 0 0 1 ]
#align nat.xgcd_aux_val Nat.xgcd_aux_val
theorem xgcd_val ( x y ) : xgcd x y = ( gcdA x y , gcdB x y ) := by
unfold gcdA gcdB ; cases xgcd x y mk (fstβ , sndβ ) = ((fstβ , sndβ ) .fst , (fstβ , sndβ ) .snd ) ; mk (fstβ , sndβ ) = ((fstβ , sndβ ) .fst , (fstβ , sndβ ) .snd ) rfl
#align nat.xgcd_val Nat.xgcd_val
section
variable ( x y : β )
private def P : β Γ β€ Γ β€ β Prop
| ( r , s , t ) => ( r : β€ ) = x * s + y * t
theorem xgcd_aux_P : β {r r' : β } {s t s' t' : β€ }, Nat.P x y (r , s , t ) β Nat.P x y (r' , s' , t' ) β Nat.P x y (xgcdAux r s t r' s' t' ) xgcd_aux_P { r r' } :
β { s t s' t' }, P x y ( r , s , t ) β P x y ( r' , s' , t' ) β P x y ( xgcdAux r s t r' s' t' ) := by
β {s t s' t' : β€ }, Nat.P x y (r , s , t ) β Nat.P x y (r' , s' , t' ) β Nat.P x y (xgcdAux r s t r' s' t' ) induction r , r' using gcd.induction : β {P : β β β β Prop } (m n : β ), (β (n : β ), P 0 n ) β (β (m n : β ), 0 < m β P (n % m ) m β P m n ) β P m n gcd.induction with
β {s t s' t' : β€ }, Nat.P x y (r , s , t ) β Nat.P x y (r' , s' , t' ) β Nat.P x y (xgcdAux r s t r' s' t' ) | H0 => H0 β {s t s' t' : β€ }, Nat.P x y (0 , s , t ) β Nat.P x y (nβ , s' , t' ) β Nat.P x y (xgcdAux 0 s t nβ s' t' ) simp
β {s t s' t' : β€ }, Nat.P x y (r , s , t ) β Nat.P x y (r' , s' , t' ) β Nat.P x y (xgcdAux r s t r' s' t' ) | H1 a b h IH =>
x, y, a, b : β h : 0 < a IH : β {s t s' t' : β€ }, Nat.P x y (b % a , s , t ) β Nat.P x y (a , s' , t' ) β Nat.P x y (xgcdAux (b % a ) s t a s' t' ) H1 β {s t s' t' : β€ }, Nat.P x y (a , s , t ) β Nat.P x y (b , s' , t' ) β Nat.P x y (xgcdAux a s t b s' t' ) intro s t s' t' p p' : Nat.P x y (b , s' , t' )
p' x, y, a, b : β h : 0 < a IH : β {s t s' t' : β€ }, Nat.P x y (b % a , s , t ) β Nat.P x y (a , s' , t' ) β Nat.P x y (xgcdAux (b % a ) s t a s' t' ) s, t, s', t' : β€ p : Nat.P x y (a , s , t ) p' : Nat.P x y (b , s' , t' ) H1
x, y, a, b : β h : 0 < a IH : β {s t s' t' : β€ }, Nat.P x y (b % a , s , t ) β Nat.P x y (a , s' , t' ) β Nat.P x y (xgcdAux (b % a ) s t a s' t' ) H1 β {s t s' t' : β€ }, Nat.P x y (a , s , t ) β Nat.P x y (b , s' , t' ) β Nat.P x y (xgcdAux a s t b s' t' ) rw [ x, y, a, b : β h : 0 < a IH : β {s t s' t' : β€ }, Nat.P x y (b % a , s , t ) β Nat.P x y (a , s' , t' ) β Nat.P x y (xgcdAux (b % a ) s t a s' t' ) s, t, s', t' : β€ p : Nat.P x y (a , s , t ) p' : Nat.P x y (b , s' , t' ) H1 xgcd_aux_rec h x, y, a, b : β h : 0 < a IH : β {s t s' t' : β€ }, Nat.P x y (b % a , s , t ) β Nat.P x y (a , s' , t' ) β Nat.P x y (xgcdAux (b % a ) s t a s' t' ) s, t, s', t' : β€ p : Nat.P x y (a , s , t ) p' : Nat.P x y (b , s' , t' ) H1 Nat.P x y (xgcdAux (b % a ) (s' - βb / βa * s ) (t' - βb / βa * t ) a s t )] x, y, a, b : β h : 0 < a IH : β {s t s' t' : β€ }, Nat.P x y (b % a , s , t ) β Nat.P x y (a , s' , t' ) β Nat.P x y (xgcdAux (b % a ) s t a s' t' ) s, t, s', t' : β€ p : Nat.P x y (a , s , t ) p' : Nat.P x y (b , s' , t' ) H1 Nat.P x y (xgcdAux (b % a ) (s' - βb / βa * s ) (t' - βb / βa * t ) a s t ); x, y, a, b : β h : 0 < a IH : β {s t s' t' : β€ }, Nat.P x y (b % a , s , t ) β Nat.P x y (a , s' , t' ) β Nat.P x y (xgcdAux (b % a ) s t a s' t' ) s, t, s', t' : β€ p : Nat.P x y (a , s , t ) p' : Nat.P x y (b , s' , t' ) H1 Nat.P x y (xgcdAux (b % a ) (s' - βb / βa * s ) (t' - βb / βa * t ) a s t ) x, y, a, b : β h : 0 < a IH : β {s t s' t' : β€ }, Nat.P x y (b % a , s , t ) β Nat.P x y (a , s' , t' ) β Nat.P x y (xgcdAux (b % a ) s t a s' t' ) H1 β {s t s' t' : β€ }, Nat.P x y (a , s , t ) β Nat.P x y (b , s' , t' ) β Nat.P x y (xgcdAux a s t b s' t' ) refine' IH _ : Nat.P x y (b % a , ?m.19718 , ?m.19719 ) _ p x, y, a, b : β h : 0 < a IH : β {s t s' t' : β€ }, Nat.P x y (b % a , s , t ) β Nat.P x y (a , s' , t' ) β Nat.P x y (xgcdAux (b % a ) s t a s' t' ) s, t, s', t' : β€ p : Nat.P x y (a , s , t ) p' : Nat.P x y (b , s' , t' ) H1 Nat.P x y (b % a , s' - βb / βa * s , t' - βb / βa * t ) ; x, y, a, b : β h : 0 < a IH : β {s t s' t' : β€ }, Nat.P x y (b % a , s , t ) β Nat.P x y (a , s' , t' ) β Nat.P x y (xgcdAux (b % a ) s t a s' t' ) s, t, s', t' : β€ p : Nat.P x y (a , s , t ) p' : Nat.P x y (b , s' , t' ) H1 Nat.P x y (b % a , s' - βb / βa * s , t' - βb / βa * t ) x, y, a, b : β h : 0 < a IH : β {s t s' t' : β€ }, Nat.P x y (b % a , s , t ) β Nat.P x y (a , s' , t' ) β Nat.P x y (xgcdAux (b % a ) s t a s' t' ) H1 β {s t s' t' : β€ }, Nat.P x y (a , s , t ) β Nat.P x y (b , s' , t' ) β Nat.P x y (xgcdAux a s t b s' t' ) dsimp [ P ] at * x, y, a, b : β h : 0 < a IH : β {s t s' t' : β€ },
βb % βa = βx * s + βy * t β
βa = βx * s' + βy * t' β
β(xgcdAux (b % a ) s t a s' t' ).fst = βx * (xgcdAux (b % a ) s t a s' t' ).2 .fst + βy * (xgcdAux (b % a ) s t a s' t' ).2 .snd s, t, s', t' : β€ p : βa = βx * s + βy * t p' : βb = βx * s' + βy * t' H1 βb % βa = βx * (s' - βb / βa * s ) + βy * (t' - βb / βa * t )
x, y, a, b : β h : 0 < a IH : β {s t s' t' : β€ }, Nat.P x y (b % a , s , t ) β Nat.P x y (a , s' , t' ) β Nat.P x y (xgcdAux (b % a ) s t a s' t' ) H1 β {s t s' t' : β€ }, Nat.P x y (a , s , t ) β Nat.P x y (b , s' , t' ) β Nat.P x y (xgcdAux a s t b s' t' ) rw [ x, y, a, b : β h : 0 < a IH : β {s t s' t' : β€ },
βb % βa = βx * s + βy * t β
βa = βx * s' + βy * t' β
β(xgcdAux (b % a ) s t a s' t' ).fst = βx * (xgcdAux (b % a ) s t a s' t' ).2 .fst + βy * (xgcdAux (b % a ) s t a s' t' ).2 .snd s, t, s', t' : β€ p : βa = βx * s + βy * t p' : βb = βx * s' + βy * t' H1 βb % βa = βx * (s' - βb / βa * s ) + βy * (t' - βb / βa * t )Int.emod_def : β (a b : β€ ), a % b = a - b * (a / b ) Int.emod_defx, y, a, b : β h : 0 < a IH : β {s t s' t' : β€ },
βb % βa = βx * s + βy * t β
βa = βx * s' + βy * t' β
β(xgcdAux (b % a ) s t a s' t' ).fst = βx * (xgcdAux (b % a ) s t a s' t' ).2 .fst + βy * (xgcdAux (b % a ) s t a s' t' ).2 .snd s, t, s', t' : β€ p : βa = βx * s + βy * t p' : βb = βx * s' + βy * t' H1 βb - βa * (βb / βa ) = βx * (s' - βb / βa * s ) + βy * (t' - βb / βa * t )] x, y, a, b : β h : 0 < a IH : β {s t s' t' : β€ },
βb % βa = βx * s + βy * t β
βa = βx * s' + βy * t' β
β(xgcdAux (b % a ) s t a s' t' ).fst = βx * (xgcdAux (b % a ) s t a s' t' ).2 .fst + βy * (xgcdAux (b % a ) s t a s' t' ).2 .snd s, t, s', t' : β€ p : βa = βx * s + βy * t p' : βb = βx * s' + βy * t' H1 βb - βa * (βb / βa ) = βx * (s' - βb / βa * s ) + βy * (t' - βb / βa * t ); x, y, a, b : β h : 0 < a IH : β {s t s' t' : β€ },
βb % βa = βx * s + βy * t β
βa = βx * s' + βy * t' β
β(xgcdAux (b % a ) s t a s' t' ).fst = βx * (xgcdAux (b % a ) s t a s' t' ).2 .fst + βy * (xgcdAux (b % a ) s t a s' t' ).2 .snd s, t, s', t' : β€ p : βa = βx * s + βy * t p' : βb = βx * s' + βy * t' H1 βb - βa * (βb / βa ) = βx * (s' - βb / βa * s ) + βy * (t' - βb / βa * t ) x, y, a, b : β h : 0 < a IH : β {s t s' t' : β€ }, Nat.P x y (b % a , s , t ) β Nat.P x y (a , s' , t' ) β Nat.P x y (xgcdAux (b % a ) s t a s' t' ) H1 β {s t s' t' : β€ }, Nat.P x y (a , s , t ) β Nat.P x y (b , s' , t' ) β Nat.P x y (xgcdAux a s t b s' t' ) generalize ( b / a : β€ ) = k x, y, a, b : β h : 0 < a IH : β {s t s' t' : β€ },
βb % βa = βx * s + βy * t β
βa = βx * s' + βy * t' β
β(xgcdAux (b % a ) s t a s' t' ).fst = βx * (xgcdAux (b % a ) s t a s' t' ).2 .fst + βy * (xgcdAux (b % a ) s t a s' t' ).2 .snd s, t, s', t' : β€ p : βa = βx * s + βy * t p' : βb = βx * s' + βy * t' k : β€ H1 βb - βa * k = βx * (s' - k * s ) + βy * (t' - k * t )
x, y, a, b : β h : 0 < a IH : β {s t s' t' : β€ }, Nat.P x y (b % a , s , t ) β Nat.P x y (a , s' , t' ) β Nat.P x y (xgcdAux (b % a ) s t a s' t' ) H1 β {s t s' t' : β€ }, Nat.P x y (a , s , t ) β Nat.P x y (b , s' , t' ) β Nat.P x y (xgcdAux a s t b s' t' ) rw [ x, y, a, b : β h : 0 < a IH : β {s t s' t' : β€ },
βb % βa = βx * s + βy * t β
βa = βx * s' + βy * t' β
β(xgcdAux (b % a ) s t a s' t' ).fst = βx * (xgcdAux (b % a ) s t a s' t' ).2 .fst + βy * (xgcdAux (b % a ) s t a s' t' ).2 .snd s, t, s', t' : β€ p : βa = βx * s + βy * t p' : βb = βx * s' + βy * t' k : β€ H1 βb - βa * k = βx * (s' - k * s ) + βy * (t' - k * t )p : βa = βx * s + βy * t p , x, y, a, b : β h : 0 < a IH : β {s t s' t' : β€ },
βb % βa = βx * s + βy * t β
βa = βx * s' + βy * t' β
β(xgcdAux (b % a ) s t a s' t' ).fst = βx * (xgcdAux (b % a ) s t a s' t' ).2 .fst + βy * (xgcdAux (b % a ) s t a s' t' ).2 .snd s, t, s', t' : β€ p : βa = βx * s + βy * t p' : βb = βx * s' + βy * t' k : β€ H1 βb - (βx * s + βy * t ) * k = βx * (s' - k * s ) + βy * (t' - k * t ) x, y, a, b : β h : 0 < a IH : β {s t s' t' : β€ },
βb % βa = βx * s + βy * t β
βa = βx * s' + βy * t' β
β(xgcdAux (b % a ) s t a s' t' ).fst = βx * (xgcdAux (b % a ) s t a s' t' ).2 .fst + βy * (xgcdAux (b % a ) s t a s' t' ).2 .snd s, t, s', t' : β€ p : βa = βx * s + βy * t p' : βb = βx * s' + βy * t' k : β€ H1 βb - βa * k = βx * (s' - k * s ) + βy * (t' - k * t )p' : βb = βx * s' + βy * t' p' , x, y, a, b : β h : 0 < a IH : β {s t s' t' : β€ },
βb % βa = βx * s + βy * t β
βa = βx * s' + βy * t' β
β(xgcdAux (b % a ) s t a s' t' ).fst = βx * (xgcdAux (b % a ) s t a s' t' ).2 .fst + βy * (xgcdAux (b % a ) s t a s' t' ).2 .snd s, t, s', t' : β€ p : βa = βx * s + βy * t p' : βb = βx * s' + βy * t' k : β€ H1 βx * s' + βy * t' - (βx * s + βy * t ) * k = βx * (s' - k * s ) + βy * (t' - k * t ) x, y, a, b : β h : 0 < a IH : β {s t s' t' : β€ },
βb % βa = βx * s + βy * t β
βa = βx * s' + βy * t' β
β(xgcdAux (b % a ) s t a s' t' ).fst = βx * (xgcdAux (b % a ) s t a s' t' ).2 .fst + βy * (xgcdAux (b % a ) s t a s' t' ).2 .snd s, t, s', t' : β€ p : βa = βx * s + βy * t p' : βb = βx * s' + βy * t' k : β€ H1 βb - βa * k = βx * (s' - k * s ) + βy * (t' - k * t )mul_sub , x, y, a, b : β h : 0 < a IH : β {s t s' t' : β€ },
βb % βa = βx * s + βy * t β
βa = βx * s' + βy * t' β
β(xgcdAux (b % a ) s t a s' t' ).fst = βx * (xgcdAux (b % a ) s t a s' t' ).2 .fst + βy * (xgcdAux (b % a ) s t a s' t' ).2 .snd s, t, s', t' : β€ p : βa = βx * s + βy * t p' : βb = βx * s' + βy * t' k : β€ H1 βx * s' + βy * t' - (βx * s + βy * t ) * k = βx * s' - βx * (k * s ) + βy * (t' - k * t ) x, y, a, b : β h : 0 < a IH : β {s t s' t' : β€ },
βb % βa = βx * s + βy * t β
βa = βx * s' + βy * t' β
β(xgcdAux (b % a ) s t a s' t' ).fst = βx * (xgcdAux (b % a ) s t a s' t' ).2 .fst + βy * (xgcdAux (b % a ) s t a s' t' ).2 .snd s, t, s', t' : β€ p : βa = βx * s + βy * t p' : βb = βx * s' + βy * t' k : β€ H1 βb - βa * k = βx * (s' - k * s ) + βy * (t' - k * t )sub_add_eq_add_sub , x, y, a, b : β h : 0 < a IH : β {s t s' t' : β€ },
βb % βa = βx * s + βy * t β
βa = βx * s' + βy * t' β
β(xgcdAux (b % a ) s t a s' t' ).fst = βx * (xgcdAux (b % a ) s t a s' t' ).2 .fst + βy * (xgcdAux (b % a ) s t a s' t' ).2 .snd s, t, s', t' : β€ p : βa = βx * s + βy * t p' : βb = βx * s' + βy * t' k : β€ H1 βx * s' + βy * t' - (βx * s + βy * t ) * k = βx * s' + βy * (t' - k * t ) - βx * (k * s ) x, y, a, b : β h : 0 < a IH : β {s t s' t' : β€ },
βb % βa = βx * s + βy * t β
βa = βx * s' + βy * t' β
β(xgcdAux (b % a ) s t a s' t' ).fst = βx * (xgcdAux (b % a ) s t a s' t' ).2 .fst + βy * (xgcdAux (b % a ) s t a s' t' ).2 .snd s, t, s', t' : β€ p : βa = βx * s + βy * t p' : βb = βx * s' + βy * t' k : β€ H1 βb - βa * k = βx * (s' - k * s ) + βy * (t' - k * t )mul_sub , x, y, a, b : β h : 0 < a IH : β {s t s' t' : β€ },
βb % βa = βx * s + βy * t β
βa = βx * s' + βy * t' β
β(xgcdAux (b % a ) s t a s' t' ).fst = βx * (xgcdAux (b % a ) s t a s' t' ).2 .fst + βy * (xgcdAux (b % a ) s t a s' t' ).2 .snd s, t, s', t' : β€ p : βa = βx * s + βy * t p' : βb = βx * s' + βy * t' k : β€ H1 βx * s' + βy * t' - (βx * s + βy * t ) * k = βx * s' + (βy * t' - βy * (k * t ) ) - βx * (k * s ) x, y, a, b : β h : 0 < a IH : β {s t s' t' : β€ },
βb % βa = βx * s + βy * t β
βa = βx * s' + βy * t' β
β(xgcdAux (b % a ) s t a s' t' ).fst = βx * (xgcdAux (b % a ) s t a s' t' ).2 .fst + βy * (xgcdAux (b % a ) s t a s' t' ).2 .snd s, t, s', t' : β€ p : βa = βx * s + βy * t p' : βb = βx * s' + βy * t' k : β€ H1 βb - βa * k = βx * (s' - k * s ) + βy * (t' - k * t )add_mul , x, y, a, b : β h : 0 < a IH : β {s t s' t' : β€ },
βb % βa = βx * s + βy * t β
βa = βx * s' + βy * t' β
β(xgcdAux (b % a ) s t a s' t' ).fst = βx * (xgcdAux (b % a ) s t a s' t' ).2 .fst + βy * (xgcdAux (b % a ) s t a s' t' ).2 .snd s, t, s', t' : β€ p : βa = βx * s + βy * t p' : βb = βx * s' + βy * t' k : β€ H1 βx * s' + βy * t' - (βx * s * k + βy * t * k ) = βx * s' + (βy * t' - βy * (k * t ) ) - βx * (k * s ) x, y, a, b : β h : 0 < a IH : β {s t s' t' : β€ },
βb % βa = βx * s + βy * t β
βa = βx * s' + βy * t' β
β(xgcdAux (b % a ) s t a s' t' ).fst = βx * (xgcdAux (b % a ) s t a s' t' ).2 .fst + βy * (xgcdAux (b % a ) s t a s' t' ).2 .snd s, t, s', t' : β€ p : βa = βx * s + βy * t p' : βb = βx * s' + βy * t' k : β€ H1 βb - βa * k = βx * (s' - k * s ) + βy * (t' - k * t )mul_comm k t , x, y, a, b : β h : 0 < a IH : β {s t s' t' : β€ },
βb % βa = βx * s + βy * t β
βa = βx * s' + βy * t' β
β(xgcdAux (b % a ) s t a s' t' ).fst = βx * (xgcdAux (b % a ) s t a s' t' ).2 .fst + βy * (xgcdAux (b % a ) s t a s' t' ).2 .snd s, t, s', t' : β€ p : βa = βx * s + βy * t p' : βb = βx * s' + βy * t' k : β€ H1 βx * s' + βy * t' - (βx * s * k + βy * t * k ) = βx * s' + (βy * t' - βy * (t * k ) ) - βx * (k * s ) x, y, a, b : β h : 0 < a IH : β {s t s' t' : β€ },
βb % βa = βx * s + βy * t β
βa = βx * s' + βy * t' β
β(xgcdAux (b % a ) s t a s' t' ).fst = βx * (xgcdAux (b % a ) s t a s' t' ).2 .fst + βy * (xgcdAux (b % a ) s t a s' t' ).2 .snd s, t, s', t' : β€ p : βa = βx * s + βy * t p' : βb = βx * s' + βy * t' k : β€ H1 βb - βa * k = βx * (s' - k * s ) + βy * (t' - k * t )mul_comm k s , x, y, a, b : β h : 0 < a IH : β {s t s' t' : β€ },
βb % βa = βx * s + βy * t β
βa = βx * s' + βy * t' β
β(xgcdAux (b % a ) s t a s' t' ).fst = βx * (xgcdAux (b % a ) s t a s' t' ).2 .fst + βy * (xgcdAux (b % a ) s t a s' t' ).2 .snd s, t, s', t' : β€ p : βa = βx * s + βy * t p' : βb = βx * s' + βy * t' k : β€ H1 βx * s' + βy * t' - (βx * s * k + βy * t * k ) = βx * s' + (βy * t' - βy * (t * k ) ) - βx * (s * k )
x, y, a, b : β h : 0 < a IH : β {s t s' t' : β€ },
βb % βa = βx * s + βy * t β
βa = βx * s' + βy * t' β
β(xgcdAux (b % a ) s t a s' t' ).fst = βx * (xgcdAux (b % a ) s t a s' t' ).2 .fst + βy * (xgcdAux (b % a ) s t a s' t' ).2 .snd s, t, s', t' : β€ p : βa = βx * s + βy * t p' : βb = βx * s' + βy * t' k : β€ H1 βb - βa * k = βx * (s' - k * s ) + βy * (t' - k * t )β mul_assoc : β {G : Type ?u.20545} [inst : Semigroup G ] (a b c : G ), a * b * c = a * (b * c ) mul_assoc, x, y, a, b : β h : 0 < a IH : β {s t s' t' : β€ },
βb % βa = βx * s + βy * t β
βa = βx * s' + βy * t' β
β(xgcdAux (b % a ) s t a s' t' ).fst = βx * (xgcdAux (b % a ) s t a s' t' ).2 .fst + βy * (xgcdAux (b % a ) s t a s' t' ).2 .snd s, t, s', t' : β€ p : βa = βx * s + βy * t p' : βb = βx * s' + βy * t' k : β€ H1 βx * s' + βy * t' - (βx * s * k + βy * t * k ) = βx * s' + (βy * t' - βy * t * k ) - βx * (s * k ) x, y, a, b : β h : 0 < a IH : β {s t s' t' : β€ },
βb % βa = βx * s + βy * t β
βa = βx * s' + βy * t' β
β(xgcdAux (b % a ) s t a s' t' ).fst = βx * (xgcdAux (b % a ) s t a s' t' ).2 .fst + βy * (xgcdAux (b % a ) s t a s' t' ).2 .snd s, t, s', t' : β€ p : βa = βx * s + βy * t p' : βb = βx * s' + βy * t' k : β€ H1 βb - βa * k = βx * (s' - k * s ) + βy * (t' - k * t )β mul_assoc : β {G : Type ?u.20602} [inst : Semigroup G ] (a b c : G ), a * b * c = a * (b * c ) mul_assoc, x, y, a, b : β h : 0 < a IH : β {s t s' t' : β€ },
βb % βa = βx * s + βy * t β
βa = βx * s' + βy * t' β
β(xgcdAux (b % a ) s t a s' t' ).fst = βx * (xgcdAux (b % a ) s t a s' t' ).2 .fst + βy * (xgcdAux (b % a ) s t a s' t' ).2 .snd s, t, s', t' : β€ p : βa = βx * s + βy * t p' : βb = βx * s' + βy * t' k : β€ H1 βx * s' + βy * t' - (βx * s * k + βy * t * k ) = βx * s' + (βy * t' - βy * t * k ) - βx * s * k x, y, a, b : β h : 0 < a IH : β {s t s' t' : β€ },
βb % βa = βx * s + βy * t β
βa = βx * s' + βy * t' β
β(xgcdAux (b % a ) s t a s' t' ).fst = βx * (xgcdAux (b % a ) s t a s' t' ).2 .fst + βy * (xgcdAux (b % a ) s t a s' t' ).2 .snd s, t, s', t' : β€ p : βa = βx * s + βy * t p' : βb = βx * s' + βy * t' k : β€ H1 βb - βa * k = βx * (s' - k * s ) + βy * (t' - k * t )add_comm ( x * s * k ), x, y, a, b : β h : 0 < a IH : β {s t s' t' : β€ },
βb % βa = βx * s + βy * t β
βa = βx * s' + βy * t' β
β(xgcdAux (b % a ) s t a s' t' ).fst = βx * (xgcdAux (b % a ) s t a s' t' ).2 .fst + βy * (xgcdAux (b % a ) s t a s' t' ).2 .snd s, t, s', t' : β€ p : βa = βx * s + βy * t p' : βb = βx * s' + βy * t' k : β€ H1 βx * s' + βy * t' - (βy * t * k + βx * s * k ) = βx * s' + (βy * t' - βy * t * k ) - βx * s * k x, y, a, b : β h : 0 < a IH : β {s t s' t' : β€ },
βb % βa = βx * s + βy * t β
βa = βx * s' + βy * t' β
β(xgcdAux (b % a ) s t a s' t' ).fst = βx * (xgcdAux (b % a ) s t a s' t' ).2 .fst + βy * (xgcdAux (b % a ) s t a s' t' ).2 .snd s, t, s', t' : β€ p : βa = βx * s + βy * t p' : βb = βx * s' + βy * t' k : β€ H1 βb - βa * k = βx * (s' - k * s ) + βy * (t' - k * t )β add_sub_assoc , x, y, a, b : β h : 0 < a IH : β {s t s' t' : β€ },
βb % βa = βx * s + βy * t β
βa = βx * s' + βy * t' β
β(xgcdAux (b % a ) s t a s' t' ).fst = βx * (xgcdAux (b % a ) s t a s' t' ).2 .fst + βy * (xgcdAux (b % a ) s t a s' t' ).2 .snd s, t, s', t' : β€ p : βa = βx * s + βy * t p' : βb = βx * s' + βy * t' k : β€ H1 βx * s' + βy * t' - (βy * t * k + βx * s * k ) = βx * s' + βy * t' - βy * t * k - βx * s * k x, y, a, b : β h : 0 < a IH : β {s t s' t' : β€ },
βb % βa = βx * s + βy * t β
βa = βx * s' + βy * t' β
β(xgcdAux (b % a ) s t a s' t' ).fst = βx * (xgcdAux (b % a ) s t a s' t' ).2 .fst + βy * (xgcdAux (b % a ) s t a s' t' ).2 .snd s, t, s', t' : β€ p : βa = βx * s + βy * t p' : βb = βx * s' + βy * t' k : β€ H1 βb - βa * k = βx * (s' - k * s ) + βy * (t' - k * t )sub_sub x, y, a, b : β h : 0 < a IH : β {s t s' t' : β€ },
βb % βa = βx * s + βy * t β
βa = βx * s' + βy * t' β
β(xgcdAux (b % a ) s t a s' t' ).fst = βx * (xgcdAux (b % a ) s t a s' t' ).2 .fst + βy * (xgcdAux (b % a ) s t a s' t' ).2 .snd s, t, s', t' : β€ p : βa = βx * s + βy * t p' : βb = βx * s' + βy * t' k : β€ H1 βx * s' + βy * t' - (βy * t * k + βx * s * k ) = βx * s' + βy * t' - (βy * t * k + βx * s * k )]
set_option linter.uppercaseLean3 false in
#align nat.xgcd_aux_P Nat.xgcd_aux_P : β (x y : β ) {r r' : β } {s t s' t' : β€ },
Nat.P x y (r , s , t ) β Nat.P x y (r' , s' , t' ) β Nat.P x y (xgcdAux r s t r' s' t' ) Nat.xgcd_aux_P
/-- **BΓ©zout's lemma**: given `x y : β`, `gcd x y = x * a + y * b`, where `a = gcd_a x y` and
`b = gcd_b x y` are computed by the extended Euclidean algorithm.
-/
theorem gcd_eq_gcd_ab : ( gcd x y : β€ ) = x * gcdA x y + y * gcdB x y := by
have := @ xgcd_aux_P : β (x y : β ) {r r' : β } {s t s' t' : β€ },
Nat.P x y (r , s , t ) β Nat.P x y (r' , s' , t' ) β Nat.P x y (xgcdAux r s t r' s' t' ) xgcd_aux_P x y x y 1 0 0 1 ( by simp [ P ] ) ( by simp [ P ] )
rwa [ xgcd_aux_val , xgcd_val ] at this
#align nat.gcd_eq_gcd_ab Nat.gcd_eq_gcd_ab
end
theorem exists_mul_emod_eq_gcd : β {k n : β }, gcd n k < k β β m , n * m % k = gcd n k exists_mul_emod_eq_gcd { k n : β } ( hk : gcd n k < k ) : β m , n * m % k = gcd n k := by
have hk' := Int.ofNat_ne_zero : β {n : β }, βn β 0 β n β 0 Int.ofNat_ne_zero. 2 : β {a b : Prop }, (a β b ) β b β a 2 ( ne_of_gt : β {a b : β }, b < a β a β b ne_of_gt ( lt_of_le_of_lt : β {Ξ± : Type ?u.23265} [inst : Preorder Ξ± ] {a b c : Ξ± }, a β€ b β b < c β a < c lt_of_le_of_lt ( zero_le : β (n : β ), 0 β€ n zero_le ( gcd n k )) hk ))
have key := congr_arg : β {Ξ± : Sort ?u.23355} {Ξ² : Sort ?u.23354} {aβ aβ : Ξ± } (f : Ξ± β Ξ² ), aβ = aβ β f aβ = f aβ congr_arg ( fun ( m : β€ ) => ( m % k ). toNat ) ( gcd_eq_gcd_ab n k )
simp only at key
rw [ Int.add_mul_emod_self_left : β (a b c : β€ ), (a + b * c ) % b = a % b Int.add_mul_emod_self_left, β Int.coe_nat_mod : β (m n : β ), β(m % n ) = βm % βn Int.coe_nat_mod, Int.toNat_coe_nat , mod_eq_of_lt : β {a b : β }, a < b β a % b = a mod_eq_of_lt hk ] at key
refine' β¨( n . gcdA k % k ). toNat , Eq.trans : β {Ξ± : Sort ?u.23744} {a b c : Ξ± }, a = b β b = c β a = c Eq.trans ( Int.ofNat.inj _ ) key . symm : β {Ξ± : Sort ?u.23752} {a b : Ξ± }, a = b β b = a symmβ©
rw [ Int.ofNat_eq_coe , Int.coe_nat_mod : β (m n : β ), β(m % n ) = βm % βn Int.coe_nat_mod, Int.ofNat_mul : β (n m : β ), β(n * m ) = βn * βm Int.ofNat_mul, Int.toNat_of_nonneg ( Int.emod_nonneg : β (a : β€ ) {b : β€ }, b β 0 β 0 β€ a % b Int.emod_nonneg _ hk' ),
Int.ofNat_eq_coe , Int.toNat_of_nonneg ( Int.emod_nonneg : β (a : β€ ) {b : β€ }, b β 0 β 0 β€ a % b Int.emod_nonneg _ hk' ), Int.mul_emod : β (a b n : β€ ), a * b % n = a % n * (b % n ) % n Int.mul_emod, Int.emod_emod : β (a b : β€ ), a % b % b = a % b Int.emod_emod,
β Int.mul_emod : β (a b n : β€ ), a * b % n = a % n * (b % n ) % n Int.mul_emod]
#align nat.exists_mul_mod_eq_gcd Nat.exists_mul_emod_eq_gcd : β {k n : β }, gcd n k < k β β m , n * m % k = gcd n k Nat.exists_mul_emod_eq_gcd
theorem exists_mul_emod_eq_one_of_coprime : β {k n : β }, coprime n k β 1 < k β β m , n * m % k = 1 exists_mul_emod_eq_one_of_coprime { k n : β } ( hkn : coprime n k ) ( hk : 1 < k ) :
β m , n * m % k = 1 :=
Exists.recOn : β {Ξ± : Sort ?u.24008} {p : Ξ± β Prop } {motive : Exists p β Prop } (t : Exists p ),
(β (w : Ξ± ) (h : p w ), motive (_ : Exists p ) ) β motive t Exists.recOn ( exists_mul_emod_eq_gcd : β {k n : β }, gcd n k < k β β m , n * m % k = gcd n k exists_mul_emod_eq_gcd ( lt_of_le_of_lt : β {Ξ± : Type ?u.24037} [inst : Preorder Ξ± ] {a b c : Ξ± }, a β€ b β b < c β a < c lt_of_le_of_lt ( le_of_eq : β {Ξ± : Type ?u.24114} [inst : Preorder Ξ± ] {a b : Ξ± }, a = b β a β€ b le_of_eq hkn ) hk )) fun m hm β¦
β¨ m , hm . trans : β {Ξ± : Sort ?u.24171} {a b c : Ξ± }, a = b β b = c β a = c trans hkn β©
#align nat.exists_mul_mod_eq_one_of_coprime Nat.exists_mul_emod_eq_one_of_coprime : β {k n : β }, coprime n k β 1 < k β β m , n * m % k = 1 Nat.exists_mul_emod_eq_one_of_coprime
end Nat
/-! ### Divisibility over β€ -/
namespace Int
theorem gcd_def ( i j : β€ ) : gcd i j = Nat.gcd i . natAbs j . natAbs := rfl : β {Ξ± : Sort ?u.24207} {a : Ξ± }, a = a rfl
protected theorem coe_nat_gcd ( m n : β ) : Int.gcd β m β n = Nat.gcd m n :=
rfl : β {Ξ± : Sort ?u.24316} {a : Ξ± }, a = a rfl
#align int.coe_nat_gcd Int.coe_nat_gcd
/-- The extended GCD `a` value in the equation `gcd x y = x * a + y * b`. -/
def gcdA : β€ β β€ β β€
| ofNat m , n => m . gcdA n . natAbs
| -[ m +1], n => - m . succ . gcdA n . natAbs
#align int.gcd_a Int.gcdA
/-- The extended GCD `b` value in the equation `gcd x y = x * a + y * b`. -/
def gcdB : β€ β β€ β β€
| m , ofNat n => m . natAbs . gcdB n
| m , -[ n +1] => - m . natAbs . gcdB n . succ
#align int.gcd_b Int.gcdB
/-- **BΓ©zout's lemma** -/
theorem gcd_eq_gcd_ab : β x y : β€ , ( gcd x y : β€ ) = x * gcdA x y + y * gcdB x y
| (m : β), (n : β) => Nat.gcd_eq_gcd_ab _ _
| (m : β), -[ n +1] =>
show ( _ : β€ ) = _ + -( n + 1 ) * - _ by rw [ neg_mul_neg ] ; apply Nat.gcd_eq_gcd_ab
| -[ m +1], (n : β) =>
show ( _ : β€ ) = -( m + 1 ) * - _ + _ by rw [ neg_mul_neg ] ; apply Nat.gcd_eq_gcd_ab
| -[ m +1], -[ n +1] =>
show ( _ : β€ ) = -( m + 1 ) * - _ + -( n + 1 ) * - _ by
rw [ neg_mul_neg , neg_mul_neg ]
apply Nat.gcd_eq_gcd_ab
#align int.gcd_eq_gcd_ab Int.gcd_eq_gcd_ab
theorem natAbs_ediv ( a b : β€ ) ( H : b β£ a ) : natAbs ( a / b ) = natAbs a / natAbs b := by
rcases Nat.eq_zero_or_pos : β (n : β ), n = 0 β¨ n > 0 Nat.eq_zero_or_pos ( natAbs b ) with ( h | h )
rw [ natAbs_eq_zero . 1 : β {a b : Prop }, (a β b ) β a β b 1 h ]
simp [ Int.ediv_zero : β (a : β€ ), a / 0 = 0 Int.ediv_zero]
calc
natAbs ( a / b ) = natAbs ( a / b ) * 1 := by rw [ mul_one ]
_ = natAbs ( a / b ) * ( natAbs b / natAbs b ) := by rw [ Nat.div_self : β {n : β }, 0 < n β n / n = 1 Nat.div_self h ]
_ = natAbs ( a / b ) * natAbs b / natAbs b := by rw [ Nat.mul_div_assoc : β {k n : β } (m : β ), k β£ n β m * n / k = m * (n / k ) Nat.mul_div_assoc _ dvd_rfl : β {Ξ± : Type ?u.28245} [inst : Monoid Ξ± ] {a : Ξ± }, a β£ a dvd_rfl]
_ = natAbs ( a / b * b ) / natAbs b :=