constant-table.scm 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. ; Part of Scheme 48 1.9. See file COPYING for notices and license.
  2. ; Authors: Mike Sperber
  3. ; Looking up in an eq? table that's known in advance.
  4. ; Keys can't be #f.
  5. ; Based on the idea described in Will Clinger's paper at the
  6. ; 2005 Scheme Workshop.
  7. (define-record-type constant-table :constant-table
  8. (really-make-constant-table hash-function
  9. keys values
  10. max-work)
  11. constant-table?
  12. (hash-function constant-table-hash-function)
  13. (keys constant-table-keys)
  14. (values constant-table-values)
  15. (max-work constant-table-max-work))
  16. (define (table-bits entry-count)
  17. ;; upper approximation for log2(entry-count)
  18. (inexact->exact (round (* 2 (log (+ entry-count 1))))))
  19. (define (shorten-vector vec size)
  20. (if (= size (vector-length vec))
  21. vec
  22. (do ((new (make-vector size))
  23. (i 0 (+ 1 i)))
  24. ((= i size) new)
  25. (vector-set! new i (vector-ref vec i)))))
  26. (define (make-constant-table entries-alist hash-function)
  27. (let* ((entry-count (length entries-alist))
  28. (bit-count (table-bits entry-count))
  29. (modulus (expt 2 bit-count))
  30. (size (* 2 modulus))
  31. (mask (- modulus 1))
  32. (keys (make-vector size #f))
  33. (values (make-vector size #f))
  34. (max-index 0)
  35. (max-work 0))
  36. (define (compute-index key)
  37. (let loop ((index (bitwise-and (hash-function key) mask))
  38. (work 0))
  39. (if (not (vector-ref keys index))
  40. (begin
  41. (set! max-work (max work max-work))
  42. (set! max-index (max index max-index))
  43. index)
  44. (loop (+ 1 index) (+ 1 work)))))
  45. (for-each (lambda (p)
  46. (let ((key (car p))
  47. (val (cdr p)))
  48. (let ((index (compute-index key)))
  49. (vector-set! keys index key)
  50. (vector-set! values index val))))
  51. entries-alist)
  52. (really-make-constant-table
  53. (lambda (key)
  54. (bitwise-and (hash-function key) mask))
  55. (shorten-vector keys (+ 1 max-index))
  56. (shorten-vector values (+ 1 max-index))
  57. max-work)))
  58. (define (constant-table-lookup table key)
  59. (let ((hash ((constant-table-hash-function table) key))
  60. (keys (constant-table-keys table)))
  61. (let ((max-index (min (+ hash (constant-table-max-work table))
  62. (- (vector-length keys) 1))))
  63. (let loop ((index hash))
  64. (cond
  65. ((> index max-index) #f)
  66. ((eq? key (vector-ref keys index))
  67. (vector-ref (constant-table-values table) index))
  68. (else
  69. (loop (+ 1 index))))))))