File: Mathlib/Data/PNat/Xgcd.lean

full_name: PNat.XgcdType.wp
code: /-- A term of `XgcdType` is a system of six naturals.  They should
 be thought of as representing the matrix
 [[w, x], [y, z]] = [[wp + 1, x], [y, zp + 1]]
 together with the vector [a, b] = [ap + 1, bp + 1].
-/
structure XgcdType where
  /-- `wp` is a variable which changes through the algorithm. -/
  wp : ℕ
  /-- `x` satisfies `a / d = w + x` at the final step. -/
  x : ℕ
  /-- `y` satisfies `b / d = z + y` at the final step. -/
  y : ℕ
  /-- `zp` is a variable which changes through the algorithm. -/
  zp : ℕ
  /-- `ap` is a variable which changes through the algorithm. -/
  ap : ℕ
  /-- `bp` is a variable which changes through the algorithm. -/
  bp : ℕ
  deriving Inhabited
goal: ℕ

full_name: PNat.XgcdType.ap
code: /-- A term of `XgcdType` is a system of six naturals.  They should
 be thought of as representing the matrix
 [[w, x], [y, z]] = [[wp + 1, x], [y, zp + 1]]
 together with the vector [a, b] = [ap + 1, bp + 1].
-/
structure XgcdType where
  /-- `wp` is a variable which changes through the algorithm. -/
  wp : ℕ
  /-- `x` satisfies `a / d = w + x` at the final step. -/
  x : ℕ
  /-- `y` satisfies `b / d = z + y` at the final step. -/
  y : ℕ
  /-- `zp` is a variable which changes through the algorithm. -/
  zp : ℕ
  /-- `ap` is a variable which changes through the algorithm. -/
  ap : ℕ
  /-- `bp` is a variable which changes through the algorithm. -/
  bp : ℕ
  deriving Inhabited
goal: ℕ

full_name: PNat.instInhabitedXgcdType
code: /-- A term of `XgcdType` is a system of six naturals.  They should
 be thought of as representing the matrix
 [[w, x], [y, z]] = [[wp + 1, x], [y, zp + 1]]
 together with the vector [a, b] = [ap + 1, bp + 1].
-/
structure XgcdType where
  /-- `wp` is a variable which changes through the algorithm. -/
  wp : ℕ
  /-- `x` satisfies `a / d = w + x` at the final step. -/
  x : ℕ
  /-- `y` satisfies `b / d = z + y` at the final step. -/
  y : ℕ
  /-- `zp` is a variable which changes through the algorithm. -/
  zp : ℕ
  /-- `ap` is a variable which changes through the algorithm. -/
  ap : ℕ
  /-- `bp` is a variable which changes through the algorithm. -/
  bp : ℕ
  deriving Inhabited
goal: Inhabited PNat.XgcdType

full_name: PNat.XgcdType.bp
code: /-- A term of `XgcdType` is a system of six naturals.  They should
 be thought of as representing the matrix
 [[w, x], [y, z]] = [[wp + 1, x], [y, zp + 1]]
 together with the vector [a, b] = [ap + 1, bp + 1].
-/
structure XgcdType where
  /-- `wp` is a variable which changes through the algorithm. -/
  wp : ℕ
  /-- `x` satisfies `a / d = w + x` at the final step. -/
  x : ℕ
  /-- `y` satisfies `b / d = z + y` at the final step. -/
  y : ℕ
  /-- `zp` is a variable which changes through the algorithm. -/
  zp : ℕ
  /-- `ap` is a variable which changes through the algorithm. -/
  ap : ℕ
  /-- `bp` is a variable which changes through the algorithm. -/
  bp : ℕ
  deriving Inhabited
goal: ℕ

full_name: PNat.XgcdType.y
code: /-- A term of `XgcdType` is a system of six naturals.  They should
 be thought of as representing the matrix
 [[w, x], [y, z]] = [[wp + 1, x], [y, zp + 1]]
 together with the vector [a, b] = [ap + 1, bp + 1].
-/
structure XgcdType where
  /-- `wp` is a variable which changes through the algorithm. -/
  wp : ℕ
  /-- `x` satisfies `a / d = w + x` at the final step. -/
  x : ℕ
  /-- `y` satisfies `b / d = z + y` at the final step. -/
  y : ℕ
  /-- `zp` is a variable which changes through the algorithm. -/
  zp : ℕ
  /-- `ap` is a variable which changes through the algorithm. -/
  ap : ℕ
  /-- `bp` is a variable which changes through the algorithm. -/
  bp : ℕ
  deriving Inhabited
goal: ℕ

full_name: PNat.XgcdType.x
code: /-- A term of `XgcdType` is a system of six naturals.  They should
 be thought of as representing the matrix
 [[w, x], [y, z]] = [[wp + 1, x], [y, zp + 1]]
 together with the vector [a, b] = [ap + 1, bp + 1].
-/
structure XgcdType where
  /-- `wp` is a variable which changes through the algorithm. -/
  wp : ℕ
  /-- `x` satisfies `a / d = w + x` at the final step. -/
  x : ℕ
  /-- `y` satisfies `b / d = z + y` at the final step. -/
  y : ℕ
  /-- `zp` is a variable which changes through the algorithm. -/
  zp : ℕ
  /-- `ap` is a variable which changes through the algorithm. -/
  ap : ℕ
  /-- `bp` is a variable which changes through the algorithm. -/
  bp : ℕ
  deriving Inhabited
goal: ℕ

full_name: PNat.XgcdType
code: /-- A term of `XgcdType` is a system of six naturals.  They should
 be thought of as representing the matrix
 [[w, x], [y, z]] = [[wp + 1, x], [y, zp + 1]]
 together with the vector [a, b] = [ap + 1, bp + 1].
-/
structure XgcdType where
  /-- `wp` is a variable which changes through the algorithm. -/
  wp : ℕ
  /-- `x` satisfies `a / d = w + x` at the final step. -/
  x : ℕ
  /-- `y` satisfies `b / d = z + y` at the final step. -/
  y : ℕ
  /-- `zp` is a variable which changes through the algorithm. -/
  zp : ℕ
  /-- `ap` is a variable which changes through the algorithm. -/
  ap : ℕ
  /-- `bp` is a variable which changes through the algorithm. -/
  bp : ℕ
  deriving Inhabited
goal: Type

full_name: PNat.XgcdType.zp
code: /-- A term of `XgcdType` is a system of six naturals.  They should
 be thought of as representing the matrix
 [[w, x], [y, z]] = [[wp + 1, x], [y, zp + 1]]
 together with the vector [a, b] = [ap + 1, bp + 1].
-/
structure XgcdType where
  /-- `wp` is a variable which changes through the algorithm. -/
  wp : ℕ
  /-- `x` satisfies `a / d = w + x` at the final step. -/
  x : ℕ
  /-- `y` satisfies `b / d = z + y` at the final step. -/
  y : ℕ
  /-- `zp` is a variable which changes through the algorithm. -/
  zp : ℕ
  /-- `ap` is a variable which changes through the algorithm. -/
  ap : ℕ
  /-- `bp` is a variable which changes through the algorithm. -/
  bp : ℕ
  deriving Inhabited
goal: ℕ

full_name: PNat.XgcdType.instSizeOf
code: instance : SizeOf XgcdType 
goal: SizeOf PNat.XgcdType

full_name: PNat.XgcdType.instRepr
code: /-- The `Repr` instance converts terms to strings in a way that
 reflects the matrix/vector interpretation as above. -/
instance : Repr XgcdType 
goal: Repr PNat.XgcdType

full_name: PNat.XgcdType.mk'
code: /-- Another `mk` using ℕ and ℕ+ -/
def mk' (w : ℕ+) (x : ℕ) (y : ℕ) (z : ℕ+) (a : ℕ+) (b : ℕ+) : XgcdType 
goal: PNat.XgcdType

full_name: PNat.XgcdType.w
code: /-- `w = wp + 1` -/
def w : ℕ+ 
goal: ℕ+

full_name: PNat.XgcdType.z
code: /-- `z = zp + 1` -/
def z : ℕ+ 
goal: ℕ+

full_name: PNat.XgcdType.a
code: /-- `a = ap + 1` -/
def a : ℕ+ 
goal: ℕ+

full_name: PNat.XgcdType.b
code: /-- `b = bp + 1` -/
def b : ℕ+ 
goal: ℕ+

full_name: PNat.XgcdType.r
code: /-- `r = a % b`: remainder -/
def r : ℕ 
goal: ℕ

full_name: PNat.XgcdType.q
code: /-- `q = ap / bp`: quotient -/
def q : ℕ 
goal: ℕ

full_name: PNat.XgcdType.qp
code: /-- `qp = q - 1` -/
def qp : ℕ 
goal: ℕ

full_name: PNat.XgcdType.vp
code: /-- The map `v` gives the product of the matrix
 [[w, x], [y, z]] = [[wp + 1, x], [y, zp + 1]]
 and the vector [a, b] = [ap + 1, bp + 1].  The map
 `vp` gives [sp, tp] such that v = [sp + 1, tp + 1].
-/
def vp : ℕ × ℕ 
goal: ℕ × ℕ

full_name: PNat.XgcdType.v
code: /-- `v = [sp + 1, tp + 1]`, check `vp` -/
def v : ℕ × ℕ 
goal: ℕ × ℕ

full_name: PNat.XgcdType.succ₂
code: /-- `succ₂ [t.1, t.2] = [t.1.succ, t.2.succ]` -/
def succ₂ (t : ℕ × ℕ) : ℕ × ℕ 
goal: ℕ × ℕ

full_name: PNat.XgcdType.v_eq_succ_vp
code: theorem v_eq_succ_vp : u.v = succ₂ u.vp 
goal: u.v = PNat.XgcdType.succ₂ u.vp

full_name: PNat.XgcdType.IsSpecial
code: /-- `IsSpecial` holds if the matrix has determinant one. -/
def IsSpecial : Prop 
goal: Prop

full_name: PNat.XgcdType.IsSpecial'
code: /-- `IsSpecial'` is an alternative of `IsSpecial`. -/
def IsSpecial' : Prop 
goal: Prop

full_name: PNat.XgcdType.isSpecial_iff
code: theorem isSpecial_iff : u.IsSpecial ↔ u.IsSpecial' 
goal: u.IsSpecial ↔ u.IsSpecial'

full_name: PNat.XgcdType.IsReduced
code: /-- `IsReduced` holds if the two entries in the vector are the
 same.  The reduction algorithm will produce a system with this
 property, whose product vector is the same as for the original
 system. -/
def IsReduced : Prop 
goal: Prop

full_name: PNat.XgcdType.IsReduced'
code: /-- `IsReduced'` is an alternative of `IsReduced`. -/
def IsReduced' : Prop 
goal: Prop

full_name: PNat.XgcdType.isReduced_iff
code: theorem isReduced_iff : u.IsReduced ↔ u.IsReduced' 
goal: u.IsReduced ↔ u.IsReduced'

full_name: PNat.XgcdType.flip
code: /-- `flip` flips the placement of variables during the algorithm. -/
def flip : XgcdType 
goal: PNat.XgcdType

full_name: PNat.XgcdType.flip_w
code: @[simp]
theorem flip_w : (flip u).w = u.z 
goal: u.flip.w = u.z

full_name: PNat.XgcdType.flip_x
code: @[simp]
theorem flip_x : (flip u).x = u.y 
goal: u.flip.x = u.y

full_name: PNat.XgcdType.flip_y
code: @[simp]
theorem flip_y : (flip u).y = u.x 
goal: u.flip.y = u.x

full_name: PNat.XgcdType.flip_z
code: @[simp]
theorem flip_z : (flip u).z = u.w 
goal: u.flip.z = u.w

full_name: PNat.XgcdType.flip_a
code: @[simp]
theorem flip_a : (flip u).a = u.b 
goal: u.flip.a = u.b

full_name: PNat.XgcdType.flip_b
code: @[simp]
theorem flip_b : (flip u).b = u.a 
goal: u.flip.b = u.a

full_name: PNat.XgcdType.flip_isReduced
code: theorem flip_isReduced : (flip u).IsReduced ↔ u.IsReduced 
goal: u.flip.IsReduced ↔ u.IsReduced

full_name: PNat.XgcdType.flip_isSpecial
code: theorem flip_isSpecial : (flip u).IsSpecial ↔ u.IsSpecial 
goal: u.flip.IsSpecial ↔ u.IsSpecial

full_name: PNat.XgcdType.flip_v
code: theorem flip_v : (flip u).v = u.v.swap 
goal: u.flip.v = u.v.swap

full_name: PNat.XgcdType.rq_eq
code: /-- Properties of division with remainder for a / b.  -/
theorem rq_eq : u.r + (u.bp + 1) * u.q = u.ap + 1 
goal: u.r + (u.bp + 1) * u.q = u.ap + 1

full_name: PNat.XgcdType.qp_eq
code: theorem qp_eq (hr : u.r = 0) : u.q = u.qp + 1 
goal: u.q = u.qp + 1

full_name: PNat.XgcdType.start
code: /-- The following function provides the starting point for
 our algorithm.  We will apply an iterative reduction process
 to it, which will produce a system satisfying IsReduced.
 The gcd can be read off from this final system.
-/
def start (a b : ℕ+) : XgcdType 
goal: PNat.XgcdType

full_name: PNat.XgcdType.start_isSpecial
code: theorem start_isSpecial (a b : ℕ+) : (start a b).IsSpecial 
goal: (PNat.XgcdType.start a b).IsSpecial

full_name: PNat.XgcdType.start_v
code: theorem start_v (a b : ℕ+) : (start a b).v = ⟨a, b⟩ 
goal: (PNat.XgcdType.start a b).v = (↑a, ↑b)

full_name: PNat.XgcdType.finish
code: /-- `finish` happens when the reducing process ends. -/
def finish : XgcdType 
goal: PNat.XgcdType

full_name: PNat.XgcdType.finish_isReduced
code: theorem finish_isReduced : u.finish.IsReduced 
goal: u.finish.IsReduced

full_name: PNat.XgcdType.finish_isSpecial
code: theorem finish_isSpecial (hs : u.IsSpecial) : u.finish.IsSpecial 
goal: u.finish.IsSpecial

full_name: PNat.XgcdType.finish_v
code: theorem finish_v (hr : u.r = 0) : u.finish.v = u.v 
goal: u.finish.v = u.v

full_name: PNat.XgcdType.step
code: /-- This is the main reduction step, which is used when u.r ≠ 0, or
 equivalently b does not divide a. -/
def step : XgcdType 
goal: PNat.XgcdType

full_name: PNat.XgcdType.step_wf
code: /-- We will apply the above step recursively.  The following result
 is used to ensure that the process terminates. -/
theorem step_wf (hr : u.r ≠ 0) : SizeOf.sizeOf u.step < SizeOf.sizeOf u 
goal: sizeOf u.step < sizeOf u

full_name: PNat.XgcdType.step_isSpecial
code: theorem step_isSpecial (hs : u.IsSpecial) : u.step.IsSpecial 
goal: u.step.IsSpecial

full_name: PNat.XgcdType.step_v
code: /-- The reduction step does not change the product vector. -/
theorem step_v (hr : u.r ≠ 0) : u.step.v = u.v.swap 
goal: u.step.v = u.v.swap

full_name: PNat.XgcdType.reduce
code: /-- We can now define the full reduction function, which applies
 step as long as possible, and then applies finish. Note that the
 "have" statement puts a fact in the local context, and the
 equation compiler uses this fact to help construct the full
 definition in terms of well-founded recursion.  The same fact
 needs to be introduced in all the inductive proofs of properties
 given below. -/
def reduce (u : XgcdType) : XgcdType 
goal: PNat.XgcdType

full_name: PNat.XgcdType.reduce_a
code: theorem reduce_a {u : XgcdType} (h : u.r = 0) : u.reduce = u.finish 
goal: u.reduce = u.finish

full_name: PNat.XgcdType.reduce_b
code: theorem reduce_b {u : XgcdType} (h : u.r ≠ 0) : u.reduce = u.step.reduce.flip 
goal: u.reduce = u.step.reduce.flip

full_name: PNat.XgcdType.reduce_isReduced
code: theorem reduce_isReduced : ∀ u : XgcdType, u.reduce.IsReduced
  
goal: u.reduce.IsReduced

full_name: PNat.XgcdType.reduce_isReduced'
code: theorem reduce_isReduced' (u : XgcdType) : u.reduce.IsReduced' 
goal: u.reduce.IsReduced'

full_name: PNat.XgcdType.reduce_isSpecial
code: theorem reduce_isSpecial : ∀ u : XgcdType, u.IsSpecial → u.reduce.IsSpecial
  
goal: u.IsSpecial → u.reduce.IsSpecial

full_name: PNat.XgcdType.reduce_isSpecial'
code: theorem reduce_isSpecial' (u : XgcdType) (hs : u.IsSpecial) : u.reduce.IsSpecial' 
goal: u.reduce.IsSpecial'

full_name: PNat.XgcdType.reduce_v
code: theorem reduce_v : ∀ u : XgcdType, u.reduce.v = u.v
  
goal: u.reduce.v = u.v

full_name: PNat.xgcd
code: /-- Extended Euclidean algorithm -/
def xgcd : XgcdType 
goal: PNat.XgcdType

full_name: PNat.gcdD
code: /-- `gcdD a b = gcd a b` -/
def gcdD : ℕ+ 
goal: ℕ+

full_name: PNat.gcdW
code: /-- Final value of `w` -/
def gcdW : ℕ+ 
goal: ℕ+

full_name: PNat.gcdX
code: /-- Final value of `x` -/
def gcdX : ℕ 
goal: ℕ

full_name: PNat.gcdY
code: /-- Final value of `y` -/
def gcdY : ℕ 
goal: ℕ

full_name: PNat.gcdZ
code: /-- Final value of `z` -/
def gcdZ : ℕ+ 
goal: ℕ+

full_name: PNat.gcdA'
code: /-- Final value of `a / d` -/
def gcdA' : ℕ+ 
goal: ℕ+

full_name: PNat.gcdB'
code: /-- Final value of `b / d` -/
def gcdB' : ℕ+ 
goal: ℕ+

full_name: PNat.gcdA'_coe
code: theorem gcdA'_coe : (gcdA' a b : ℕ) = gcdW a b + gcdX a b 
goal: ↑(a.gcdA' b) = ↑(a.gcdW b) + a.gcdX b

full_name: PNat.gcdB'_coe
code: theorem gcdB'_coe : (gcdB' a b : ℕ) = gcdY a b + gcdZ a b 
goal: ↑(a.gcdB' b) = a.gcdY b + ↑(a.gcdZ b)

full_name: PNat.gcd_props
code: theorem gcd_props :
    let d := gcdD a b
    let w := gcdW a b
    let x := gcdX a b
    let y := gcdY a b
    let z := gcdZ a b
    let a' := gcdA' a b
    let b' := gcdB' a b
    w * z = succPNat (x * y) ∧
      a = a' * d ∧
        b = b' * d ∧
          z * a' = succPNat (x * b') ∧
            w * b' = succPNat (y * a') ∧ (z * a : ℕ) = x * b + d ∧ (w * b : ℕ) = y * a + d 
goal: let d := a.gcdD b;
let w := a.gcdW b;
let x := a.gcdX b;
let y := a.gcdY b;
let z := a.gcdZ b;
let a' := a.gcdA' b;
let b' := a.gcdB' b;
w * z = (x * y).succPNat ∧
  a = a' * d ∧
    b = b' * d ∧
      z * a' = (x * ↑b').succPNat ∧ w * b' = (y * ↑a').succPNat ∧ ↑z * ↑a = x * ↑b + ↑d ∧ ↑w * ↑b = y * ↑a + ↑d

full_name: PNat.gcd_eq
code: theorem gcd_eq : gcdD a b = gcd a b 
goal: a.gcdD b = a.gcd b

full_name: PNat.gcd_det_eq
code: theorem gcd_det_eq : gcdW a b * gcdZ a b = succPNat (gcdX a b * gcdY a b) 
goal: a.gcdW b * a.gcdZ b = (a.gcdX b * a.gcdY b).succPNat

full_name: PNat.gcd_a_eq
code: theorem gcd_a_eq : a = gcdA' a b * gcd a b 
goal: a = a.gcdA' b * a.gcd b

full_name: PNat.gcd_b_eq
code: theorem gcd_b_eq : b = gcdB' a b * gcd a b 
goal: b = a.gcdB' b * a.gcd b

full_name: PNat.gcd_rel_left'
code: theorem gcd_rel_left' : gcdZ a b * gcdA' a b = succPNat (gcdX a b * gcdB' a b) 
goal: a.gcdZ b * a.gcdA' b = (a.gcdX b * ↑(a.gcdB' b)).succPNat

full_name: PNat.gcd_rel_right'
code: theorem gcd_rel_right' : gcdW a b * gcdB' a b = succPNat (gcdY a b * gcdA' a b) 
goal: a.gcdW b * a.gcdB' b = (a.gcdY b * ↑(a.gcdA' b)).succPNat

full_name: PNat.gcd_rel_left
code: theorem gcd_rel_left : (gcdZ a b * a : ℕ) = gcdX a b * b + gcd a b 
goal: ↑(a.gcdZ b) * ↑a = a.gcdX b * ↑b + ↑(a.gcd b)

full_name: PNat.gcd_rel_right
code: theorem gcd_rel_right : (gcdW a b * b : ℕ) = gcdY a b * a + gcd a b 
goal: ↑(a.gcdW b) * ↑b = a.gcdY b * ↑a + ↑(a.gcd b)