Improve calculation of hash values.

This commit is contained in:
Jesse D. McDonald 2011-12-08 17:14:04 -06:00
parent d473552806
commit 173c117d86
1 changed files with 51 additions and 51 deletions

50
gc.c
View File

@ -484,9 +484,9 @@ builtin_fn_t *get_builtin_fn(value_t v)
return _get_builtin_fn(v); return _get_builtin_fn(v);
} }
static size_t dbj2_hash(uint8_t *bytes, size_t size) static fixnum_t dbj2_hash(uint8_t *bytes, size_t size)
{ {
size_t hash = 5381; fixnum_t hash = 5381;
for (size_t i = 0; i < size; ++i) for (size_t i = 0; i < size; ++i)
{ {
@ -498,10 +498,29 @@ static size_t dbj2_hash(uint8_t *bytes, size_t size)
static value_t _get_hash_value(value_t v, seen_value_t *seen) static value_t _get_hash_value(value_t v, seen_value_t *seen)
{ {
if (is_float(v))
{
double d = _get_float(v);
return fixnum_value(dbj2_hash((uint8_t*)&d, sizeof d));
}
else if (is_byte_string(v))
{
byte_string_t *str = _get_byte_string(v);
return fixnum_value(dbj2_hash(str->bytes, str->size));
}
else if (is_builtin_fn(v))
{
return fixnum_value((uintptr_t)_get_builtin_fn(v) >> 2);
}
else if (!is_object(v))
{
/* Non-objects compare by value */
return fixnum_value(v + (v >> 2));
}
else
{
seen_value_t new_seen = { v, seen }; seen_value_t new_seen = { v, seen };
if (is_object(v) && !(is_float(v) || is_byte_string(v) || is_builtin_fn(v)))
{
for (seen_value_t *sv = seen; sv; sv = sv->prev) for (seen_value_t *sv = seen; sv; sv = sv->prev)
{ {
if (v == sv->value) if (v == sv->value)
@ -509,23 +528,8 @@ static value_t _get_hash_value(value_t v, seen_value_t *seen)
return 0; return 0;
} }
} }
}
if (!is_object(v)) if (is_pair(v))
{
/* Non-objects compare by value */
return fixnum_value(v ^ (v >> 2));
}
else if (is_float(v))
{
double d = _get_float(v);
return fixnum_value(dbj2_hash((uint8_t*)&d, sizeof d));
}
else if (is_builtin_fn(v))
{
return fixnum_value((uintptr_t)_get_builtin_fn(v) >> 2);
}
else if (is_pair(v))
{ {
/* Lists and trees compare by value, not reference. */ /* Lists and trees compare by value, not reference. */
value_t seed = fixnum_value(0); value_t seed = fixnum_value(0);
@ -538,11 +542,6 @@ static value_t _get_hash_value(value_t v, seen_value_t *seen)
/* Boxes compare by value, not by reference. */ /* Boxes compare by value, not by reference. */
return _get_hash_value(_get_box(v)->value, &new_seen); return _get_hash_value(_get_box(v)->value, &new_seen);
} }
else if (is_byte_string(v))
{
byte_string_t *str = _get_byte_string(v);
return fixnum_value(dbj2_hash(str->bytes, str->size));
}
else if (is_vector(v)) else if (is_vector(v))
{ {
/* Vectors compare by reference. */ /* Vectors compare by reference. */
@ -557,6 +556,7 @@ static value_t _get_hash_value(value_t v, seen_value_t *seen)
{ {
return _get_hash_value(_get_object(v)->tag, &new_seen); return _get_hash_value(_get_object(v)->tag, &new_seen);
} }
}
} }
value_t get_hash_value(value_t v) value_t get_hash_value(value_t v)