Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

use hash consistent with equiv

  • Loading branch information...
commit b5f5ba2e15dc2f20e14e05141f7de7c6a3d91179 1 parent f006a81
Rich Hickey richhickey authored
26 clojure.iml
View
@@ -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>
15 src/jvm/clojure/lang/APersistentMap.java
View
@@ -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;
12 src/jvm/clojure/lang/APersistentSet.java
View
@@ -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());
}
13 src/jvm/clojure/lang/APersistentVector.java
View
@@ -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);
}
11 src/jvm/clojure/lang/ASeq.java
View
@@ -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();
17 src/jvm/clojure/lang/IHashEq.java
View
@@ -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();
+}
9 src/jvm/clojure/lang/LazySeq.java
View
@@ -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)
18 src/jvm/clojure/lang/Numbers.java
View
@@ -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();
28 src/jvm/clojure/lang/PersistentHashMap.java
View
@@ -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);
10 src/jvm/clojure/lang/Util.java
View
@@ -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);
Please sign in to comment.
Something went wrong with that request. Please try again.