diff options
author | Paul Phillips <paulp@improving.org> | 2012-05-09 15:52:44 -0700 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2012-05-09 15:53:08 -0700 |
commit | 1cd498f9091504b42030d4b81c6f659bc386115f (patch) | |
tree | dd9757785890a2098620893f1884ed85c63cd801 /src/library | |
parent | d459104447df2132fc510c7d3cb096ec3092b070 (diff) | |
download | scala-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.java | 61 | ||||
-rw-r--r-- | src/library/scala/runtime/ScalaRunTime.scala | 30 |
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. |