Permalink
Browse files

Improve hashing of bignums

  • Loading branch information...
1 parent 9c98781 commit 209a4d2b99d548a9da55f59c414f43342c2a779d @feeley feeley committed Mar 10, 2014
Showing with 5 additions and 1 deletion.
  1. +5 −1 lib/_system.scm
View
@@ -380,7 +380,11 @@
(macro-number-dispatch obj
(##eq?-hash obj) ;; obj = not a number
(##fxand obj (macro-max-fixnum32)) ;; obj = fixnum
- (##modulo obj 331804481) ;; obj = bignum
+ (let loop ((i (##fx- (##bignum.mdigit-length obj) 1)) (h 0)) ;; obj = bignum
+ (if (##fx< i 0)
+ h
+ (loop (##fx- i 1)
+ (combine (##bignum.mdigit-ref obj i) h))))
(combine (hash (macro-ratnum-numerator obj)) ;; obj = ratnum
(hash (macro-ratnum-denominator obj)))
(combine (##u16vector-ref obj 0) ;; obj = flonum

4 comments on commit 209a4d2

Collaborator

gambiteer replied Mar 10, 2014

Marc: It appears, upon inspecting the new code, that for all powers of 2 the new hash function will give as results only 16 different values on a 32-bit machine (perhaps 64, depending on how many zero mdigits at the top of the bignum).

Would it be better to start the loop with h = (##bignum.mdigit-length obj)?

Collaborator

gambiteer replied Mar 10, 2014

Try this at home:

(define (iota n) (if (zero? n) '() (cons n (iota (- n 1)))))
(map ##eqv?-hash (map (lambda (x) (expt 2 x)) (iota 600)))

If you print it and sort it, you find that the most common hashes (more than one hit) are
2 142606336
2 192937984
2 276824064
2 411041792
2 4194304
2 432013312
2 461373440
2 58720256
3 327155712
3 8388608
4 285212672
4 385875968
5 117440512
5 16777216
9 134217728
9 234881024
9 33554432
9 402653184
9 469762048
9 67108864
18 268435456
248 0

That's the count, followed by the hash. So over half the hashes are one of the following

  9  33554432
  9  402653184
  9  469762048
  9  67108864
 18  268435456
248  0
Owner

feeley replied Sep 16, 2014

As far as I can tell this has been fixed. The new hashing function combines the digits differently.

Collaborator

gambiteer replied Sep 17, 2014

OK.

Please sign in to comment.