aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTom Tromey2018-08-04 11:08:31 -0600
committerTom Tromey2018-08-04 11:08:31 -0600
commit1303f8a4806fb170c14375c53b0f79d03e288eb3 (patch)
treee840c741418d06d6546f5dc90f387b3680990d49
parent91d505d8e2cd8a5736f4ed76bb5aabfbc4410e89 (diff)
downloademacs-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.c34
-rw-r--r--test/src/fns-tests.el11
2 files changed, 41 insertions, 4 deletions
diff --git a/src/fns.c b/src/fns.c
index b14481d0101..ac93a2f6d81 100644
--- a/src/fns.c
+++ b/src/fns.c
@@ -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)
3775static EMACS_UINT 3779static EMACS_UINT
3776hashfn_eql (struct hash_table_test *ht, Lisp_Object key) 3780hashfn_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
4420static EMACS_UINT
4421sxhash_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)