9cdc2949

By: ValentinHirschi <valentin.hirschi@gmail.com>

Round Float products once and keep factors of ±1 exact

Multiplying a Float by a reference rounded the more precise factor to the
other's precision before multiplying, so `a * &b` and `b * &a` (and the
by-value `a * b`) could differ in the last bit, and `z * z.conj()` of a
complex Float whose components have different precisions kept a nonzero
imaginary part. Products and quotients are now rounded once, to the
smaller precision.

A factor of exactly ±1 now only sets the sign of the other factor and
keeps its precision. Evaluators form `a - b` as `a + (-1) b`, with the
`-1` at the working precision, while computed values can carry more bits
(a square root has one more than its argument). Rounding `b` to the
precision of the `-1` left `sqrt(x) - abs(sqrt(x))` a nonzero one-bit
residue for about half of all x, and exact zero and sign tests in
`Complex<Float>` evaluators took the wrong branch on it, at any precision.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
GitHub
configure