diff options
Diffstat (limited to 'zix')
-rw-r--r-- | zix/digest.c | 90 | ||||
-rw-r--r-- | zix/digest.h | 26 |
2 files changed, 103 insertions, 13 deletions
diff --git a/zix/digest.c b/zix/digest.c index d6ceb0e..4fc7608 100644 --- a/zix/digest.c +++ b/zix/digest.c @@ -1,5 +1,5 @@ /* - Copyright 2012-2014 David Robillard <http://drobilla.net> + Copyright 2012-2020 David Robillard <http://drobilla.net> Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above @@ -20,23 +20,29 @@ # include <smmintrin.h> #endif +#include <assert.h> +#include <stdint.h> + +#ifdef __SSE4_2__ + +// SSE 4.2 CRC32 + ZIX_API uint32_t zix_digest_start(void) { -#ifdef __SSE4_2__ - return 1; // CRC32 initial value -#else - return 5381; // DJB hash initial value -#endif + return 1; } ZIX_API uint32_t zix_digest_add(uint32_t hash, const void* const buf, const size_t len) { const uint8_t* str = (const uint8_t*)buf; -#ifdef __SSE4_2__ - // SSE 4.2 CRC32 - for (size_t i = 0; i < (len / sizeof(uint32_t)); ++i) { + + for (size_t i = 0; i < (len / sizeof(uint64_t)); ++i) { + hash = (uint32_t)_mm_crc32_u64(hash, *(const uint64_t*)str); + str += sizeof(uint64_t); + } + if (len & sizeof(uint32_t)) { hash = _mm_crc32_u32(hash, *(const uint32_t*)str); str += sizeof(uint32_t); } @@ -47,11 +53,71 @@ zix_digest_add(uint32_t hash, const void* const buf, const size_t len) if (len & sizeof(uint8_t)) { hash = _mm_crc32_u8(hash, *(const uint8_t*)str); } + + return hash; +} + +ZIX_API uint32_t +zix_digest_add_64(uint32_t hash, const void* const buf, const size_t len) +{ + assert((uintptr_t)buf % sizeof(uint64_t) == 0); + assert(len % sizeof(uint64_t) == 0); + + const uint64_t* ptr = (const uint64_t*)buf; + + for (size_t i = 0; i < (len / sizeof(uint64_t)); ++i) { + hash = (uint32_t)_mm_crc32_u64(hash, *ptr); + ++ptr; + } + + return hash; +} + +ZIX_API uint32_t +zix_digest_add_ptr(const uint32_t hash, const void* const ptr) +{ +#if UINTPTR_MAX == UINT64_MAX + return (uint32_t)_mm_crc32_u64(hash, (uintptr_t)ptr); +#else + return _mm_crc32_u32(hash, (uintptr_t)ptr); +#endif +} + #else - // Classic DJB hash + +// Classic DJB hash + +ZIX_API uint32_t +zix_digest_start(void) +{ + return 5381; +} + +ZIX_API uint32_t +zix_digest_add(uint32_t hash, const void* const buf, const size_t len) +{ + const uint8_t* str = (const uint8_t*)buf; + for (size_t i = 0; i < len; ++i) { - hash = (hash << 5u) + hash + str[i]; + hash = (hash << 5) + hash + str[i]; } -#endif + return hash; } + +ZIX_API uint32_t +zix_digest_add_64(uint32_t hash, const void* const buf, const size_t len) +{ + assert((uintptr_t)buf % sizeof(uint64_t) == 0); + assert(len % sizeof(uint64_t) == 0); + + return zix_digest_add(hash, buf, len); +} + +ZIX_API uint32_t +zix_digest_add_ptr(const uint32_t hash, const void* const ptr) +{ + return zix_digest_add(hash, &ptr, sizeof(ptr)); +} + +#endif diff --git a/zix/digest.h b/zix/digest.h index 264c918..16ba9b9 100644 --- a/zix/digest.h +++ b/zix/digest.h @@ -1,5 +1,5 @@ /* - Copyright 2012 David Robillard <http://drobilla.net> + Copyright 2012-2020 David Robillard <http://drobilla.net> Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above @@ -26,12 +26,36 @@ extern "C" { #endif +/** + Return an initial empty digest value. +*/ ZIX_API uint32_t zix_digest_start(void); +/** + Update `hash` to include `buf`, a buffer of `len` bytes. + + This can be used for any size or alignment. +*/ ZIX_API uint32_t zix_digest_add(uint32_t hash, const void* buf, size_t len); +/** + Update `hash` to include `buf`, a 64-bit aligned buffer of `len` bytes. + + Both `buf` and `len` must be evenly divisible by 8 (64 bits). +*/ +ZIX_API uint32_t +zix_digest_add_64(uint32_t hash, const void* buf, size_t len); + +/** + Update `hash` to include `ptr`. + + This hashes the value of the pointer itself, and does not dereference `ptr`. +*/ +ZIX_API uint32_t +zix_digest_add_ptr(uint32_t hash, const void* ptr); + #ifdef __cplusplus } /* extern "C" */ #endif |