Mark Dickinson <dicki...@gmail.com> added the comment:

> am still studying the new one

Sorry - I should have added at least _some_ comments to it.

Here's the underlying principle, which I think of as "The magic of 
round-to-odd":

Suppose x is a positive real number and e is an integer satisfying 2^e <= x. 
Then assuming IEEE 754 binary64 floating-point format, the quantity:

    2^(e-54) * to-odd(x / 2^(e-54))

rounds to the same value as x does under _any_ of the standard IEEE 754 
rounding modes, including the round-ties-to-even rounding mode that we care 
about here.

Here, to-odd is the function R -> Z that maps each integer to itself, but maps 
each non-integral real number x to the *odd* integer nearest x. (So for example 
all of 2.1, 2.3, 2.9, 3.0, 3.1, 3.9 map to 3.)

This works because (x / 2^(e-54)) gives us an integer with at least 55 bits: 
the 53 bits we'll need in the eventual significand, a rounding bit, and then 
the to-odd supplies a "sticky" bit that records inexactness. Note that the 
principle works in the subnormal range too - no additional tricks are needed 
for that. In that case we just end up wastefully computing a few more bits than 
we actually _need_ to determine the correctly-rounded value.

The code applies this principle to the case x = sqrt(n/m) and
e = (n.bit_length() - m.bit_length() - 1)//2. The condition 2^e <= x holds 
because:

    2^(n.bit_length() - 1) <= n
    m < 2^m.bit_length()
 
so

    2^(n.bit_length() - 1 - m.bit_length()) < n/m

and taking square roots gives

    2^((n.bit_length() - 1 - m.bit_length())/2) < √(n/m)

so taking e = (n.bit_length() - 1 - m.bit_length())//2, we have

    2^e <= 2^((n.bit_length() - 1 - m.bit_length())/2) < √(n/m)

Now putting q = e - 54, we need to compute

    2^q * round-to-odd(√(n/m) / 2^q)

rounded to a float. The two branches both do this computation, by moving 2^q 
into either the numerator or denominator of the fraction as appropriate 
depending on the sign of q.

----------

_______________________________________
Python tracker <rep...@bugs.python.org>
<https://bugs.python.org/issue45876>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to