Documentation

Ratpoints.Proof.Bisection

The intervals of the Sturm step #

The structure of the intervals that the Sturm step (Ratpoints.Sturm.computeSturm) leaves, over the values of the ends of their doubles: the bisection (Ratpoints.Sturm.iterate) at a depth of at most 55, where the search clamps it, meets only intervals of four shapes (Ratpoints.Sturm.EndsWF): the ends at infinity ∓LONG_MAX with the exponent 0, finite ends n / 2 ^ e with |n| ≤ 2 ^ 53 and 0 ≤ e ≤ 55, increasing, whose midpoints (Ratpoints.Sturm.midpoint) the longs compute without overflow strictly between the ends (Ratpoints.Sturm.EndsWF.halves); the doubles ldexp((double)n, -e) of the ends are exact, ±2 ^ 63 at infinity (Ratpoints.Sturm.EndsWF.hasValue_left), so that the intervals it keeps, joined where one ends at the beginning of the next (Ratpoints.Sturm.AreIntervals.addInterval), are closed, increasing and strictly apart (Ratpoints.Sturm.AreIntervals, Ratpoints.Sturm.iterate_wf). Their intersection with well-formed intervals of the caller (Ratpoints.Sturm.intersectList, the loop of Ratpoints.Sturm.intersect) is well formed, inside both, and holds every value that lies in both (Ratpoints.Sturm.intervalsWF_intersectList, Ratpoints.Sturm.inIntervals_of_inIntervals_intersectList, Ratpoints.Sturm.inIntervals_intersectList); hence the Sturm step leaves well-formed intervals inside the caller's (Ratpoints.Sturm.computeSturm_wf).

Main definitions #

Main statements #

The value of an end n / 2 ^ e of the bisection, ±2 ^ 63 for the ends ±LONG_MAX at infinity, as their doubles have it.

Equations
Instances For
    @[reducible, inline]

    The double x is not a NaN and has the value q.

    Equations
    Instances For
      theorem Ratpoints.Sturm.hasValue_ldexp_ofInt64 {n e : Int64} (hn : n.toInt.natAbs ≤ 2 ^ 53) (he0 : 0 ≤ e.toInt) (he : e.toInt ≤ 64) :

      The double ldexp((double)n, -e) of an end n / 2 ^ e of the bisection is exact for |n| ≤ 2 ^ 53 and 0 ≤ e ≤ 64.

      The end LONG_MAX at +∞ of the bisection has the double 2 ^ 63.

      The end -LONG_MAX at -∞ of the bisection has the double -2 ^ 63.

      structure Ratpoints.Sturm.EndsWF (depth : ℕ) (nl nr del der : Int64) :

      The interval from nl / 2 ^ del to nr / 2 ^ der of the bisection at the depth depth, as Ratpoints.Sturm.iterate meets it when the depth is at most 55: one of the four shapes of the intervals of the bisection (the whole line, the ends at infinity ∓LONG_MAX with the exponent 0, an infinite interval with the finite end 0 or on its side of 0, two finite ends with the exponent 0 when they have the same exponent), the exponents from 0 to the depth, the finite ends, scaled to the larger exponent, at most 2 ^ depth / 4 in absolute value (from the depth 1 on), and the ends increasing.

      Instances For
        theorem Ratpoints.Sturm.EndsWF.natAbs_left_le {depth : ℕ} {nl nr del der : Int64} (h : EndsWF depth nl nr del der) (hd : depth ≤ 55) (hl : nl ≠ -longMax) :
        nl.toInt.natAbs ≤ 2 ^ 53
        theorem Ratpoints.Sturm.EndsWF.natAbs_right_le {depth : ℕ} {nl nr del der : Int64} (h : EndsWF depth nl nr del der) (hd : depth ≤ 55) (hr : nr ≠ longMax) :
        nr.toInt.natAbs ≤ 2 ^ 53
        theorem Ratpoints.Sturm.endValue_of_ne {n : Int64} (e : Int64) (h1 : n ≠ longMax) (h2 : n ≠ -longMax) :
        endValue n e = ↑n.toInt * 2 ^ (-e.toInt)
        theorem Ratpoints.Sturm.endValue_eq_div {n e : Int64} (h1 : n ≠ longMax) (h2 : n ≠ -longMax) (h0 : 0 ≤ e.toInt) :
        endValue n e = ↑n.toInt / 2 ^ e.toInt.toNat

        The value of a finite end n / 2 ^ e, e ≥ 0, as the quotient that the evaluation of the chain at it (Ratpoints.Sturm.evalSign) reads.

        theorem Ratpoints.Sturm.endValue_lt_endValue_iff {nl nr del der : Int64} (hl1 : nl ≠ longMax) (hl2 : nl ≠ -longMax) (hr1 : nr ≠ longMax) (hr2 : nr ≠ -longMax) (hp : 0 ≤ del.toInt) (hq : 0 ≤ der.toInt) :
        endValue nl del < endValue nr der ↔ nl.toInt * 2 ^ der.toInt.toNat < nr.toInt * 2 ^ del.toInt.toNat

        Two finite ends a / 2 ^ p and b / 2 ^ q, p, q ≥ 0, compare as a 2 ^ q and b 2 ^ p.

        theorem Ratpoints.Sturm.EndsWF.hasValue_left {depth : ℕ} {nl nr del der : Int64} (h : EndsWF depth nl nr del der) (hd : depth ≤ 55) :

        The double of the lower end of an interval of the bisection has the value of the end.

        theorem Ratpoints.Sturm.EndsWF.hasValue_right {depth : ℕ} {nl nr del der : Int64} (h : EndsWF depth nl nr del der) (hd : depth ≤ 55) :

        The double of the upper end of an interval of the bisection has the value of the end.

        theorem Ratpoints.Sturm.endsWF_left_inf {depth : ℕ} {nr : Int64} (hd : depth ≤ 55) (h1 : 1 ≤ depth) (hb : nr.toInt ≤ 0) (hB : 4 * |nr.toInt| ≤ 2 ^ depth) :
        EndsWF depth (-longMax) nr 0 0
        theorem Ratpoints.Sturm.endsWF_right_inf {depth : ℕ} {nl : Int64} (hd : depth ≤ 55) (h1 : 1 ≤ depth) (ha : 0 ≤ nl.toInt) (hA : 4 * |nl.toInt| ≤ 2 ^ depth) :
        EndsWF depth nl longMax 0 0
        theorem Ratpoints.Sturm.endsWF_finite {depth : ℕ} {nl nr del der : Int64} (hd : depth ≤ 55) (h1 : 1 ≤ depth) (hp0 : 0 ≤ del.toInt) (hpd : del.toInt ≤ ↑depth) (hq0 : 0 ≤ der.toInt) (hqd : der.toInt ≤ ↑depth) (heq : del = der → del = 0) (hA : 4 * |nl.toInt| * 2 ^ (der.toInt - del.toInt).toNat ≤ 2 ^ depth) (hB : 4 * |nr.toInt| * 2 ^ (del.toInt - der.toInt).toNat ≤ 2 ^ depth) (hlt : nl.toInt * 2 ^ der.toInt.toNat < nr.toInt * 2 ^ del.toInt.toNat) :
        EndsWF depth nl nr del der
        theorem Ratpoints.Sturm.endsWF_finite_zero {depth : ℕ} {nl nr : Int64} (hd : depth ≤ 55) (h1 : 1 ≤ depth) (hA : 4 * |nl.toInt| ≤ 2 ^ depth) (hB : 4 * |nr.toInt| ≤ 2 ^ depth) (hlt : nl.toInt < nr.toInt) :
        EndsWF depth nl nr 0 0

        The midpoint #

        theorem Ratpoints.Sturm.midpoint_of_left_inf {nr : Int64} (del der : Int64) (h : nr ≠ longMax) :
        midpoint (-longMax) nr del der = (if nr = 0 then -1 else 2 * nr, 0)
        theorem Ratpoints.Sturm.midpoint_of_right_inf {nl : Int64} (del der : Int64) (h : nl ≠ -longMax) :
        midpoint nl longMax del der = (if nl = 0 then 1 else 2 * nl, 0)
        theorem Ratpoints.Sturm.midpoint_of_eq {nl nr : Int64} (del : Int64) (hl : nl ≠ -longMax) (hr : nr ≠ longMax) :
        midpoint nl nr del del = if nl + nr &&& 1 = 0 then ((nl + nr) >>> 1, 0) else (nl + nr, 1)
        theorem Ratpoints.Sturm.midpoint_of_lt {nl nr del der : Int64} (hl : nl ≠ -longMax) (hr : nr ≠ longMax) (h : der < del) :
        midpoint nl nr del der = (nl + nr * 1 <<< (del - der), del + 1)
        theorem Ratpoints.Sturm.midpoint_of_gt {nl nr del der : Int64} (hl : nl ≠ -longMax) (hr : nr ≠ longMax) (h : del < der) :
        midpoint nl nr del der = (nl * 1 <<< (der - del) + nr, der + 1)
        theorem Ratpoints.Sturm.toInt_ite_two_mul {n : Int64} (c : Int64) (h : n.toInt.natAbs ≤ 2 ^ 53) :
        (if n = 0 then c else 2 * n).toInt = if n.toInt = 0 then c.toInt else 2 * n.toInt
        theorem Ratpoints.Sturm.EndsWF.midpoint_left_inf {depth : ℕ} {nr del der : Int64} (h : EndsWF depth (-longMax) nr del der) (hd : depth < 55) (hr : nr ≠ longMax) :
        EndsWF (depth + 1) (-longMax) (midpoint (-longMax) nr del der).1 del (midpoint (-longMax) nr del der).2 ∧ EndsWF (depth + 1) (midpoint (-longMax) nr del der).1 nr (midpoint (-longMax) nr del der).2 der
        theorem Ratpoints.Sturm.EndsWF.midpoint_right_inf {depth : ℕ} {nl del der : Int64} (h : EndsWF depth nl longMax del der) (hd : depth < 55) (hl : nl ≠ -longMax) :
        EndsWF (depth + 1) nl (midpoint nl longMax del der).1 del (midpoint nl longMax del der).2 ∧ EndsWF (depth + 1) (midpoint nl longMax del der).1 longMax (midpoint nl longMax del der).2 der
        theorem Ratpoints.Sturm.endsWF_halves_of_even {depth : ℕ} {nl nr m : Int64} (hd : depth < 55) (hA : 4 * ↑nl.toInt.natAbs ≤ 2 ^ depth) (hB : 4 * ↑nr.toInt.natAbs ≤ 2 ^ depth) (hlt : nl.toInt < nr.toInt) (hm : 2 * m.toInt = nl.toInt + nr.toInt) :
        EndsWF (depth + 1) nl m 0 0 ∧ EndsWF (depth + 1) m nr 0 0

        The halves of a finite interval [a, b] with the exponents 0 at its midpoint m, 2 m = a + b, when a + b is even.

        theorem Ratpoints.Sturm.endsWF_halves_of_odd {depth : ℕ} {nl nr m : Int64} (hd : depth < 55) (hA : 4 * ↑nl.toInt.natAbs ≤ 2 ^ depth) (hB : 4 * ↑nr.toInt.natAbs ≤ 2 ^ depth) (hlt : nl.toInt < nr.toInt) (hm : m.toInt = nl.toInt + nr.toInt) :
        EndsWF (depth + 1) nl m 0 1 ∧ EndsWF (depth + 1) m nr 1 0

        The halves of a finite interval [a, b] with the exponents 0 at its midpoint (a + b) / 2 with the exponent 1, when a + b is odd.

        theorem Ratpoints.Sturm.EndsWF.midpoint_eq {depth : ℕ} {nl nr del : Int64} (h : EndsWF depth nl nr del del) (hd : depth < 55) (hl : nl ≠ -longMax) (hr : nr ≠ longMax) :
        EndsWF (depth + 1) nl (midpoint nl nr del del).1 del (midpoint nl nr del del).2 ∧ EndsWF (depth + 1) (midpoint nl nr del del).1 nr (midpoint nl nr del del).2 del
        theorem Ratpoints.Sturm.endsWF_halves_of_lt {depth k : ℕ} {nl nr m del der dem : Int64} (hd : depth < 55) (hq : 0 ≤ der.toInt) (hk : del.toInt = der.toInt + (↑k + 1)) (hpd : del.toInt ≤ ↑depth) (hA : 4 * |nl.toInt| ≤ 2 ^ depth) (hB : 4 * |nr.toInt| * 2 ^ (k + 1) ≤ 2 ^ depth) (hlt : nl.toInt < nr.toInt * 2 ^ (k + 1)) (hm : m.toInt = nl.toInt + nr.toInt * 2 ^ (k + 1)) (hdem : dem.toInt = del.toInt + 1) :
        EndsWF (depth + 1) nl m del dem ∧ EndsWF (depth + 1) m nr dem der

        The halves of a finite interval [a / 2 ^ p, b / 2 ^ q] with q < p at its midpoint m / 2 ^ (p + 1), m = a + b 2 ^ (p - q).

        theorem Ratpoints.Sturm.toInt_add_mul_one_shiftLeft {k : ℕ} {nl nr del der : Int64} (hk : del.toInt - der.toInt = ↑k + 1) (hk63 : k + 1 < 63) (hA : |nl.toInt| ≤ 2 ^ 52) (hB : |nr.toInt| * 2 ^ (k + 1) ≤ 2 ^ 52) :
        (nl + nr * 1 <<< (del - der)).toInt = nl.toInt + nr.toInt * 2 ^ (k + 1)

        The midpoint a + b 2 ^ (p - q) of the interval from a / 2 ^ p to b / 2 ^ q, q < p, computed in longs, without overflow for |a| and |b| 2 ^ (p - q) at most 2 ^ 52.

        theorem Ratpoints.Sturm.EndsWF.midpoint_lt {depth : ℕ} {nl nr del der : Int64} (h : EndsWF depth nl nr del der) (hd : depth < 55) (hl : nl ≠ -longMax) (hr : nr ≠ longMax) (hlt : der < del) :
        EndsWF (depth + 1) nl (midpoint nl nr del der).1 del (midpoint nl nr del der).2 ∧ EndsWF (depth + 1) (midpoint nl nr del der).1 nr (midpoint nl nr del der).2 der
        theorem Ratpoints.Sturm.endsWF_halves_of_gt {depth k : ℕ} {nl nr m del der dem : Int64} (hd : depth < 55) (hp : 0 ≤ del.toInt) (hk : der.toInt = del.toInt + (↑k + 1)) (hqd : der.toInt ≤ ↑depth) (hA : 4 * |nl.toInt| * 2 ^ (k + 1) ≤ 2 ^ depth) (hB : 4 * |nr.toInt| ≤ 2 ^ depth) (hlt : nl.toInt * 2 ^ (k + 1) < nr.toInt) (hm : m.toInt = nl.toInt * 2 ^ (k + 1) + nr.toInt) (hdem : dem.toInt = der.toInt + 1) :
        EndsWF (depth + 1) nl m del dem ∧ EndsWF (depth + 1) m nr dem der

        The halves of a finite interval [a / 2 ^ p, b / 2 ^ q] with p < q at its midpoint m / 2 ^ (q + 1), m = a 2 ^ (q - p) + b.

        theorem Ratpoints.Sturm.toInt_mul_one_shiftLeft_add {k : ℕ} {nl nr del der : Int64} (hk : der.toInt - del.toInt = ↑k + 1) (hk63 : k + 1 < 63) (hA : |nl.toInt| * 2 ^ (k + 1) ≤ 2 ^ 52) (hB : |nr.toInt| ≤ 2 ^ 52) :
        (nl * 1 <<< (der - del) + nr).toInt = nl.toInt * 2 ^ (k + 1) + nr.toInt

        The midpoint a 2 ^ (q - p) + b of the interval from a / 2 ^ p to b / 2 ^ q, p < q, computed in longs, without overflow for |a| 2 ^ (q - p) and |b| at most 2 ^ 52.

        theorem Ratpoints.Sturm.EndsWF.midpoint_gt {depth : ℕ} {nl nr del der : Int64} (h : EndsWF depth nl nr del der) (hd : depth < 55) (hl : nl ≠ -longMax) (hr : nr ≠ longMax) (hlt : del < der) :
        EndsWF (depth + 1) nl (midpoint nl nr del der).1 del (midpoint nl nr del der).2 ∧ EndsWF (depth + 1) (midpoint nl nr del der).1 nr (midpoint nl nr del der).2 der
        theorem Ratpoints.Sturm.EndsWF.halves {depth : ℕ} {nl nr del der : Int64} (h : EndsWF depth nl nr del der) (hd : depth < 55) :
        EndsWF (depth + 1) nl (midpoint nl nr del der).1 del (midpoint nl nr del der).2 ∧ EndsWF (depth + 1) (midpoint nl nr del der).1 nr (midpoint nl nr del der).2 der

        An interval of doubles whose ends are not NaNs and whose lower end is at most its upper end, by their values.

        Equations
        Instances For

          The relation of two intervals of doubles of which the first ends strictly before the second begins, by the values of their ends.

          Equations
          Instances For

            Intervals of doubles without a NaN, each with its ends in order, increasing and strictly apart, by the values of their ends.

            Equations
            Instances For
              theorem Ratpoints.Sturm.addInterval_eq (iv : Array (Double × Double)) (nl nr del der : Int64) :
              addInterval iv nl nr del der = match iv.back? with | some (lo, up) => if up.beq ((Double.ofInt64 nl).ldexp (-del.toInt)) = true then iv.pop.push (lo, (Double.ofInt64 nr).ldexp (-der.toInt)) else iv.push ((Double.ofInt64 nl).ldexp (-del.toInt), (Double.ofInt64 nr).ldexp (-der.toInt)) | none => iv.push ((Double.ofInt64 nl).ldexp (-del.toInt), (Double.ofInt64 nr).ldexp (-der.toInt))

              Every interval of increasing intervals strictly apart ends at the end of the last at the latest.

              theorem Ratpoints.Sturm.AreIntervals.pop_push {iv : Array (Double × Double)} (hiv : AreIntervals iv.toList) {lo up u : Double} (hback : iv.back? = some (lo, up)) (hu : u.isNaN = false) (hlt : doubleValue up.bits ≤ doubleValue u.bits) :

              The join of the interval up to u to the last interval kept, from lo to up, keeps the intervals increasing and strictly apart when u lies above up.

              theorem Ratpoints.Sturm.AreIntervals.push {iv : Array (Double × Double)} (hiv : AreIntervals iv.toList) {y x : Double × Double} (hback : iv.back? = some y) (hx : IsInterval x) (hlt : doubleValue y.2.bits < doubleValue x.1.bits) :

              A new last interval x after increasing intervals strictly apart that end before x begins keeps them so.

              theorem Ratpoints.Sturm.snd_eq_of_mem_back?_addInterval (iv : Array (Double × Double)) (nl nr del der : Int64) (i : Double × Double) :
              i ∈ (addInterval iv nl nr del der).back? → i.2 = (Double.ofInt64 nr).ldexp (-der.toInt)

              The last interval kept after the bisection adds the interval up to u ends at u, whether it is the new interval or the join of it to the last interval before.

              theorem Ratpoints.Sturm.AreIntervals.addInterval {iv : Array (Double × Double)} {nl nr del der : Int64} {L U : ℚ} (hiv : AreIntervals iv.toList) (hb : ∀ i ∈ iv.back?, doubleValue i.2.bits ≤ WithBotTop.coe L) (hl : HasValue ((Double.ofInt64 nl).ldexp (-del.toInt)) L) (hu : HasValue ((Double.ofInt64 nr).ldexp (-der.toInt)) U) (hLU : L < U) :

              The intervals kept stay increasing and strictly apart when the bisection adds the interval from l to u (their values L < U) after kept intervals that end at L at the latest, joining it to the last of them when that ends at L.

              theorem Ratpoints.Sturm.exists_mem_addInterval_of_exists_mem {iv : Array (Double × Double)} {nl nr del der : Int64} {L U : ℚ} (hiv : ∀ i ∈ iv.toList, IsInterval i) (hb : ∀ i ∈ iv.back?, doubleValue i.2.bits ≤ WithBotTop.coe L) (hu : HasValue ((Double.ofInt64 nr).ldexp (-der.toInt)) U) (hLU : L < U) {x : WithBotTop ℚ} (hx : ∃ i ∈ iv.toList, doubleValue i.1.bits ≤ x ∧ x ≤ doubleValue i.2.bits) :
              ∃ i ∈ (addInterval iv nl nr del der).toList, doubleValue i.1.bits ≤ x ∧ x ≤ doubleValue i.2.bits

              What the intervals kept hold stays held when the bisection adds an interval up to u after them, with the value U above L, the last of them ending at L at the latest: the join extends the last interval.

              theorem Ratpoints.Sturm.exists_mem_addInterval {iv : Array (Double × Double)} {nl nr del der : Int64} {L U : ℚ} (hiv : ∀ i ∈ iv.toList, IsInterval i) (hl : HasValue ((Double.ofInt64 nl).ldexp (-del.toInt)) L) (hu : HasValue ((Double.ofInt64 nr).ldexp (-der.toInt)) U) {x : WithBotTop ℚ} (hx : WithBotTop.coe L ≤ x ∧ x ≤ WithBotTop.coe U) :
              ∃ i ∈ (addInterval iv nl nr del der).toList, doubleValue i.1.bits ≤ x ∧ x ≤ doubleValue i.2.bits

              The intervals kept hold every value from L to U after the bisection adds the interval from l to u with these values.

              theorem Ratpoints.Sturm.iterate_wf {rows : Array (Array ℤ)} {k iter : ℕ} {nl nr del der : Int64} {cleft cright : ℕ} {sl sr : ℤ} {depth : ℕ} {acc : Array (Double × Double)} (hE : EndsWF depth nl nr del der) (hit : iter ≤ 55) (hd : depth ≤ iter) (hacc : AreIntervals acc.toList) (hb : ∀ i ∈ acc.back?, doubleValue i.2.bits ≤ WithBotTop.coe (endValue nl del)) :
              AreIntervals (iterate rows k iter nl nr del der cleft cright sl sr depth acc).run.toList ∧ ∀ i ∈ (iterate rows k iter nl nr del der cleft cright sl sr depth acc).run.back?, doubleValue i.2.bits ≤ WithBotTop.coe (endValue nr der)

              The intervals that the bisection keeps from the interval from nl / 2 ^ del to nr / 2 ^ der at the depth depth ≤ iter ≤ 55, after kept intervals that end at its lower end at the latest, are increasing and strictly apart and end at its upper end at the latest.

              theorem Ratpoints.Sturm.areIntervals_run_iterate_zero {rows : Array (Array ℤ)} {k iter cleft cright : ℕ} {sl sr : ℤ} (hit : iter ≤ 55) :
              AreIntervals (iterate rows k iter (-longMax) longMax 0 0 cleft cright sl sr 0 #[]).run.toList

              The first call of the bisection, on the whole line at the depth 0 with no interval kept so far, keeps intervals increasing and strictly apart.

              theorem Ratpoints.Sturm.exists_of_mem_intersectList {as bs : List (Double × Double)} (has : ∀ a ∈ as, IsInterval a) (hbs : ∀ b ∈ bs, IsInterval b) {i : Double × Double} (hi : i ∈ intersectList as bs) :
              ∃ a ∈ as, ∃ b ∈ bs, (meet a b).1 = some i

              An interval of the intersection is that of an interval of each list, which it meets.

              theorem Ratpoints.Sturm.exists_le_of_mem_intersectList {as bs : List (Double × Double)} (has : ∀ a ∈ as, IsInterval a) (hbs : ∀ b ∈ bs, IsInterval b) {j : Double × Double} (hj : j ∈ intersectList as bs) :
              (∃ a ∈ as, doubleValue a.1.bits ≤ doubleValue j.1.bits) ∧ ∃ b ∈ bs, doubleValue b.1.bits ≤ doubleValue j.1.bits

              An interval of the intersection begins at the beginning of an interval of each list at the earliest.

              theorem Ratpoints.Sturm.pairwise_intersectList {as bs : List (Double × Double)} (has : ∀ a ∈ as, IsInterval a) (hbs : ∀ b ∈ bs, IsInterval b) (hpa : List.Pairwise EndsBefore as) (hpb : List.Pairwise EndsBefore bs) :

              A value in two intervals lies in the interval that Ratpoints.Sturm.meet notes for them.

              theorem Ratpoints.Sturm.exists_meet_of_snd_eq_true {a b : Double × Double} {bs : List (Double × Double)} (ha : IsInterval a) (hb : IsInterval b) (hpb : List.Pairwise EndsBefore (b :: bs)) (hf : (meet a b).2 = true) {x : WithBotTop ℚ} (hxa : doubleValue a.1.bits ≤ x ∧ x ≤ doubleValue a.2.bits) {b' : Double × Double} (hb' : b' ∈ b :: bs) (hxb : doubleValue b'.1.bits ≤ x ∧ x ≤ doubleValue b'.2.bits) :
              ∃ (i : Double × Double), (meet a b).1 = some i ∧ doubleValue i.1.bits ≤ x ∧ x ≤ doubleValue i.2.bits

              A value in an interval a and an interval of b :: bs lies in the interval that Ratpoints.Sturm.meet notes for a and b when the step goes on with the next interval after a: an interval after b begins after the end of a.

              theorem Ratpoints.Sturm.exists_meet_of_snd_eq_false {a b : Double × Double} {as : List (Double × Double)} (ha : IsInterval a) (hb : IsInterval b) (hpa : List.Pairwise EndsBefore (a :: as)) (hf : (meet a b).2 = false) {x : WithBotTop ℚ} {a' : Double × Double} (ha' : a' ∈ a :: as) (hxa : doubleValue a'.1.bits ≤ x ∧ x ≤ doubleValue a'.2.bits) (hxb : doubleValue b.1.bits ≤ x ∧ x ≤ doubleValue b.2.bits) :
              ∃ (i : Double × Double), (meet a b).1 = some i ∧ doubleValue i.1.bits ≤ x ∧ x ≤ doubleValue i.2.bits

              A value in an interval of a :: as and an interval b lies in the interval that Ratpoints.Sturm.meet notes for a and b when the step goes on with the next interval after b: an interval after a begins after the end of b.

              theorem Ratpoints.Sturm.exists_mem_intersectList {as bs : List (Double × Double)} (has : ∀ a ∈ as, IsInterval a) (hbs : ∀ b ∈ bs, IsInterval b) (hpa : List.Pairwise EndsBefore as) (hpb : List.Pairwise EndsBefore bs) {x : WithBotTop ℚ} (hxa : ∃ a ∈ as, doubleValue a.1.bits ≤ x ∧ x ≤ doubleValue a.2.bits) (hxb : ∃ b ∈ bs, doubleValue b.1.bits ≤ x ∧ x ≤ doubleValue b.2.bits) :
              ∃ i ∈ intersectList as bs, doubleValue i.1.bits ≤ x ∧ x ≤ doubleValue i.2.bits

              A value in an interval of each list lies in an interval of their intersection: the step at the two intervals notes their intersection, and every other step moves past an interval that ends before one of them begins.

              theorem Ratpoints.Sturm.run_computeSturm_of_chain_eq_some {c : List ℤ} {d iter : ℕ} {ivs : Array (Double × Double)} {rows : Array (Array ℤ)} (hc : (chain c d).run = some rows) :
              (computeSturm c d iter ivs).run = if (countsAtInfinity rows (rows.size - 1)).run.2 = (countsAtInfinity rows (rows.size - 1)).run.1 ∧ c.getD 0 0 < 0 then some #[] else some (intersect (iterate rows (rows.size - 1) iter (-longMax) longMax 0 0 (countsAtInfinity rows (rows.size - 1)).run.2 (countsAtInfinity rows (rows.size - 1)).run.1 (if d % 2 = 1 then -(c.getD d 0).sign else (c.getD d 0).sign) (c.getD d 0).sign 0 #[]).run ivs).run

              The Sturm step after a successful chain: no interval at the exit when f has no real root and f(0) < 0, and otherwise the intersection of the intervals that the bisection keeps from [-∞, +∞] with the caller's.

              theorem Ratpoints.Sturm.computeSturm_wf {c : List ℤ} {d iter : ℕ} {ivs iv' : Array (Double × Double)} (hit : iter ≤ 55) (hwf : IntervalsWF (domainBits ivs.toList)) (h : (computeSturm c d iter ivs).run = some iv') :

              The intervals of the Sturm step at a depth of at most 55 for well-formed intervals of the caller are well formed and inside the caller's intervals.