The contracts of the Sturm step #
The steps of the remainder chain Ratpoints.Sturm.chain as plain functions, by well-founded
recursion where the model has a loop, the predicate of a remainder chain, and the contract of the
chain as a @[spec] theorem proved with vcgen, the program logic of Lean core, with loop
invariants that are named definitions; the contracts of the evaluation of a row at a dyadic number
(Ratpoints.Sturm.evalSign: the sign of the value of the Horner rule in integers), of the signs and
the count of sign changes of the chain there (Ratpoints.Sturm.signsAt) and at ±∞
(Ratpoints.Sturm.countsAtInfinity); the loop of the intersection with the caller's intervals
(Ratpoints.Sturm.intersect) as a recursion on the two lists (Ratpoints.Sturm.intersectList); and
the failure of the Sturm step (Ratpoints.Sturm.computeSturm) exactly when the chain fails.
Main definitions #
Ratpoints.Sturm.dropZeros,Ratpoints.Sturm.reduceOnce,Ratpoints.Sturm.fullReduce: the zero leading coefficients of a remainder dropped, one reduction step followed by that drop, and the reduction of a remainder until its degree is below that of the divisor,#[]when it becomes zero.Ratpoints.Sturm.content,Ratpoints.Sturm.normalize: the gcd of the coefficients of a remainder, and the remainder negated and divided by it.Ratpoints.Sturm.IsChain: a remainder chain of a polynomial and its derivative.Ratpoints.Sturm.IsChainResult: the result of the chain as its contract states it, a chain whose last row is constant, ornonewhen a chain reduces to zero.Ratpoints.Sturm.hornerValue: the value of a row atn / 2 ^ etimes2 ^ (e deg), by the Horner rule ofRatpoints.Sturm.evalSign.Ratpoints.Sturm.signCount: the sign changes thatRatpoints.Sturm.signsAtcounts, zeros skipped.Ratpoints.Sturm.signAtTop,Ratpoints.Sturm.signAtBot: the signs of the rows at±∞.Ratpoints.Sturm.intersectList: the intersection of two lists of intervals by the steps ofRatpoints.Sturm.intersect.
Main statements #
Ratpoints.Sturm.chain_spec: the loops ofRatpoints.Sturm.chainend, and its result satisfiesRatpoints.Sturm.IsChainResult;Ratpoints.Sturm.isChainResult_run_chainstates this without the program logic.Ratpoints.Sturm.IsChain.size_le: a chain of a polynomial of degreedhas at mostd + 1rows.Ratpoints.Sturm.evalSign_spec,Ratpoints.Sturm.signsAt_spec,Ratpoints.Sturm.countsAtInfinity_spec,Ratpoints.Sturm.intersect_spec: the contracts of the evaluation, the signs at a midpoint, the counts at±∞and the intersection, with the plain statementsRatpoints.Sturm.run_evalSign,Ratpoints.Sturm.run_signsAt,Ratpoints.Sturm.run_countsAtInfinityandRatpoints.Sturm.toList_run_intersect.Ratpoints.Sturm.run_computeSturm_eq_none_iff: the Sturm step fails exactly when the chain does.
Implementation notes #
The file uses Lean core and Std only, as Ratpoints.Proof.Words does; the lemmas on arrays,
lists, ranges and integers that are not about the model are in Ratpoints.Proof.Containers, those
on longs in Ratpoints.Proof.Bits. The plain statements let the files with Mathlib use the
contracts without the program logic; the values of the doubles of the intervals are in
Ratpoints.Proof.Bisection.
The steps of the chain #
The array t with its zero entries on top dropped, the zero leading coefficients of a
remainder: the loop of Ratpoints.Sturm.chain after a reduction step.
Equations
Instances For
One reduction of t by s with the leading entry, which cancels, dropped, and then the zeros
on top: one pass of the reduction loop of Ratpoints.Sturm.chain.
Equations
Instances For
The reduction loop of Ratpoints.Sturm.chain: t reduced by s until its size is below that
of s, and #[] when a reduction leaves nothing, where the chain returns none.
Equations
- Ratpoints.Sturm.fullReduce s t = if s.size ≤ t.size then if (Ratpoints.Sturm.reduceOnce s t).size = 0 then #[] else Ratpoints.Sturm.fullReduce s (Ratpoints.Sturm.reduceOnce s t) else t
Instances For
The gcd of the entries of t, the loop of Ratpoints.Sturm.chain over the coefficients of a
remainder, there with a break once the gcd is 1.
Equations
- Ratpoints.Sturm.content t = Array.foldl (fun (g : Nat) (a : Int) => g.gcd a.natAbs) 0 t
Instances For
The array t negated and divided by the gcd of its entries: the change of sign and the
division of a remainder by the gcd of its coefficients in Ratpoints.Sturm.chain.
Equations
- Ratpoints.Sturm.normalize t = Array.map (fun (x : Int) => x / ↑(Ratpoints.Sturm.content (Array.map Neg.neg t))) (Array.map Neg.neg t)
Instances For
Remainder chains #
The rows ch are a remainder chain of the polynomial f of degree d with the coefficients
c₀, …, c_d, the entries of c, as Ratpoints.Sturm.chain computes it.
The chain has
fandf'at least.The first row is
f, the coefficientsc₀, …, c_d.The second row is
f', the coefficients(n + 1) c_(n+1)forn < d.- getElem!_add_two (k : Nat) (hk : k + 2 < ch.size) : ch[k + 2]! = normalize (fullReduce ch[k + 1]! ch[k]!)
Each further row is the full reduction of the row two before by the row before, negated and divided by the gcd of its entries.
Every row has a nonzero last entry, its leading coefficient.
The sizes decrease strictly from
f'on.
Instances For
The result of Ratpoints.Sturm.chain as its contract states it: some ch for a chain ch
whose last row is constant; none when there is a chain whose last row is not constant and reduces
the row before it to zero, which Ratpoints.Sturm.fullReduce gives as #[].
Equations
Instances For
The invariants #
The rows while the loop of Ratpoints.Sturm.chain over k runs, after the indices pref, with
the indices suff still to come: a chain (Ratpoints.Sturm.IsChain), whose last row is constant
once no index is left; while indices are left, one row for each index done after f and f', the
last one not constant, its size and the number of rows adding up to at most d + 2.
Equations
- One or more equations did not get rendered due to their size.
Instances For
The invariant of the loop of Ratpoints.Sturm.chain over k, on the pair of the value of an
early return and the rows: no return yet and Ratpoints.Sturm.ChainLoopInvariant, or the
return of none, which ends the loop, with the result none of the contract.
Equations
Instances For
The invariant of the reduction loop of Ratpoints.Sturm.chain of t₀ by s, on the pair of
the value of an early return and the remainder: no return, the same full reduction as t₀, a
nonzero last entry, and at the exit a size below that of s; or, at the exit, the return of
none, when the full reduction of t₀ leaves nothing.
Equations
- One or more equations did not get rendered due to their size.
Instances For
The invariant of the loop of Ratpoints.Sturm.chain that drops the zeros on top of t₀: the
same result of Ratpoints.Sturm.dropZeros, and no zero on top at the exit.
Equations
- Ratpoints.Sturm.DropZerosInvariant t₀ exit t = (Ratpoints.Sturm.dropZeros t = Ratpoints.Sturm.dropZeros t₀ ∧ (exit = true → ¬(t.back? == some 0) = true))
Instances For
The invariant of the loop of Ratpoints.Sturm.chain over the entries of a remainder: the gcd of
the entries pref done, the break at 1 included.
Equations
- Ratpoints.Sturm.ContentInvariant pref g = (g = List.foldl (fun (g : Nat) (a : Int) => g.gcd a.natAbs) 0 pref)
Instances For
The verification conditions, one lemma each in the shape vcgen states it #
At the index cur, the chain has cur rows: the reduction is of the row cur - 2 by the row
cur - 1, the last one.
The step of the loop over k: the normalized full reduction t pushed onto the chain.
Ratpoints.Sturm.chain_spec as a plain statement, which the files with Mathlib use without the
program logic.
The signs of the chain #
The value of the polynomial with the coefficients row, constant term first, at num / 2 ^ e,
times 2 ^ (e deg), deg the size of row less one, as the Horner rule of
Ratpoints.Sturm.evalSign computes it in integers, after j of its steps: from the leading
coefficient, w ↦ w num + c_(deg - j - 1) 2 ^ (e (j + 1)) at the step j.
Equations
Instances For
The invariant of the loop of Ratpoints.Sturm.evalSign after the steps pref: the value of
the Horner rule after as many steps, and the exponent of the next step.
Equations
Instances For
A step of the loop of Ratpoints.Sturm.evalSign; the exponents denexp (j + 1) stay below
2 ^ 63.
The number of sign changes that the loop of Ratpoints.Sturm.signsAt counts in the signs l
after the sign s: a sign -s counts and becomes the sign compared, another sign that is not 0
becomes the sign compared, and a 0 is skipped. For a sign s ≠ 0 this is the number of sign
changes of s followed by l, the zeros skipped.
Equations
- Ratpoints.Sturm.signCount x✝ [] = 0
- Ratpoints.Sturm.signCount x✝ (t :: ts) = if t = -x✝ then Ratpoints.Sturm.signCount t ts + 1 else if t ≠ 0 then Ratpoints.Sturm.signCount t ts else Ratpoints.Sturm.signCount x✝ ts
Instances For
The invariant of the loop of Ratpoints.Sturm.signsAt with the indices suff still to come:
the count so far and the count of the signs σ n still to come after the sign compared add up to
total.
Equations
- Ratpoints.Sturm.SignsAtInvariant σ total suff x = (x.fst + Ratpoints.Sturm.signCount x.snd (List.map σ suff) = total)
Instances For
The sign of the row n of the chain rows at -∞: that of its leading coefficient, negated
for odd degree.
Equations
- Ratpoints.Sturm.signAtBot rows n = if (rows[n]!.size - 1) % 2 = 1 then -Ratpoints.Sturm.signAtTop rows n else Ratpoints.Sturm.signAtTop rows n
Instances For
The invariant of the loop of Ratpoints.Sturm.countsAtInfinity after the indices pref: the
numbers of the indices n among them where the signs of the rows n and n + 1 differ at +∞ and
at -∞.
Equations
- One or more equations did not get rendered due to their size.
Instances For
The exponents denexp (j + 1) of the Horner rule stay below 2 ^ 63, so that the long e
does not overflow.
Ratpoints.Sturm.signsAt_spec as a plain statement: the signs σ 0 and σ 1 of f and f'
at the midpoint, and the number of sign changes of σ 0, …, σ k, the signs of the rows of the
chain there, the zeros skipped (Ratpoints.Sturm.signCount).
Ratpoints.Sturm.countsAtInfinity_spec as a plain statement: the numbers of the indices
n < k where the signs of the rows n and n + 1 of the chain differ at +∞ and at -∞, the
numbers of sign changes of a chain whose rows have nonzero leading coefficients.
The intersection with the caller's intervals #
The intersection of the intervals loc with the intervals ivs, by the steps of
Ratpoints.Sturm.intersect (Ratpoints.Sturm.meet) as a recursion on the two lists: the interval
that a step notes, followed by the intersection of the rest, without the interval of loc or of
ivs that ends first.
Equations
Instances For
The invariant of the loop of Ratpoints.Sturm.intersect on the cursors n1, n2 and the
intervals noted: they followed by the intersection of the rest of the lists are the intersection of
the lists, and at the exit the rest of one of the lists is empty.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Ratpoints.Sturm.intersect_spec as a plain statement.