mixle.engines.extended module¶
Fast extended precision via error-free transformations – the “big boy math” end of mixle’s numeric spectrum, with no mpmath/gmpy2 in the hot path.
mpmath and gmpy2 are per-object and non-vectorized (~1000x slower than float64 at ~100-bit
precision); they belong in tests as a correctness oracle, never in compute. The fast way to exceed
float64 is error-free transformations (Dekker/Knuth TwoSum / TwoProd): represent a number
as an unevaluated sum of float64 components (hi + lo) and carry the rounding error explicitly.
Every operation is a handful of float64 ops that vectorize over numpy arrays, so a double-double
(~106-bit mantissa, “fp128”) costs ~5-25x a float64 op – versus ~1000x for mpmath at the same
precision.
This module provides the double-double primitives and the two reductions that matter for mixle’s EM
hot paths – an accurate sum and dot product – where catastrophic cancellation (E[x^2]-E[x]^2,
log-sum-exp of near-equal terms) otherwise eats precision. Beyond double-double, quad-double / multi-limb
take over (a Cython/C job); this file is the part that needs only numpy.
Caveat: the Veltkamp split overflows for |x| > ~1e300; mixle’s log-densities are far from that.
- two_sum(a, b)[source]
Error-free transformation of a sum: returns
(s, e)witha + b == s + eexactly.Knuth’s TwoSum – no assumption on the relative magnitudes of
aandb. Vectorized.
- quick_two_sum(a, b)[source]
Error-free sum assuming
|a| >= |b|(Dekker). One fewer op thantwo_sum().
- two_prod(a, b)[source]
Error-free transformation of a product:
(p, e)witha * b == p + eexactly (Dekker).Uses the Veltkamp split because numpy exposes no fused-multiply-add. Vectorized.
- class DoubleDouble(hi, lo=0.0)[source]
Bases:
objectAn (almost) ~106-bit float as two non-overlapping
float64arrayshi + lo.Scalars or numpy arrays; operations broadcast. The invariant is
|lo| <= 0.5 * ulp(hi).- Parameters:
hi (Any)
lo (Any)
- hi
- lo
- dd_sum(x)[source]
Accurate sum of a
float64array in double-double precision – vectorized, no Python loop over elements.Pairwise tree reduction with an error-free
two_sum()combine at every node:O(n)work inO(log n)vectorized passes, accumulating the rounding error into thelocomponent. The result is correct to ~106 bits even for catastrophically cancelling inputs thatfloat64sums get wrong.- Parameters:
x (Any)
- Return type:
DoubleDouble
- dd_dot(a, b)[source]
Accurate dot product
sum(a_i * b_i)in double-double precision.Uses the compiled hardware-FMA kernel when available (one
fmaper element, ~3x faster than the pure-numpy Veltkamp-split path and bit-for-bit identical); otherwise each product is split error-free bytwo_prod()and the products + errors are summed bydd_sum(). Defeats the cancellation that wrecks a naivefloat64dot.