l3lab/ntp-mathlib huggingface dataset:
theorem flip_isReduced : (flip u).IsReduced ↔ u.IsReduced := by
  dsimp [IsReduced, flip]
  

Proof state:
u : XgcdType
⊢ u.bp = u.ap ↔ u.ap = u.bp

Next tactic:
constructor
theorem flip_isReduced : (flip u).IsReduced ↔ u.IsReduced := by
  dsimp [IsReduced, flip]
  constructor <;> 

Proof state:
case mp
u : XgcdType
⊢ u.bp = u.ap → u.ap = u.bp

Next tactic:
intro h
theorem flip_isReduced : (flip u).IsReduced ↔ u.IsReduced := by
  dsimp [IsReduced, flip]
  constructor <;> 

Proof state:
case mpr
u : XgcdType
⊢ u.ap = u.bp → u.bp = u.ap

Next tactic:
intro h
theorem flip_isReduced : (flip u).IsReduced ↔ u.IsReduced := by
  dsimp [IsReduced, flip]
  constructor <;> intro h <;> 

Proof state:
case mp
u : XgcdType
h : u.bp = u.ap
⊢ u.ap = u.bp

Next tactic:
exact h.symm
theorem flip_isReduced : (flip u).IsReduced ↔ u.IsReduced := by
  dsimp [IsReduced, flip]
  constructor <;> intro h <;> 

Proof state:
case mpr
u : XgcdType
h : u.ap = u.bp
⊢ u.bp = u.ap

Next tactic:
exact h.symm
theorem flip_isSpecial : (flip u).IsSpecial ↔ u.IsSpecial := by
  

Proof state:
u : XgcdType
⊢ IsSpecial (flip u) ↔ IsSpecial u

Next tactic:
dsimp [IsSpecial, flip]
theorem flip_isSpecial : (flip u).IsSpecial ↔ u.IsSpecial := by
  dsimp [IsSpecial, flip]
  

Proof state:
u : XgcdType
⊢ u.zp + u.wp + u.zp * u.wp = u.y * u.x ↔ u.wp + u.zp + u.wp * u.zp = u.x * u.y

Next tactic:
rw [mul_comm u.x, mul_comm u.zp, add_comm u.zp]
theorem flip_v : (flip u).v = u.v.swap := by
  

Proof state:
u : XgcdType
⊢ v (flip u) = Prod.swap (v u)

Next tactic:
dsimp [v]
theorem flip_v : (flip u).v = u.v.swap := by
  dsimp [v]
  

Proof state:
u : XgcdType
⊢ (↑(z u) * ↑(b u) + u.y * ↑(a u), u.x * ↑(b u) + ↑(w u) * ↑(a u)) =
    (u.y * ↑(a u) + ↑(z u) * ↑(b u), ↑(w u) * ↑(a u) + u.x * ↑(b u))

Next tactic:
ext
theorem flip_v : (flip u).v = u.v.swap := by
  dsimp [v]
  ext
  · 

Proof state:
case a
u : XgcdType
⊢ (↑(z u) * ↑(b u) + u.y * ↑(a u), u.x * ↑(b u) + ↑(w u) * ↑(a u)).1 =
    (u.y * ↑(a u) + ↑(z u) * ↑(b u), ↑(w u) * ↑(a u) + u.x * ↑(b u)).1

Next tactic:
simp only
theorem flip_v : (flip u).v = u.v.swap := by
  dsimp [v]
  ext
  · simp only
    

Proof state:
case a
u : XgcdType
⊢ ↑(z u) * ↑(b u) + u.y * ↑(a u) = u.y * ↑(a u) + ↑(z u) * ↑(b u)

Next tactic:
ring
theorem flip_v : (flip u).v = u.v.swap := by
  dsimp [v]
  ext
  · simp only
    ring
  · 

Proof state:
case a
u : XgcdType
⊢ (↑(z u) * ↑(b u) + u.y * ↑(a u), u.x * ↑(b u) + ↑(w u) * ↑(a u)).2 =
    (u.y * ↑(a u) + ↑(z u) * ↑(b u), ↑(w u) * ↑(a u) + u.x * ↑(b u)).2

Next tactic:
simp only
theorem flip_v : (flip u).v = u.v.swap := by
  dsimp [v]
  ext
  · simp only
    ring
  · simp only
    

Proof state:
case a
u : XgcdType
⊢ u.x * ↑(b u) + ↑(w u) * ↑(a u) = ↑(w u) * ↑(a u) + u.x * ↑(b u)

Next tactic:
ring
theorem qp_eq (hr : u.r = 0) : u.q = u.qp + 1 := by
  

Proof state:
u : XgcdType
hr : r u = 0
⊢ q u = qp u + 1

Next tactic:
by_cases hq : u.q = 0
theorem qp_eq (hr : u.r = 0) : u.q = u.qp + 1 := by
  by_cases hq : u.q = 0
  · 

Proof state:
case pos
u : XgcdType
hr : r u = 0
hq : q u = 0
⊢ q u = qp u + 1

Next tactic:
let h := u.rq_eq
theorem qp_eq (hr : u.r = 0) : u.q = u.qp + 1 := by
  by_cases hq : u.q = 0
  · let h := u.rq_eq
    

Proof state:
case pos
u : XgcdType
hr : r u = 0
hq : q u = 0
h : r u + (u.bp + 1) * q u = u.ap + 1 := rq_eq u
⊢ q u = qp u + 1

Next tactic:
rw [hr, hq, mul_zero, add_zero] at h
theorem qp_eq (hr : u.r = 0) : u.q = u.qp + 1 := by
  by_cases hq : u.q = 0
  · let h := u.rq_eq
    rw [hr, hq, mul_zero, add_zero] at h
    

Proof state:
case pos
u : XgcdType
hr : r u = 0
hq : q u = 0
h : 0 = u.ap + 1
⊢ q u = qp u + 1

Next tactic:
cases h
theorem qp_eq (hr : u.r = 0) : u.q = u.qp + 1 := by
  by_cases hq : u.q = 0
  · let h := u.rq_eq
    rw [hr, hq, mul_zero, add_zero] at h
    cases h
  · 

Proof state:
case neg
u : XgcdType
hr : r u = 0
hq : ¬q u = 0
⊢ q u = qp u + 1

Next tactic:
exact (Nat.succ_pred_eq_of_pos (Nat.pos_of_ne_zero hq)).symm
theorem start_isSpecial (a b : ℕ+) : (start a b).IsSpecial := by
  

Proof state:
u : XgcdType
a b : ℕ+
⊢ IsSpecial (start a b)

Next tactic:
dsimp [start, IsSpecial]
theorem start_v (a b : ℕ+) : (start a b).v = ⟨a, b⟩ := by
  

Proof state:
u : XgcdType
a b : ℕ+
⊢ v (start a b) = (↑a, ↑b)

Next tactic:
dsimp [start, v, XgcdType.a, XgcdType.b, w, z]
theorem start_v (a b : ℕ+) : (start a b).v = ⟨a, b⟩ := by
  dsimp [start, v, XgcdType.a, XgcdType.b, w, z]
  

Proof state:
u : XgcdType
a b : ℕ+
⊢ (succ 0 * succ (↑a - 1) + 0 * succ (↑b - 1), 0 * succ (↑a - 1) + succ 0 * succ (↑b - 1)) = (↑a, ↑b)

Next tactic:
have : succ 0 = 1 := rfl
theorem start_v (a b : ℕ+) : (start a b).v = ⟨a, b⟩ := by
  dsimp [start, v, XgcdType.a, XgcdType.b, w, z]
  have : succ 0 = 1 := rfl
  

Proof state:
u : XgcdType
a b : ℕ+
this : succ 0 = 1
⊢ (succ 0 * succ (↑a - 1) + 0 * succ (↑b - 1), 0 * succ (↑a - 1) + succ 0 * succ (↑b - 1)) = (↑a, ↑b)

Next tactic:
rw [this, one_mul, one_mul, zero_mul, zero_mul, zero_add, add_zero]
theorem start_v (a b : ℕ+) : (start a b).v = ⟨a, b⟩ := by
  dsimp [start, v, XgcdType.a, XgcdType.b, w, z]
  have : succ 0 = 1 := rfl
  rw [this, one_mul, one_mul, zero_mul, zero_mul, zero_add, add_zero]
  

Proof state:
u : XgcdType
a b : ℕ+
this : succ 0 = 1
⊢ (succ (↑a - 1), succ (↑b - 1)) = (↑a, ↑b)

Next tactic:
rw [← Nat.pred_eq_sub_one, ← Nat.pred_eq_sub_one]
theorem start_v (a b : ℕ+) : (start a b).v = ⟨a, b⟩ := by
  dsimp [start, v, XgcdType.a, XgcdType.b, w, z]
  have : succ 0 = 1 := rfl
  rw [this, one_mul, one_mul, zero_mul, zero_mul, zero_add, add_zero]
  rw [← Nat.pred_eq_sub_one, ← Nat.pred_eq_sub_one]
  

Proof state:
u : XgcdType
a b : ℕ+
this : succ 0 = 1
⊢ (succ (pred ↑a), succ (pred ↑b)) = (↑a, ↑b)

Next tactic:
rw [Nat.succ_pred_eq_of_pos a.pos, Nat.succ_pred_eq_of_pos b.pos]
theorem finish_isReduced : u.finish.IsReduced := by
  

Proof state:
u : XgcdType
⊢ IsReduced (finish u)

Next tactic:
dsimp [IsReduced]
theorem finish_isReduced : u.finish.IsReduced := by
  dsimp [IsReduced]
  

Proof state:
u : XgcdType
⊢ (finish u).ap = (finish u).bp

Next tactic:
rfl
theorem finish_isSpecial (hs : u.IsSpecial) : u.finish.IsSpecial := by
  

Proof state:
u : XgcdType
hs : IsSpecial u
⊢ IsSpecial (finish u)

Next tactic:
dsimp [IsSpecial, finish] at hs ⊢
theorem finish_isSpecial (hs : u.IsSpecial) : u.finish.IsSpecial := by
  dsimp [IsSpecial, finish] at hs ⊢
  

Proof state:
u : XgcdType
hs : u.wp + u.zp + u.wp * u.zp = u.x * u.y
⊢ u.wp + (u.y * qp u + u.zp) + u.wp * (u.y * qp u + u.zp) = ((u.wp + 1) * qp u + u.x) * u.y

Next tactic:
rw [add_mul _ _ u.y, add_comm _ (u.x * u.y), ← hs]
theorem finish_isSpecial (hs : u.IsSpecial) : u.finish.IsSpecial := by
  dsimp [IsSpecial, finish] at hs ⊢
  rw [add_mul _ _ u.y, add_comm _ (u.x * u.y), ← hs]
  

Proof state:
u : XgcdType
hs : u.wp + u.zp + u.wp * u.zp = u.x * u.y
⊢ u.wp + (u.y * qp u + u.zp) + u.wp * (u.y * qp u + u.zp) = u.wp + u.zp + u.wp * u.zp + (u.wp + 1) * qp u * u.y

Next tactic:
ring
theorem finish_v (hr : u.r = 0) : u.finish.v = u.v := by
  

Proof state:
u : XgcdType
hr : r u = 0
⊢ v (finish u) = v u

Next tactic:
let ha : u.r + u.b * u.q = u.a := u.rq_eq
theorem finish_v (hr : u.r = 0) : u.finish.v = u.v := by
  let ha : u.r + u.b * u.q = u.a := u.rq_eq
  

Proof state:
u : XgcdType
hr : r u = 0
ha : r u + ↑(b u) * q u = ↑(a u) := rq_eq u
⊢ v (finish u) = v u

Next tactic:
rw [hr, zero_add] at ha
theorem finish_v (hr : u.r = 0) : u.finish.v = u.v := by
  let ha : u.r + u.b * u.q = u.a := u.rq_eq
  rw [hr, zero_add] at ha
  

Proof state:
u : XgcdType
hr : r u = 0
ha : ↑(b u) * q u = ↑(a u)
⊢ v (finish u) = v u

Next tactic:
ext
theorem finish_v (hr : u.r = 0) : u.finish.v = u.v := by
  let ha : u.r + u.b * u.q = u.a := u.rq_eq
  rw [hr, zero_add] at ha
  ext
  · 

Proof state:
case a
u : XgcdType
hr : r u = 0
ha : ↑(b u) * q u = ↑(a u)
⊢ (v (finish u)).1 = (v u).1

Next tactic:
change (u.wp + 1) * u.b + ((u.wp + 1) * u.qp + u.x) * u.b = u.w * u.a + u.x * u.b
theorem finish_v (hr : u.r = 0) : u.finish.v = u.v := by
  let ha : u.r + u.b * u.q = u.a := u.rq_eq
  rw [hr, zero_add] at ha
  ext
  · change (u.wp + 1) * u.b + ((u.wp + 1) * u.qp + u.x) * u.b = u.w * u.a + u.x * u.b
    

Proof state:
case a
u : XgcdType
hr : r u = 0
ha : ↑(b u) * q u = ↑(a u)
⊢ (u.wp + 1) * ↑(b u) + ((u.wp + 1) * qp u + u.x) * ↑(b u) = ↑(w u) * ↑(a u) + u.x * ↑(b u)

Next tactic:
have : u.wp + 1 = u.w := rfl
theorem finish_v (hr : u.r = 0) : u.finish.v = u.v := by
  let ha : u.r + u.b * u.q = u.a := u.rq_eq
  rw [hr, zero_add] at ha
  ext
  · change (u.wp + 1) * u.b + ((u.wp + 1) * u.qp + u.x) * u.b = u.w * u.a + u.x * u.b
    have : u.wp + 1 = u.w := rfl
    

Proof state:
case a
u : XgcdType
hr : r u = 0
ha : ↑(b u) * q u = ↑(a u)
this : u.wp + 1 = ↑(w u)
⊢ (u.wp + 1) * ↑(b u) + ((u.wp + 1) * qp u + u.x) * ↑(b u) = ↑(w u) * ↑(a u) + u.x * ↑(b u)

Next tactic:
rw [this, ← ha, u.qp_eq hr]
theorem finish_v (hr : u.r = 0) : u.finish.v = u.v := by
  let ha : u.r + u.b * u.q = u.a := u.rq_eq
  rw [hr, zero_add] at ha
  ext
  · change (u.wp + 1) * u.b + ((u.wp + 1) * u.qp + u.x) * u.b = u.w * u.a + u.x * u.b
    have : u.wp + 1 = u.w := rfl
    rw [this, ← ha, u.qp_eq hr]
    

Proof state:
case a
u : XgcdType
hr : r u = 0
ha : ↑(b u) * q u = ↑(a u)
this : u.wp + 1 = ↑(w u)
⊢ ↑(w u) * ↑(b u) + (↑(w u) * qp u + u.x) * ↑(b u) = ↑(w u) * (↑(b u) * (qp u + 1)) + u.x * ↑(b u)

Next tactic:
ring
theorem finish_v (hr : u.r = 0) : u.finish.v = u.v := by
  let ha : u.r + u.b * u.q = u.a := u.rq_eq
  rw [hr, zero_add] at ha
  ext
  · change (u.wp + 1) * u.b + ((u.wp + 1) * u.qp + u.x) * u.b = u.w * u.a + u.x * u.b
    have : u.wp + 1 = u.w := rfl
    rw [this, ← ha, u.qp_eq hr]
    ring
  · 

Proof state:
case a
u : XgcdType
hr : r u = 0
ha : ↑(b u) * q u = ↑(a u)
⊢ (v (finish u)).2 = (v u).2

Next tactic:
change u.y * u.b + (u.y * u.qp + u.z) * u.b = u.y * u.a + u.z * u.b
theorem finish_v (hr : u.r = 0) : u.finish.v = u.v := by
  let ha : u.r + u.b * u.q = u.a := u.rq_eq
  rw [hr, zero_add] at ha
  ext
  · change (u.wp + 1) * u.b + ((u.wp + 1) * u.qp + u.x) * u.b = u.w * u.a + u.x * u.b
    have : u.wp + 1 = u.w := rfl
    rw [this, ← ha, u.qp_eq hr]
    ring
  · change u.y * u.b + (u.y * u.qp + u.z) * u.b = u.y * u.a + u.z * u.b
    

Proof state:
case a
u : XgcdType
hr : r u = 0
ha : ↑(b u) * q u = ↑(a u)
⊢ u.y * ↑(b u) + (u.y * qp u + ↑(z u)) * ↑(b u) = u.y * ↑(a u) + ↑(z u) * ↑(b u)

Next tactic:
rw [← ha, u.qp_eq hr]
theorem finish_v (hr : u.r = 0) : u.finish.v = u.v := by
  let ha : u.r + u.b * u.q = u.a := u.rq_eq
  rw [hr, zero_add] at ha
  ext
  · change (u.wp + 1) * u.b + ((u.wp + 1) * u.qp + u.x) * u.b = u.w * u.a + u.x * u.b
    have : u.wp + 1 = u.w := rfl
    rw [this, ← ha, u.qp_eq hr]
    ring
  · change u.y * u.b + (u.y * u.qp + u.z) * u.b = u.y * u.a + u.z * u.b
    rw [← ha, u.qp_eq hr]
    

Proof state:
case a
u : XgcdType
hr : r u = 0
ha : ↑(b u) * q u = ↑(a u)
⊢ u.y * ↑(b u) + (u.y * qp u + ↑(z u)) * ↑(b u) = u.y * (↑(b u) * (qp u + 1)) + ↑(z u) * ↑(b u)

Next tactic:
ring
/-- 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 := by
  

Proof state:
u : XgcdType
hr : r u ≠ 0
⊢ sizeOf (step u) < sizeOf u

Next tactic:
change u.r - 1 < u.bp
/-- 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 := by
  change u.r - 1 < u.bp
  

Proof state:
u : XgcdType
hr : r u ≠ 0
⊢ r u - 1 < u.bp

Next tactic:
have h₀ : u.r - 1 + 1 = u.r := Nat.succ_pred_eq_of_pos (Nat.pos_of_ne_zero hr)
/-- 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 := by
  change u.r - 1 < u.bp
  have h₀ : u.r - 1 + 1 = u.r := Nat.succ_pred_eq_of_pos (Nat.pos_of_ne_zero hr)
  

Proof state:
u : XgcdType
hr : r u ≠ 0
h₀ : r u - 1 + 1 = r u
⊢ r u - 1 < u.bp

Next tactic:
have h₁ : u.r < u.bp + 1 := Nat.mod_lt (u.ap + 1) u.bp.succ_pos
/-- 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 := by
  change u.r - 1 < u.bp
  have h₀ : u.r - 1 + 1 = u.r := Nat.succ_pred_eq_of_pos (Nat.pos_of_ne_zero hr)
  have h₁ : u.r < u.bp + 1 := Nat.mod_lt (u.ap + 1) u.bp.succ_pos
  

Proof state:
u : XgcdType
hr : r u ≠ 0
h₀ : r u - 1 + 1 = r u
h₁ : r u < u.bp + 1
⊢ r u - 1 < u.bp

Next tactic:
rw [← h₀] at h₁
/-- 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 := by
  change u.r - 1 < u.bp
  have h₀ : u.r - 1 + 1 = u.r := Nat.succ_pred_eq_of_pos (Nat.pos_of_ne_zero hr)
  have h₁ : u.r < u.bp + 1 := Nat.mod_lt (u.ap + 1) u.bp.succ_pos
  rw [← h₀] at h₁
  

Proof state:
u : XgcdType
hr : r u ≠ 0
h₀ : r u - 1 + 1 = r u
h₁ : r u - 1 + 1 < u.bp + 1
⊢ r u - 1 < u.bp

Next tactic:
exact lt_of_succ_lt_succ h₁
theorem step_isSpecial (hs : u.IsSpecial) : u.step.IsSpecial := by
  

Proof state:
u : XgcdType
hs : IsSpecial u
⊢ IsSpecial (step u)

Next tactic:
dsimp [IsSpecial, step] at hs ⊢
theorem step_isSpecial (hs : u.IsSpecial) : u.step.IsSpecial := by
  dsimp [IsSpecial, step] at hs ⊢
  

Proof state:
u : XgcdType
hs : u.wp + u.zp + u.wp * u.zp = u.x * u.y
⊢ u.y * q u + u.zp + u.wp + (u.y * q u + u.zp) * u.wp = u.y * ((u.wp + 1) * q u + u.x)

Next tactic:
rw [mul_add, mul_comm u.y u.x, ← hs]
theorem step_isSpecial (hs : u.IsSpecial) : u.step.IsSpecial := by
  dsimp [IsSpecial, step] at hs ⊢
  rw [mul_add, mul_comm u.y u.x, ← hs]
  

Proof state:
u : XgcdType
hs : u.wp + u.zp + u.wp * u.zp = u.x * u.y
⊢ u.y * q u + u.zp + u.wp + (u.y * q u + u.zp) * u.wp = u.y * ((u.wp + 1) * q u) + (u.wp + u.zp + u.wp * u.zp)

Next tactic:
ring
/-- The reduction step does not change the product vector. -/
theorem step_v (hr : u.r ≠ 0) : u.step.v = u.v.swap := by
  

Proof state:
u : XgcdType
hr : r u ≠ 0
⊢ v (step u) = Prod.swap (v u)

Next tactic:
let ha : u.r + u.b * u.q = u.a := u.rq_eq
/-- The reduction step does not change the product vector. -/
theorem step_v (hr : u.r ≠ 0) : u.step.v = u.v.swap := by
  let ha : u.r + u.b * u.q = u.a := u.rq_eq
  

Proof state:
u : XgcdType
hr : r u ≠ 0
ha : r u + ↑(b u) * q u = ↑(a u) := rq_eq u
⊢ v (step u) = Prod.swap (v u)

Next tactic:
let hr : u.r - 1 + 1 = u.r := (add_comm _ 1).trans (add_tsub_cancel_of_le (Nat.pos_of_ne_zero hr))
/-- The reduction step does not change the product vector. -/
theorem step_v (hr : u.r ≠ 0) : u.step.v = u.v.swap := by
  let ha : u.r + u.b * u.q = u.a := u.rq_eq
  let hr : u.r - 1 + 1 = u.r := (add_comm _ 1).trans (add_tsub_cancel_of_le (Nat.pos_of_ne_zero hr))
  

Proof state:
u : XgcdType
hr✝ : r u ≠ 0
ha : r u + ↑(b u) * q u = ↑(a u) := rq_eq u
hr : r u - 1 + 1 = r u := (add_comm (r u - 1) 1).trans (add_tsub_cancel_of_le (Nat.pos_of_ne_zero hr✝))
⊢ v (step u) = Prod.swap (v u)

Next tactic:
ext
/-- The reduction step does not change the product vector. -/
theorem step_v (hr : u.r ≠ 0) : u.step.v = u.v.swap := by
  let ha : u.r + u.b * u.q = u.a := u.rq_eq
  let hr : u.r - 1 + 1 = u.r := (add_comm _ 1).trans (add_tsub_cancel_of_le (Nat.pos_of_ne_zero hr))
  ext
  · 

Proof state:
case a
u : XgcdType
hr✝ : r u ≠ 0
ha : r u + ↑(b u) * q u = ↑(a u) := rq_eq u
hr : r u - 1 + 1 = r u := (add_comm (r u - 1) 1).trans (add_tsub_cancel_of_le (Nat.pos_of_ne_zero hr✝))
⊢ (v (step u)).1 = (Prod.swap (v u)).1

Next tactic:
change ((u.y * u.q + u.z) * u.b + u.y * (u.r - 1 + 1) : ℕ) = u.y * u.a + u.z * u.b
/-- The reduction step does not change the product vector. -/
theorem step_v (hr : u.r ≠ 0) : u.step.v = u.v.swap := by
  let ha : u.r + u.b * u.q = u.a := u.rq_eq
  let hr : u.r - 1 + 1 = u.r := (add_comm _ 1).trans (add_tsub_cancel_of_le (Nat.pos_of_ne_zero hr))
  ext
  · change ((u.y * u.q + u.z) * u.b + u.y * (u.r - 1 + 1) : ℕ) = u.y * u.a + u.z * u.b
    

Proof state:
case a
u : XgcdType
hr✝ : r u ≠ 0
ha : r u + ↑(b u) * q u = ↑(a u) := rq_eq u
hr : r u - 1 + 1 = r u := (add_comm (r u - 1) 1).trans (add_tsub_cancel_of_le (Nat.pos_of_ne_zero hr✝))
⊢ (u.y * q u + ↑(z u)) * ↑(b u) + u.y * (r u - 1 + 1) = u.y * ↑(a u) + ↑(z u) * ↑(b u)

Next tactic:
rw [← ha, hr]
/-- The reduction step does not change the product vector. -/
theorem step_v (hr : u.r ≠ 0) : u.step.v = u.v.swap := by
  let ha : u.r + u.b * u.q = u.a := u.rq_eq
  let hr : u.r - 1 + 1 = u.r := (add_comm _ 1).trans (add_tsub_cancel_of_le (Nat.pos_of_ne_zero hr))
  ext
  · change ((u.y * u.q + u.z) * u.b + u.y * (u.r - 1 + 1) : ℕ) = u.y * u.a + u.z * u.b
    rw [← ha, hr]
    

Proof state:
case a
u : XgcdType
hr✝ : r u ≠ 0
ha : r u + ↑(b u) * q u = ↑(a u) := rq_eq u
hr : r u - 1 + 1 = r u := (add_comm (r u - 1) 1).trans (add_tsub_cancel_of_le (Nat.pos_of_ne_zero hr✝))
⊢ (u.y * q u + ↑(z u)) * ↑(b u) + u.y * r u = u.y * (r u + ↑(b u) * q u) + ↑(z u) * ↑(b u)

Next tactic:
ring
/-- The reduction step does not change the product vector. -/
theorem step_v (hr : u.r ≠ 0) : u.step.v = u.v.swap := by
  let ha : u.r + u.b * u.q = u.a := u.rq_eq
  let hr : u.r - 1 + 1 = u.r := (add_comm _ 1).trans (add_tsub_cancel_of_le (Nat.pos_of_ne_zero hr))
  ext
  · change ((u.y * u.q + u.z) * u.b + u.y * (u.r - 1 + 1) : ℕ) = u.y * u.a + u.z * u.b
    rw [← ha, hr]
    ring
  · 

Proof state:
case a
u : XgcdType
hr✝ : r u ≠ 0
ha : r u + ↑(b u) * q u = ↑(a u) := rq_eq u
hr : r u - 1 + 1 = r u := (add_comm (r u - 1) 1).trans (add_tsub_cancel_of_le (Nat.pos_of_ne_zero hr✝))
⊢ (v (step u)).2 = (Prod.swap (v u)).2

Next tactic:
change ((u.w * u.q + u.x) * u.b + u.w * (u.r - 1 + 1) : ℕ) = u.w * u.a + u.x * u.b
/-- The reduction step does not change the product vector. -/
theorem step_v (hr : u.r ≠ 0) : u.step.v = u.v.swap := by
  let ha : u.r + u.b * u.q = u.a := u.rq_eq
  let hr : u.r - 1 + 1 = u.r := (add_comm _ 1).trans (add_tsub_cancel_of_le (Nat.pos_of_ne_zero hr))
  ext
  · change ((u.y * u.q + u.z) * u.b + u.y * (u.r - 1 + 1) : ℕ) = u.y * u.a + u.z * u.b
    rw [← ha, hr]
    ring
  · change ((u.w * u.q + u.x) * u.b + u.w * (u.r - 1 + 1) : ℕ) = u.w * u.a + u.x * u.b
    

Proof state:
case a
u : XgcdType
hr✝ : r u ≠ 0
ha : r u + ↑(b u) * q u = ↑(a u) := rq_eq u
hr : r u - 1 + 1 = r u := (add_comm (r u - 1) 1).trans (add_tsub_cancel_of_le (Nat.pos_of_ne_zero hr✝))
⊢ (↑(w u) * q u + u.x) * ↑(b u) + ↑(w u) * (r u - 1 + 1) = ↑(w u) * ↑(a u) + u.x * ↑(b u)

Next tactic:
rw [← ha, hr]
/-- The reduction step does not change the product vector. -/
theorem step_v (hr : u.r ≠ 0) : u.step.v = u.v.swap := by
  let ha : u.r + u.b * u.q = u.a := u.rq_eq
  let hr : u.r - 1 + 1 = u.r := (add_comm _ 1).trans (add_tsub_cancel_of_le (Nat.pos_of_ne_zero hr))
  ext
  · change ((u.y * u.q + u.z) * u.b + u.y * (u.r - 1 + 1) : ℕ) = u.y * u.a + u.z * u.b
    rw [← ha, hr]
    ring
  · change ((u.w * u.q + u.x) * u.b + u.w * (u.r - 1 + 1) : ℕ) = u.w * u.a + u.x * u.b
    rw [← ha, hr]
    

Proof state:
case a
u : XgcdType
hr✝ : r u ≠ 0
ha : r u + ↑(b u) * q u = ↑(a u) := rq_eq u
hr : r u - 1 + 1 = r u := (add_comm (r u - 1) 1).trans (add_tsub_cancel_of_le (Nat.pos_of_ne_zero hr✝))
⊢ (↑(w u) * q u + u.x) * ↑(b u) + ↑(w u) * r u = ↑(w u) * (r u + ↑(b u) * q u) + u.x * ↑(b u)

Next tactic:
ring
/-- 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 :=
  dite (u.r = 0) (fun _ => u.finish) fun _h =>
    flip (reduce u.step)
decreasing_by 

Proof state:
u : XgcdType
_h : ¬r u = 0
⊢ (invImage (fun a => sizeOf a) instWellFoundedRelation).1 (step u) u

Next tactic:
apply u.step_wf _h
theorem reduce_a {u : XgcdType} (h : u.r = 0) : u.reduce = u.finish := by
  

Proof state:
u✝ u : XgcdType
h : r u = 0
⊢ reduce u = finish u

Next tactic:
rw [reduce]
theorem reduce_a {u : XgcdType} (h : u.r = 0) : u.reduce = u.finish := by
  rw [reduce]
  

Proof state:
u✝ u : XgcdType
h : r u = 0
⊢ (if x : r u = 0 then finish u else flip (reduce (step u))) = finish u

Next tactic:
exact if_pos h
theorem reduce_b {u : XgcdType} (h : u.r ≠ 0) : u.reduce = u.step.reduce.flip := by
  

Proof state:
u✝ u : XgcdType
h : r u ≠ 0
⊢ reduce u = flip (reduce (step u))

Next tactic:
rw [reduce]
theorem reduce_b {u : XgcdType} (h : u.r ≠ 0) : u.reduce = u.step.reduce.flip := by
  rw [reduce]
  

Proof state:
u✝ u : XgcdType
h : r u ≠ 0
⊢ (if x : r u = 0 then finish u else flip (reduce (step u))) = flip (reduce (step u))

Next tactic:
exact if_neg h
theorem reduce_isReduced : ∀ u : XgcdType, u.reduce.IsReduced
  | u =>
    dite (u.r = 0)
      (fun h => by
        

Proof state:
u✝ x✝ : XgcdType
u : XgcdType := x✝
h : r u = 0
⊢ IsReduced (reduce x✝)

Next tactic:
rw [reduce_a h]
theorem reduce_isReduced : ∀ u : XgcdType, u.reduce.IsReduced
  | u =>
    dite (u.r = 0)
      (fun h => by
        rw [reduce_a h]
        

Proof state:
u✝ x✝ : XgcdType
u : XgcdType := x✝
h : r u = 0
⊢ IsReduced (finish u)

Next tactic:
exact u.finish_isReduced
theorem reduce_isReduced : ∀ u : XgcdType, u.reduce.IsReduced
  | u =>
    dite (u.r = 0)
      (fun h => by
        rw [reduce_a h]
        exact u.finish_isReduced)
      fun h => by
      

Proof state:
u✝ x✝ : XgcdType
u : XgcdType := x✝
h : ¬r u = 0
⊢ IsReduced (reduce x✝)

Next tactic:
have : SizeOf.sizeOf u.step < SizeOf.sizeOf u := u.step_wf h
theorem reduce_isReduced : ∀ u : XgcdType, u.reduce.IsReduced
  | u =>
    dite (u.r = 0)
      (fun h => by
        rw [reduce_a h]
        exact u.finish_isReduced)
      fun h => by
      have : SizeOf.sizeOf u.step < SizeOf.sizeOf u := u.step_wf h
      

Proof state:
u✝ x✝ : XgcdType
u : XgcdType := x✝
h : ¬r u = 0
this : sizeOf (step u) < sizeOf u
⊢ IsReduced (reduce x✝)

Next tactic:
rw [reduce_b h, flip_isReduced]
theorem reduce_isReduced : ∀ u : XgcdType, u.reduce.IsReduced
  | u =>
    dite (u.r = 0)
      (fun h => by
        rw [reduce_a h]
        exact u.finish_isReduced)
      fun h => by
      have : SizeOf.sizeOf u.step < SizeOf.sizeOf u := u.step_wf h
      rw [reduce_b h, flip_isReduced]
      

Proof state:
u✝ x✝ : XgcdType
u : XgcdType := x✝
h : ¬r u = 0
this : sizeOf (step u) < sizeOf u
⊢ IsReduced (reduce (step u))

Next tactic:
apply reduce_isReduced
theorem reduce_isSpecial : ∀ u : XgcdType, u.IsSpecial → u.reduce.IsSpecial
  | u =>
    dite (u.r = 0)
      (fun h hs => by
        

Proof state:
u✝ x✝ : XgcdType
u : XgcdType := x✝
h : r u = 0
hs : IsSpecial x✝
⊢ IsSpecial (reduce x✝)

Next tactic:
rw [reduce_a h]
theorem reduce_isSpecial : ∀ u : XgcdType, u.IsSpecial → u.reduce.IsSpecial
  | u =>
    dite (u.r = 0)
      (fun h hs => by
        rw [reduce_a h]
        

Proof state:
u✝ x✝ : XgcdType
u : XgcdType := x✝
h : r u = 0
hs : IsSpecial x✝
⊢ IsSpecial (finish u)

Next tactic:
exact u.finish_isSpecial hs
theorem reduce_isSpecial : ∀ u : XgcdType, u.IsSpecial → u.reduce.IsSpecial
  | u =>
    dite (u.r = 0)
      (fun h hs => by
        rw [reduce_a h]
        exact u.finish_isSpecial hs)
      fun h hs => by
      

Proof state:
u✝ x✝ : XgcdType
u : XgcdType := x✝
h : ¬r u = 0
hs : IsSpecial x✝
⊢ IsSpecial (reduce x✝)

Next tactic:
have : SizeOf.sizeOf u.step < SizeOf.sizeOf u := u.step_wf h
theorem reduce_isSpecial : ∀ u : XgcdType, u.IsSpecial → u.reduce.IsSpecial
  | u =>
    dite (u.r = 0)
      (fun h hs => by
        rw [reduce_a h]
        exact u.finish_isSpecial hs)
      fun h hs => by
      have : SizeOf.sizeOf u.step < SizeOf.sizeOf u := u.step_wf h
      

Proof state:
u✝ x✝ : XgcdType
u : XgcdType := x✝
h : ¬r u = 0
hs : IsSpecial x✝
this : sizeOf (step u) < sizeOf u
⊢ IsSpecial (reduce x✝)

Next tactic:
rw [reduce_b h]