4
;;; Created: 2005-03-19 by Zach Beane <xach@xach.com>
6
;;; A hashtable whose keys and values are known to be fixnums^Wof a
7
;;; fixed, relatively small size. Sadly, not small enough to be
8
;;; fixnums on LispWorks.
10
;;; This table isn't general; it assumes that the compressor never
11
;;; uses zero for a key.
13
;;; Copyright (c) 2005 Zachary Beane, All Rights Reserved
15
;;; Redistribution and use in source and binary forms, with or without
16
;;; modification, are permitted provided that the following conditions
19
;;; * Redistributions of source code must retain the above copyright
20
;;; notice, this list of conditions and the following disclaimer.
22
;;; * Redistributions in binary form must reproduce the above
23
;;; copyright notice, this list of conditions and the following
24
;;; disclaimer in the documentation and/or other materials
25
;;; provided with the distribution.
27
;;; THIS SOFTWARE IS PROVIDED BY THE AUTHOR 'AS IS' AND ANY EXPRESSED
28
;;; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
29
;;; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30
;;; ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
31
;;; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32
;;; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
33
;;; GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34
;;; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
35
;;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
36
;;; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
37
;;; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39
;;; $Id: fixhash.lisp,v 1.7 2005/04/01 21:55:24 xach Exp $
43
(:export :make-fixhash-table
49
(deftype fixhash-integer ()
50
"#xFFFFFF is out of fixnum range on LispWorks."
51
'(integer 0 #xFFFFFF))
59
(defstruct fixhash-table
60
(level 0 :type fixnum)
61
(size 4096 :type fixnum)
62
(keys/values (make-array (* 4096 2)
63
:element-type 'fixhash-integer
65
:type (simple-array fixhash-integer (*)))
66
(last-key 0 :type fixhash-integer)
67
(last-key-pos 0 :type fixnum))
69
(defmethod print-object ((fixhash-table fixhash-table) stream)
70
(print-unreadable-object (fixhash-table stream :type t :identity t)
71
(format stream "~D/~D"
72
(fixhash-table-level fixhash-table)
73
(fixhash-table-size fixhash-table))))
76
(declare (optimize (speed 3) (safety 0)))
77
(let ((level (fixhash-table-level table))
78
(keys/values (fixhash-table-keys/values table))
79
(size (fixhash-table-size table)))
81
(error "Hash table full"))
82
(let* ((new-size (svref *sizes* (incf level)))
83
(new-keys/values (make-array (the fixnum (* new-size 2))
85
:element-type 'fixhash-integer)))
86
(dotimes (i (* size 2))
87
(setf (aref new-keys/values i) (aref keys/values i)))
88
(setf (fixhash-table-keys/values table) new-keys/values
89
(fixhash-table-size table) new-size
90
(fixhash-table-level table) level))))
92
(defun getfixhash (k fixhash-table)
93
(declare (optimize (speed 3) (safety 0) (debug 0)
94
#+lispworks (hcl:fixnum-safety 0))
95
(type fixhash-integer k))
96
(let* ((size (fixhash-table-size fixhash-table))
99
(h2 (logior 1 (mod k (1- size))))
102
(table (fixhash-table-keys/values fixhash-table)))
103
(declare (type (integer 0 131072) size mask h1 h2 j i*h2))
104
(dotimes (i size (and (rehash fixhash-table) 0))
107
(setf j (ash (logand mask (+ h1 i*h2)) 1))
108
(let ((kt (aref table j)))
110
(return (aref table (1+ j))))
112
(setf (fixhash-table-last-key fixhash-table) k
113
(fixhash-table-last-key-pos fixhash-table) j)
116
(defun (setf getfixhash) (new-value k fixhash-table)
117
(declare (optimize (speed 3) (safety 0) (debug 0)
118
#+lispworks (hcl:fixnum-safety 0))
119
(type fixhash-integer new-value k))
120
(let ((last-key (fixhash-table-last-key fixhash-table))
121
(last-key-pos (fixhash-table-last-key-pos fixhash-table))
122
(table (fixhash-table-keys/values fixhash-table)))
124
(setf (aref table last-key-pos) k
125
(aref table (1+ last-key-pos)) new-value)
126
(let* ((size (fixhash-table-size fixhash-table))
129
(h2 (logior 1 (mod k (1- size))))
132
(declare (type (integer 0 131072) h2 h1 i*h2 size mask))
136
(setf j (ash (logand mask (+ h1 i*h2)) 1))
137
(let ((kt (aref table j)))
138
(when (or (= k kt) (zerop kt))
139
(setf (aref table j) k
140
(aref table (1+ j)) new-value)
141
(return new-value))))))))
143
(defun clrfixhash (fixhash-table)
144
(declare (optimize (speed 3) (safety 0)
145
#+lispworks (hcl:fixnum-safety 0)))
146
(let ((table (fixhash-table-keys/values fixhash-table)))
147
(dotimes (i (length table))
149
(setf (aref table i) 0)))