home *** CD-ROM | disk | FTP | other *** search
- ; "hash.scm", hashing functions for Scheme.
- ; Copyright (c) 1992, 1993, 1995 Aubrey Jaffer
- ;
- ;Permission to copy this software, to redistribute it, and to use it
- ;for any purpose is granted, subject to the following restrictions and
- ;understandings.
- ;
- ;1. Any copy made of this software must include this copyright notice
- ;in full.
- ;
- ;2. I have made no warrantee or representation that the operation of
- ;this software will be error-free, and I am under no obligation to
- ;provide any services, by way of maintenance, update, or otherwise.
- ;
- ;3. In conjunction with products arising from the use of this
- ;material, there shall be no use of my name in any advertising,
- ;promotional, or sales literature without prior written consent in
- ;each case.
-
- (define (hash:hash-char-ci char n)
- (modulo (char->integer (char-downcase char)) n))
-
- (define hash:hash-char hash:hash-char-ci)
-
- (define (hash:hash-symbol sym n)
- (hash:hash-string (symbol->string sym) n))
-
- ;;; This can overflow on implemenatations where inexacts have a larger
- ;;; range than exact integers.
- (define hash:hash-number
- (if (provided? 'inexact)
- (lambda (num n)
- (if (integer? num)
- (modulo (if (exact? num) num (inexact->exact num)) n)
- (hash:hash-string-ci
- (number->string (if (exact? num) (exact->inexact num) num))
- n)))
- (lambda (num n)
- (if (integer? num)
- (modulo num n)
- (hash:hash-string-ci (number->string num) n)))))
-
- (define (hash:hash-string-ci str n)
- (let ((len (string-length str)))
- (if (> len 5)
- (let loop ((h (modulo 264 n)) (i 5))
- (if (positive? i)
- (loop (modulo (+ (* h 256)
- (char->integer
- (char-downcase
- (string-ref str (modulo h len)))))
- n)
- (- i 1))
- h))
- (let loop ((h 0) (i (- len 1)))
- (if (>= i 0)
- (loop (modulo (+ (* h 256)
- (char->integer
- (char-downcase (string-ref str i))))
- n)
- (- i 1))
- h)))))
-
- (define hash:hash-string hash:hash-string-ci)
-
- (define (hash:hash obj n)
- (let hs ((d 10) (obj obj))
- (cond
- ((number? obj) (hash:hash-number obj n))
- ((char? obj) (modulo (char->integer (char-downcase obj)) n))
- ((symbol? obj) (hash:hash-symbol obj n))
- ((string? obj) (hash:hash-string obj n))
- ((vector? obj)
- (let ((len (vector-length obj)))
- (if (> len 5)
- (let lp ((h 1) (i (quotient d 2)))
- (if (positive? i)
- (lp (modulo (+ (* h 256)
- (hs 2 (vector-ref obj (modulo h len))))
- n)
- (- i 1))
- h))
- (let loop ((h (- n 1)) (i (- len 1)))
- (if (>= i 0)
- (loop (modulo (+ (* h 256) (hs (quotient d len)
- (vector-ref obj i)))
- n)
- (- i 1))
- h)))))
- ((pair? obj)
- (if (positive? d) (modulo (+ (hs (quotient d 2) (car obj))
- (hs (quotient d 2) (cdr obj)))
- n)
- 1))
- (else
- (modulo
- (cond
- ((null? obj) 256)
- ((boolean? obj) (if obj 257 258))
- ((eof-object? obj) 259)
- ((input-port? obj) 260)
- ((output-port? obj) 261)
- ((procedure? obj) 262)
- ((and (provided? 'RECORD) (record? obj))
- (let* ((rtd (record-type-descriptor obj))
- (fns (record-type-field-names rtd))
- (len (length fns)))
- (if (> len 5)
- (let lp ((h (modulo 266 n)) (i (quotient d 2)))
- (if (positive? i)
- (lp (modulo
- (+ (* h 256)
- (hs 2 ((record-accessor
- rtd (list-ref fns (modulo h len)))
- obj)))
- n)
- (- i 1))
- h))
- (let loop ((h (- n 1)) (i (- len 1)))
- (if (>= i 0)
- (loop (modulo
- (+ (* h 256)
- (hs (quotient d len)
- ((record-accessor
- rtd (list-ref fns (modulo h len)))
- obj)))
- n)
- (- i 1))
- h)))))
- (else 263))
- n)))))
-
- (define hash hash:hash)
- (define hashv hash:hash)
-
- ;;; Object-hash is somewhat expensive on copying GC systems (like
- ;;; PC-Scheme and MITScheme). We use it only on strings, pairs,
- ;;; vectors, and records. This also allows us to use it for both
- ;;; hashq and hashv.
-
- (if (provided? 'object-hash)
- (set! hashv
- (if (provided? 'record)
- (lambda (obj k)
- (if (or (string? obj) (pair? obj) (vector? obj) (record? obj))
- (modulo (object-hash obj) k)
- (hash:hash obj k)))
- (lambda (obj k)
- (if (or (string? obj) (pair? obj) (vector? obj))
- (modulo (object-hash obj) k)
- (hash:hash obj k))))))
-
- (define hashq hashv)
-