raw floating-point bits in '==' value object comparisons (again/still)

Remi Forax forax at univ-mlv.fr
Mon Mar 11 13:33:57 UTC 2024


Last week, I explain at JChateau (think JCrete in France, less sun, more chateaux) how value types work from the user POV, among other subject describing the semantics of ==.

First, most of the attendee knew the semantics difference between == on double and Double.equals(). I suppose it's because people that attend to such (un-)conference have a more intimate knowledge of Java than an average developer. Second, no attendee knew that NaN was a prefix.

So it let me think again on that subject.

1) The argument that of Dan that we want to be able to create a class with two different NaN, does not hold because instead of storing the values as double, the values can be stored as long.

  value class C {
      private double d;
      C(double d) { this.d = d; }
      long bits() { return Double.doubleToRawLongBits(d); }
  }

  C c1 = new C(Double.longBitsToDouble(0x7ff0000000000001L));
  C c2 = new C(Double.longBitsToDouble(0x7ff0000000000002L));
  assert c1.bits() != c2.bits();

can be rewritten as

  value class C {
      private long l;
      C(double d) { this.l = Double.doubleToRawLongBits(d); }
      long bits() { return l; }
  }    


2) The de-duplication of value instances by the GC works with both the bitwise equivalence and the representational equivalence.
  
 If the GC only de-duplicate the value instance based only on the bitwise equivalence, it is a valid algorithm under the representational equivalence.


So I not convinced that the bitwise equivalence should be choosen instead of the representational equivalence, for me two semantics instead of three is a win.

Rémi


More information about the valhalla-spec-observers mailing list