diff --git a/src/__internal/include.h b/src/__internal/include.h index 9bed823..562bde3 100644 --- a/src/__internal/include.h +++ b/src/__internal/include.h @@ -65,7 +65,7 @@ typedef vtype_hash hash_t; extern int libcdsb_vtype_compare_values(const void* s0, vtype t0, const void* s1, vtype t1); extern int libcdsb_vtype_compare_values_eq(const void* s0, const void* s1, vtype t); -extern hash_t libcdsb_vtype_hash(void* value, vtype type); +extern hash_t libcdsb_vtype_hash(const void* value, vtype type); #define vtype_stringify libcdsb_vtype_stringify #define vtype_name libcdsb_vtype_name diff --git a/src/vtype.c b/src/vtype.c index a6108c4..45663d8 100644 --- a/src/vtype.c +++ b/src/vtype.c @@ -31,14 +31,32 @@ static ldbl_t normalize_value(const void* v, vtype t) { } static hash_t ldouble_hash(ldbl_t s) { - hash_t x, y; - ldbl_t m; + hash_t hash; - m = modfl(s, &s); - x = llrintl(s); - y = floorl(m * 10000); + if (sizeof(hash_t) == sizeof(u64_t)) { + if (is_little_endian) { + hash = *((u64_t*)&s); + hash ^= *((u16_t*)(((u64_t*)&s) + 1)); + } else { + memcpy(&hash, ((char*)&s) + sizeof(u16_t), sizeof(u64_t)); + hash ^= *((u16_t*)&s); + } + } else { + if (is_little_endian) { + hash = *((u32_t*)&s) ^ *((u32_t*)&s + 1); + hash ^= *((u16_t*)(((u32_t*)&s) + 2)); + } else { + u32_t x; - return x ^ y; + memcpy(&hash, ((char*)&s) + sizeof(u16_t), sizeof(u32_t)); + memcpy(&x, ((char*)&s) + sizeof(u16_t) + sizeof(u32_t), sizeof(u32_t)); + + hash ^= x; + hash ^= *((u16_t*)&s); + } + } + + return hash; } /*#####################################################################################################################*/ @@ -99,7 +117,7 @@ int libcdsb_vtype_compare_values_eq(const void* s0, const void* s1, vtype t) { /*#####################################################################################################################*/ -hash_t libcdsb_vtype_hash(void* v, vtype t) { +hash_t libcdsb_vtype_hash(const void* v, vtype t) { switch (t) { default: abort(); @@ -116,7 +134,11 @@ hash_t libcdsb_vtype_hash(void* v, vtype t) { case VTYPE_POINTER: if (!is_x64) goto x86_ptr; case VTYPE_INT64: - case VTYPE_UINT64: return (hash_t)(*(u64_t*)v); + case VTYPE_UINT64: if (sizeof(hash_t) == sizeof(u64_t)) { + return (hash_t)(*(u64_t*)v); + } else { + return (hash_t)(*(u32_t*)v) ^ (*((u32_t*)v + 1)); + } case VTYPE_STRING: return string_hash(v); case VTYPE_ARRAY: return array_hash(v);