Value object equality & floating-point values

Dan Smith daniel.smith at oracle.com
Tue Feb 13 21:00:36 UTC 2024


> On Feb 13, 2024, at 12:22 PM, John Rose <john.r.rose at oracle.com> wrote:
> 
> On 12 Feb 2024, at 13:00, Dan Smith wrote:
> 
>>> For each `float` or `double` field in a value class, the constructor will generate normalization code
> 
> Indeed we considered this, but consider the tradeoff:
> 
> Benefit:  Somebody who is looking very closely indeed at NaNs sees a different op== behavior.  That person is pleased, yay!
> 
> Cost:  Everybody who stores floats and doubles in value classes sees object creation slow down due to branchy normalization logic, at least wherever hardware creates unpredictable NaNs and/or NaNs that don’t fit the Java model of “good” NaNs.
> 
> The cost is too risky, just to please a few NaN-detectives.

Another thing worth pointing out about field storage normalization: as it applies to the (value) class Double, it effectively deprecates the 'doubleToRawLongBits' method and implies that, from now on, in the boxed Double world, there's only one NaN.

Stephen pointed out in valhalla-spec-observers that the factory method 'longBitsToDouble' turns out to allow for some amount of normalization—countering my claim that it must preserve all bits as provided. That is true, yet the Double API as a whole is clearly designed to support multiple NaNs. Without them, the introductory discussion about bit-wise vs. representational equivalence, and the distinction between 'doubleToLongBits' and 'doubleToRawLongBits', become moot.

So the 'longBitsToDouble' specification may give us an opening to change the space of things encodable with Double, but I don't find much enthusiasm for taking advantage of that opening. An API that is fully conversant in the full 64 bits of the IEEE binary64 type seems like the right fit for the class Double.

Then we can turn to other value classes that want to wrap 'double' fields. Some of them very well may want to normalize—and their authors are free to do so. Others might want to do encoding tricks with NaN, as far as the hardware allows. Yet others might opt for an integral type instead for their internal encoding (e.g., in my HalfFloat example above), and again these classes are free to normalize or not normalize in their own program logic.

This leaves the platform itself to take a hands-off, least-common-denominator approach: bitwise equivalence, with classes responsible for managing their own bits and their own 'equals' relations.



More information about the valhalla-spec-experts mailing list