The executable endpoint test dyadicSign (p(hi)) == 0 decides whether hi
is a real root of toPolyℝ p: the exact dyadic evaluation has the same sign as
the real evaluation (sign_dyadicSign, toReal_evalDyadic), so it is zero
exactly at a root.
Node count. For positive-degree square-free p and lo < hi, the exact
Sturm count on (lo, hi] splits as the number of positive roots of the Möbius
transform (= the p-roots in the open interval (a, b)) plus the endpoint
indicator [p(hi) = 0]. No width budget is needed: the count is exact.
The V ≥ 2 row is impossible at the depth budget. Two or more
transform-roots outside the sector correspond to two distinct roots of p inside
the two-circle region, which are closer than 4·2^{−sepPrec p}, contradicting
the Mahler separation bound.
The V = 1 ∧ p(hi) = 0 row is impossible at the depth budget. It puts
two real roots — an interior root and hi — in (lo, hi], a Sturm count of 2,
contradicting sturmCount_le_one.
The Descartes engine succeeds on nonzero square-free input.
For nonzero p passing the executable SquareFreeRat test,
ZPoly.isolateDescartes? p ≠ none, so the runtime never falls back to the Sturm
engine.
Positive degree is the real content (isolateDescartes?_isSome_of_degree_pos,
the two-circle termination argument); a nonzero constant certifies through the
empty chain. As with isolateSturm?_isSome, the p ≠ 0 hypothesis is added
because SquareFreeRat 0 is vacuous while ZPoly.isolateDescartes? 0 = none.