repair for hash-keys-subset?

When comparing a part of a hamt that is a collision node versus a
subtree node, a "hash code" was extracted from the collision node ---
but that's really a code for an integer key is that used for the
collision element. The comparison should instead use a code extracted
from the reference to the collision node (which is the code that is
common to all colliding keys).
This commit is contained in:
Matthew Flatt 2017-04-26 15:27:39 -06:00
parent f8aeed279b
commit 6de3659664
2 changed files with 41 additions and 2 deletions

View File

@ -35,6 +35,44 @@
#hash([one . 1] [two . 2] [three . 3] [four . 4]))
h))
(let ()
(struct a (n m)
#:property
prop:equal+hash
(list (lambda (a b eql) (and (= (a-n a) (a-n b))
(= (a-m a) (a-m b))))
(lambda (a hc) (a-n a))
(lambda (a hc) (a-n a))))
(define ht0 (hash (a 1 0) #t))
;; A hash table with two keys that have the same hash code
(define ht1 (hash (a 1 0) #t
(a 1 2) #t))
;; Another hash table with the same two keys, plus another
;; with an extra key whose hash code is different but the
;; same in the last 5 bits:
(define ht2 (hash (a 1 0) #t
(a 1 2) #t
(a 33 0) #t))
;; A hash table with no collision, but the same last
;; 5 bits for both keys:
(define ht3 (hash (a 1 0) #t
(a 33 0) #t))
;; Subset must compare a collision node with a subtree node (that
;; contains a collision node):
(test #t hash-keys-subset? ht1 ht2)
(test #t hash-keys-subset? ht3 ht2)
(test #t hash-keys-subset? ht0 ht3)
(test #t hash-keys-subset? ht0 ht2)
(test #t hash-keys-subset? ht0 ht1)
(test #f hash-keys-subset? ht2 ht1)
(test #f hash-keys-subset? ht2 ht0)
(test #f hash-keys-subset? ht1 ht0)
(test #f hash-keys-subset? ht1 ht3))
(let ()
(define-syntax (define-hash-iterations-tester stx)
(syntax-case stx ()

View File

@ -89,9 +89,10 @@ HAMT_NONGCING int HAMT_SUBSET_OF(Scheme_Hash_Tree *t1, Scheme_Hash_Tree *t2, int
if (HASHTR_SUBTREEP(k2)) {
/* check each element of collision */
uintptr_t code;
code = _mzHAMT_CODE(t1, pos1, popcount1);
for (i = ((Scheme_Hash_Tree *)k1)->count; i--; ) {
uintptr_t code;
hamt_at_index(((Scheme_Hash_Tree *)k1), i, &key, HAMT_IF_VAL(&val, NULL), &code);
hamt_at_index(((Scheme_Hash_Tree *)k1), i, &key, HAMT_IF_VAL(&val, NULL), NULL);
if (!HAMT_ELEMENT_OF(key, HAMT_IF_VAL(val, NULL), code,
(Scheme_Hash_Tree *)k2,
shift + mzHAMT_LOG_WORD_SIZE,