From 8a4653637a2b693cdcc730a93e17badaac14d56e Mon Sep 17 00:00:00 2001 From: Sébastien Doeraene Date: Thu, 21 Apr 2016 15:06:25 +0200 Subject: Bring Statics.doubleHash in sync with BoxesRunTime.hashFromDouble. The two algorithms were different, and could result in different hash codes for some values, namely, valid long values that were not also valid int values. The other two functions `longHash` and `floatHash` are rewritten to keep a common style with `doubleHash`, but their algorithm does not change. --- src/library/scala/runtime/Statics.java | 26 ++++++++++++------------- test/junit/scala/runtime/ScalaRunTimeTest.scala | 8 ++++++++ 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/src/library/scala/runtime/Statics.java b/src/library/scala/runtime/Statics.java index 485511ecbb..93fe681856 100644 --- a/src/library/scala/runtime/Statics.java +++ b/src/library/scala/runtime/Statics.java @@ -36,10 +36,11 @@ public final class Statics { } public static int longHash(long lv) { - if ((int)lv == lv) - return (int)lv; - else - return (int)(lv ^ (lv >>> 32)); + int iv = (int)lv; + if (iv == lv) + return iv; + + return java.lang.Long.hashCode(lv); } public static int doubleHash(double dv) { @@ -47,16 +48,15 @@ public final class Statics { if (iv == dv) return iv; - float fv = (float)dv; - if (fv == dv) - return java.lang.Float.floatToIntBits(fv); - long lv = (long)dv; if (lv == dv) - return (int)lv; + return java.lang.Long.hashCode(lv); + + float fv = (float)dv; + if (fv == dv) + return java.lang.Float.hashCode(fv); - lv = Double.doubleToLongBits(dv); - return (int)(lv ^ (lv >>> 32)); + return java.lang.Double.hashCode(dv); } public static int floatHash(float fv) { @@ -66,9 +66,9 @@ public final class Statics { long lv = (long)fv; if (lv == fv) - return (int)(lv^(lv>>>32)); + return java.lang.Long.hashCode(lv); - return java.lang.Float.floatToIntBits(fv); + return java.lang.Float.hashCode(fv); } public static int anyHash(Object x) { diff --git a/test/junit/scala/runtime/ScalaRunTimeTest.scala b/test/junit/scala/runtime/ScalaRunTimeTest.scala index 5bfb12610e..9efbdd44de 100644 --- a/test/junit/scala/runtime/ScalaRunTimeTest.scala +++ b/test/junit/scala/runtime/ScalaRunTimeTest.scala @@ -8,6 +8,14 @@ import org.junit.runners.JUnit4 /** Tests for the runtime object ScalaRunTime */ @RunWith(classOf[JUnit4]) class ScalaRunTimeTest { + @Test + def hashConsistentWithStaticsHash(): Unit = { + val problematicValue: Double = -Math.pow(2, 53) + 1 + val scalaRunTimeHash = ScalaRunTime.hash(problematicValue) + val staticsHash = Statics.anyHash(problematicValue) + assertEquals(scalaRunTimeHash, staticsHash) + } + @Test def testStingOf() { import ScalaRunTime.stringOf -- cgit v1.2.3