diff options
Diffstat (limited to 'modules/language/python/hash.scm')
-rw-r--r-- | modules/language/python/hash.scm | 48 |
1 files changed, 48 insertions, 0 deletions
diff --git a/modules/language/python/hash.scm b/modules/language/python/hash.scm new file mode 100644 index 0000000..ca5e32e --- /dev/null +++ b/modules/language/python/hash.scm @@ -0,0 +1,48 @@ +(define-module (language python hash) + #:use-module (oop goops) + #:use-module (oop pf-objects) + #:export (py-hash complexity xy pyhash-N)) + +(define-syntax-rule (aif it p x y) (let ((it p)) (if it x y))) + +(define N #xefffffffffffffff) +(define pyhash-N N) + +(define-inlinable (xy v seed) + (modulo + (logxor seed + (+ (py-hash v) + #x9e3779b9 + (ash seed 6) + (ash seed -2))) + N)) + +(define complexity 10) + +;; The default is to use guile's hash function +(define-method (py-hash x) (hash x N)) + +(define-method (py-hash (x <pair>)) + (define i 0) + (let lp ((x x)) + (if (< i complexity) + (begin + (set! i (+ i 1)) + (if (pair? x) + (xy (lp (car x)) (lp (cdr x))) + (py-hash x))) + 0))) + +(define-method (py-hash (x <vector>)) + (let ((n (min complexity (vector-length x)))) + (let lp ((i 0) (s 0)) + (if (< i n) + (lp (+ i 1) + (xy (py-hash (vector-ref x i)) s)) + s)))) + +(define-method (py-hash (x <p>)) + (aif it (ref x '__hash__) + (it) + (hash x complexity))) + |