[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
hash bug, Yuasa fix
A bug report:
From boyer Sat Mar 11 22:06:44 1989
To: yuasa%tutics.tut.junet%utokyo-relay.csnet@RELAY.CS.NET
Subject: obscure hash bug?
Reply-to: boyer@cli.com
Surely the fourth form below should not return b1!
(setq ht (make-hash-table :test #'equal :size 1))
(setf (gethash 'a ht) 'a1)
(setf (gethash 'b ht) 'b1)
(gethash 'c ht)
A bug fix:
Date: Thu, 16 Mar 89 22:23:05 jst
From: Taiichi Yuasa <yuasa%tutics.tut.junet%utokyo-relay.csnet@RELAY.CS.NET>
To: boyer@CLI.COM
Subject: Re: obscure hash bug?
>Date: Sat, 11 Mar 89
>From: boyer@cli.com
>Subject: obscure hash bug?
Yes, there were bugs in hash functions in file c/hash.d. To fix these
bugs,
replace the definitions of the C functions gethash, sethash, and
extend_hashtable, and add a new C function gethash1, as follows.
struct htent *
gethash(key, hashtable)
object key;
object hashtable;
{
enum httest htest;
int hsize;
struct htent *e;
object hkey;
int i, j = -1, k;
bool b;
htest = (enum httest)hashtable->ht.ht_test;
hsize = hashtable->ht.ht_size;
if (htest == htt_eq)
i = (int)key / 4;
else if (htest == htt_eql)
i = hash_eql(key);
else if (htest == htt_equal)
i = hash_equal(key);
i &= 0x7fffffff;
for (i %= hsize, k = 0; k < hsize; i = (i + 1) % hsize, k++) {
e = &hashtable->ht.ht_self[i];
hkey = e->hte_key;
if (hkey == OBJNULL) {
if (e->hte_value == OBJNULL)
if (j < 0)
return(e);
else
return(&hashtable->ht.ht_self[j]);
else
if (j < 0)
j = i;
else
;
continue;
}
if (htest == htt_eq)
b = key == hkey;
else if (htest == htt_eql)
b = eql(key, hkey);
else if (htest == htt_equal)
b = equal(key, hkey);
if (b)
return(&hashtable->ht.ht_self[i]);
}
return(&hashtable->ht.ht_self[j]);
}
struct htent *
gethash1(key, hashtable)
object key;
object hashtable;
{
enum httest htest;
int i, hsize;
bool b;
htest = (enum httest)hashtable->ht.ht_test;
hsize = hashtable->ht.ht_size;
if (htest == htt_eq)
i = (int)key / 4;
else if (htest == htt_eql)
i = hash_eql(key);
else if (htest == htt_equal)
i = hash_equal(key);
i &= 0x7fffffff;
for (i %= hsize; ; i = (i + 1) % hsize)
if (hashtable->ht.ht_self[i].hte_key == OBJNULL)
return(&hashtable->ht.ht_self[i]);
}
sethash(key, hashtable, value)
object key, hashtable, value;
{
int i;
bool over;
struct htent *e;
e = gethash(key, hashtable);
if (e->hte_key != OBJNULL) {
e->hte_value = value;
return;
}
i = hashtable->ht.ht_nent + 1;
if (i >= hashtable->ht.ht_size)
over = TRUE;
else if (type_of(hashtable->ht.ht_rhthresh) == t_fixnum)
over = i >= fix(hashtable->ht.ht_rhthresh);
else if (type_of(hashtable->ht.ht_rhthresh) == t_shortfloat)
over =
i >= hashtable->ht.ht_size * sf(hashtable->ht.ht_rhthresh);
else if (type_of(hashtable->ht.ht_rhthresh) == t_longfloat)
over =
i >= hashtable->ht.ht_size * lf(hashtable->ht.ht_rhthresh);
if (over) {
extend_hashtable(hashtable);
e = gethash1(key, hashtable);
}
hashtable->ht.ht_nent++;
e->hte_key = key;
e->hte_value = value;
}
extend_hashtable(hashtable)
object hashtable;
{
object old, key;
int old_size, new_size, i;
struct htent *e;
old_size = hashtable->ht.ht_size;
if (type_of(hashtable->ht.ht_rhsize) == t_fixnum)
new_size = old_size + fix(hashtable->ht.ht_rhsize);
else if (type_of(hashtable->ht.ht_rhsize) == t_shortfloat)
new_size = old_size * sf(hashtable->ht.ht_rhsize);
else if (type_of(hashtable->ht.ht_rhsize) == t_longfloat)
new_size = old_size * lf(hashtable->ht.ht_rhsize);
if (new_size <= old_size)
new_size = old_size + 1;
old = alloc_object(t_hashtable);
old->ht = hashtable->ht;
vs_push(old);
hashtable->ht.ht_self = NULL;
hashtable->ht.ht_size = new_size;
if (type_of(hashtable->ht.ht_rhthresh) == t_fixnum)
hashtable->ht.ht_rhthresh =
make_fixnum(fix(hashtable->ht.ht_rhthresh) +
(new_size - old->ht.ht_size));
hashtable->ht.ht_self =
(struct htent *)alloc_relblock(new_size * sizeof(struct htent));
for (i = 0; i < new_size; i++) {
hashtable->ht.ht_self[i].hte_key = OBJNULL;
hashtable->ht.ht_self[i].hte_value = OBJNULL;
}
for (i = 0; i < old_size; i++)
if ((key = old->ht.ht_self[i].hte_key) != OBJNULL) {
e = gethash1(key, hashtable);
e->hte_key = key;
e->hte_value = old->ht.ht_self[i].hte_value;
}
vs_pop;
}
--- Taiichi