timesTwoPower: broken in 7.8

Previous Topic Next Topic
classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view

timesTwoPower: broken in 7.8

Nicolas Cellier

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
unnecessary underflow/overflow.

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]]].

You might want to check implementation in latest Squeak trunk

Hope that helps...

vwnc mailing list
[hidden email]