Feature suggestion: Add static equals methods to Float and Double
hboehm at google.com
Tue Jan 8 18:55:59 UTC 2019
The IEEE standard does say that for quiet NaNs, the value (or one of them)
"should" be preserved by most operations on the quiet NaN. I have not heard
of implementations violating this for anything other than the "quiet" bit.
Thus I don't immediately see why it would be problematic to encode an
explicitly programmer-introduced error cause in the remaining bits (as
opposed to relying on hardware-generated patterns). I have not seen
non-testing code that does so, but I would be mildly surprised if it
doesn't exist somewhere.
On Tue, Jan 8, 2019 at 1:16 AM Ulf Adams <ulfjack at google.com> wrote:
> Technically, another option would be to have Java standardize a meaning,
> and I take it you're not mentioning that because of the performance
> On Tue, Jan 8, 2019 at 2:37 AM John Rose <john.r.rose at oracle.com> wrote:
>> As I think you expect, isSubstitutible(x,y) will mean that x and y are
>> for all practical purposes. One hard question is nailing down what are
>> "all practical purposes". Certainly it's unfair to flip a coin while
>> x and y separately, and claim that a distinct outcome proves a difference.
>> What about viewing the bits of x and y using the Unsafe API? That's
>> unfair also, since it opens the door to implementation-dependent behavior
>> which might detect a difference (an irrelevant difference) between x and
>> Now, floatToRawIntBits can detect differences between NaNs which
>> have different numeric codes. Are two such NaNs substitutable or not?
>> The evidence in favor:
>> - They become equivalent when boxed in a Float, and Float claims to
>> be an all-purpose box for float values.
>> - The extra information produced by floatToRawIntBits is implementation
>> specific, and in particular processor dependent.
>> - Joe Darcy suggested to me that some processors, like x87, may
>> perturb NaN bits (turning off the "signalling" bit, for example), even
>> if the float value is simply bound to a parameter. This means that
>> the operand to floatToRawIntBits *might*, in compiled code, possibly
>> have *some* of its bits perturbed. (Thanks, Joe, for that and similar
>> hair-raising stories.)
>> - The previous point implies that compiled code and interpreted code
>> might, in the same JVM instance, produce different results on the
>> same argument. That is quite implementation specific indeed!
>> The evidence against:
>> - The existing standard API point floatToRawIntBits is not going away.
>> So the isSubstitutable API point must document that floatToRawIntBits
>> has the processor-dependent ability to conjure up different bits for
>> x and y. Maybe it should be called isAlmostSubstitutable??
>> The right trade-off here, I think, is to align isSubstitutable with
>> and simply increase the warnings on floatToRawIntBits, that this method
>> can produce platform-specific results in an unpredictable way, and that
>> in particular it can produce distinct answers for otherwise substitutable
>> I also suggested to Dr. Deprecator (Stuart Marks) that floatToRawIntBits
>> might be a candidate for deprecation; he said it would be a lot of expense
>> for relatively little benefit. I think at least the javadoc for
>> should not speak so confidently, as it does, of "preserving Not-a-Number
>> (NaN) values", as if these values were something that had a stable
>> semantics, as if they could somehow carry application information.
>> More background (thanks again to Joe): The NaN bits don't have a standard
>> format. Different CPUs can (and often do) disagree on which bits
>> mean what, and how standard arithmetic operations consume and produce
>> them. There is apparently no agreed standard NaN pattern, although
>> Java favors the "all zero" bit pattern as normative. Different CPUs
>> may disagree on which bits denote signaling or quiet NaNs, and when
>> such bits may be queried or modified. Adding the possible distinct
>> treatment of the "same" NaN value in compiled vs. interpreted code
>> (as well as strictfp vs. non-strictfp code), and the use of "raw" NaN
>> bits seems a very risky proposition, useful only for people writing
>> processor-specific code, with great care.
>> In hindsight, I think it would have been nice to place the "raw bits"
>> API points to Unsafe or a separate module. But when those API
>> points were designed (1.0), there were no such hiding places.
>> And it's probably too costly to fix now. If the sweet spot is to
>> acknowledge the wart, but not let it spread, then we design the
>> substitutability test based on Float::equals, not floatToRawIntBits.
>> — John
>> On Jan 6, 2019, at 4:36 PM, Hans Boehm <hboehm at google.com> wrote:
>> > IIUC, isSubstitutible() is not quite what's being proposed here. The
>> > proposed definition here uses floatToIntBits(), not floatToRawIntBits().
>> > Hans
>> > On Sun, Jan 6, 2019 at 3:59 PM Brian Goetz <brian.goetz at oracle.com>
>> >> Followers of Project Valhalla will see that this issue comes up when
>> >> defining equality on value types. The relation you are looking for is
>> >> being called "substitutible"; it asks whether there is any way to
>> >> distinguish between two values. For primitives other than
>> >> this coincides with `==`, and similarly for references.
>> >> An `isSubstitutible()` API point will likely emerge from Valhalla.
More information about the core-libs-dev