(DEFINE-FILE-INFO READTABLE "XCL" PACKAGE "XCL") (IL:FILECREATED "16-May-90 18:22:09" IL:|{DSK}local>lde>lispcore>sources>IMPLICIT-KEY-HASH.;2| 13907 IL:|changes| IL:|to:| (IL:VARS IL:IMPLICIT-KEY-HASHCOMS) IL:|previous| IL:|date:| "24-Jan-88 16:54:16" IL:|{DSK}local>lde>lispcore>sources>IMPLICIT-KEY-HASH.;1|) ; Copyright (c) 1987, 1988, 1990 by Venue & Xerox Corporation. All rights reserved. (IL:PRETTYCOMPRINT IL:IMPLICIT-KEY-HASHCOMS) (IL:RPAQQ IL:IMPLICIT-KEY-HASHCOMS ((IL:STRUCTURES IMPLICIT-KEY-HASH-TABLE) (IL:VARIABLES *DELETED-IMPLICIT-HASH-SLOT*) (IL:FUNCTIONS MAKE-IMPLICIT-KEY-HASH-TABLE GET-IMPLICIT-KEY-HASH PUT-IMPLICIT-KEY-HASH IMPLICIT-KEY-MAP-HASH CLEAR-IMPLICIT-KEY-HASH IMPLICIT-KEY-REHASH ADJUST-IMPLICIT-KEY-HASH) (IL:FUNCTIONS GET-IK-VALUE PUT-IK-VALUE GET-IK-KEY REPROBE 16BIT-+) (IL:SETFS GET-IMPLICIT-KEY-HASH GET-IK-VALUE) (FILE-ENVIRONMENTS "IMPLICIT-KEY-HASH"))) (DEFSTRUCT (IMPLICIT-KEY-HASH-TABLE (:CONC-NAME IK-HASH-) (:CONSTRUCTOR %MAKE-IK-HASH-TABLE) (:COPIER NIL) (:PREDICATE NIL) (:FAST-ACCESSORS T)) BASE (LAST-INDEX 0 :TYPE (UNSIGNED-BYTE 16)) (NUM-SLOTS 0 :TYPE (UNSIGNED-BYTE 16)) (NUM-KEYS 0 :TYPE (UNSIGNED-BYTE 16)) (NULL-SLOTS 0 :TYPE (UNSIGNED-BYTE 16)) KEY-ACCESSOR) (DEFVAR *DELETED-IMPLICIT-HASH-SLOT* "Unique string") (DEFUN MAKE-IMPLICIT-KEY-HASH-TABLE (&OPTIONAL (MIN-KEYS 20) (KEY-ACCESSOR :FIRST)) (IL:* IL:|;;| "Does eq hashing") (LET* ((NUM-SLOTS (IL:* IL:|;;| "num-slots is always a power of two") (DO ((IDEAL-SIZE (ASH (TRUNCATE (1- MIN-KEYS) 3) 2)) (I 8 (+ I I))) ((> I IDEAL-SIZE) I))) (LOGICAL-SLOTS (IL:* IL:|;;| "75% of NUM-SLOTS") (+ (ASH NUM-SLOTS -1) (ASH NUM-SLOTS -2)))) (%MAKE-IK-HASH-TABLE :BASE (IL:\\ALLOCBLOCK NUM-SLOTS IL:PTRBLOCK.GCT) :LAST-INDEX (1- NUM-SLOTS) :NUM-SLOTS LOGICAL-SLOTS :NUM-KEYS 0 :NULL-SLOTS LOGICAL-SLOTS :KEY-ACCESSOR KEY-ACCESSOR))) (DEFUN GET-IMPLICIT-KEY-HASH (ITEM IK-HASH-TABLE) (IF (NOT (TYPEP IK-HASH-TABLE 'IMPLICIT-KEY-HASH-TABLE)) (ERROR "Not an implicit key hash table: ~s" IK-HASH-TABLE)) (IL:* IL:|;;| "Do first index outside of loop, so don't have to do setup on fast case") (PROG* ((BITS (IL:\\EQHASHINGBITS ITEM)) (LIMIT (IK-HASH-LAST-INDEX IK-HASH-TABLE)) (INDEX (LOGAND BITS LIMIT)) (BASE (IK-HASH-BASE IK-HASH-TABLE)) (VALUE (GET-IK-VALUE BASE INDEX)) (KEY-ACCESSOR (IK-HASH-KEY-ACCESSOR IK-HASH-TABLE)) (DELETED-INDICATOR *DELETED-IMPLICIT-HASH-SLOT*) REPROBE) (COND ((EQ VALUE DELETED-INDICATOR) (IL:* IL:|;;| "Deleted slot -- continue") ) (VALUE (IL:* IL:|;;| "Slot is occupied ") (IF (EQ ITEM (GET-IK-KEY VALUE KEY-ACCESSOR)) (GO FOUND) (IL:* IL:|;;| "Else try again") )) (T (IL:* IL:|;;| "Null slot") (RETURN NIL))) (IL:* IL:|;;| "Compute reprobe interval") (SETQ REPROBE (REPROBE BITS LIMIT)) LP (IL:* IL:|;;| "Since table size is a power of two, any wraparound in the IPLUS16 will be consistent with the LOGAND") (SETQ INDEX (LOGAND (16BIT-+ INDEX REPROBE) LIMIT)) (SETQ VALUE (GET-IK-VALUE BASE INDEX)) (COND ((EQ VALUE DELETED-INDICATOR) (IL:* IL:|;;| "Deleted slot -- continue") ) (VALUE (IL:* IL:|;;| "Slot is occupied ") (IF (EQ ITEM (GET-IK-KEY VALUE KEY-ACCESSOR)) (GO FOUND) (IL:* IL:|;;| "Else try again") )) (T (IL:* IL:|;;| "Null slot") (RETURN NIL))) (GO LP) FOUND (RETURN VALUE))) (DEFUN PUT-IMPLICIT-KEY-HASH (ITEM IK-HASH-TABLE NEW-VALUE) (IL:* IL:|;;| "Puthash nil is equivalent to remhash for these tables") (IF (NOT (TYPEP IK-HASH-TABLE 'IMPLICIT-KEY-HASH-TABLE)) (ERROR "Not an implicit key hash table: ~s" IK-HASH-TABLE)) (PROG ((BITS (IL:\\EQHASHINGBITS ITEM)) (LIMIT (IK-HASH-LAST-INDEX IK-HASH-TABLE)) (BASE (IK-HASH-BASE IK-HASH-TABLE)) (KEY-ACCESSOR (IK-HASH-KEY-ACCESSOR IK-HASH-TABLE)) (DELETED-INDICATOR *DELETED-IMPLICIT-HASH-SLOT*) INDEX VALUE FIRST-INDEX REPROBE DELETED-SLOT-INDEX) PHTOP (IL:* IL:|;;| "Handle first probe outside loop in case it wins") (SETQ INDEX (LOGAND BITS LIMIT)) (SETQ VALUE (GET-IK-VALUE BASE INDEX)) (COND ((EQ VALUE DELETED-INDICATOR) (IL:* IL:|;;| "Found a deleted slot -- continue lookup") (SETQ DELETED-SLOT-INDEX INDEX)) (VALUE (IL:* IL:|;;| "Slot is occupied") (IF (EQ ITEM (GET-IK-KEY VALUE KEY-ACCESSOR)) (GO FOUND) (IL:* IL:|;;| "else try again") )) (T (IL:* IL:|;;| "Empty slot") (GO ADDNEWENTRY))) (IL:* IL:|;;| "Chase reprobe chain") (SETQ FIRST-INDEX INDEX) (SETQ REPROBE (REPROBE BITS LIMIT)) LP (SETQ INDEX (LOGAND (16BIT-+ INDEX REPROBE) LIMIT)) (WHEN (EQ INDEX FIRST-INDEX) (IL:* IL:|;;| "We don't allow full occupancy, so if we get to the beginning without finding an empty slot, we must have found a deleted one") (SETQ INDEX (OR DELETED-SLOT-INDEX (ERROR "No vacant slot in Implicit key hash table: ~s" IK-HASH-TABLE))) (GO ADDNEWENTRY)) (SETQ VALUE (GET-IK-VALUE BASE INDEX)) (COND ((EQ VALUE DELETED-INDICATOR) (IL:* IL:|;;| "Found a deleted slot -- continue lookup") (SETQ DELETED-SLOT-INDEX INDEX)) (VALUE (IL:* IL:|;;| "Slot is occupied") (IF (EQ ITEM (GET-IK-KEY VALUE KEY-ACCESSOR)) (GO FOUND) (IL:* IL:|;;| "else try again") )) (T (IL:* IL:|;;| "Empty slot") (IF DELETED-SLOT-INDEX (SETQ INDEX DELETED-SLOT-INDEX)) (GO ADDNEWENTRY))) (GO LP) FOUND (IL:UNINTERRUPTABLY (SETF (GET-IK-VALUE BASE INDEX) (OR NEW-VALUE DELETED-INDICATOR)) (IF (NULL NEW-VALUE) (DECF (IK-HASH-NUM-KEYS IK-HASH-TABLE)))) (RETURN NEW-VALUE) ADDNEWENTRY (IL:* IL:|;;| "Didn't find this item in table.") (IF (NULL NEW-VALUE) (IL:* IL:|;;| "Nothing to add") (RETURN NEW-VALUE)) (WHEN (EQ 0 (IK-HASH-NULL-SLOTS IK-HASH-TABLE)) (IL:UNINTERRUPTABLY (LET* ((NUM-SLOTS (IK-HASH-NUM-SLOTS IK-HASH-TABLE)) (NEW-ARRAY (IMPLICIT-KEY-REHASH IK-HASH-TABLE (MAKE-IMPLICIT-KEY-HASH-TABLE (IL:* IL:|;;| "1.5 times NUM-SLOTS") (+ NUM-SLOTS (ASH (1+ NUM-SLOTS) -1)) KEY-ACCESSOR)))) (SETQ IK-HASH-TABLE (ADJUST-IMPLICIT-KEY-HASH IK-HASH-TABLE NEW-ARRAY)) (IL:* IL:|;;| "update local state") (SETQ LIMIT (IK-HASH-LAST-INDEX IK-HASH-TABLE)) (SETQ BASE (IK-HASH-BASE IK-HASH-TABLE)) (IL:* IL:|;;| "Non-NIL DELSLOT is an index into the old array") (SETQ DELETED-SLOT-INDEX NIL))) (GO PHTOP)) (IL:UNINTERRUPTABLY (IF (NOT (EQ INDEX DELETED-SLOT-INDEX)) (DECF (IK-HASH-NULL-SLOTS IK-HASH-TABLE))) (INCF (IK-HASH-NUM-KEYS IK-HASH-TABLE)) (SETF (GET-IK-VALUE BASE INDEX) NEW-VALUE)) (RETURN NEW-VALUE))) (DEFUN IMPLICIT-KEY-MAP-HASH (FN IK-HASH-TABLE) (IF (NOT (TYPEP IK-HASH-TABLE 'IMPLICIT-KEY-HASH-TABLE)) (ERROR "Not an implicit key hash table: ~s" IK-HASH-TABLE)) (LET* ((BASE (IK-HASH-BASE IK-HASH-TABLE)) (LAST-INDEX (1+ (IK-HASH-LAST-INDEX IK-HASH-TABLE))) (LAST-ADDRESS (IL:\\ADDBASE (IL:\\ADDBASE BASE LAST-INDEX) LAST-INDEX)) (KEY-ACCESSOR (IK-HASH-KEY-ACCESSOR IK-HASH-TABLE)) (NULL-SLOT-INDICATOR *DELETED-IMPLICIT-HASH-SLOT*) VALUE) (LOOP (IF (EQ BASE LAST-ADDRESS) (RETURN NIL)) (SETQ VALUE (IL:\\GETBASEPTR BASE 0)) (IF (AND VALUE (NOT (EQ VALUE NULL-SLOT-INDICATOR))) (FUNCALL FN VALUE (GET-IK-KEY VALUE KEY-ACCESSOR))) (SETQ BASE (IL:\\ADDBASE BASE 2))))) (DEFUN CLEAR-IMPLICIT-KEY-HASH (IK-HASH-TABLE) (IF (NOT (TYPEP IK-HASH-TABLE 'IMPLICIT-KEY-HASH-TABLE)) (ERROR "Not an implicit key hash table: ~s" IK-HASH-TABLE)) (LET* ((BASE (IK-HASH-BASE IK-HASH-TABLE)) (LAST-INDEX (1+ (IK-HASH-LAST-INDEX IK-HASH-TABLE))) (LAST-ADDRESS (IL:\\ADDBASE (IL:\\ADDBASE BASE LAST-INDEX) LAST-INDEX))) (IL:UNINTERRUPTABLY (LOOP (IF (EQ BASE LAST-ADDRESS) (RETURN NIL)) (IL:\\RPLPTR BASE 0 NIL) (SETQ BASE (IL:\\ADDBASE BASE 2))) (SETF (IK-HASH-NULL-SLOTS IK-HASH-TABLE) (IK-HASH-NUM-SLOTS IK-HASH-TABLE)) (SETF (IK-HASH-NUM-KEYS IK-HASH-TABLE) 0)) IK-HASH-TABLE)) (DEFUN IMPLICIT-KEY-REHASH (FROM-TABLE TO-TABLE) (IF (NOT (TYPEP FROM-TABLE 'IMPLICIT-KEY-HASH-TABLE)) (ERROR "Not an implicit key hash table: ~s" FROM-TABLE)) (CLEAR-IMPLICIT-KEY-HASH TO-TABLE) (IF (NOT (< (IK-HASH-NUM-SLOTS FROM-TABLE) (IK-HASH-NUM-SLOTS TO-TABLE))) (ERROR "To table too small: ~s" TO-TABLE)) (LET* ((FROM-BASE (IK-HASH-BASE FROM-TABLE)) (FROM-LAST-INDEX (1+ (IK-HASH-LAST-INDEX FROM-TABLE))) (LAST-ADDRESS (IL:\\ADDBASE (IL:\\ADDBASE FROM-BASE FROM-LAST-INDEX) FROM-LAST-INDEX)) (KEY-ACCESSOR (IK-HASH-KEY-ACCESSOR FROM-TABLE)) (NULL-SLOT-INDICATOR *DELETED-IMPLICIT-HASH-SLOT*) VALUE) (LOOP (IF (EQ FROM-BASE LAST-ADDRESS) (RETURN TO-TABLE)) (SETQ VALUE (IL:\\GETBASEPTR FROM-BASE 0)) (IF (AND VALUE (NOT (EQ VALUE NULL-SLOT-INDICATOR))) (PUT-IMPLICIT-KEY-HASH (GET-IK-KEY VALUE KEY-ACCESSOR) TO-TABLE VALUE)) (SETQ FROM-BASE (IL:\\ADDBASE FROM-BASE 2))))) (DEFUN ADJUST-IMPLICIT-KEY-HASH (OLD-IK-TABLE NEW-IK-TABLE) (IL:UNINTERRUPTABLY (SETF (IK-HASH-BASE OLD-IK-TABLE) (IK-HASH-BASE NEW-IK-TABLE)) (SETF (IK-HASH-LAST-INDEX OLD-IK-TABLE) (IK-HASH-LAST-INDEX NEW-IK-TABLE)) (SETF (IK-HASH-NUM-SLOTS OLD-IK-TABLE) (IK-HASH-NUM-SLOTS NEW-IK-TABLE)) (SETF (IK-HASH-NUM-KEYS OLD-IK-TABLE) (IK-HASH-NUM-KEYS NEW-IK-TABLE)) (SETF (IK-HASH-NULL-SLOTS OLD-IK-TABLE) (IK-HASH-NULL-SLOTS NEW-IK-TABLE)) (SETF (IK-HASH-KEY-ACCESSOR OLD-IK-TABLE) (IK-HASH-KEY-ACCESSOR NEW-IK-TABLE))) OLD-IK-TABLE) (DEFMACRO GET-IK-VALUE (BASE INDEX) `(IL:\\GETBASEPTR ,BASE (IL:LLSH ,INDEX 1))) (DEFMACRO PUT-IK-VALUE (BASE INDEX NEW-VALUE) `(IL:\\RPLPTR ,BASE (IL:LLSH ,INDEX 1) ,NEW-VALUE)) (DEFMACRO GET-IK-KEY (VALUE KEY-ACCESSOR) (ONCE-ONLY (VALUE KEY-ACCESSOR) `(IF (EQ KEY-ACCESSOR :FIRST) (IL:\\GETBASEPTR ,VALUE 0) (FUNCALL ,KEY-ACCESSOR ,VALUE)))) (DEFMACRO REPROBE (BITS LAST-INDEX) `(LOGIOR (LOGAND (LOGXOR ,BITS (IL:LRSH ,BITS 8)) (MIN 63 ,LAST-INDEX)) 1)) (DEFMACRO 16BIT-+ (A B) `(IL:\\LOLOC (IL:\\ADDBASE ,A ,B))) (DEFSETF GET-IMPLICIT-KEY-HASH PUT-IMPLICIT-KEY-HASH) (DEFSETF GET-IK-VALUE PUT-IK-VALUE) (DEFINE-FILE-ENVIRONMENT "IMPLICIT-KEY-HASH" :READTABLE "XCL" :PACKAGE "XCL" :COMPILER :COMPILE-FILE) (IL:PUTPROPS IL:IMPLICIT-KEY-HASH IL:COPYRIGHT ("Venue & Xerox Corporation" 1987 1988 1990)) (IL:DECLARE\: IL:DONTCOPY (IL:FILEMAP (NIL))) IL:STOP