Technically, another option would be to have Java standardize a meaning, and I take it you're not mentioning that because of the performance implications?
On Tue, Jan 8, 2019 at 2:37 AM John Rose <john.r.r...@oracle.com> wrote: > As I think you expect, isSubstitutible(x,y) will mean that x and y are > equivalent > for all practical purposes. One hard question is nailing down what are > "all practical purposes". Certainly it's unfair to flip a coin while > evaluating > 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 y. > > 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 > Float::equals > 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 > results. > > 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 > floatToRawIntBits > 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 <hbo...@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.go...@oracle.com> > wrote: > > > >> 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 float/double, > >> this coincides with `==`, and similarly for references. > >> > >> An `isSubstitutible()` API point will likely emerge from Valhalla. > >