Skip to content
Permalink
Browse files

use hash consistent with equiv

  • Loading branch information...
richhickey committed Oct 23, 2011
1 parent f006a81 commit b5f5ba2e15dc2f20e14e05141f7de7c6a3d91179
@@ -1,29 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<module relativePaths="true" type="JAVA_MODULE" version="4">
<component name="FacetManager">
<facet type="Clojure" name="Clojure">
<configuration />
</facet>
</component>
<component name="NewModuleRootManager" inherit-compiler-output="false">
<output url="file://$MODULE_DIR$/classes" />
<exclude-output />
<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_5" inherit-compiler-output="false">
<output url="file://$MODULE_DIR$/target/classes" />
<output-test url="file://$MODULE_DIR$/target/test-classes" />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src/resources" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/clj" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/test/java" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/jvm" isTestSource="false" />
<excludeFolder url="file://$MODULE_DIR$/target" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="asm-3.0" level="project" />
<orderEntry type="module-library">
<library>
<CLASSES>
<root url="jar://$APPLICATION_HOME_DIR$/lib/javaee.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</orderEntry>
</component>
</module>

@@ -13,7 +13,7 @@
import java.io.Serializable;
import java.util.*;

public abstract class APersistentMap extends AFn implements IPersistentMap, Map, Iterable, Serializable, MapEquivalence {
public abstract class APersistentMap extends AFn implements IPersistentMap, Map, Iterable, Serializable, MapEquivalence, IHashEq {
int _hash = -1;

public String toString(){
@@ -54,7 +54,7 @@ static public boolean mapEquals(IPersistentMap m1, Object obj){
return false;
Map m = (Map) obj;

if(m.size() != m1.count() || m.hashCode() != m1.hashCode())
if(m.size() != m1.count())
return false;

for(ISeq s = m1.seq(); s != null; s = s.next())
@@ -110,6 +110,17 @@ static public int mapHash(IPersistentMap m){
return hash;
}

public int hasheq(){
int hash = 0;
for(ISeq s = this.seq(); s != null; s = s.next())
{
Map.Entry e = (Map.Entry) s.first();
hash += Util.hasheq(e.getKey()) ^
Util.hasheq(e.getValue());
}
return hash;
}

static public class KeySeq extends ASeq{
ISeq seq;

@@ -17,7 +17,7 @@
import java.util.Iterator;
import java.util.Set;

public abstract class APersistentSet extends AFn implements IPersistentSet, Collection, Set, Serializable {
public abstract class APersistentSet extends AFn implements IPersistentSet, Collection, Set, Serializable, IHashEq {
int _hash = -1;
final IPersistentMap impl;

@@ -92,6 +92,16 @@ public int hashCode(){
return _hash;
}

public int hasheq(){
int hash = 0;
for(ISeq s = seq(); s != null; s = s.next())
{
Object e = s.first();
hash += Util.hasheq(e);
}
return hash;
}

public Object[] toArray(){
return RT.seqToArray(seq());
}
@@ -18,7 +18,7 @@
public abstract class APersistentVector extends AFn implements IPersistentVector, Iterable,
List,
RandomAccess, Comparable,
Serializable {
Serializable, IHashEq {
int _hash = -1;

public String toString(){
@@ -152,6 +152,17 @@ public int hashCode(){
return _hash;
}

public int hasheq(){
int hash = 1;
Iterator i = iterator();
while(i.hasNext())
{
Object obj = i.next();
hash = 31 * hash + Util.hasheq(obj);
}
return hash;
}

public Object get(int index){
return nth(index);
}
@@ -13,7 +13,7 @@
import java.io.Serializable;
import java.util.*;

public abstract class ASeq extends Obj implements ISeq, Sequential, List, Serializable {
public abstract class ASeq extends Obj implements ISeq, Sequential, List, Serializable, IHashEq {
transient int _hash = -1;

public String toString(){
@@ -73,6 +73,15 @@ public int hashCode(){
return _hash;
}

public int hasheq(){
int hash = 1;
for(ISeq s = seq(); s != null; s = s.next())
{
hash = 31 * hash + Util.hasheq(s.first());
}
return hash;
}


//public Object reduce(IFn f) {
// Object ret = first();
@@ -0,0 +1,17 @@
/**
* Copyright (c) Rich Hickey. All rights reserved.
* The use and distribution terms for this software are covered by the
* Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
* which can be found in the file epl-v10.html at the root of this distribution.
* By using this software in any fashion, you are agreeing to be bound by
* the terms of this license.
* You must not remove this notice, or any other, from this software.
**/

/* rich 10/23/11 */

package clojure.lang;

public interface IHashEq{
int hasheq();
}
@@ -14,7 +14,7 @@

import java.util.*;

public final class LazySeq extends Obj implements ISeq, Sequential, List, IPending{
public final class LazySeq extends Obj implements ISeq, Sequential, List, IPending, IHashEq{

private IFn fn;
private Object sv;
@@ -118,6 +118,13 @@ public int hashCode(){
return Util.hash(seq());
}

public int hasheq(){
ISeq s = seq();
if(s == null)
return 1;
return Util.hasheq(seq());
}

public boolean equals(Object o){
ISeq s = seq();
if(s != null)
@@ -941,11 +941,11 @@ public Number dec(Number x){
static Ops ops(Object x){
Class xc = x.getClass();

if(xc == Integer.class)
if(xc == Long.class)
return LONG_OPS;
else if(xc == Double.class)
return DOUBLE_OPS;
else if(xc == Long.class)
else if(xc == Integer.class)
return LONG_OPS;
else if(xc == Float.class)
return DOUBLE_OPS;
@@ -961,6 +961,20 @@ else if(xc == BigDecimal.class)
return LONG_OPS;
}

static int hasheq(Number x){
Class xc = x.getClass();

if(xc == Long.class
|| xc == Integer.class
|| xc == Short.class
|| xc == Byte.class)
{
long lpart = x.longValue();
return (int) (lpart ^ (lpart >>> 32));
}
return x.hashCode();
}

static Category category(Object x){
Class xc = x.getClass();

@@ -117,16 +117,20 @@ public PersistentHashMap(IPersistentMap meta, int count, INode root, boolean has
this.nullValue = nullValue;
}

static int hash(Object k){
return Util.hasheq(k);
}

public boolean containsKey(Object key){
if(key == null)
return hasNull;
return (root != null) ? root.find(0, Util.hash(key), key, NOT_FOUND) != NOT_FOUND : false;
return (root != null) ? root.find(0, hash(key), key, NOT_FOUND) != NOT_FOUND : false;
}

public IMapEntry entryAt(Object key){
if(key == null)
return hasNull ? new MapEntry(null, nullValue) : null;
return (root != null) ? root.find(0, Util.hash(key), key) : null;
return (root != null) ? root.find(0, hash(key), key) : null;
}

public IPersistentMap assoc(Object key, Object val){
@@ -137,7 +141,7 @@ public IPersistentMap assoc(Object key, Object val){
}
Box addedLeaf = new Box(null);
INode newroot = (root == null ? BitmapIndexedNode.EMPTY : root)
.assoc(0, Util.hash(key), key, val, addedLeaf);
.assoc(0, hash(key), key, val, addedLeaf);
if(newroot == root)
return this;
return new PersistentHashMap(meta(), addedLeaf.val == null ? count : count + 1, newroot, hasNull, nullValue);
@@ -146,7 +150,7 @@ public IPersistentMap assoc(Object key, Object val){
public Object valAt(Object key, Object notFound){
if(key == null)
return hasNull ? nullValue : notFound;
return root != null ? root.find(0, Util.hash(key), key, notFound) : notFound;
return root != null ? root.find(0, hash(key), key, notFound) : notFound;
}

public Object valAt(Object key){
@@ -164,7 +168,7 @@ public IPersistentMap without(Object key){
return hasNull ? new PersistentHashMap(meta(), count - 1, root, false, null) : this;
if(root == null)
return this;
INode newroot = root.without(0, Util.hash(key), key);
INode newroot = root.without(0, hash(key), key);
if(newroot == root)
return this;
return new PersistentHashMap(meta(), count - 1, newroot, hasNull, nullValue);
@@ -238,7 +242,7 @@ ITransientMap doAssoc(Object key, Object val) {
// Box leafFlag = new Box(null);
leafFlag.val = null;
INode n = (root == null ? BitmapIndexedNode.EMPTY : root)
.assoc(edit, 0, Util.hash(key), key, val, leafFlag);
.assoc(edit, 0, hash(key), key, val, leafFlag);
if (n != this.root)
this.root = n;
if(leafFlag.val != null) this.count++;
@@ -256,7 +260,7 @@ ITransientMap doWithout(Object key) {
if (root == null) return this;
// Box leafFlag = new Box(null);
leafFlag.val = null;
INode n = root.without(edit, 0, Util.hash(key), key, leafFlag);
INode n = root.without(edit, 0, hash(key), key, leafFlag);
if (n != root)
this.root = n;
if(leafFlag.val != null) this.count--;
@@ -276,7 +280,7 @@ Object doValAt(Object key, Object notFound) {
return notFound;
if (root == null)
return null;
return root.find(0, Util.hash(key), key, notFound);
return root.find(0, hash(key), key, notFound);
}

int doCount() {
@@ -525,7 +529,7 @@ public INode assoc(int shift, int hash, Object key, Object val, Box addedLeaf){
if (array[j] == null)
nodes[i] = (INode) array[j+1];
else
nodes[i] = EMPTY.assoc(shift + 5, Util.hash(array[j]), array[j], array[j+1], addedLeaf);
nodes[i] = EMPTY.assoc(shift + 5, hash(array[j]), array[j], array[j+1], addedLeaf);
j += 2;
}
return new ArrayNode(null, n + 1, nodes);
@@ -670,7 +674,7 @@ public INode assoc(AtomicReference<Thread> edit, int shift, int hash, Object key
if (array[j] == null)
nodes[i] = (INode) array[j+1];
else
nodes[i] = EMPTY.assoc(edit, shift + 5, Util.hash(array[j]), array[j], array[j+1], addedLeaf);
nodes[i] = EMPTY.assoc(edit, shift + 5, hash(array[j]), array[j], array[j+1], addedLeaf);
j += 2;
}
return new ArrayNode(edit, n + 1, nodes);
@@ -976,7 +980,7 @@ public static void main(String[] args){
}

private static INode createNode(int shift, Object key1, Object val1, int key2hash, Object key2, Object val2) {
int key1hash = Util.hash(key1);
int key1hash = hash(key1);
if(key1hash == key2hash)
return new HashCollisionNode(null, key1hash, 2, new Object[] {key1, val1, key2, val2});
Box _ = new Box(null);
@@ -987,7 +991,7 @@ private static INode createNode(int shift, Object key1, Object val1, int key2has
}

private static INode createNode(AtomicReference<Thread> edit, int shift, Object key1, Object val1, int key2hash, Object key2, Object val2) {
int key1hash = Util.hash(key1);
int key1hash = hash(key1);
if(key1hash == key2hash)
return new HashCollisionNode(null, key1hash, 2, new Object[] {key1, val1, key2, val2});
Box _ = new Box(null);
@@ -116,6 +116,16 @@ static public int hash(Object o){
return o.hashCode();
}

static public int hasheq(Object o){
if(o == null)
return 0;
if(o instanceof Number)
return Numbers.hasheq((Number)o);
else if(o instanceof IHashEq)
return ((IHashEq)o).hasheq();
return o.hashCode();
}

static public int hashCombine(int seed, int hash){
//a la boost
seed ^= hash + 0x9e3779b9 + (seed << 6) + (seed >> 2);

0 comments on commit b5f5ba2

Please sign in to comment.
You can’t perform that action at this time.