Changeset 12965
- Timestamp:
- 10/09/10 20:50:41 (12 years ago)
- Location:
- trunk/abcl/src/org/armedbear/lisp
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/abcl/src/org/armedbear/lisp/EqHashTable.java
r12946 r12965 36 36 public final class EqHashTable extends HashTable 37 37 { 38 private LispObject cachedKey;39 private int cachedIndex;40 41 private int mask;42 43 38 public EqHashTable(int size, LispObject rehashSize, 44 39 LispObject rehashThreshold) 45 40 { 46 super(calculateInitialCapacity(size), rehashSize, rehashThreshold); 47 mask = buckets.length - 1; 48 } 49 50 @Override 51 public Symbol getTest() 52 { 53 return Symbol.EQ; 54 } 55 56 @Override 57 public synchronized LispObject get(LispObject key) 58 { 59 final int index; 60 if (key == cachedKey) { 61 index = cachedIndex; 62 } else { 63 index = key.sxhash() & mask; 64 cachedKey = key; 65 cachedIndex = index; 66 } 67 HashEntry e = buckets[index]; 68 while (e != null) { 69 if (key == e.key) 70 return e.value; 71 e = e.next; 72 } 73 return null; 74 } 75 76 @Override 77 public synchronized void put(LispObject key, LispObject value) 78 { 79 int index; 80 if (key == cachedKey) { 81 index = cachedIndex; 82 } else { 83 index = key.sxhash() & mask; 84 cachedKey = key; 85 cachedIndex = index; 86 } 87 HashEntry e = buckets[index]; 88 while (e != null) { 89 if (key == e.key) { 90 e.value = value; 91 return; 92 } 93 e = e.next; 94 } 95 // Not found. We need to add a new entry. 96 if (++count > threshold) { 97 rehash(); 98 // Need a new hash value to suit the bigger table. 99 index = key.sxhash() & mask; 100 cachedKey = key; 101 cachedIndex = index; 102 } 103 e = new HashEntry(key, value); 104 e.next = buckets[index]; 105 buckets[index] = e; 106 } 107 108 @Override 109 public LispObject remove(LispObject key) 110 { 111 final int index; 112 if (key == cachedKey) { 113 index = cachedIndex; 114 } else { 115 index = key.sxhash() & mask; 116 cachedKey = key; 117 cachedIndex = index; 118 } 119 HashEntry e = buckets[index]; 120 HashEntry last = null; 121 while (e != null) { 122 if (key == e.key) { 123 if (last == null) 124 buckets[index] = e.next; 125 else 126 last.next = e.next; 127 --count; 128 return e.value; 129 } 130 last = e; 131 e = e.next; 132 } 133 return null; 134 } 135 136 @Override 137 protected void rehash() 138 { 139 cachedKey = null; // Invalidate the cache! 140 HashEntry[] oldBuckets = buckets; 141 final int newCapacity = buckets.length * 2; 142 threshold = (int) (newCapacity * loadFactor); 143 buckets = new HashEntry[newCapacity]; 144 mask = buckets.length - 1; 145 for (int i = oldBuckets.length; i-- > 0;) { 146 HashEntry e = oldBuckets[i]; 147 while (e != null) { 148 final int index = e.key.sxhash() & mask; 149 HashEntry dest = buckets[index]; 150 if (dest != null) { 151 while (dest.next != null) 152 dest = dest.next; 153 dest.next = e; 154 } else 155 buckets[index] = e; 156 HashEntry next = e.next; 157 e.next = null; 158 e = next; 159 } 160 } 41 super(new Comparator(), calculateInitialCapacity(size), 42 rehashSize, rehashThreshold); 161 43 } 162 44 } -
trunk/abcl/src/org/armedbear/lisp/EqlHashTable.java
r12963 r12965 36 36 public final class EqlHashTable extends HashTable 37 37 { 38 private int mask;39 40 38 public EqlHashTable(int size, LispObject rehashSize, 41 39 LispObject rehashThreshold) 42 40 { 43 super(calculateInitialCapacity(size), rehashSize, rehashThreshold); 44 mask = buckets.length - 1; 45 } 46 47 @Override 48 public Symbol getTest() 49 { 50 return Symbol.EQL; 51 } 52 53 @Override 54 public synchronized LispObject get(LispObject key) 55 { 56 HashEntry e = buckets[key.sxhash() & mask]; 57 while (e != null) 58 { 59 if (key.eql(e.key)) 60 return e.value; 61 e = e.next; 62 } 63 return null; 64 } 65 66 @Override 67 public synchronized void put(LispObject key, LispObject value) 68 { 69 int index = key.sxhash() & mask; 70 HashEntry e = buckets[index]; 71 while (e != null) 72 { 73 if (key.eql(e.key)) 74 { 75 e.value = value; 76 return; 77 } 78 e = e.next; 79 } 80 // Not found. We need to add a new entry. 81 if (++count > threshold) 82 { 83 rehash(); 84 // Need a new hash value to suit the bigger table. 85 index = key.sxhash() & mask; 86 } 87 e = new HashEntry(key, value); 88 e.next = buckets[index]; 89 buckets[index] = e; 90 } 91 92 @Override 93 public LispObject remove(LispObject key) 94 { 95 final int index = key.sxhash() & mask; 96 HashEntry e = buckets[index]; 97 HashEntry last = null; 98 while (e != null) 99 { 100 if (key.eql(e.key)) 101 { 102 if (last == null) 103 buckets[index] = e.next; 104 else 105 last.next = e.next; 106 --count; 107 return e.value; 108 } 109 last = e; 110 e = e.next; 111 } 112 return null; 113 } 114 115 @Override 116 protected void rehash() 117 { 118 HashEntry[] oldBuckets = buckets; 119 int newCapacity = buckets.length * 2; 120 threshold = (int) (newCapacity * loadFactor); 121 buckets = new HashEntry[newCapacity]; 122 mask = buckets.length - 1; 123 for (int i = oldBuckets.length; i-- > 0;) 124 { 125 HashEntry e = oldBuckets[i]; 126 while (e != null) 127 { 128 final int index = e.key.sxhash() & mask; 129 HashEntry dest = buckets[index]; 130 if (dest != null) 131 { 132 while (dest.next != null) 133 dest = dest.next; 134 dest.next = e; 135 } 136 else 137 buckets[index] = e; 138 HashEntry next = e.next; 139 e.next = null; 140 e = next; 141 } 142 } 41 super(new EqlComparator(), calculateInitialCapacity(size), 42 rehashSize, rehashThreshold); 143 43 } 144 44 } -
trunk/abcl/src/org/armedbear/lisp/EqualHashTable.java
r12946 r12965 36 36 public final class EqualHashTable extends HashTable 37 37 { 38 private int mask;39 40 38 public EqualHashTable(int size, LispObject rehashSize, 41 39 LispObject rehashThreshold) 42 40 { 43 super(calculateInitialCapacity(size), rehashSize, rehashThreshold); 44 mask = buckets.length - 1; 45 } 46 47 @Override 48 public Symbol getTest() 49 { 50 return Symbol.EQUAL; 51 } 52 53 @Override 54 public synchronized LispObject get(LispObject key) 55 { 56 HashEntry e = buckets[key.sxhash() & mask]; 57 while (e != null) 58 { 59 if (key == e.key || key.equal(e.key)) 60 return e.value; 61 e = e.next; 62 } 63 return null; 64 } 65 66 @Override 67 public synchronized void put(LispObject key, LispObject value) 68 { 69 int index = key.sxhash() & mask; 70 HashEntry e = buckets[index]; 71 while (e != null) 72 { 73 if (key == e.key || key.equal(e.key)) 74 { 75 e.value = value; 76 return; 77 } 78 e = e.next; 79 } 80 // Not found. We need to add a new entry. 81 if (++count > threshold) 82 { 83 rehash(); 84 // Need a new hash value to suit the bigger table. 85 index = key.sxhash() & mask; 86 } 87 e = new HashEntry(key, value); 88 e.next = buckets[index]; 89 buckets[index] = e; 90 } 91 92 @Override 93 public LispObject remove(LispObject key) 94 { 95 final int index = key.sxhash() & mask; 96 HashEntry e = buckets[index]; 97 HashEntry last = null; 98 while (e != null) 99 { 100 if (key == e.key || key.equal(e.key)) 101 { 102 if (last == null) 103 buckets[index] = e.next; 104 else 105 last.next = e.next; 106 --count; 107 return e.value; 108 } 109 last = e; 110 e = e.next; 111 } 112 return null; 113 } 114 115 @Override 116 protected void rehash() 117 { 118 HashEntry[] oldBuckets = buckets; 119 int newCapacity = buckets.length * 2; 120 threshold = (int) (newCapacity * loadFactor); 121 buckets = new HashEntry[newCapacity]; 122 mask = buckets.length - 1; 123 for (int i = oldBuckets.length; i-- > 0;) 124 { 125 HashEntry e = oldBuckets[i]; 126 while (e != null) 127 { 128 final int index = e.key.sxhash() & mask; 129 HashEntry dest = buckets[index]; 130 if (dest != null) 131 { 132 while (dest.next != null) 133 dest = dest.next; 134 dest.next = e; 135 } 136 else 137 buckets[index] = e; 138 HashEntry next = e.next; 139 e.next = null; 140 e = next; 141 } 142 } 41 super(new EqualComparator(), calculateInitialCapacity(size), 42 rehashSize, rehashThreshold); 143 43 } 144 44 } -
trunk/abcl/src/org/armedbear/lisp/EqualpHashTable.java
r12946 r12965 39 39 LispObject rehashThreshold) 40 40 { 41 super(size, rehashSize, rehashThreshold); 42 } 43 44 @Override 45 public Symbol getTest() 46 { 47 return Symbol.EQUALP; 48 } 49 50 @Override 51 public synchronized LispObject get(LispObject key) 52 { 53 final int index = key.psxhash() % buckets.length; 54 HashEntry e = buckets[index]; 55 while (e != null) 56 { 57 if (key.equalp(e.key)) 58 return e.value; 59 e = e.next; 60 } 61 return null; 62 } 63 64 @Override 65 public synchronized void put(LispObject key, LispObject value) 66 { 67 int index = key.psxhash() % buckets.length; 68 HashEntry e = buckets[index]; 69 while (e != null) 70 { 71 if (key.equalp(e.key)) 72 { 73 e.value = value; 74 return; 75 } 76 e = e.next; 77 } 78 // Not found. We need to add a new entry. 79 if (++count > threshold) 80 { 81 rehash(); 82 // Need a new hash value to suit the bigger table. 83 index = key.psxhash() % buckets.length; 84 } 85 e = new HashEntry(key, value); 86 e.next = buckets[index]; 87 buckets[index] = e; 88 } 89 90 @Override 91 public LispObject remove(LispObject key) 92 { 93 final int index = key.psxhash() % buckets.length; 94 HashEntry e = buckets[index]; 95 HashEntry last = null; 96 while (e != null) 97 { 98 if (key.equalp(e.key)) 99 { 100 if (last == null) 101 buckets[index] = e.next; 102 else 103 last.next = e.next; 104 --count; 105 return e.value; 106 } 107 last = e; 108 e = e.next; 109 } 110 return null; 111 } 112 113 @Override 114 protected void rehash() 115 { 116 HashEntry[] oldBuckets = buckets; 117 int newCapacity = buckets.length * 2 + 1; 118 threshold = (int) (newCapacity * loadFactor); 119 buckets = new HashEntry[newCapacity]; 120 for (int i = oldBuckets.length; i-- > 0;) 121 { 122 HashEntry e = oldBuckets[i]; 123 while (e != null) 124 { 125 final int index = e.key.psxhash() % buckets.length; 126 HashEntry dest = buckets[index]; 127 if (dest != null) 128 { 129 while (dest.next != null) 130 dest = dest.next; 131 dest.next = e; 132 } 133 else 134 buckets[index] = e; 135 HashEntry next = e.next; 136 e.next = null; 137 e = next; 138 } 139 } 41 super(new EqualpComparator(), size, rehashSize, rehashThreshold); 140 42 } 141 43 } -
trunk/abcl/src/org/armedbear/lisp/HashTable.java
r12962 r12965 31 31 * exception statement from your version. 32 32 */ 33 34 33 package org.armedbear.lisp; 35 34 36 35 import static org.armedbear.lisp.Lisp.*; 37 36 38 public abstract class HashTable extends LispObject 39 { 40 private static final int DEFAULT_SIZE = 16; 41 42 protected static final float loadFactor = 0.75f; 43 44 protected final LispObject rehashSize; 45 protected final LispObject rehashThreshold; 46 47 // The rounded product of the capacity and the load factor. When the number 48 // of elements exceeds the threshold, the implementation calls rehash(). 49 protected int threshold; 50 51 // Array containing the actual key-value mappings. 52 protected HashEntry[] buckets; 53 54 // The number of key-value pairs. 55 protected int count; 37 public abstract class HashTable extends LispObject { 38 39 private static final int DEFAULT_SIZE = 16; 40 protected static final float loadFactor = 0.75f; 41 protected final LispObject rehashSize; 42 protected final LispObject rehashThreshold; 43 // The rounded product of the capacity and the load factor. When the number 44 // of elements exceeds the threshold, the implementation calls rehash(). 45 protected int threshold; 46 // Array containing the actual key-value mappings. 47 protected HashEntry[] buckets; 48 // The number of key-value pairs. 49 protected int count; 50 private int mask; 51 final Comparator comparator; 56 52 57 53 protected HashTable(int size, LispObject rehashSize, 58 54 LispObject rehashThreshold) 59 55 { 60 this.rehashSize = rehashSize; 61 this.rehashThreshold = rehashThreshold; 62 buckets = new HashEntry[size]; 63 threshold = (int) (size * loadFactor); 64 } 65 66 protected static int calculateInitialCapacity(int size) 67 { 68 int capacity = 1; 69 while (capacity < size) 70 capacity <<= 1; 71 return capacity; 72 } 73 74 public final LispObject getRehashSize() 75 { 76 return rehashSize; 77 } 78 79 public final LispObject getRehashThreshold() 80 { 81 return rehashThreshold; 82 } 83 84 public int getSize() 85 { 86 return buckets.length; 87 } 88 89 public int getCount() 90 { 91 return count; 92 } 93 94 public abstract Symbol getTest(); 95 96 @Override 97 public LispObject typeOf() 98 { 99 return Symbol.HASH_TABLE; 100 } 101 102 @Override 103 public LispObject classOf() 104 { 105 return BuiltInClass.HASH_TABLE; 106 } 107 108 @Override 109 public LispObject typep(LispObject type) 110 { 111 if (type == Symbol.HASH_TABLE) 112 return T; 113 if (type == BuiltInClass.HASH_TABLE) 114 return T; 115 return super.typep(type); 116 } 117 118 @Override 119 public boolean equalp(LispObject obj) 120 { 121 if (this == obj) 122 return true; 123 if (obj instanceof HashTable) 124 { 125 HashTable ht = (HashTable) obj; 126 if (count != ht.count) 127 return false; 128 if (getTest() != ht.getTest()) 129 return false; 130 LispObject entries = ENTRIES(); 131 while (entries != NIL) 132 { 133 LispObject entry = entries.car(); 134 LispObject key = entry.car(); 135 LispObject value = entry.cdr(); 136 if (!value.equalp(ht.get(key))) 137 return false; 138 entries = entries.cdr(); 139 } 140 return true; 141 } 142 return false; 143 } 144 145 @Override 146 public LispObject getParts() 147 { 148 LispObject parts = NIL; 149 for (int i = 0; i < buckets.length; i++) 150 { 151 HashEntry e = buckets[i]; 152 while (e != null) 153 { 154 parts = parts.push(new Cons("KEY [bucket " + i + "]", e.key)); 155 parts = parts.push(new Cons("VALUE", e.value)); 56 protected HashTable(Comparator c, int size, LispObject rehashSize, 57 LispObject rehashThreshold) { 58 this.rehashSize = rehashSize; 59 this.rehashThreshold = rehashThreshold; 60 buckets = new HashEntry[size]; 61 threshold = (int) (size * loadFactor); 62 comparator = c; 63 mask = buckets.length - 1; 64 } 65 66 protected static int calculateInitialCapacity(int size) { 67 int capacity = 1; 68 while (capacity < size) { 69 capacity <<= 1; 70 } 71 return capacity; 72 } 73 74 public final LispObject getRehashSize() { 75 return rehashSize; 76 } 77 78 public final LispObject getRehashThreshold() { 79 return rehashThreshold; 80 } 81 82 public int getSize() { 83 return buckets.length; 84 } 85 86 public int getCount() { 87 return count; 88 } 89 90 @Override 91 public LispObject typeOf() { 92 return Symbol.HASH_TABLE; 93 } 94 95 @Override 96 public LispObject classOf() { 97 return BuiltInClass.HASH_TABLE; 98 } 99 100 @Override 101 public LispObject typep(LispObject type) { 102 if (type == Symbol.HASH_TABLE) { 103 return T; 104 } 105 if (type == BuiltInClass.HASH_TABLE) { 106 return T; 107 } 108 return super.typep(type); 109 } 110 111 @Override 112 public boolean equalp(LispObject obj) { 113 if (this == obj) { 114 return true; 115 } 116 if (obj instanceof HashTable) { 117 HashTable ht = (HashTable) obj; 118 if (count != ht.count) { 119 return false; 120 } 121 if (getTest() != ht.getTest()) { 122 return false; 123 } 124 LispObject entries = ENTRIES(); 125 while (entries != NIL) { 126 LispObject entry = entries.car(); 127 LispObject key = entry.car(); 128 LispObject value = entry.cdr(); 129 if (!value.equalp(ht.get(key))) { 130 return false; 131 } 132 entries = entries.cdr(); 133 } 134 return true; 135 } 136 return false; 137 } 138 139 @Override 140 public LispObject getParts() { 141 LispObject parts = NIL; 142 for (int i = 0; i < buckets.length; i++) { 143 HashEntry e = buckets[i]; 144 while (e != null) { 145 parts = parts.push(new Cons("KEY [bucket " + i + "]", e.key)); 146 parts = parts.push(new Cons("VALUE", e.value)); 147 e = e.next; 148 } 149 } 150 return parts.nreverse(); 151 } 152 153 public synchronized void clear() { 154 for (int i = buckets.length; i-- > 0;) { 155 buckets[i] = null; 156 } 157 count = 0; 158 } 159 160 // gethash key hash-table &optional default => value, present-p 161 public synchronized LispObject gethash(LispObject key) { 162 LispObject value = get(key); 163 final LispObject presentp; 164 if (value == null) { 165 value = presentp = NIL; 166 } else { 167 presentp = T; 168 } 169 return LispThread.currentThread().setValues(value, presentp); 170 } 171 172 // gethash key hash-table &optional default => value, present-p 173 public synchronized LispObject gethash(LispObject key, 174 LispObject defaultValue) { 175 LispObject value = get(key); 176 final LispObject presentp; 177 if (value == null) { 178 value = defaultValue; 179 presentp = NIL; 180 } else { 181 presentp = T; 182 } 183 return LispThread.currentThread().setValues(value, presentp); 184 } 185 186 public synchronized LispObject gethash1(LispObject key) { 187 final LispObject value = get(key); 188 return value != null ? value : NIL; 189 } 190 191 public synchronized LispObject puthash(LispObject key, LispObject newValue) { 192 put(key, newValue); 193 return newValue; 194 } 195 196 // remhash key hash-table => generalized-boolean 197 public synchronized LispObject remhash(LispObject key) { 198 // A value in a Lisp hash table can never be null, so... 199 return remove(key) != null ? T : NIL; 200 } 201 202 @Override 203 public String writeToString() { 204 if (Symbol.PRINT_READABLY.symbolValue(LispThread.currentThread()) != NIL) { 205 error(new PrintNotReadable(list(Keyword.OBJECT, this))); 206 return null; // Not reached. 207 } 208 StringBuilder sb = new StringBuilder(getTest().writeToString()); 209 sb.append(' '); 210 sb.append(Symbol.HASH_TABLE.writeToString()); 211 sb.append(' '); 212 sb.append(count); 213 if (count == 1) { 214 sb.append(" entry"); 215 } else { 216 sb.append(" entries"); 217 } 218 sb.append(", "); 219 sb.append(buckets.length); 220 sb.append(" buckets"); 221 return unreadableString(sb.toString()); 222 } 223 224 public Symbol getTest() { 225 return comparator.getTest(); 226 } 227 228 synchronized public LispObject get(LispObject key) { 229 int index = comparator.hash(key) & mask; 230 HashEntry e = buckets[index]; 231 while (e != null) { 232 if (comparator.keysEqual(key, e.key)) { 233 return e.value; 234 } 156 235 e = e.next; 157 } 158 } 159 return parts.nreverse(); 160 } 161 162 public synchronized void clear() 163 { 164 for (int i = buckets.length; i-- > 0;) 165 buckets[i] = null; 166 count = 0; 167 } 168 169 // gethash key hash-table &optional default => value, present-p 170 public synchronized LispObject gethash(LispObject key) 171 172 { 173 LispObject value = get(key); 174 final LispObject presentp; 175 if (value == null) 176 value = presentp = NIL; 177 else 178 presentp = T; 179 return LispThread.currentThread().setValues(value, presentp); 180 } 181 182 // gethash key hash-table &optional default => value, present-p 183 public synchronized LispObject gethash(LispObject key, 184 LispObject defaultValue) 185 186 { 187 LispObject value = get(key); 188 final LispObject presentp; 189 if (value == null) 190 { 191 value = defaultValue; 192 presentp = NIL; 193 } 194 else 195 presentp = T; 196 return LispThread.currentThread().setValues(value, presentp); 197 } 198 199 public synchronized LispObject gethash1(LispObject key) 200 201 { 202 final LispObject value = get(key); 203 return value != null ? value : NIL; 204 } 205 206 public synchronized LispObject puthash(LispObject key, LispObject newValue) 207 208 { 209 put(key, newValue); 210 return newValue; 211 } 212 213 // remhash key hash-table => generalized-boolean 214 public synchronized LispObject remhash(LispObject key) 215 216 { 217 // A value in a Lisp hash table can never be null, so... 218 return remove(key) != null ? T : NIL; 219 } 220 221 @Override 222 public String writeToString() 223 { 224 if (Symbol.PRINT_READABLY.symbolValue(LispThread.currentThread()) != NIL) 225 { 226 error(new PrintNotReadable(list(Keyword.OBJECT, this))); 227 return null; // Not reached. 228 } 229 StringBuilder sb = new StringBuilder(getTest().writeToString()); 230 sb.append(' '); 231 sb.append(Symbol.HASH_TABLE.writeToString()); 232 sb.append(' '); 233 sb.append(count); 234 if (count == 1) 235 sb.append(" entry"); 236 else 237 sb.append(" entries"); 238 sb.append(", "); 239 sb.append(buckets.length); 240 sb.append(" buckets"); 241 return unreadableString(sb.toString()); 242 } 243 244 public abstract LispObject get(LispObject key); 245 246 public abstract void put(LispObject key, LispObject value) 247 ; 248 249 public abstract LispObject remove(LispObject key); 250 251 protected abstract void rehash(); 252 253 // Returns a list of (key . value) pairs. 254 public LispObject ENTRIES() 255 { 256 LispObject list = NIL; 257 for (int i = buckets.length; i-- > 0;) 258 { 259 HashEntry e = buckets[i]; 260 while (e != null) 261 { 262 list = new Cons(new Cons(e.key, e.value), list); 236 } 237 return null; 238 } 239 240 synchronized public void put(LispObject key, LispObject value) { 241 int index = comparator.hash(key) & mask; 242 for (HashEntry e = buckets[index]; e != null; e = e.next) { 243 if (comparator.keysEqual(key, e.key)) { 244 e.value = value; 245 return; 246 } 247 } 248 // Not found. We need to add a new entry. 249 if (++count > threshold) { 250 rehash(); 251 // Need a new hash value to suit the bigger table. 252 index = comparator.hash(key) & mask; 253 } 254 buckets[index] = new HashEntry(key, value, buckets[index]); 255 } 256 257 synchronized public LispObject remove(LispObject key) { 258 int index = comparator.hash(key) & mask; 259 260 HashEntry e = buckets[index]; 261 HashEntry last = null; 262 while (e != null) { 263 if (comparator.keysEqual(key, e.key)) { 264 if (last == null) { 265 buckets[index] = e.next; 266 } else { 267 last.next = e.next; 268 } 269 --count; 270 return e.value; 271 } 272 last = e; 263 273 e = e.next; 264 } 265 } 266 return list; 267 } 268 269 public LispObject MAPHASH(LispObject function) 270 { 271 for (int i = buckets.length; i-- > 0;) 272 { 273 HashEntry e = buckets[i]; 274 while (e != null) 275 { 276 function.execute(e.key, e.value); 277 e = e.next; 278 } 279 } 280 return NIL; 281 } 282 283 protected static class HashEntry 284 { 285 LispObject key; 286 LispObject value; 287 HashEntry next; 288 289 HashEntry(LispObject key, LispObject value) 290 { 291 this.key = key; 292 this.value = value; 293 } 294 } 295 296 // For EQUALP hash tables. 297 @Override 298 public int psxhash() 299 { 300 long result = 2062775257; // Chosen at random. 301 result = mix(result, count); 302 result = mix(result, getTest().sxhash()); 303 return (int) (result & 0x7fffffff); 304 } 274 } 275 return null; 276 } 277 278 synchronized protected void rehash() { 279 final int newCapacity = buckets.length * 2; 280 threshold = (int) (newCapacity * loadFactor); 281 mask = newCapacity - 1; 282 HashEntry[] newBuckets = new HashEntry[newCapacity]; 283 284 for (int i = buckets.length; i-- > 0;) { 285 HashEntry e = buckets[i]; 286 while (e != null) { 287 final int index = comparator.hash(e.key) & mask; 288 newBuckets[index] = new HashEntry(e.key,e.value, newBuckets[index]); 289 e = e.next; 290 } 291 } 292 buckets = newBuckets; 293 } 294 295 // Returns a list of (key . value) pairs. 296 public LispObject ENTRIES() { 297 LispObject list = NIL; 298 for (int i = buckets.length; i-- > 0;) { 299 HashEntry e = buckets[i]; 300 while (e != null) { 301 list = new Cons(new Cons(e.key, e.value), list); 302 e = e.next; 303 } 304 } 305 return list; 306 } 307 308 public LispObject MAPHASH(LispObject function) { 309 for (int i = buckets.length; i-- > 0;) { 310 HashEntry e = buckets[i]; 311 while (e != null) { 312 function.execute(e.key, e.value); 313 e = e.next; 314 } 315 } 316 return NIL; 317 } 318 319 protected static class Comparator { 320 Symbol getTest() { 321 return Symbol.EQ; 322 } 323 324 boolean keysEqual(LispObject key1, LispObject key2) { 325 return key1 == key2; 326 } 327 328 int hash(LispObject key) { 329 return key.sxhash(); 330 } 331 } 332 333 protected static class EqlComparator extends Comparator { 334 @Override 335 Symbol getTest() { 336 return Symbol.EQL; 337 } 338 339 @Override 340 boolean keysEqual(LispObject key1, LispObject key2) { 341 return key1.eql(key2); 342 } 343 } 344 345 protected static class EqualComparator extends Comparator { 346 @Override 347 Symbol getTest() { 348 return Symbol.EQUAL; 349 } 350 351 @Override 352 boolean keysEqual(LispObject key1, LispObject key2) { 353 return key1.equal(key2); 354 } 355 } 356 357 protected static class EqualpComparator extends Comparator { 358 @Override 359 Symbol getTest() { 360 return Symbol.EQUALP; 361 } 362 363 @Override 364 boolean keysEqual(LispObject key1, LispObject key2) { 365 return key1.equalp(key2); 366 } 367 368 @Override 369 int hash(LispObject key) { 370 return key.psxhash(); 371 } 372 } 373 374 protected static class HashEntry { 375 376 LispObject key; 377 LispObject value; 378 HashEntry next; 379 380 HashEntry(LispObject key, LispObject value, HashEntry next) { 381 this.key = key; 382 this.value = value; 383 this.next = next; 384 } 385 } 386 387 // For EQUALP hash tables. 388 @Override 389 public int psxhash() { 390 long result = 2062775257; // Chosen at random. 391 result = mix(result, count); 392 result = mix(result, getTest().sxhash()); 393 return (int) (result & 0x7fffffff); 394 } 305 395 }
Note: See TracChangeset
for help on using the changeset viewer.