Add separate 32/64 bit versions to guf_rand

This commit is contained in:
jun 2025-03-29 01:55:26 +01:00
parent 05f995e855
commit d062784425
6 changed files with 763 additions and 210 deletions

View File

@ -28,14 +28,31 @@
#if GUF_PLATFORM_BITS <= 32
#define GUF_HASH_32_BIT
#define GUF_RAND_32_BIT
#endif
#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L)
#define GUF_STDC_AT_LEAST_C11
#if defined(__STDC_VERSION__)
#if __STDC_VERSION__ >= 199901L
#define GUF_STDC_AT_LEAST_C99
#else
#error "libguf only supports C99 and above"
#endif
#if __STDC_VERSION__ >= 201112L
#define GUF_STDC_AT_LEAST_C11
#endif
#if __STDC_VERSION__ >= 201710L
#define GUF_STDC_AT_LEAST_C17
#endif
#if __STDC_VERSION__ >= 202311L
#define GUF_STDC_AT_LEAST_C23
#endif
#endif
#if (defined(__cplusplus) && __cplusplus >= 201103L)
#define GUF_STDCPP_AT_LEAST_CPP11
#if defined(__cplusplus)
#if __cplusplus >= 201103L
#define GUF_STDCPP_AT_LEAST_CPP11
#endif
#endif
/*

View File

@ -19,10 +19,14 @@
*/
#define GUF_HASH32_INIT UINT32_C(2166136261)
#define GUF_HASH64_INIT UINT64_C(14695981039346656037)
#ifdef UINT64_MAX
#define GUF_HASH64_INIT UINT64_C(14695981039346656037)
#endif
GUF_HASH_KWRDS uint32_t guf_hash32(const void *data, ptrdiff_t num_bytes, uint32_t hash); // FNV-1a (32 bit)
GUF_HASH_KWRDS uint64_t guf_hash64(const void *data, ptrdiff_t num_bytes, uint64_t hash); // FNV-1a (64 bit)
#ifdef UINT64_MAX
GUF_HASH_KWRDS uint64_t guf_hash64(const void *data, ptrdiff_t num_bytes, uint64_t hash); // FNV-1a (64 bit)
#endif
#ifdef GUF_HASH_32_BIT
typedef uint32_t guf_hash_size_t;
@ -32,6 +36,9 @@ GUF_HASH_KWRDS uint64_t guf_hash64(const void *data, ptrdiff_t num_bytes, uint64
return guf_hash32(data, num_bytes, hash);
}
#else
#ifndef UINT64_MAX
#error "guf_hash.h: Platform does not support uint64_t (define GUF_HASH_32_BIT to fix)"
#endif
typedef uint64_t guf_hash_size_t;
#define GUF_HASH_INIT GUF_HASH64_INIT
#define GUF_HASH_MAX UINT64_MAX
@ -59,18 +66,20 @@ GUF_HASH_KWRDS uint32_t guf_hash32(const void *data, ptrdiff_t num_bytes, uint32
return hash;
}
GUF_HASH_KWRDS uint64_t guf_hash64(const void *data, ptrdiff_t num_bytes, uint64_t hash)
{
GUF_ASSERT_RELEASE(data);
GUF_ASSERT_RELEASE(num_bytes >= 0);
const unsigned char *data_bytes = (const unsigned char*)data; // This does not break strict-aliasing rules I think...
const uint64_t FNV_64_PRIME = UINT64_C(1099511628211);
for (ptrdiff_t i = 0; i < num_bytes; ++i) {
hash ^= data_bytes[i];
hash *= FNV_64_PRIME;
#ifdef UINT64_MAX
GUF_HASH_KWRDS uint64_t guf_hash64(const void *data, ptrdiff_t num_bytes, uint64_t hash)
{
GUF_ASSERT_RELEASE(data);
GUF_ASSERT_RELEASE(num_bytes >= 0);
const unsigned char *data_bytes = (const unsigned char*)data; // This does not break strict-aliasing rules I think...
const uint64_t FNV_64_PRIME = UINT64_C(1099511628211);
for (ptrdiff_t i = 0; i < num_bytes; ++i) {
hash ^= data_bytes[i];
hash *= FNV_64_PRIME;
}
return hash;
}
return hash;
}
#endif
#undef GUF_HASH_IMPL
#undef GUF_HASH_IMPL_STATIC

View File

@ -124,6 +124,17 @@ static inline bool guf_sub_is_overflow_i32(int32_t a, int32_t b)
(b > 0 && a < INT32_MIN + b); // a - b underflow
}
static inline bool guf_add_is_overflow_i64(int64_t a, int64_t b)
{
return (b > 0 && a > INT64_MAX - b) || // a + b overflow
(b < 0 && a < INT64_MIN - b); // a + b underflow
}
static inline bool guf_sub_is_overflow_i64(int64_t a, int64_t b)
{
return (b < 0 && a > INT64_MAX + b) || // a - b overflow
(b > 0 && a < INT64_MIN + b); // a - b underflow
}
static inline bool guf_size_calc_safe(ptrdiff_t count, ptrdiff_t sizeof_elem, ptrdiff_t *result)
{
if (count < 0 || sizeof_elem <= 0) {

File diff suppressed because it is too large Load Diff

View File

@ -4,19 +4,69 @@
#ifndef GUF_UTILS_H
#define GUF_UTILS_H
#include "guf_common.h"
#include "guf_assert.h"
static inline bool guf_platform_is_big_endian(void)
static inline void guf_platform_assert_endianness(void)
{
unsigned i = 1;
const unsigned i = 1;
const char *bytes = (const char*)&i;
return bytes[0] != 1;
const bool is_big_endian = bytes[0] != 1;
#if defined(GUF_PLATFORM_LITTLE_ENDIAN)
GUF_ASSERT_RELEASE(!is_big_endian)
#elif defined(GUF_PLATFORM_BIG_ENDIAN)
GUF_ASSERT_RELEASE(is_big_endian)
#endif
}
static inline int guf_platform_native_word_bits(void)
static inline void guf_platform_assert_native_word_bits(void)
{
const int bits = sizeof(void*) * CHAR_BIT;
return bits;
GUF_ASSERT_RELEASE(GUF_PLATFORM_BITS == bits);
}
#ifdef NDEBUG
#define GUF_DBG_STR "release"
#else
#define GUF_DBG_STR "debug"
#endif
#if defined(GUF_STDC_AT_LEAST_C23)
#ifdef GUF_PLATFORM_LITTLE_ENDIAN
#define GUF_PLATFORM_STRING "C23 (or above) " GUF_STRINGIFY(GUF_PLATFORM_BITS) "-bit " "little-endian " GUF_DBG_STR
#else
#define GUF_PLATFORM_STRING "C23 (or above) " GUF_STRINGIFY(GUF_PLATFORM_BITS) "-bit " "big-endian " GUF_DBG_STR
#endif
#elif defined(GUF_STDC_AT_LEAST_C17)
#ifdef GUF_PLATFORM_LITTLE_ENDIAN
#define GUF_PLATFORM_STRING "C17 " GUF_STRINGIFY(GUF_PLATFORM_BITS) "-bit " "little-endian " GUF_DBG_STR
#else
#define GUF_PLATFORM_STRING "C17 " GUF_STRINGIFY(GUF_PLATFORM_BITS) "-bit " "big-endian " GUF_DBG_STR
#endif
#elif defined(GUF_STDC_AT_LEAST_C11)
#ifdef GUF_PLATFORM_LITTLE_ENDIAN
#define GUF_PLATFORM_STRING "C11 " GUF_STRINGIFY(GUF_PLATFORM_BITS) "-bit " "little-endian " GUF_DBG_STR
#else
#define GUF_PLATFORM_STRING "C11 " GUF_STRINGIFY(GUF_PLATFORM_BITS) "-bit " "big-endian " GUF_DBG_STR
#endif
#elif defined(GUF_STDC_AT_LEAST_C99)
#ifdef GUF_PLATFORM_LITTLE_ENDIAN
#define GUF_PLATFORM_STRING "C99 " GUF_STRINGIFY(GUF_PLATFORM_BITS) "-bit " "little-endian " GUF_DBG_STR
#else
#define GUF_PLATFORM_STRING "C99 " GUF_STRINGIFY(GUF_PLATFORM_BITS) "-bit " "big-endian " GUF_DBG_STR
#endif
#elif defined(GUF_STDCPP_AT_LEAST_CPP11)
#ifdef GUF_PLATFORM_LITTLE_ENDIAN
#define GUF_PLATFORM_STRING "C++11 (or above) " GUF_STRINGIFY(GUF_PLATFORM_BITS) "-bit " "little-endian " GUF_DBG_STR
#else
#define GUF_PLATFORM_STRING "C++11 (or above) " GUF_STRINGIFY(GUF_PLATFORM_BITS) "-bit " "big-endian " GUF_DBG_STR
#endif
#else
#ifdef GUF_PLATFORM_LITTLE_ENDIAN
#define GUF_PLATFORM_STRING "C?? " GUF_STRINGIFY(GUF_PLATFORM_BITS) "-bit " "little-endian " GUF_DBG_STR
#else
#define GUF_PLATFORM_STRING "C?? " GUF_STRINGIFY(GUF_PLATFORM_BITS) "-bit " "big-endian " GUF_DBG_STR
#endif
#endif
#endif

View File

@ -8,6 +8,7 @@
#include "guf_alloc_libc.h"
#include "guf_cstr.h"
#include "guf_linalg.h"
#include "guf_utils.h"
#define GUF_T float
#define GUF_SORT_IMPL_STATIC
@ -46,13 +47,16 @@
#include "guf_dbuf.h"
#define GUF_RAND_IMPL_STATIC
// #define GUF_RAND_32_BIT
#include "guf_rand.h"
#include "impls/dict_impl.h"
int main(void)
{
printf("libguf test: compiled with C %ld\n", __STDC_VERSION__);
printf("libguf example: " GUF_PLATFORM_STRING "\n");
guf_platform_assert_endianness();
guf_platform_assert_native_word_bits();
guf_allocator test_allocator = guf_allocator_libc;
guf_libc_alloc_ctx test_allocator_ctx = {.alloc_type_id = 0, .thread_id = 0, .zero_init = true};
@ -206,7 +210,7 @@ int main(void)
dbuf_int_free(&integers, NULL);
printf("\n");
guf_randstate rng;
guf_randstate_init(&rng, time(NULL));
guf_randstate_init(&rng, (guf_rand_seed_t)time(NULL));
int heads = 0, tails = 0;
int throws = 10;
for (i = 0; i < throws; ++i) {