I just had to implement #timesTwoPower: fallback code in Squeak because,
though Squeak VM has kept the ldexp(...) primitive, the primitive may fail
for large int.
So I wanted to use some kind of divide and conquer method to avoid the
Implementing #timesTwoPower: may seem easy because multiplying by a power of
two is an exact operation, we all know that...
Err, surprise, it can also be inexact in case of gradual underflow.
Indeed, gradual underflow make the float loose some bits, so it has to round
to nearest even...
And as we all know, two inexact operations might differ from a single one.
The divide and conquer might be decomposing an inexact operation into
several ones... Too bad.
Since I knew that VW did remove the primitive, I wanted to check if the
implementation was robust enough...
Hmm no, it's a bit too naive...
The following snippet answers true, when it should be false:
| f |
f := 100000 / 3.0d0.
f := f - f unitOfLeastPrecision.
((f timesTwoPower: f class emin - f class precision) timesTwoPower: -1)
= (f timesTwoPower: f class emin - f class precision - 1).
I found the failing case in Squeak with:
1 to: 100 do: [:i |
f := f predecessor.
1 to: 20 do: [:k |
((f timesTwoPower: f class emin-f class precision) timesTwoPower: k negated)
(f timesTwoPower: f class emin-f class precision-k)
ifFalse: [self halt]]].