summaryrefslogtreecommitdiff
path: root/src/library
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2012-05-09 15:52:44 -0700
committerPaul Phillips <paulp@improving.org>2012-05-09 15:53:08 -0700
commit1cd498f9091504b42030d4b81c6f659bc386115f (patch)
treedd9757785890a2098620893f1884ed85c63cd801 /src/library
parentd459104447df2132fc510c7d3cb096ec3092b070 (diff)
downloadscala-1cd498f9091504b42030d4b81c6f659bc386115f.tar.gz
scala-1cd498f9091504b42030d4b81c6f659bc386115f.tar.bz2
scala-1cd498f9091504b42030d4b81c6f659bc386115f.zip
Revert recent commits.
This reverts commit 9b6f51d3ae6ddc6571d3101ea715e25a05aa8adb. This reverts commit b5919100e785df58bde35bb24abe9d60b4da08a2.
Diffstat (limited to 'src/library')
-rw-r--r--src/library/scala/runtime/BoxesRunTime.java61
-rw-r--r--src/library/scala/runtime/ScalaRunTime.scala30
2 files changed, 63 insertions, 28 deletions
diff --git a/src/library/scala/runtime/BoxesRunTime.java b/src/library/scala/runtime/BoxesRunTime.java
index 0df196b2a6..258a176671 100644
--- a/src/library/scala/runtime/BoxesRunTime.java
+++ b/src/library/scala/runtime/BoxesRunTime.java
@@ -203,6 +203,67 @@ public final class BoxesRunTime
}
}
+ /** Hashcode algorithm is driven by the requirements imposed
+ * by primitive equality semantics, namely that equal objects
+ * have equal hashCodes. The first priority are the integral/char
+ * types, which already have the same hashCodes for the same
+ * values except for Long. So Long's hashCode is altered to
+ * conform to Int's for all values in Int's range.
+ *
+ * Float is problematic because it's far too small to hold
+ * all the Ints, so for instance Int.MaxValue.toFloat claims
+ * to be == to each of the largest 64 Ints. There is no way
+ * to preserve equals/hashCode alignment without compromising
+ * the hashCode distribution, so Floats are only guaranteed
+ * to have the same hashCode for whole Floats in the range
+ * Short.MinValue to Short.MaxValue (2^16 total.)
+ *
+ * Double has its hashCode altered to match the entire Int range,
+ * but is not guaranteed beyond that. (But could/should it be?
+ * The hashCode is only 32 bits so this is a more tractable
+ * issue than Float's, but it might be better simply to exclude it.)
+ *
+ * Note: BigInt and BigDecimal, being arbitrary precision, could
+ * be made consistent with all other types for the Int range, but
+ * as yet have not.
+ *
+ * Note: Among primitives, Float.NaN != Float.NaN, but the boxed
+ * verisons are equal. This still needs reconciliation.
+ */
+ public static int hashFromLong(java.lang.Long n) {
+ int iv = n.intValue();
+ if (iv == n.longValue()) return iv;
+ else return n.hashCode();
+ }
+ public static int hashFromDouble(java.lang.Double n) {
+ int iv = n.intValue();
+ double dv = n.doubleValue();
+ if (iv == dv) return iv;
+
+ long lv = n.longValue();
+ if (lv == dv) return java.lang.Long.valueOf(lv).hashCode();
+ else return n.hashCode();
+ }
+ public static int hashFromFloat(java.lang.Float n) {
+ int iv = n.intValue();
+ float fv = n.floatValue();
+ if (iv == fv) return iv;
+
+ long lv = n.longValue();
+ if (lv == fv) return java.lang.Long.valueOf(lv).hashCode();
+ else return n.hashCode();
+ }
+ public static int hashFromNumber(java.lang.Number n) {
+ if (n instanceof java.lang.Long) return hashFromLong((java.lang.Long)n);
+ else if (n instanceof java.lang.Double) return hashFromDouble((java.lang.Double)n);
+ else if (n instanceof java.lang.Float) return hashFromFloat((java.lang.Float)n);
+ else return n.hashCode();
+ }
+ public static int hashFromObject(Object a) {
+ if (a instanceof Number) return hashFromNumber((Number)a);
+ else return a.hashCode();
+ }
+
private static int unboxCharOrInt(Object arg1, int code) {
if (code == CHAR)
return ((java.lang.Character) arg1).charValue();
diff --git a/src/library/scala/runtime/ScalaRunTime.scala b/src/library/scala/runtime/ScalaRunTime.scala
index 6bf25b8464..a04fd23710 100644
--- a/src/library/scala/runtime/ScalaRunTime.scala
+++ b/src/library/scala/runtime/ScalaRunTime.scala
@@ -233,39 +233,12 @@ object ScalaRunTime {
//
// Note that these are the implementations called by ##, so they
// must not call ## themselves.
- //
- // Hashcode algorithm is driven by the requirements imposed
- // by primitive equality semantics, namely that equal objects
- // have equal hashCodes. The first priority are the integral/char
- // types, which already have the same hashCodes for the same
- // values except for Long. So Long's hashCode is altered to
- // conform to Int's for all values in Int's range.
- //
- // Float is problematic because it's far too small to hold
- // all the Ints, so for instance Int.MaxValue.toFloat claims
- // to be == to each of the largest 64 Ints. There is no way
- // to preserve equals/hashCode alignment without compromising
- // the hashCode distribution, so Floats are only guaranteed
- // to have the same hashCode for whole Floats in the range
- // Short.MinValue to Short.MaxValue (2^16 total.)
- //
- // Double has its hashCode altered to match the entire Int range,
- // but is not guaranteed beyond that. (But could/should it be?
- // The hashCode is only 32 bits so this is a more tractable
- // issue than Float's, but it might be better simply to exclude it.)
- //
- // Note: BigInt and BigDecimal, being arbitrary precision, could
- // be made consistent with all other types for the Int range, but
- // as yet have not.
- //
- // Note: Among primitives, Float.NaN != Float.NaN, but the boxed
- // versions are equal. This still needs reconciliation.
@inline def hash(x: Any): Int = x match {
case null => 0
- case x: Long => hash(x)
case x: Double => hash(x)
case x: Float => hash(x)
+ case x: java.lang.Number => hash(x)
case _ => x.hashCode
}
@@ -293,6 +266,7 @@ object ScalaRunTime {
val high = (lv >>> 32).toInt
low ^ (high + lowSign)
}
+ @inline def hash(x: Number): Int = runtime.BoxesRunTime.hashFromNumber(x)
// The remaining overloads are here for completeness, but the compiler
// inlines these definitions directly so they're not generally used.