Improve calculation of hash values.
This commit is contained in:
parent
d473552806
commit
173c117d86
50
gc.c
50
gc.c
|
|
@ -484,9 +484,9 @@ builtin_fn_t *get_builtin_fn(value_t 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)
|
||||
{
|
||||
|
|
@ -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)
|
||||
{
|
||||
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 };
|
||||
|
||||
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)
|
||||
{
|
||||
if (v == sv->value)
|
||||
|
|
@ -509,23 +528,8 @@ static value_t _get_hash_value(value_t v, seen_value_t *seen)
|
|||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_object(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))
|
||||
if (is_pair(v))
|
||||
{
|
||||
/* Lists and trees compare by value, not reference. */
|
||||
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. */
|
||||
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))
|
||||
{
|
||||
/* 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
value_t get_hash_value(value_t v)
|
||||
|
|
|
|||
Loading…
Reference in New Issue