-- Mathlib/Algebra/ContinuedFractions/Computation/CorrectnessTerminating.lean
theorem of_correctness_of_nth_stream_eq_none (nth_stream_eq_none : IntFractPair.stream v n = none) :
    v = (of v).convs (n - 1)

Proof state:
case succ.inl
K : Type u_1
inst✝¹ : LinearOrderedField K
v : K
n✝ : ℕ
inst✝ : FloorRing K
n : ℕ
IH : IntFractPair.stream v n = none → v = (of v).convs (n - 1)
nth_stream_eq_none✝ : IntFractPair.stream v (n + 1) = none
g : GenContFract K := of v
nth_stream_eq_none : IntFractPair.stream v n = none
⊢ v = g.convs n

Tactic:
cases n with
| zero => contradiction
| succ n' =>
  have : g.TerminatedAt n' :=
    of_terminatedAt_n_iff_succ_nth_intFractPair_stream_eq_none.2
      nth_stream_eq_none
  have : g.convs (n' + 1) = g.convs n' :=
    convs_stable_of_terminated n'.le_succ this
  rw [this]
  exact IH nth_stream_eq_none

Result:
no goals

Proof state:
case zero
K : Type u_1
inst✝¹ : LinearOrderedField K
v : K
n : ℕ
inst✝ : FloorRing K
nth_stream_eq_none : IntFractPair.stream v 0 = none
⊢ v = (of v).convs (0 - 1)

Tactic:
contradiction

Result:
no goals

Proof state:
case succ.inl.succ
K : Type u_1
inst✝¹ : LinearOrderedField K
v : K
n : ℕ
inst✝ : FloorRing K
g : GenContFract K := of v
n' : ℕ
IH : IntFractPair.stream v (n' + 1) = none → v = (of v).convs (n' + 1 - 1)
nth_stream_eq_none✝ : IntFractPair.stream v (n' + 1 + 1) = none
nth_stream_eq_none : IntFractPair.stream v (n' + 1) = none
this✝ : g.TerminatedAt n'
this : g.convs (n' + 1) = g.convs n'
⊢ v = g.convs n'

Tactic:
exact IH nth_stream_eq_none

Result:
no goals

Proof state:
case succ
K : Type u_1
inst✝¹ : LinearOrderedField K
v : K
n✝ : ℕ
inst✝ : FloorRing K
n : ℕ
IH : IntFractPair.stream v n = none → v = (of v).convs (n - 1)
nth_stream_eq_none : IntFractPair.stream v (n + 1) = none
g : GenContFract K := of v
⊢ v = g.convs n

Tactic:
obtain ⟨nth_stream_eq_none⟩ | ⟨ifp_n, nth_stream_eq, nth_stream_fr_eq_zero⟩ :
  IntFractPair.stream v n = none ∨ ∃ ifp, IntFractPair.stream v n = some ifp ∧ ifp.fr = 0 :=
  IntFractPair.succ_nth_stream_eq_none_iff.1 nth_stream_eq_none

Result:
case succ.inl
K : Type u_1
inst✝¹ : LinearOrderedField K
v : K
n✝ : ℕ
inst✝ : FloorRing K
n : ℕ
IH : IntFractPair.stream v n = none → v = (of v).convs (n - 1)
nth_stream_eq_none✝ : IntFractPair.stream v (n + 1) = none
g : GenContFract K := of v
nth_stream_eq_none : IntFractPair.stream v n = none
⊢ v = g.convs n

case succ.inr.intro.intro
K : Type u_1
inst✝¹ : LinearOrderedField K
v : K
n✝ : ℕ
inst✝ : FloorRing K
n : ℕ
IH : IntFractPair.stream v n = none → v = (of v).convs (n - 1)
nth_stream_eq_none : IntFractPair.stream v (n + 1) = none
g : GenContFract K := of v
ifp_n : IntFractPair K
nth_stream_eq : IntFractPair.stream v n = some ifp_n
nth_stream_fr_eq_zero : ifp_n.fr = 0
⊢ v = g.convs n

Proof state:
case succ.inl.zero
K : Type u_1
inst✝¹ : LinearOrderedField K
v : K
n : ℕ
inst✝ : FloorRing K
g : GenContFract K := of v
IH : IntFractPair.stream v 0 = none → v = (of v).convs (0 - 1)
nth_stream_eq_none✝ : IntFractPair.stream v (0 + 1) = none
nth_stream_eq_none : IntFractPair.stream v 0 = none
⊢ v = g.convs 0

Tactic:
contradiction

Result:
no goals

Proof state:
case succ
K : Type u_1
inst✝¹ : LinearOrderedField K
v : K
n✝ : ℕ
inst✝ : FloorRing K
n : ℕ
IH : IntFractPair.stream v n = none → v = (of v).convs (n - 1)
nth_stream_eq_none : IntFractPair.stream v (n + 1) = none
⊢ v = (of v).convs (n + 1 - 1)

Tactic:
let g := of v

Result:
case succ
K : Type u_1
inst✝¹ : LinearOrderedField K
v : K
n✝ : ℕ
inst✝ : FloorRing K
n : ℕ
IH : IntFractPair.stream v n = none → v = (of v).convs (n - 1)
nth_stream_eq_none : IntFractPair.stream v (n + 1) = none
g : GenContFract K := of v
⊢ v = (of v).convs (n + 1 - 1)

Proof state:
case succ.inl.succ
K : Type u_1
inst✝¹ : LinearOrderedField K
v : K
n : ℕ
inst✝ : FloorRing K
g : GenContFract K := of v
n' : ℕ
IH : IntFractPair.stream v (n' + 1) = none → v = (of v).convs (n' + 1 - 1)
nth_stream_eq_none✝ : IntFractPair.stream v (n' + 1 + 1) = none
nth_stream_eq_none : IntFractPair.stream v (n' + 1) = none
this : g.TerminatedAt n'
⊢ v = g.convs (n' + 1)

Tactic:
have : g.convs (n' + 1) = g.convs n' :=
  convs_stable_of_terminated n'.le_succ this

Result:
case succ.inl.succ
K : Type u_1
inst✝¹ : LinearOrderedField K
v : K
n : ℕ
inst✝ : FloorRing K
g : GenContFract K := of v
n' : ℕ
IH : IntFractPair.stream v (n' + 1) = none → v = (of v).convs (n' + 1 - 1)
nth_stream_eq_none✝ : IntFractPair.stream v (n' + 1 + 1) = none
nth_stream_eq_none : IntFractPair.stream v (n' + 1) = none
this✝ : g.TerminatedAt n'
this : g.convs (n' + 1) = g.convs n'
⊢ v = g.convs (n' + 1)

Proof state:
case succ.inl.succ
K : Type u_1
inst✝¹ : LinearOrderedField K
v : K
n : ℕ
inst✝ : FloorRing K
g : GenContFract K := of v
n' : ℕ
IH : IntFractPair.stream v (n' + 1) = none → v = (of v).convs (n' + 1 - 1)
nth_stream_eq_none✝ : IntFractPair.stream v (n' + 1 + 1) = none
nth_stream_eq_none : IntFractPair.stream v (n' + 1) = none
this✝ : g.TerminatedAt n'
this : g.convs (n' + 1) = g.convs n'
⊢ v = g.convs (n' + 1)

Tactic:
rw [this]

Result:
case succ.inl.succ
K : Type u_1
inst✝¹ : LinearOrderedField K
v : K
n : ℕ
inst✝ : FloorRing K
g : GenContFract K := of v
n' : ℕ
IH : IntFractPair.stream v (n' + 1) = none → v = (of v).convs (n' + 1 - 1)
nth_stream_eq_none✝ : IntFractPair.stream v (n' + 1 + 1) = none
nth_stream_eq_none : IntFractPair.stream v (n' + 1) = none
this✝ : g.TerminatedAt n'
this : g.convs (n' + 1) = g.convs n'
⊢ v = g.convs n'

Proof state:
case succ.inl.succ
K : Type u_1
inst✝¹ : LinearOrderedField K
v : K
n : ℕ
inst✝ : FloorRing K
g : GenContFract K := of v
n' : ℕ
IH : IntFractPair.stream v (n' + 1) = none → v = (of v).convs (n' + 1 - 1)
nth_stream_eq_none✝ : IntFractPair.stream v (n' + 1 + 1) = none
nth_stream_eq_none : IntFractPair.stream v (n' + 1) = none
⊢ v = g.convs (n' + 1)

Tactic:
have : g.TerminatedAt n' :=
  of_terminatedAt_n_iff_succ_nth_intFractPair_stream_eq_none.2
    nth_stream_eq_none

Result:
case succ.inl.succ
K : Type u_1
inst✝¹ : LinearOrderedField K
v : K
n : ℕ
inst✝ : FloorRing K
g : GenContFract K := of v
n' : ℕ
IH : IntFractPair.stream v (n' + 1) = none → v = (of v).convs (n' + 1 - 1)
nth_stream_eq_none✝ : IntFractPair.stream v (n' + 1 + 1) = none
nth_stream_eq_none : IntFractPair.stream v (n' + 1) = none
this : g.TerminatedAt n'
⊢ v = g.convs (n' + 1)

Proof state:
case succ
K : Type u_1
inst✝¹ : LinearOrderedField K
v : K
n✝ : ℕ
inst✝ : FloorRing K
n : ℕ
IH : IntFractPair.stream v n = none → v = (of v).convs (n - 1)
nth_stream_eq_none : IntFractPair.stream v (n + 1) = none
g : GenContFract K := of v
⊢ v = (of v).convs (n + 1 - 1)

Tactic:
change v = g.convs n

Result:
case succ
K : Type u_1
inst✝¹ : LinearOrderedField K
v : K
n✝ : ℕ
inst✝ : FloorRing K
n : ℕ
IH : IntFractPair.stream v n = none → v = (of v).convs (n - 1)
nth_stream_eq_none : IntFractPair.stream v (n + 1) = none
g : GenContFract K := of v
⊢ v = g.convs n

Proof state:
case succ.inr.intro.intro
K : Type u_1
inst✝¹ : LinearOrderedField K
v : K
n✝ : ℕ
inst✝ : FloorRing K
n : ℕ
IH : IntFractPair.stream v n = none → v = (of v).convs (n - 1)
nth_stream_eq_none : IntFractPair.stream v (n + 1) = none
g : GenContFract K := of v
ifp_n : IntFractPair K
nth_stream_eq : IntFractPair.stream v n = some ifp_n
nth_stream_fr_eq_zero : ifp_n.fr = 0
⊢ v = g.convs n

Tactic:
simpa [nth_stream_fr_eq_zero, compExactValue] using
  compExactValue_correctness_of_stream_eq_some nth_stream_eq

Result:
no goals