made cons hashing tail recursive on cdrs

plus one more test
This commit is contained in:
JeffBezanson 2009-05-20 18:52:09 +00:00
parent ff650e3049
commit 99c17feac1
2 changed files with 26 additions and 15 deletions

View File

@ -308,21 +308,24 @@ static uptrint_t bounded_hash(value_t a, int bound, int *oob)
return h; return h;
case TAG_CONS: case TAG_CONS:
do {
if (bound <= 0) { if (bound <= 0) {
*oob = 1; *oob = 1;
return 1; return h;
} }
h = bounded_hash(car_(a), bound/2, oob); h = MIX(h, bounded_hash(car_(a), bound/2, &oob2));
// bounds balancing: try to share the bounds efficiently // bounds balancing: try to share the bounds efficiently
// between the car and cdr so we can hash better when a list is // so we can hash better when a list is cdr-deep (a common case)
// car-shallow and cdr-deep (a common case) or vice-versa. if (oob2)
if (*oob)
bound/=2; bound/=2;
else else
bound--; bound--;
h = MIX(h, bounded_hash(cdr_(a), bound, &oob2)+2);
// recursive OOB propagation. otherwise this case is slow: // recursive OOB propagation. otherwise this case is slow:
// (hash '#2=('#0=(#1=(#1#) . #0#) . #2#)) // (hash '#2=((#0=(#1=(#1#) . #0#)) . #2#))
*oob = *oob || oob2;
a = cdr_(a);
} while (iscons(a));
h = MIX(h, bounded_hash(a, bound-1, &oob2)+2);
*oob = *oob || oob2; *oob = *oob || oob2;
return h; return h;
} }

View File

@ -130,6 +130,14 @@
(hash '#0=((1 . #0#) . #0#)) (hash '#0=((1 . #0#) . #0#))
(hash '#1=((1 . #1#) (2 . #1#) . #1#))))) (hash '#1=((1 . #1#) (2 . #1#) . #1#)))))
(assert (equal?
(hash '(#0=(#0#) 0))
(hash '(#1=(((((#1#))))) 0))))
(assert (not (equal?
(hash '(#0=(#0#) 0))
(hash '(#1=(((((#1#))))) 1)))))
(assert (equal? (assert (equal?
(hash #0=[1 [2 [#0#]] 3]) (hash #0=[1 [2 [#0#]] 3])
(hash #1=[1 [2 [[1 [2 [#1#]] 3]]] 3]))) (hash #1=[1 [2 [[1 [2 [#1#]] 3]]] 3])))