diff options
author | Lukas Rytz <lukas.rytz@typesafe.com> | 2016-04-22 08:36:11 +0200 |
---|---|---|
committer | Lukas Rytz <lukas.rytz@typesafe.com> | 2016-04-22 08:36:11 +0200 |
commit | 6863c5c390d59f4ccee4f1b877479128a8682820 (patch) | |
tree | 6250c816c8a751dd8db0a92f137ce1856e39fca7 /src/library | |
parent | 7a24bd6bcde707e25b17e8e1f8dcdea21c51e17a (diff) | |
parent | cce701650143d13c8b292bffd590bf7c8eb532d7 (diff) | |
download | scala-6863c5c390d59f4ccee4f1b877479128a8682820.tar.gz scala-6863c5c390d59f4ccee4f1b877479128a8682820.tar.bz2 scala-6863c5c390d59f4ccee4f1b877479128a8682820.zip |
Merge pull request #5110 from sjrd/remove-duplicate-implem-of-hashcodes
Remove the duplicate implem of hash codes for numbers.
Diffstat (limited to 'src/library')
-rw-r--r-- | src/library/scala/reflect/ClassTag.scala | 2 | ||||
-rw-r--r-- | src/library/scala/runtime/BoxesRunTime.java | 60 | ||||
-rw-r--r-- | src/library/scala/runtime/ScalaRunTime.scala | 8 | ||||
-rw-r--r-- | src/library/scala/runtime/Statics.java | 54 |
4 files changed, 45 insertions, 79 deletions
diff --git a/src/library/scala/reflect/ClassTag.scala b/src/library/scala/reflect/ClassTag.scala index 7f037ce17b..1811d3a00f 100644 --- a/src/library/scala/reflect/ClassTag.scala +++ b/src/library/scala/reflect/ClassTag.scala @@ -101,7 +101,7 @@ trait ClassTag[T] extends ClassManifestDeprecatedApis[T] with Equals with Serial // case class accessories override def canEqual(x: Any) = x.isInstanceOf[ClassTag[_]] override def equals(x: Any) = x.isInstanceOf[ClassTag[_]] && this.runtimeClass == x.asInstanceOf[ClassTag[_]].runtimeClass - override def hashCode = scala.runtime.ScalaRunTime.hash(runtimeClass) + override def hashCode = runtimeClass.## override def toString = { def prettyprint(clazz: jClass[_]): String = if (clazz.isArray) s"Array[${prettyprint(clazz.getComponentType)}]" else diff --git a/src/library/scala/runtime/BoxesRunTime.java b/src/library/scala/runtime/BoxesRunTime.java index b6b512d529..6b3874fc1f 100644 --- a/src/library/scala/runtime/BoxesRunTime.java +++ b/src/library/scala/runtime/BoxesRunTime.java @@ -198,66 +198,6 @@ 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 - * versions 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.hashCode(lv); - - float fv = n.floatValue(); - if (fv == dv) return java.lang.Float.hashCode(fv); - 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.hashCode(lv); - 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(); - } - 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 02f39f6f5f..b31a94576a 100644 --- a/src/library/scala/runtime/ScalaRunTime.scala +++ b/src/library/scala/runtime/ScalaRunTime.scala @@ -158,11 +158,9 @@ object ScalaRunTime { } } - /** Implementation of `##`. */ - def hash(x: Any): Int = - if (x == null) 0 - else if (x.isInstanceOf[java.lang.Number]) BoxesRunTime.hashFromNumber(x.asInstanceOf[java.lang.Number]) - else x.hashCode + /** Old implementation of `##`. */ + @deprecated("Use scala.runtime.Statics.anyHash instead.", "2.12.0") + def hash(x: Any): Int = Statics.anyHash(x.asInstanceOf[Object]) /** Given any Scala value, convert it to a String. * diff --git a/src/library/scala/runtime/Statics.java b/src/library/scala/runtime/Statics.java index 485511ecbb..62390cb9d0 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,11 +66,39 @@ 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); } + /** + * 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. + */ public static int anyHash(Object x) { if (x == null) return 0; |