Skip to content

Commit

Permalink
add hashCode/equals to BigInt, refine number =, new method equal chec…
Browse files Browse the repository at this point in the history
…ks for matching category before equivalence, move array and hashMap to equiv for keys
  • Loading branch information
richhickey committed Jun 23, 2010
1 parent 16fa2f1 commit c8ce463
Show file tree
Hide file tree
Showing 5 changed files with 119 additions and 118 deletions.
123 changes: 49 additions & 74 deletions src/jvm/clojure/lang/BigInt.java
Expand Up @@ -14,121 +14,96 @@

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();
}

}
28 changes: 28 additions & 0 deletions src/jvm/clojure/lang/Numbers.java
Expand Up @@ -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);
}
Expand Down Expand Up @@ -1108,6 +1113,8 @@ public Number shiftRight(Number x, int n){
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();

Expand All @@ -1129,6 +1136,27 @@ else if(xc == BigDecimal.class)
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();

Expand Down
4 changes: 1 addition & 3 deletions src/jvm/clojure/lang/PersistentArrayMap.java
Expand Up @@ -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(){
Expand Down
18 changes: 9 additions & 9 deletions src/jvm/clojure/lang/PersistentHashMap.java
Expand Up @@ -503,7 +503,7 @@ public INode assoc(int shift, int hash, Object key, Object val, Box addedLeaf){
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));
Expand Down Expand Up @@ -558,7 +558,7 @@ public INode without(int shift, int hash, Object key){
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;
Expand All @@ -573,7 +573,7 @@ public IMapEntry find(int shift, int hash, Object key){
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;
}
Expand All @@ -587,7 +587,7 @@ public Object find(int shift, int hash, Object key, Object notFound){
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;
}
Expand Down Expand Up @@ -641,7 +641,7 @@ public INode assoc(AtomicReference<Thread> edit, int shift, int hash, Object key
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);
Expand Down Expand Up @@ -707,7 +707,7 @@ public INode without(AtomicReference<Thread> edit, int shift, int hash, Object k
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);
Expand Down Expand Up @@ -763,7 +763,7 @@ public IMapEntry find(int shift, int hash, Object key){
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;
}
Expand All @@ -772,7 +772,7 @@ public Object find(int shift, int hash, Object key, Object notFound){
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;
}
Expand All @@ -784,7 +784,7 @@ public ISeq nodeSeq(){
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;
Expand Down

0 comments on commit c8ce463

Please sign in to comment.