From c2698d58f8e4bcdfade0c87c7517498e3ea38ab6 Mon Sep 17 00:00:00 2001 From: Andy Fingerhut Date: Tue, 13 Nov 2012 19:39:17 -0800 Subject: [PATCH] CLJ-1036: Make hasheq return equal values for BigInteger's as for other integer types And also for Float and Double types. --- src/clj/clojure/core.clj | 4 ++-- src/jvm/clojure/lang/Numbers.java | 11 ++++++++++- test/clojure/test_clojure/numbers.clj | 28 ++++++++++++++++++++++++++++ 3 files changed, 40 insertions(+), 3 deletions(-) diff --git a/src/clj/clojure/core.clj b/src/clj/clojure/core.clj index 985532a..e9c2a93 100644 --- a/src/clj/clojure/core.clj +++ b/src/clj/clojure/core.clj @@ -3257,7 +3257,7 @@ "Coerce to BigInt" {:tag clojure.lang.BigInt :static true - :added "1.3"} + :added "1.0"} [x] (cond (instance? clojure.lang.BigInt x) x (instance? BigInteger x) (clojure.lang.BigInt/fromBigInteger x) @@ -3269,7 +3269,7 @@ (defn biginteger "Coerce to BigInteger" {:tag BigInteger - :added "1.0" + :added "1.3" :static true} [x] (cond (instance? BigInteger x) x diff --git a/src/jvm/clojure/lang/Numbers.java b/src/jvm/clojure/lang/Numbers.java index a50f287..638905d 100644 --- a/src/jvm/clojure/lang/Numbers.java +++ b/src/jvm/clojure/lang/Numbers.java @@ -967,11 +967,20 @@ static int hasheq(Number x){ if(xc == Long.class || xc == Integer.class || xc == Short.class - || xc == Byte.class) + || xc == Byte.class + || (xc == BigInteger.class && (((BigInteger) x).bitLength() < 64))) { long lpart = x.longValue(); return (int) (lpart ^ (lpart >>> 32)); } + if(xc == Double.class) + { + // floatToIntBits should be equal to what we would get + // by constructing a Float from x.floatValue() and + // calling hashCode() on it, but this way doesn't need + // to allocate memory. + return Float.floatToIntBits(x.floatValue()); + } return x.hashCode(); } diff --git a/test/clojure/test_clojure/numbers.clj b/test/clojure/test_clojure/numbers.clj index d00b3f4..430e0a5 100644 --- a/test/clojure/test_clojure/numbers.clj +++ b/test/clojure/test_clojure/numbers.clj @@ -639,3 +639,31 @@ Math/pow overflows to Infinity." (assert (= a (+ (* q d) r) (unchecked-add (unchecked-multiply q d) r)))))) + +(deftest hash-same-for-equal-numbers + (letfn [(hash-same [n types] + (let [s (map (fn [convert-fn] (convert-fn n)) types)] + (if (apply = s) + (apply = (map hash s)) + ;; If they are not all equal, then we don't care if + ;; their hash values are equal or not. + true))) + (float-val [^double d] + (. (Double. d) floatValue))] + (testing "hash same for equal integer types" + (are [n types] (hash-same n types) + -1 [byte short int long bigint biginteger] + Byte/MIN_VALUE [byte short int long bigint biginteger] + Byte/MAX_VALUE [byte short int long bigint biginteger] + Long/MIN_VALUE [long bigint biginteger] + Long/MAX_VALUE [long bigint biginteger] + 12345678901234567890 [bigint biginteger] + -88888888888888888888N [bigint biginteger])) + (testing "hash same for equal float types" + (are [n types] (hash-same n types) + -1.0 [float double] + 12345678901234567890 [float double] + Float/MIN_VALUE [float double] + Float/MAX_VALUE [float double] + Double/MIN_VALUE [float-val double] + Double/MAX_VALUE [float-val double])))) -- 1.8.0