diff options
author | Sébastien Doeraene <sjrdoeraene@gmail.com> | 2016-04-21 15:06:25 +0200 |
---|---|---|
committer | Sébastien Doeraene <sjrdoeraene@gmail.com> | 2016-04-21 15:06:25 +0200 |
commit | 8a4653637a2b693cdcc730a93e17badaac14d56e (patch) | |
tree | 9bb1bd0aa5d12a7b757a9cab51e0a07e2bf7072e | |
parent | 4f2a20e843c0f07352dff87767cad13636942a3e (diff) | |
download | scala-8a4653637a2b693cdcc730a93e17badaac14d56e.tar.gz scala-8a4653637a2b693cdcc730a93e17badaac14d56e.tar.bz2 scala-8a4653637a2b693cdcc730a93e17badaac14d56e.zip |
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.
-rw-r--r-- | src/library/scala/runtime/Statics.java | 26 | ||||
-rw-r--r-- | 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 @@ -9,6 +9,14 @@ import org.junit.runners.JUnit4 @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 import scala.collection._ |