12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182 |
- ; Part of Scheme 48 1.9. See file COPYING for notices and license.
- ; Authors: Mike Sperber
- ; Looking up in an eq? table that's known in advance.
- ; Keys can't be #f.
- ; Based on the idea described in Will Clinger's paper at the
- ; 2005 Scheme Workshop.
- (define-record-type constant-table :constant-table
- (really-make-constant-table hash-function
- keys values
- max-work)
- constant-table?
- (hash-function constant-table-hash-function)
- (keys constant-table-keys)
- (values constant-table-values)
- (max-work constant-table-max-work))
- (define (table-bits entry-count)
- ;; upper approximation for log2(entry-count)
- (inexact->exact (round (* 2 (log (+ entry-count 1))))))
- (define (shorten-vector vec size)
- (if (= size (vector-length vec))
- vec
- (do ((new (make-vector size))
- (i 0 (+ 1 i)))
- ((= i size) new)
- (vector-set! new i (vector-ref vec i)))))
- (define (make-constant-table entries-alist hash-function)
- (let* ((entry-count (length entries-alist))
- (bit-count (table-bits entry-count))
- (modulus (expt 2 bit-count))
- (size (* 2 modulus))
- (mask (- modulus 1))
- (keys (make-vector size #f))
- (values (make-vector size #f))
- (max-index 0)
- (max-work 0))
- (define (compute-index key)
- (let loop ((index (bitwise-and (hash-function key) mask))
- (work 0))
- (if (not (vector-ref keys index))
- (begin
- (set! max-work (max work max-work))
- (set! max-index (max index max-index))
- index)
- (loop (+ 1 index) (+ 1 work)))))
- (for-each (lambda (p)
- (let ((key (car p))
- (val (cdr p)))
- (let ((index (compute-index key)))
- (vector-set! keys index key)
- (vector-set! values index val))))
- entries-alist)
- (really-make-constant-table
- (lambda (key)
- (bitwise-and (hash-function key) mask))
- (shorten-vector keys (+ 1 max-index))
- (shorten-vector values (+ 1 max-index))
- max-work)))
- (define (constant-table-lookup table key)
- (let ((hash ((constant-table-hash-function table) key))
- (keys (constant-table-keys table)))
- (let ((max-index (min (+ hash (constant-table-max-work table))
- (- (vector-length keys) 1))))
- (let loop ((index hash))
- (cond
- ((> index max-index) #f)
- ((eq? key (vector-ref keys index))
- (vector-ref (constant-table-values table) index))
- (else
- (loop (+ 1 index))))))))
|