/-- Shows that the recurrence relation (`convergents`) and direct evaluation (`convergents'`) of the
gcf coincide at position `n` if the sequence of fractions contains strictly positive values only.
Requiring positivity of all values is just one possible condition to obtain this result.
For example, the dual - sequences with strictly negative values only - would also work.

In practice, one most commonly deals with (regular) continued fractions, which satisfy the
positivity criterion required here. The analogous result for them
(see `ContinuedFractions.convergents_eq_convergents`) hence follows directly from this theorem.
-/
theorem convergents_eq_convergents' [LinearOrderedField K]
    (s_pos : ∀ {gp : Pair K} {m : ℕ}, m < n → g.s.get? m = some gp → 0 < gp.a ∧ 0 < gp.b) :
    g.convergents n = g.convergents' n := by
  induction' n with n IH generalizing g
  case zero => simp
  case succ =>
    let g' := squashGCF g n
    -- first replace the rhs with the squashed computation
    suffices g.convergents (n + 1) = g'.convergents' n by
      rwa [succ_nth_convergent'_eq_squashGCF_nth_convergent']
    cases' Decidable.em (TerminatedAt g n) with terminated_at_n not_terminated_at_n
    · have g'_eq_g : g' = g := squashGCF_eq_self_of_terminated terminated_at_n
      rw [convergents_stable_of_terminated n.le_succ terminated_at_n, g'_eq_g, IH _]
      intro _ _ m_lt_n s_mth_eq
      exact s_pos (Nat.lt.step m_lt_n) s_mth_eq
    · suffices g.convergents (n + 1) = g'.convergents n by
        -- invoke the IH for the squashed gcf
        rwa [← IH]
        intro gp' m m_lt_n s_mth_eq'
        -- case distinction on m + 1 = n or m + 1 < n
        cases' m_lt_n with n succ_m_lt_n
        · -- the difficult case at the squashed position: we first obtain the values from
          -- the sequence
          obtain ⟨gp_succ_m, s_succ_mth_eq⟩ : ∃ gp_succ_m, g.s.get? (m + 1) = some gp_succ_m
          exact Option.ne_none_iff_exists'.mp not_terminated_at_n
          obtain ⟨gp_m, mth_s_eq⟩ : ∃ gp_m, g.s.get? m = some gp_m
          

Proof state:
K : Type u_1
s : Stream'.Seq (Pair K)
inst✝ : LinearOrderedField K
g : GeneralizedContinuedFraction K
gp' : Pair K
m : ℕ
IH :
  ∀ {g : GeneralizedContinuedFraction K},
    (∀ {gp : Pair K} {m_1 : ℕ}, m_1 < Nat.succ m → Stream'.Seq.get? g.s m_1 = some gp → 0 < gp.a ∧ 0 < gp.b) →
      convergents g (Nat.succ m) = convergents' g (Nat.succ m)
s_pos :
  ∀ {gp : Pair K} {m_1 : ℕ}, m_1 < Nat.succ (Nat.succ m) → Stream'.Seq.get? g.s m_1 = some gp → 0 < gp.a ∧ 0 < gp.b
g' : GeneralizedContinuedFraction K := squashGCF g (Nat.succ m)
not_terminated_at_n : ¬TerminatedAt g (Nat.succ m)
this : convergents g (Nat.succ m + 1) = convergents g' (Nat.succ m)
s_mth_eq' : Stream'.Seq.get? g'.s m = some gp'
gp_succ_m : Pair K
s_succ_mth_eq : Stream'.Seq.get? g.s (m + 1) = some gp_succ_m
⊢ ∃ gp_m, Stream'.Seq.get? g.s m = some gp_m
case refl.intro.intro
K : Type u_1
s : Stream'.Seq (Pair K)
inst✝ : LinearOrderedField K
g : GeneralizedContinuedFraction K
gp' : Pair K
m : ℕ
IH :
  ∀ {g : GeneralizedContinuedFraction K},
    (∀ {gp : Pair K} {m_1 : ℕ}, m_1 < Nat.succ m → Stream'.Seq.get? g.s m_1 = some gp → 0 < gp.a ∧ 0 < gp.b) →
      convergents g (Nat.succ m) = convergents' g (Nat.succ m)
s_pos :
  ∀ {gp : Pair K} {m_1 : ℕ}, m_1 < Nat.succ (Nat.succ m) → Stream'.Seq.get? g.s m_1 = some gp → 0 < gp.a ∧ 0 < gp.b
g' : GeneralizedContinuedFraction K := squashGCF g (Nat.succ m)
not_terminated_at_n : ¬TerminatedAt g (Nat.succ m)
this : convergents g (Nat.succ m + 1) = convergents g' (Nat.succ m)
s_mth_eq' : Stream'.Seq.get? g'.s m = some gp'
gp_succ_m : Pair K
s_succ_mth_eq : Stream'.Seq.get? g.s (m + 1) = some gp_succ_m
gp_m : Pair K
mth_s_eq : Stream'.Seq.get? g.s m = some gp_m
⊢ 0 < gp'.a ∧ 0 < gp'.b

Next tactic:
exact g.s.ge_stable m.le_succ s_succ_mth_eq