summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSébastien Doeraene <sjrdoeraene@gmail.com>2016-04-21 15:06:25 +0200
committerSébastien Doeraene <sjrdoeraene@gmail.com>2016-04-21 15:06:25 +0200
commit8a4653637a2b693cdcc730a93e17badaac14d56e (patch)
tree9bb1bd0aa5d12a7b757a9cab51e0a07e2bf7072e
parent4f2a20e843c0f07352dff87767cad13636942a3e (diff)
downloadscala-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.java26
-rw-r--r--test/junit/scala/runtime/ScalaRunTimeTest.scala8
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._