summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRich Hickey <richhickey@gmail.com>2010-06-23 16:43:24 -0400
committerRich Hickey <richhickey@gmail.com>2010-06-23 16:43:24 -0400
commitc8ce4638779e91ba0792549e3dbded2393662a00 (patch)
tree271dc1a55e37d16fffa1cef995fb128b1d1e86dc
parent16fa2f141dd39b56f4e70ef534c938b4f1527a41 (diff)
add hashCode/equals to BigInt, refine number =, new method equal checks for matching category before equivalence, move array and hashMap to equiv for keys
-rw-r--r--src/jvm/clojure/lang/BigInt.java123
-rw-r--r--src/jvm/clojure/lang/Numbers.java28
-rw-r--r--src/jvm/clojure/lang/PersistentArrayMap.java4
-rw-r--r--src/jvm/clojure/lang/PersistentHashMap.java18
-rw-r--r--src/jvm/clojure/lang/Util.java64
5 files changed, 119 insertions, 118 deletions
diff --git a/src/jvm/clojure/lang/BigInt.java b/src/jvm/clojure/lang/BigInt.java
index 7cf441fa..1732a760 100644
--- a/src/jvm/clojure/lang/BigInt.java
+++ b/src/jvm/clojure/lang/BigInt.java
@@ -14,121 +14,96 @@ package clojure.lang;
import java.math.BigInteger;
-public class BigInt extends Number{
+public final class BigInt extends Number{
-final long lng;
-final BigInteger bint;
-static final BigInteger MIN_LONG = BigInteger.valueOf(Long.MIN_VALUE);
-static final BigInteger MAX_LONG = BigInteger.valueOf(Long.MAX_VALUE);
+final public long lpart;
+final public BigInteger bipart;
-private BigInt(long lng, BigInteger bint){
- this.lng = lng;
- this.bint = bint;
+//must follow Long
+public int hashCode(){
+ if(bipart == null)
+ return (int) (this.lpart ^ (this.lpart >>> 32));
+ return bipart.hashCode();
}
-public BigInteger getBigInteger(){
- return bint;
+public boolean equals(Object obj){
+ if(this == obj)
+ return true;
+ if(obj instanceof BigInt)
+ {
+ BigInt o = (BigInt) obj;
+ if(bipart == null)
+ return o.bipart == null && this.lpart == o.lpart;
+ return o.bipart != null && this.bipart.equals(o.bipart);
+ }
+ return false;
}
-public long getLong(){
- return lng;
+private BigInt(long lpart, BigInteger bipart){
+ this.lpart = lpart;
+ this.bipart = bipart;
}
-public static BigInt fromBigInteger(BigInteger bint){
- if(MIN_LONG.compareTo(bint) <= 0 && MAX_LONG.compareTo(bint) >= 0)
- return new BigInt(bint.longValue(), null);
+public static BigInt fromBigInteger(BigInteger val){
+ if(val.bitLength() < 64)
+ return new BigInt(val.longValue(), null);
else
- return new BigInt(0, bint);
+ return new BigInt(0, val);
}
-public static BigInt fromLong(long lng){
- return new BigInt(lng, null);
+public static BigInt fromLong(long val){
+ return new BigInt(val, null);
}
public BigInteger toBigInteger(){
- if(bint == null)
- return BigInteger.valueOf(lng);
+ if(bipart == null)
+ return BigInteger.valueOf(lpart);
else
- return bint;
+ return bipart;
}
///// java.lang.Number:
public int intValue(){
- if(bint == null)
- {
- if(lng < Integer.MIN_VALUE)
- return Integer.MIN_VALUE;
- else if(lng > Integer.MAX_VALUE)
- return Integer.MAX_VALUE;
- else
- return (int)lng;
- }
+ if(bipart == null)
+ return (int) lpart;
else
- return bint.intValue();
+ return bipart.intValue();
}
public long longValue(){
- if(bint == null)
- return lng;
+ if(bipart == null)
+ return lpart;
else
- return bint.longValue();
+ return bipart.longValue();
}
public float floatValue(){
- if(bint == null)
- {
- if(lng < Float.MIN_VALUE)
- return Float.NEGATIVE_INFINITY;
- else if(lng > Float.MAX_VALUE)
- return Float.POSITIVE_INFINITY;
- else
- return lng;
- }
+ if(bipart == null)
+ return lpart;
else
- return bint.floatValue();
+ return bipart.floatValue();
}
public double doubleValue(){
- if(bint == null)
- {
- if(lng < Double.MIN_VALUE)
- return Double.NEGATIVE_INFINITY;
- else if(lng > Double.MAX_VALUE)
- return Double.POSITIVE_INFINITY;
- else
- return lng;
- }
+ if(bipart == null)
+ return lpart;
else
- return bint.doubleValue();
+ return bipart.doubleValue();
}
public byte byteValue(){
- if(bint == null)
- {
- if(lng < Byte.MIN_VALUE)
- return Byte.MIN_VALUE;
- else if(lng > Byte.MAX_VALUE)
- return Byte.MAX_VALUE;
- else
- return (byte)lng;
- }
+ if(bipart == null)
+ return (byte) lpart;
else
- return bint.byteValue();
+ return bipart.byteValue();
}
public short shortValue(){
- if(bint == null)
- {
- if(lng < Short.MIN_VALUE)
- return Short.MIN_VALUE;
- else if(lng > Short.MAX_VALUE)
- return Short.MAX_VALUE;
- else
- return (short)lng;
- }
+ if(bipart == null)
+ return (short) lpart;
else
- return bint.shortValue();
+ return bipart.shortValue();
}
}
diff --git a/src/jvm/clojure/lang/Numbers.java b/src/jvm/clojure/lang/Numbers.java
index aa04a814..f20530a0 100644
--- a/src/jvm/clojure/lang/Numbers.java
+++ b/src/jvm/clojure/lang/Numbers.java
@@ -232,6 +232,11 @@ static public boolean equiv(Number x, Number y){
return ops(x).combine(ops(y)).equiv(x, y);
}
+static public boolean equal(Number x, Number y){
+ return category(x) == category(y)
+ && ops(x).combine(ops(y)).equiv(x, y);
+}
+
static public boolean lt(Object x, Object y){
return ops(x).combine(ops(y)).lt((Number)x, (Number)y);
}
@@ -1108,6 +1113,8 @@ static final BigDecimalOps BIGDECIMAL_OPS = new BigDecimalOps();
static final LongBitOps LONG_BITOPS = new LongBitOps();
static final BigIntegerBitOps BIGINTEGER_BITOPS = new BigIntegerBitOps();
+static public enum Category {INTEGER, FLOATING, DECIMAL, RATIO};
+
static Ops ops(Object x){
Class xc = x.getClass();
@@ -1129,6 +1136,27 @@ static Ops ops(Object x){
return LONG_OPS;
}
+static Category category(Object x){
+ Class xc = x.getClass();
+
+ if(xc == Integer.class)
+ return Category.INTEGER;
+ else if(xc == Double.class)
+ return Category.FLOATING;
+ else if(xc == Long.class)
+ return Category.INTEGER;
+ else if(xc == Float.class)
+ return Category.FLOATING;
+ else if(xc == BigInteger.class)
+ return Category.INTEGER;
+ else if(xc == Ratio.class)
+ return Category.RATIO;
+ else if(xc == BigDecimal.class)
+ return Category.DECIMAL;
+ else
+ return Category.INTEGER;
+}
+
static BitOps bitOps(Object x){
Class xc = x.getClass();
diff --git a/src/jvm/clojure/lang/PersistentArrayMap.java b/src/jvm/clojure/lang/PersistentArrayMap.java
index 5cdfdead..f2d38348 100644
--- a/src/jvm/clojure/lang/PersistentArrayMap.java
+++ b/src/jvm/clojure/lang/PersistentArrayMap.java
@@ -198,9 +198,7 @@ private int indexOf(Object key){
}
static boolean equalKey(Object k1, Object k2){
- if(k1 == null)
- return k2 == null;
- return k1.equals(k2);
+ return Util.equiv(k1, k2);
}
public Iterator iterator(){
diff --git a/src/jvm/clojure/lang/PersistentHashMap.java b/src/jvm/clojure/lang/PersistentHashMap.java
index 935fab59..b07076bc 100644
--- a/src/jvm/clojure/lang/PersistentHashMap.java
+++ b/src/jvm/clojure/lang/PersistentHashMap.java
@@ -503,7 +503,7 @@ final static class BitmapIndexedNode implements INode{
return this;
return new BitmapIndexedNode(null, bitmap, cloneAndSet(array, 2*idx+1, n));
}
- if(Util.equals(key, keyOrNull)) {
+ if(Util.equiv(key, keyOrNull)) {
if(val == valOrNode)
return this;
return new BitmapIndexedNode(null, bitmap, cloneAndSet(array, 2*idx+1, val));
@@ -558,7 +558,7 @@ final static class BitmapIndexedNode implements INode{
return null;
return new BitmapIndexedNode(null, bitmap ^ bit, removePair(array, idx));
}
- if(Util.equals(key, keyOrNull))
+ if(Util.equiv(key, keyOrNull))
// TODO: collapse
return new BitmapIndexedNode(null, bitmap ^ bit, removePair(array, idx));
return this;
@@ -573,7 +573,7 @@ final static class BitmapIndexedNode implements INode{
Object valOrNode = array[2*idx+1];
if(keyOrNull == null)
return ((INode) valOrNode).find(shift + 5, hash, key);
- if(Util.equals(key, keyOrNull))
+ if(Util.equiv(key, keyOrNull))
return new MapEntry(keyOrNull, valOrNode);
return null;
}
@@ -587,7 +587,7 @@ final static class BitmapIndexedNode implements INode{
Object valOrNode = array[2*idx+1];
if(keyOrNull == null)
return ((INode) valOrNode).find(shift + 5, hash, key, notFound);
- if(Util.equals(key, keyOrNull))
+ if(Util.equiv(key, keyOrNull))
return valOrNode;
return notFound;
}
@@ -641,7 +641,7 @@ final static class BitmapIndexedNode implements INode{
return this;
return editAndSet(edit, 2*idx+1, n);
}
- if(Util.equals(key, keyOrNull)) {
+ if(Util.equiv(key, keyOrNull)) {
if(val == valOrNode)
return this;
return editAndSet(edit, 2*idx+1, val);
@@ -707,7 +707,7 @@ final static class BitmapIndexedNode implements INode{
removedLeaf.val = removedLeaf;
return editAndRemovePair(edit, bit, idx);
}
- if(Util.equals(key, keyOrNull)) {
+ if(Util.equiv(key, keyOrNull)) {
removedLeaf.val = removedLeaf;
// TODO: collapse
return editAndRemovePair(edit, bit, idx);
@@ -763,7 +763,7 @@ final static class HashCollisionNode implements INode{
int idx = findIndex(key);
if(idx < 0)
return null;
- if(Util.equals(key, array[idx]))
+ if(Util.equiv(key, array[idx]))
return new MapEntry(array[idx], array[idx+1]);
return null;
}
@@ -772,7 +772,7 @@ final static class HashCollisionNode implements INode{
int idx = findIndex(key);
if(idx < 0)
return notFound;
- if(Util.equals(key, array[idx]))
+ if(Util.equiv(key, array[idx]))
return array[idx+1];
return notFound;
}
@@ -784,7 +784,7 @@ final static class HashCollisionNode implements INode{
public int findIndex(Object key){
for(int i = 0; i < 2*count; i+=2)
{
- if(Util.equals(key, array[i]))
+ if(Util.equiv(key, array[i]))
return i;
}
return -1;
diff --git a/src/jvm/clojure/lang/Util.java b/src/jvm/clojure/lang/Util.java
index 4817dd56..3e80172d 100644
--- a/src/jvm/clojure/lang/Util.java
+++ b/src/jvm/clojure/lang/Util.java
@@ -21,7 +21,7 @@ static public boolean equiv(Object k1, Object k2){
if(k1 != null)
{
if(k1 instanceof Number && k2 instanceof Number)
- return Numbers.equiv(k1, k2);
+ return Numbers.equal((Number)k1, (Number)k2);
else if(k1 instanceof IPersistentCollection && k2 instanceof IPersistentCollection)
return ((IPersistentCollection)k1).equiv(k2);
return k1.equals(k2);
@@ -35,7 +35,7 @@ static public boolean equals(Object k1, Object k2){
return k1 != null && k1.equals(k2);
}
-//*
+/*
static public boolean equals(long x, long y){
return x == y;
}
@@ -44,21 +44,21 @@ static public boolean equals(double x, double y){
return x == y;
}
-static public boolean equals(long x, Object y){
- return equals(Numbers.num(x),y);
-}
-
-static public boolean equals(Object x, long y){
- return equals(x,Numbers.num(y));
-}
-
-static public boolean equals(double x, Object y){
- return equals((Double)x,y);
-}
-
-static public boolean equals(Object x, double y){
- return equals(x,(Double)y);
-}
+//static public boolean equals(long x, Object y){
+// return equals(Numbers.num(x),y);
+//}
+//
+//static public boolean equals(Object x, long y){
+// return equals(x,Numbers.num(y));
+//}
+//
+//static public boolean equals(double x, Object y){
+// return equals((Double)x,y);
+//}
+//
+//static public boolean equals(Object x, double y){
+// return equals(x,(Double)y);
+//}
static public boolean equiv(long x, long y){
return x == y;
@@ -68,21 +68,21 @@ static public boolean equiv(double x, double y){
return x == y;
}
-static public boolean equiv(long x, Object y){
- return equiv(Numbers.num(x),y);
-}
-
-static public boolean equiv(Object x, long y){
- return equiv(x,Numbers.num(y));
-}
-
-static public boolean equiv(double x, Object y){
- return equiv((Double)x,y);
-}
-
-static public boolean equiv(Object x, double y){
- return equiv(x,(Double)y);
-}
+//static public boolean equiv(long x, Object y){
+// return equiv(Numbers.num(x),y);
+//}
+//
+//static public boolean equiv(Object x, long y){
+// return equiv(x,Numbers.num(y));
+//}
+//
+//static public boolean equiv(double x, Object y){
+// return equiv((Double)x,y);
+//}
+//
+//static public boolean equiv(Object x, double y){
+// return equiv(x,(Double)y);
+//}
//*/
static public boolean identical(Object k1, Object k2){