diff options
| author | Tom Tromey | 2018-08-04 11:08:31 -0600 |
|---|---|---|
| committer | Tom Tromey | 2018-08-04 11:08:31 -0600 |
| commit | 1303f8a4806fb170c14375c53b0f79d03e288eb3 (patch) | |
| tree | e840c741418d06d6546f5dc90f387b3680990d49 | |
| parent | 91d505d8e2cd8a5736f4ed76bb5aabfbc4410e89 (diff) | |
| download | emacs-1303f8a4806fb170c14375c53b0f79d03e288eb3.tar.gz emacs-1303f8a4806fb170c14375c53b0f79d03e288eb3.zip | |
Fix hash functions for bignums
* src/fns.c (cmpfn_eql, hashfn_eql): Handle bignums.
(sxhash_bignum): New function.
(sxhash): Use it.
* test/src/fns-tests.el (test-bignum-hash): New test.
| -rw-r--r-- | src/fns.c | 34 | ||||
| -rw-r--r-- | test/src/fns-tests.el | 11 |
2 files changed, 41 insertions, 4 deletions
| @@ -3717,9 +3717,13 @@ cmpfn_eql (struct hash_table_test *ht, | |||
| 3717 | Lisp_Object key1, | 3717 | Lisp_Object key1, |
| 3718 | Lisp_Object key2) | 3718 | Lisp_Object key2) |
| 3719 | { | 3719 | { |
| 3720 | return (FLOATP (key1) | 3720 | if (FLOATP (key1) |
| 3721 | && FLOATP (key2) | 3721 | && FLOATP (key2) |
| 3722 | && XFLOAT_DATA (key1) == XFLOAT_DATA (key2)); | 3722 | && XFLOAT_DATA (key1) == XFLOAT_DATA (key2)) |
| 3723 | return true; | ||
| 3724 | return (BIGNUMP (key1) | ||
| 3725 | && BIGNUMP (key2) | ||
| 3726 | && mpz_cmp (XBIGNUM (key1)->value, XBIGNUM (key2)->value) == 0); | ||
| 3723 | } | 3727 | } |
| 3724 | 3728 | ||
| 3725 | 3729 | ||
| @@ -3775,7 +3779,9 @@ hashfn_equal (struct hash_table_test *ht, Lisp_Object key) | |||
| 3775 | static EMACS_UINT | 3779 | static EMACS_UINT |
| 3776 | hashfn_eql (struct hash_table_test *ht, Lisp_Object key) | 3780 | hashfn_eql (struct hash_table_test *ht, Lisp_Object key) |
| 3777 | { | 3781 | { |
| 3778 | return FLOATP (key) ? hashfn_equal (ht, key) : hashfn_eq (ht, key); | 3782 | return ((FLOATP (key) || BIGNUMP (key)) |
| 3783 | ? hashfn_equal (ht, key) | ||
| 3784 | : hashfn_eq (ht, key)); | ||
| 3779 | } | 3785 | } |
| 3780 | 3786 | ||
| 3781 | /* Value is a hash code for KEY for use in hash table H which uses as | 3787 | /* Value is a hash code for KEY for use in hash table H which uses as |
| @@ -4409,6 +4415,20 @@ sxhash_bool_vector (Lisp_Object vec) | |||
| 4409 | return SXHASH_REDUCE (hash); | 4415 | return SXHASH_REDUCE (hash); |
| 4410 | } | 4416 | } |
| 4411 | 4417 | ||
| 4418 | /* Return a hash for a bignum. */ | ||
| 4419 | |||
| 4420 | static EMACS_UINT | ||
| 4421 | sxhash_bignum (struct Lisp_Bignum *bignum) | ||
| 4422 | { | ||
| 4423 | size_t i, nlimbs = mpz_size (bignum->value); | ||
| 4424 | EMACS_UINT hash = 0; | ||
| 4425 | |||
| 4426 | for (i = 0; i < nlimbs; ++i) | ||
| 4427 | hash = sxhash_combine (hash, mpz_getlimbn (bignum->value, i)); | ||
| 4428 | |||
| 4429 | return SXHASH_REDUCE (hash); | ||
| 4430 | } | ||
| 4431 | |||
| 4412 | 4432 | ||
| 4413 | /* Return a hash code for OBJ. DEPTH is the current depth in the Lisp | 4433 | /* Return a hash code for OBJ. DEPTH is the current depth in the Lisp |
| 4414 | structure. Value is an unsigned integer clipped to INTMASK. */ | 4434 | structure. Value is an unsigned integer clipped to INTMASK. */ |
| @@ -4428,6 +4448,12 @@ sxhash (Lisp_Object obj, int depth) | |||
| 4428 | break; | 4448 | break; |
| 4429 | 4449 | ||
| 4430 | case Lisp_Misc: | 4450 | case Lisp_Misc: |
| 4451 | if (XMISCTYPE (obj) == Lisp_Misc_Bignum) | ||
| 4452 | { | ||
| 4453 | hash = sxhash_bignum (XBIGNUM (obj)); | ||
| 4454 | break; | ||
| 4455 | } | ||
| 4456 | FALLTHROUGH; | ||
| 4431 | case Lisp_Symbol: | 4457 | case Lisp_Symbol: |
| 4432 | hash = XHASH (obj); | 4458 | hash = XHASH (obj); |
| 4433 | break; | 4459 | break; |
diff --git a/test/src/fns-tests.el b/test/src/fns-tests.el index d440cfabda4..d560f0bb0d9 100644 --- a/test/src/fns-tests.el +++ b/test/src/fns-tests.el | |||
| @@ -602,4 +602,15 @@ | |||
| 602 | (should (equal x y)) | 602 | (should (equal x y)) |
| 603 | (should-not (eql x 0.0e+NaN)))) | 603 | (should-not (eql x 0.0e+NaN)))) |
| 604 | 604 | ||
| 605 | (ert-deftest test-bignum-hash () | ||
| 606 | "Test that hash tables work for bignums." | ||
| 607 | ;; Make two bignums that are eql but not eq. | ||
| 608 | (let ((b1 (1+ most-positive-fixnum)) | ||
| 609 | (b2 (1+ most-positive-fixnum))) | ||
| 610 | (dolist (test '(eq eql equal)) | ||
| 611 | (let ((hash (make-hash-table :test test))) | ||
| 612 | (puthash b1 t hash) | ||
| 613 | (should (eq (gethash b2 hash) | ||
| 614 | (funcall test b1 b2))))))) | ||
| 615 | |||
| 605 | (provide 'fns-tests) | 616 | (provide 'fns-tests) |