diff --git a/src/guf_alloc_tracker.h b/src/guf_alloc_tracker.h index b40b65a..3af8c5d 100644 --- a/src/guf_alloc_tracker.h +++ b/src/guf_alloc_tracker.h @@ -16,13 +16,13 @@ typedef struct guf_alloc_tracker { const char *name; size_t alloc_count, realloc_count, free_count; ptrdiff_t allocated_bytes; - uint32_t id; + unsigned id; bool enabled; } guf_alloc_tracker; #if !defined(GUF_ALLOC_TRACKER_IMPL_STATIC) && !defined(GUF_ALLOC_TRACKER_IMPL) - GUF_ALLOC_TRACKER_KWRDS guf_alloc_tracker *guf_alloc_tracker_init(guf_alloc_tracker *t, uint32_t id, const char* name, FILE *log, FILE *err_log); - GUF_ALLOC_TRACKER_KWRDS guf_alloc_tracker guf_alloc_tracker_new(uint32_t id, const char* name, FILE *log, FILE *err_log); + GUF_ALLOC_TRACKER_KWRDS guf_alloc_tracker *guf_alloc_tracker_init(guf_alloc_tracker *t, unsigned id, const char* name, FILE *log, FILE *err_log); + GUF_ALLOC_TRACKER_KWRDS guf_alloc_tracker guf_alloc_tracker_new(unsigned id, const char* name, FILE *log, FILE *err_log); GUF_ALLOC_TRACKER_KWRDS void guf_alloc_tracker_print(const guf_alloc_tracker *t, FILE *f); GUF_ALLOC_TRACKER_KWRDS bool guf_alloc_tracker_found_leak(const guf_alloc_tracker *t); @@ -38,7 +38,7 @@ typedef struct guf_alloc_tracker { #define GUF_MATH_CKDINT_IMPL_STATIC #include "guf_math_ckdint.h" -GUF_ALLOC_TRACKER_KWRDS guf_alloc_tracker *guf_alloc_tracker_init(guf_alloc_tracker *t, uint32_t id, const char* name, FILE *log, FILE *err_log) +GUF_ALLOC_TRACKER_KWRDS guf_alloc_tracker *guf_alloc_tracker_init(guf_alloc_tracker *t, unsigned id, const char* name, FILE *log, FILE *err_log) { GUF_ASSERT_RELEASE(t); t->log = log; @@ -51,7 +51,7 @@ GUF_ALLOC_TRACKER_KWRDS guf_alloc_tracker *guf_alloc_tracker_init(guf_alloc_trac return t; } -GUF_ALLOC_TRACKER_KWRDS guf_alloc_tracker guf_alloc_tracker_new(uint32_t id, const char* name, FILE *log, FILE *err_log) +GUF_ALLOC_TRACKER_KWRDS guf_alloc_tracker guf_alloc_tracker_new(unsigned id, const char* name, FILE *log, FILE *err_log) { guf_alloc_tracker t; guf_alloc_tracker_init(&t, id, name, log, err_log); @@ -78,7 +78,7 @@ GUF_ALLOC_TRACKER_KWRDS void guf_alloc_tracker_print(const guf_alloc_tracker *t, } fprintf(f, - "guf_alloc_tracker (name '%s' id = %" PRIu32 "):\n" + "guf_alloc_tracker (name '%s' id = %u):\n" "allocated_bytes: %td\n" "alloc_count: %zu\n" "realloc_count: %zu\n" @@ -96,25 +96,25 @@ GUF_ALLOC_TRACKER_KWRDS bool guf_track_alloc(guf_alloc_tracker *t, ptrdiff_t siz bool success = true; if (guf_saturating_add_size_t(t->alloc_count, 1, &t->alloc_count) != GUF_MATH_CKD_SUCCESS && t->err_log) { - fprintf(t->err_log, "WARNING in guf_track_alloc (name '%s' id %" PRIu32 "): alloc_count reached SIZE_MAX\n", t->name ? t->name : "unnamed", t->id); + fprintf(t->err_log, "WARNING in guf_track_alloc (name '%s' id %u): alloc_count reached SIZE_MAX\n", t->name ? t->name : "unnamed", t->id); } if (guf_saturating_add_ptrdiff_t(t->allocated_bytes, size, &t->allocated_bytes) != GUF_MATH_CKD_SUCCESS) { if (t->err_log) { - fprintf(t->err_log, "ERROR in guf_track_alloc (name '%s' id %" PRIu32 "): allocated_byte overflow\n", t->name ? t->name : "unnamed", t->id); + fprintf(t->err_log, "ERROR in guf_track_alloc (name '%s' id %u): allocated_byte overflow\n", t->name ? t->name : "unnamed", t->id); } success = false; } if (t->allocated_bytes < 0) { if (t->err_log) { - fprintf(t->err_log, "ERROR in guf_track_alloc (name '%s' id %" PRIu32 "): allocated_bytes < 0\n", t->name ? t->name : "unnamed", t->id); + fprintf(t->err_log, "ERROR in guf_track_alloc (name '%s' id %u): allocated_bytes < 0\n", t->name ? t->name : "unnamed", t->id); } success = false; } if (t->log) { - fprintf(t->log, "guf_alloc_tracker (name '%s' id %" PRIu32 "): alloc (%td bytes) %s\n", t->name ? t->name : "unnamed", t->id, size, success ? "SUCCESS" : "FAILURE"); + fprintf(t->log, "guf_alloc_tracker (name '%s' id %u): alloc (%td bytes) %s\n", t->name ? t->name : "unnamed", t->id, size, success ? "SUCCESS" : "FAILURE"); } return success; } @@ -127,40 +127,40 @@ GUF_ALLOC_TRACKER_KWRDS bool guf_track_realloc(guf_alloc_tracker *t, ptrdiff_t o bool success = true; if (guf_saturating_add_size_t(t->realloc_count, 1, &t->realloc_count) && t->err_log) { - fprintf(t->err_log, "WARNING in guf_track_realloc (name '%s' id %" PRIu32 "): realloc_count reached SIZE_MAX\n", t->name ? t->name : "unnamed", t->id); + fprintf(t->err_log, "WARNING in guf_track_realloc (name '%s' id %u): realloc_count reached SIZE_MAX\n", t->name ? t->name : "unnamed", t->id); } if (old_size < 0 || new_size < 0) { success = false; if (t->err_log) { - fprintf(t->err_log, "ERROR in guf_track_realloc (name '%s' id %" PRIu32 "): old_size < 0 or new_size < 0\n", t->name ? t->name : "unnamed", t->id); + fprintf(t->err_log, "ERROR in guf_track_realloc (name '%s' id %u): old_size < 0 or new_size < 0\n", t->name ? t->name : "unnamed", t->id); } } if (guf_saturating_sub_ptrdiff_t(t->allocated_bytes, old_size, &t->allocated_bytes)) { success = false; if (t->err_log) { - fprintf(t->err_log, "ERROR in guf_track_realloc (name '%s' id %" PRIu32 "): allocated_bytes - old_size under/overflows\n", t->name ? t->name : "unnamed", t->id); + fprintf(t->err_log, "ERROR in guf_track_realloc (name '%s' id %u): allocated_bytes - old_size under/overflows\n", t->name ? t->name : "unnamed", t->id); } } if (t->allocated_bytes < 0) { success = false; - fprintf(t->err_log, "ERROR in guf_track_realloc (name '%s' id %" PRIu32 "): allocated_bytes < 0 after subtracting old_size\n", t->name ? t->name : "unnamed", t->id); + fprintf(t->err_log, "ERROR in guf_track_realloc (name '%s' id %u): allocated_bytes < 0 after subtracting old_size\n", t->name ? t->name : "unnamed", t->id); } if (guf_saturating_add_ptrdiff_t(t->allocated_bytes, new_size, &t->allocated_bytes)) { success = false; if (t->err_log) { - fprintf(t->err_log, "ERROR in guf_track_realloc (name '%s' id %" PRIu32 "): allocated_bytes overflow \n", t->name ? t->name : "unnamed", t->id); + fprintf(t->err_log, "ERROR in guf_track_realloc (name '%s' id %u): allocated_bytes overflow \n", t->name ? t->name : "unnamed", t->id); } } if (t->allocated_bytes < 0) { success = false; - fprintf(t->err_log, "ERROR in guf_track_realloc (name '%s' id %" PRIu32 "): allocated_bytes < 0 after adding new_size\n", t->name ? t->name : "unnamed", t->id); + fprintf(t->err_log, "ERROR in guf_track_realloc (name '%s' id %u): allocated_bytes < 0 after adding new_size\n", t->name ? t->name : "unnamed", t->id); } if (t->log) { - fprintf(t->log, "guf_alloc_tracker (name '%s' id %" PRIu32 "): realloc (from %td to %td bytes) %s\n", t->name ? t->name : "unnamed", t->id, old_size, new_size, (success ? "SUCCESS" : "FAILURE")); + fprintf(t->log, "guf_alloc_tracker (name '%s' id %u): realloc (from %td to %td bytes) %s\n", t->name ? t->name : "unnamed", t->id, old_size, new_size, (success ? "SUCCESS" : "FAILURE")); } return success; @@ -173,31 +173,31 @@ GUF_ALLOC_TRACKER_KWRDS bool guf_track_free(guf_alloc_tracker *t, ptrdiff_t size bool success = true; if (guf_saturating_add_size_t(t->free_count, 1, &t->free_count) && t->err_log) { - fprintf(t->err_log, "WARNING in guf_track_free (name '%s' id %" PRIu32 "): free_count reached SIZE_MAX\n", t->name ? t->name : "unnamed", t->id); + fprintf(t->err_log, "WARNING in guf_track_free (name '%s' id %u): free_count reached SIZE_MAX\n", t->name ? t->name : "unnamed", t->id); } if (size < 0) { success = false; if (t->err_log) { - fprintf(t->err_log, "ERROR in guf_track_free (name '%s' id %" PRIu32 "): size < 0\n", t->name ? t->name : "unnamed", t->id); + fprintf(t->err_log, "ERROR in guf_track_free (name '%s' id %u): size < 0\n", t->name ? t->name : "unnamed", t->id); } } if (t->allocated_bytes < size) { success = false; if (t->err_log) { - fprintf(t->err_log, "ERROR in guf_track_free (name '%s' id %" PRIu32 "): freed more bytes than allocated\n", t->name ? t->name : "unnamed", t->id); + fprintf(t->err_log, "ERROR in guf_track_free (name '%s' id %u): freed more bytes than allocated\n", t->name ? t->name : "unnamed", t->id); } } if (guf_saturating_sub_ptrdiff_t(t->allocated_bytes, size, &t->allocated_bytes)) { success = false; if (t->err_log) { - fprintf(t->err_log, "ERROR in guf_track_free (name '%s' id %" PRIu32 "): allocated_bytes - size under/overflows\n", t->name ? t->name : "unnamed", t->id); + fprintf(t->err_log, "ERROR in guf_track_free (name '%s' id %u): allocated_bytes - size under/overflows\n", t->name ? t->name : "unnamed", t->id); } } if (t->log) { - fprintf(t->log, "guf_alloc_tracker (name '%s' id %" PRIu32 "): free (%td bytes) %s\n", t->name ? t->name : "unnamed", t->id, size, (success ? "SUCCESS" : "FAILURE")); + fprintf(t->log, "guf_alloc_tracker (name '%s' id %u): free (%td bytes) %s\n", t->name ? t->name : "unnamed", t->id, size, (success ? "SUCCESS" : "FAILURE")); } return success; diff --git a/src/guf_common.h b/src/guf_common.h index c1fc47e..6781d08 100644 --- a/src/guf_common.h +++ b/src/guf_common.h @@ -10,22 +10,39 @@ #include #include +#ifndef GUF_PLATFORM_BIG_ENDIAN + #define GUF_PLATFORM_LITTLE_ENDIAN +#endif + #define GUF_UINT8_MAX 0xffu #define GUF_UINT16_MAX 0xffffu #define GUF_UINT32_MAX 0xfffffffful #define GUF_UINT64_MAX 0xffffffffffffffffull -#ifndef GUF_PLATFORM_BIG_ENDIAN - #define GUF_PLATFORM_LITTLE_ENDIAN -#endif +#define GUF_UWRAP_8(UINT) ( (UINT) & GUF_UINT8_MAX ) +#define GUF_UWRAP_16(UINT) ( (UINT) & GUF_UINT16_MAX ) +#define GUF_UWRAP_32(UINT) ( (UINT) & GUF_UINT32_MAX ) +#define GUF_UWRAP_64(UINT) ( (UINT) & GUF_UINT64_MAX ) -#if SIZE_MAX == UINT64_MAX +#define GUF_INT8_MAX 127 +#define GUF_INT8_MIN -128 + +#define GUF_INT16_MAX 32767 +#define GUF_INT16_MIN (-GUF_INT16_MAX - 1) + +#define GUF_INT32_MAX 2147483647L +#define GUF_INT32_MIN (-GUF_INT32_MAX - 1) + +#define GUF_INT64_MAX 9223372036854775807LL +#define GUF_INT64_MIN (-GUF_INT64_MAX - 1) + +#if SIZE_MAX == GUF_UINT64_MAX #define GUF_PLATFORM_BITS 64 -#elif SIZE_MAX == UINT32_MAX +#elif SIZE_MAX == GUF_UINT32_MAX #define GUF_PLATFORM_BITS 32 -#elif SIZE_MAX == UINT16_MAX +#elif SIZE_MAX == GUF_UINT16_MAX #define GUF_PLATFORM_BITS 16 -#elif SIZE_MAX == UINT8_MAX +#elif SIZE_MAX == GUF_UINT8_MAX #define GUF_PLATFORM_BITS 8 #else #define GUF_PLATFORM_BITS 64 diff --git a/src/guf_dict.h b/src/guf_dict.h index f6d7f1b..303ad36 100755 --- a/src/guf_dict.h +++ b/src/guf_dict.h @@ -34,18 +34,18 @@ #endif #if defined(GUF_DICT_32_BIT_HASH) - #define GUF_DICT_HASH_T uint32_t - #define GUF_DICT_HASH_T_MAX UINT32_MAX + #define GUF_DICT_HASH_T uint_fast32_t + #define GUF_DICT_HASH_T_MAX GUF_UINT32_MAX #elif defined(GUF_DICT_64_BIT_HASH) - #define GUF_DICT_HASH_T uint64_t - #define GUF_DICT_HASH_T_MAX UINT64_MAX + #define GUF_DICT_HASH_T uint_fast64_t + #define GUF_DICT_HASH_T_MAX GUF_UINT64_MAX #else #define GUF_DICT_HASH_T guf_hash_size_t #define GUF_DICT_HASH_T_MAX GUF_HASH_MAX #endif #if defined (GUF_DICT_64_BIT_IDX) - #define GUF_DICT_KV_META_T uint64_t + #define GUF_DICT_KV_META_T uint_least64_t /* Store a 16-bit hash-fragment in the upper 16-bits of kv_meta -> (2^48 - 1 is IDX_NULL, 2^48 - 2 is IDX_TOMBSTONE, 2^48 - 3 is the largest actual idx, @@ -54,15 +54,15 @@ #define GUF_DICT_KV_META_HASHFRAG_MASK UINT64_C(0xffff000000000000) #define GUF_DICT_KV_META_IDX_MASK (~UINT64_C(0xffff000000000000)) - #if GUF_DICT_HASH_T_MAX == UINT64_MAX + #if GUF_DICT_HASH_T_MAX == GUF_UINT64_MAX #define GUF_DICT_HASH_T_GET_HASHFRAG(HASH) ( (HASH) & GUF_DICT_KV_META_HASHFRAG_MASK ) - #elif GUF_DICT_HASH_T_MAX == UINT32_MAX - #define GUF_DICT_HASH_T_GET_HASHFRAG(HASH) ( (((uint64_t)(HASH)) << 32) & GUF_DICT_KV_META_HASHFRAG_MASK ) + #elif GUF_DICT_HASH_T_MAX == GUF_UINT32_MAX + #define GUF_DICT_HASH_T_GET_HASHFRAG(HASH) ( (((uint_least64_t)(HASH)) << 32u) & GUF_DICT_KV_META_HASHFRAG_MASK ) #else #error "guf_dict: invalid hash size (should not happen)" #endif #else - #define GUF_DICT_KV_META_T uint32_t + #define GUF_DICT_KV_META_T uint_least32_t /* Store a 7-bit hash-fragment in the upper 7-bits of kv_meta -> (2^25 - 1 is IDX_NULL, 2^25 - 2 is IDX_TOMBSTONE, 2^25 - 3 is the largest actual idx, @@ -71,9 +71,9 @@ #define GUF_DICT_KV_META_HASHFRAG_MASK UINT32_C(0xfe000000) #define GUF_DICT_KV_META_IDX_MASK (~UINT32_C(0xfe000000)) - #if GUF_DICT_HASH_T_MAX == UINT64_MAX - #define GUF_DICT_HASH_T_GET_HASHFRAG(HASH) ( ((uint32_t)((HASH) >> 32)) & GUF_DICT_KV_META_HASHFRAG_MASK ) - #elif GUF_DICT_HASH_T_MAX == UINT32_MAX + #if GUF_DICT_HASH_T_MAX == GUF_UINT64_MAX + #define GUF_DICT_HASH_T_GET_HASHFRAG(HASH) ( ((uint_least32_t)((HASH) >> 32u)) & GUF_DICT_KV_META_HASHFRAG_MASK ) + #elif GUF_DICT_HASH_T_MAX == GUF_UINT32_MAX #define GUF_DICT_HASH_T_GET_HASHFRAG(HASH) ( (HASH) & GUF_DICT_KV_META_HASHFRAG_MASK ) #else #error "guf_dict: invalid hash size (should not happen)" @@ -447,10 +447,11 @@ static inline size_t GUF_CAT(GUF_DICT_NAME, _probe_offset_)(size_t probe_len) return probe_len; // 1, 2, 3, 4, 5, ... #else /* + Quadratic probing: Guaranteed to visit each index once for capacities which are powers of two. cf. https://fgiesen.wordpress.com/2015/02/22/triangular-numbers-mod-2n/ (last-retrieved 2024-07-29) */ - return probe_len * (probe_len + 1) / 2; // 1, 3, 6, 10, 15, 21 ... (starting from probe_len == 1) + return probe_len * (probe_len + 1u) / 2u; // 1, 3, 6, 10, 15, 21 ... (starting from probe_len == 1) #endif } diff --git a/src/guf_hash.h b/src/guf_hash.h index ca34a4d..d1fcf3c 100644 --- a/src/guf_hash.h +++ b/src/guf_hash.h @@ -19,29 +19,22 @@ */ #define GUF_HASH32_INIT UINT32_C(2166136261) -#ifdef UINT64_MAX - #define GUF_HASH64_INIT UINT64_C(14695981039346656037) -#endif +#define GUF_HASH64_INIT UINT64_C(14695981039346656037) -GUF_HASH_KWRDS uint32_t guf_hash32(const void *data, ptrdiff_t num_bytes, uint32_t hash); // FNV-1a (32 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 +GUF_HASH_KWRDS uint_fast32_t guf_hash32(const void *data, ptrdiff_t num_bytes, uint_fast32_t hash); // FNV-1a (32 bit) +GUF_HASH_KWRDS uint_fast64_t guf_hash64(const void *data, ptrdiff_t num_bytes, uint_fast64_t hash); // FNV-1a (64 bit) #ifdef GUF_HASH_32_BIT - typedef uint32_t guf_hash_size_t; + typedef uint_fast32_t guf_hash_size_t; #define GUF_HASH_INIT GUF_HASH32_INIT - #define GUF_HASH_MAX UINT32_MAX + #define GUF_HASH_MAX GUF_UINT32_MAX static inline guf_hash_size_t guf_hash(const void *data, ptrdiff_t num_bytes, guf_hash_size_t hash) { 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; + typedef uint_fast64_t guf_hash_size_t; #define GUF_HASH_INIT GUF_HASH64_INIT - #define GUF_HASH_MAX UINT64_MAX + #define GUF_HASH_MAX GUF_UINT64_MAX static inline guf_hash_size_t guf_hash(const void *data, ptrdiff_t num_bytes, guf_hash_size_t hash) { return guf_hash64(data, num_bytes, hash); } @@ -53,36 +46,37 @@ GUF_HASH_KWRDS uint32_t guf_hash32(const void *data, ptrdiff_t num_bytes, uint32 #include "guf_assert.h" -GUF_HASH_KWRDS uint32_t guf_hash32(const void *data, ptrdiff_t num_bytes, uint32_t hash) +GUF_HASH_KWRDS uint_fast32_t guf_hash32(const void *data, ptrdiff_t num_bytes, uint_fast32_t hash) { + hash = GUF_UWRAP_32(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 uint32_t FNV_32_PRIME = UINT32_C(16777619); + const uint_fast32_t FNV_32_PRIME = UINT32_C(16777619); for (ptrdiff_t i = 0; i < num_bytes; ++i) { - hash ^= 1u * data_bytes[i]; - hash *= 1u * FNV_32_PRIME; + hash = GUF_UWRAP_32(1u * hash ^ data_bytes[i]); + hash = GUF_UWRAP_32(1u * hash * FNV_32_PRIME); } return hash; } -#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 ^= 1u * data_bytes[i]; - hash *= 1u * FNV_64_PRIME; - } - return hash; +GUF_HASH_KWRDS uint_fast64_t guf_hash64(const void *data, ptrdiff_t num_bytes, uint_fast64_t hash) +{ + hash = GUF_UWRAP_64(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 uint_fast64_t FNV_64_PRIME = UINT64_C(1099511628211); + for (ptrdiff_t i = 0; i < num_bytes; ++i) { + hash = GUF_UWRAP_64(1u * hash ^ data_bytes[i]); + hash = GUF_UWRAP_64(1u * hash * FNV_64_PRIME); } -#endif + return hash; +} #undef GUF_HASH_IMPL #undef GUF_HASH_IMPL_STATIC + #endif /* endif GUF_IMPL/GUF_IMPL_STATIC */ #undef GUF_HASH_KWRDS diff --git a/src/guf_math.h b/src/guf_math.h index c83a2ae..fa0f0ad 100644 --- a/src/guf_math.h +++ b/src/guf_math.h @@ -15,10 +15,6 @@ #define GUF_MAX_F32_LT_ONE (1.f - FLT_EPSILON/FLT_RADIX) #define GUF_MAX_F64_LT_ONE (1.0 - DBL_EPSILON/FLT_RADIX) -// Rotate left. -static inline uint64_t guf_rotl_u64(uint64_t x, int k) {return (1u*x << k) | (1u*x >> (64 - k));} -static inline uint32_t guf_rotl_u32(uint32_t x, int k) {return (1u*x << k) | (1u*x >> (32 - k));} - // Typesafe unsigned integer wrapping functions (generated with libguf/tools/intwrap-gen.py) static inline uint_least8_t guf_wrap8_uint_least8_t(uint_least8_t a) { return a & GUF_UINT8_MAX; } static inline uint_fast8_t guf_wrap8_uint_fast8_t(uint_fast8_t a) { return a & GUF_UINT8_MAX; } @@ -37,13 +33,50 @@ static inline unsigned short guf_wrap16_ushort(unsigned short a) { r static inline unsigned long guf_wrap32_ulong(unsigned long a) { return a & GUF_UINT32_MAX; } // unsigned long: >= 32 bits static inline unsigned long long guf_wrap64_ulong_long(unsigned long long a) { return a & GUF_UINT64_MAX; } // unsigned long long: >= 64 bits -#define GUF_UWRAP_8(UINT) ( (UINT) & GUF_UINT8_MAX ) -#define GUF_UWRAP_16(UINT) ( (UINT) & GUF_UINT16_MAX ) -#define GUF_UWRAP_32(UINT) ( (UINT) & GUF_UINT32_MAX ) -#define GUF_UWRAP_64(UINT) ( (UINT) & GUF_UINT64_MAX ) +// Rotate left. +#ifdef UINT32_MAX + static inline uint32_t guf_rotl_u32(uint32_t x, int k) + { + GUF_ASSERT(k > 0); + return (1u*x << k) | (1u*x >> (32 - k)); + } +#endif +#ifdef UINT64_MAX + static inline uint64_t guf_rotl_u64(uint64_t x, int k) + { + GUF_ASSERT(k > 0); + return (1u*x << k) | (1u*x >> (64 - k)); + } +#endif + +static inline uint_fast32_t guf_rotl32_uint_fast32_t(uint_fast32_t x, int k) +{ + GUF_ASSERT(k > 0); + x = guf_wrap32_uint_fast32_t(x); + return guf_wrap32_uint_fast32_t( (1u*x << k) | (1u*x >> (32 - k)) ); +} +static inline uint_fast64_t guf_rotl64_uint_fast64_t(uint_fast64_t x, int k) +{ + GUF_ASSERT(k > 0); + x = guf_wrap64_uint_fast64_t(x); + return guf_wrap64_uint_fast64_t( (1u*x << k) | (1u*x >> (64 - k)) ); +} + +static inline unsigned long guf_rotl32_ulong(unsigned long x, int k) +{ + GUF_ASSERT(k > 0); + x = guf_wrap32_ulong(x); + return guf_wrap32_ulong( (x << k) | (x >> (32 - k)) ); +} +static inline unsigned long long guf_rotl64_ulong_long(unsigned long long x, int k) +{ + GUF_ASSERT(k > 0); + x = guf_wrap64_ulong_long(x); + return guf_wrap64_ulong_long( (x << k) | (x >> (64 - k)) ); +} + // Signed min, max, clamp functions (generated with libguf/tools/min_max_clamp-gen.py) - static inline char guf_min_char(char a, char b) { return a < b ? a : b; } static inline char guf_max_char(char a, char b) { return a > b ? a : b; } static inline char guf_clamp_char(char x, char min, char max) { if (x < min) {return min;} if (x > max) {return max;} return x; } @@ -60,26 +93,26 @@ static inline long long guf_min_long_long(long long a, long long b) { return a < static inline long long guf_max_long_long(long long a, long long b) { return a > b ? a : b; } static inline long long guf_clamp_long_long(long long x, long long min, long long max) { if (x < min) {return min;} if (x > max) {return max;} return x; } -static inline int8_t guf_min_i8(int8_t a, int8_t b) { return a < b ? a : b; } -static inline int8_t guf_max_i8(int8_t a, int8_t b) { return a > b ? a : b; } -static inline int8_t guf_clamp_i8(int8_t x, int8_t min, int8_t max) { if (x < min) {return min;} if (x > max) {return max;} return x; } - -static inline int16_t guf_min_i16(int16_t a, int16_t b) { return a < b ? a : b; } -static inline int16_t guf_max_i16(int16_t a, int16_t b) { return a > b ? a : b; } -static inline int16_t guf_clamp_i16(int16_t x, int16_t min, int16_t max) { if (x < min) {return min;} if (x > max) {return max;} return x; } - -static inline int32_t guf_min_i32(int32_t a, int32_t b) { return a < b ? a : b; } -static inline int32_t guf_max_i32(int32_t a, int32_t b) { return a > b ? a : b; } -static inline int32_t guf_clamp_i32(int32_t x, int32_t min, int32_t max) { if (x < min) {return min;} if (x > max) {return max;} return x; } - -static inline int64_t guf_min_i64(int64_t a, int64_t b) { return a < b ? a : b; } -static inline int64_t guf_max_i64(int64_t a, int64_t b) { return a > b ? a : b; } -static inline int64_t guf_clamp_i64(int64_t x, int64_t min, int64_t max) { if (x < min) {return min;} if (x > max) {return max;} return x; } - static inline ptrdiff_t guf_min_ptrdiff_t(ptrdiff_t a, ptrdiff_t b) { return a < b ? a : b; } static inline ptrdiff_t guf_max_ptrdiff_t(ptrdiff_t a, ptrdiff_t b) { return a > b ? a : b; } static inline ptrdiff_t guf_clamp_ptrdiff_t(ptrdiff_t x, ptrdiff_t min, ptrdiff_t max) { if (x < min) {return min;} if (x > max) {return max;} return x; } +static inline int_fast8_t guf_min_i8_fast(int_fast8_t a, int_fast8_t b) { return a < b ? a : b; } +static inline int_fast8_t guf_max_i8_fast(int_fast8_t a, int_fast8_t b) { return a > b ? a : b; } +static inline int_fast8_t guf_clamp_i8_fast(int_fast8_t x, int_fast8_t min, int_fast8_t max) { if (x < min) {return min;} if (x > max) {return max;} return x; } + +static inline int_fast16_t guf_min_i16_fast(int_fast16_t a, int_fast16_t b) { return a < b ? a : b; } +static inline int_fast16_t guf_max_i16_fast(int_fast16_t a, int_fast16_t b) { return a > b ? a : b; } +static inline int_fast16_t guf_clamp_i16_fast(int_fast16_t x, int_fast16_t min, int_fast16_t max) { if (x < min) {return min;} if (x > max) {return max;} return x; } + +static inline int_fast32_t guf_min_i32_fast(int_fast32_t a, int_fast32_t b) { return a < b ? a : b; } +static inline int_fast32_t guf_max_i32_fast(int_fast32_t a, int_fast32_t b) { return a > b ? a : b; } +static inline int_fast32_t guf_clamp_i32_fast(int_fast32_t x, int_fast32_t min, int_fast32_t max) { if (x < min) {return min;} if (x > max) {return max;} return x; } + +static inline int_fast64_t guf_min_i64_fast(int_fast64_t a, int_fast64_t b) { return a < b ? a : b; } +static inline int_fast64_t guf_max_i64_fast(int_fast64_t a, int_fast64_t b) { return a > b ? a : b; } +static inline int_fast64_t guf_clamp_i64_fast(int_fast64_t x, int_fast64_t min, int_fast64_t max) { if (x < min) {return min;} if (x > max) {return max;} return x; } + static inline float guf_min_f32(float a, float b) { return a < b ? a : b; } static inline float guf_max_f32(float a, float b) { return a > b ? a : b; } static inline float guf_clamp_f32(float x, float min, float max) { if (x < min) {return min;} if (x > max) {return max;} return x; } @@ -88,8 +121,31 @@ static inline double guf_min_f64(double a, double b) { return a < b ? a : b; } static inline double guf_max_f64(double a, double b) { return a > b ? a : b; } static inline double guf_clamp_f64(double x, double min, double max) { if (x < min) {return min;} if (x > max) {return max;} return x; } -// Unsigned min, max, clamp functions (generated with libguf/tools/min_max_clamp-gen.py) +#ifdef INT8_MAX +static inline int8_t guf_min_i8(int8_t a, int8_t b) { return a < b ? a : b; } +static inline int8_t guf_max_i8(int8_t a, int8_t b) { return a > b ? a : b; } +static inline int8_t guf_clamp_i8(int8_t x, int8_t min, int8_t max) { if (x < min) {return min;} if (x > max) {return max;} return x; } +#endif +#ifdef INT16_MAX +static inline int16_t guf_min_i16(int16_t a, int16_t b) { return a < b ? a : b; } +static inline int16_t guf_max_i16(int16_t a, int16_t b) { return a > b ? a : b; } +static inline int16_t guf_clamp_i16(int16_t x, int16_t min, int16_t max) { if (x < min) {return min;} if (x > max) {return max;} return x; } +#endif + +#ifdef INT32_MAX +static inline int32_t guf_min_i32(int32_t a, int32_t b) { return a < b ? a : b; } +static inline int32_t guf_max_i32(int32_t a, int32_t b) { return a > b ? a : b; } +static inline int32_t guf_clamp_i32(int32_t x, int32_t min, int32_t max) { if (x < min) {return min;} if (x > max) {return max;} return x; } +#endif + +#ifdef INT64_MAX +static inline int64_t guf_min_i64(int64_t a, int64_t b) { return a < b ? a : b; } +static inline int64_t guf_max_i64(int64_t a, int64_t b) { return a > b ? a : b; } +static inline int64_t guf_clamp_i64(int64_t x, int64_t min, int64_t max) { if (x < min) {return min;} if (x > max) {return max;} return x; } +#endif + +// Unsigned min, max, clamp functions (generated with libguf/tools/min_max_clamp-gen.py) static inline unsigned char guf_min_uchar(unsigned char a, unsigned char b) { return a < b ? a : b; } static inline unsigned char guf_max_uchar(unsigned char a, unsigned char b) { return a > b ? a : b; } static inline unsigned char guf_clamp_uchar(unsigned char x, unsigned char min, unsigned char max) { if (x < min) {return min;} if (x > max) {return max;} return x; } @@ -106,51 +162,103 @@ static inline unsigned long long guf_min_ulong_long(unsigned long long a, unsign static inline unsigned long long guf_max_ulong_long(unsigned long long a, unsigned long long b) { return a > b ? a : b; } static inline unsigned long long guf_clamp_ulong_long(unsigned long long x, unsigned long long min, unsigned long long max) { if (x < min) {return min;} if (x > max) {return max;} return x; } -static inline uint8_t guf_min_u8(uint8_t a, uint8_t b) { return a < b ? a : b; } -static inline uint8_t guf_max_u8(uint8_t a, uint8_t b) { return a > b ? a : b; } -static inline uint8_t guf_clamp_u8(uint8_t x, uint8_t min, uint8_t max) { if (x < min) {return min;} if (x > max) {return max;} return x; } - -static inline uint16_t guf_min_u16(uint16_t a, uint16_t b) { return a < b ? a : b; } -static inline uint16_t guf_max_u16(uint16_t a, uint16_t b) { return a > b ? a : b; } -static inline uint16_t guf_clamp_u16(uint16_t x, uint16_t min, uint16_t max) { if (x < min) {return min;} if (x > max) {return max;} return x; } - -static inline uint32_t guf_min_u32(uint32_t a, uint32_t b) { return a < b ? a : b; } -static inline uint32_t guf_max_u32(uint32_t a, uint32_t b) { return a > b ? a : b; } -static inline uint32_t guf_clamp_u32(uint32_t x, uint32_t min, uint32_t max) { if (x < min) {return min;} if (x > max) {return max;} return x; } - -static inline uint64_t guf_min_u64(uint64_t a, uint64_t b) { return a < b ? a : b; } -static inline uint64_t guf_max_u64(uint64_t a, uint64_t b) { return a > b ? a : b; } -static inline uint64_t guf_clamp_u64(uint64_t x, uint64_t min, uint64_t max) { if (x < min) {return min;} if (x > max) {return max;} return x; } - static inline size_t guf_min_size_t(size_t a, size_t b) { return a < b ? a : b; } static inline size_t guf_max_size_t(size_t a, size_t b) { return a > b ? a : b; } static inline size_t guf_clamp_size_t(size_t x, size_t min, size_t max) { if (x < min) {return min;} if (x > max) {return max;} return x; } +static inline uint_fast8_t guf_min_u8_fast(uint_fast8_t a, uint_fast8_t b) { return a < b ? a : b; } +static inline uint_fast8_t guf_max_u8_fast(uint_fast8_t a, uint_fast8_t b) { return a > b ? a : b; } +static inline uint_fast8_t guf_clamp_u8_fast(uint_fast8_t x, uint_fast8_t min, uint_fast8_t max) { if (x < min) {return min;} if (x > max) {return max;} return x; } + +static inline uint_fast16_t guf_min_u16_fast(uint_fast16_t a, uint_fast16_t b) { return a < b ? a : b; } +static inline uint_fast16_t guf_max_u16_fast(uint_fast16_t a, uint_fast16_t b) { return a > b ? a : b; } +static inline uint_fast16_t guf_clamp_u16_fast(uint_fast16_t x, uint_fast16_t min, uint_fast16_t max) { if (x < min) {return min;} if (x > max) {return max;} return x; } + +static inline uint_fast32_t guf_min_u32_fast(uint_fast32_t a, uint_fast32_t b) { return a < b ? a : b; } +static inline uint_fast32_t guf_max_u32_fast(uint_fast32_t a, uint_fast32_t b) { return a > b ? a : b; } +static inline uint_fast32_t guf_clamp_u32_fast(uint_fast32_t x, uint_fast32_t min, uint_fast32_t max) { if (x < min) {return min;} if (x > max) {return max;} return x; } + +static inline uint_fast64_t guf_min_u64_fast(uint_fast64_t a, uint_fast64_t b) { return a < b ? a : b; } +static inline uint_fast64_t guf_max_u64_fast(uint_fast64_t a, uint_fast64_t b) { return a > b ? a : b; } +static inline uint_fast64_t guf_clamp_u64_fast(uint_fast64_t x, uint_fast64_t min, uint_fast64_t max) { if (x < min) {return min;} if (x > max) {return max;} return x; } + +#ifdef UINT8_MAX +static inline uint8_t guf_min_u8(uint8_t a, uint8_t b) { return a < b ? a : b; } +static inline uint8_t guf_max_u8(uint8_t a, uint8_t b) { return a > b ? a : b; } +static inline uint8_t guf_clamp_u8(uint8_t x, uint8_t min, uint8_t max) { if (x < min) {return min;} if (x > max) {return max;} return x; } +#endif + +#ifdef UINT16_MAX +static inline uint16_t guf_min_u16(uint16_t a, uint16_t b) { return a < b ? a : b; } +static inline uint16_t guf_max_u16(uint16_t a, uint16_t b) { return a > b ? a : b; } +static inline uint16_t guf_clamp_u16(uint16_t x, uint16_t min, uint16_t max) { if (x < min) {return min;} if (x > max) {return max;} return x; } +#endif + +#ifdef UINT32_MAX +static inline uint32_t guf_min_u32(uint32_t a, uint32_t b) { return a < b ? a : b; } +static inline uint32_t guf_max_u32(uint32_t a, uint32_t b) { return a > b ? a : b; } +static inline uint32_t guf_clamp_u32(uint32_t x, uint32_t min, uint32_t max) { if (x < min) {return min;} if (x > max) {return max;} return x; } +#endif + +#ifdef UINT64_MAX +static inline uint64_t guf_min_u64(uint64_t a, uint64_t b) { return a < b ? a : b; } +static inline uint64_t guf_max_u64(uint64_t a, uint64_t b) { return a > b ? a : b; } +static inline uint64_t guf_clamp_u64(uint64_t x, uint64_t min, uint64_t max) { if (x < min) {return min;} if (x > max) {return max;} return x; } +#endif + // abs functions with signed result (can fail/panic for abs(INT_TYPE_MIN) for platforms with two's complement signed ints; C2X for example guarantees two's complement) -static inline int guf_abs_int(int x) {if (x >= 0) {return x;} GUF_ASSERT_RELEASE(-INT_MAX == INT_MIN || x > INT_MIN); return -x;} // I would not drink that... -static inline int8_t guf_abs_i8 (int8_t x) {if (x >= 0) {return x;} GUF_ASSERT_RELEASE(-INT8_MAX == INT8_MIN || x > INT8_MIN); return -x;} -static inline int16_t guf_abs_i16(int16_t x) {if (x >= 0) {return x;} GUF_ASSERT_RELEASE(-INT16_MAX == INT16_MIN || x > INT16_MIN); return -x;} -static inline int32_t guf_abs_i32(int32_t x) {if (x >= 0) {return x;} GUF_ASSERT_RELEASE(-INT32_MAX == INT32_MIN || x > INT32_MIN); return -x;} -static inline int64_t guf_abs_i64(int64_t x) {if (x >= 0) {return x;} GUF_ASSERT_RELEASE(-INT64_MAX == INT64_MIN || x > INT64_MIN); return -x;} -static inline ptrdiff_t guf_abs_ptrdiff(ptrdiff_t x) {if (x >= 0) {return x;} GUF_ASSERT_RELEASE(-PTRDIFF_MAX == PTRDIFF_MIN || x > PTRDIFF_MIN); return -x;} +// static inline int guf_abs_int(int x) {if (x >= 0) {return x;} GUF_ASSERT_RELEASE(-INT_MAX == INT_MIN || x > INT_MIN); return -x;} // I would not drink that... +// static inline int8_t guf_abs_i8 (int8_t x) {if (x >= 0) {return x;} GUF_ASSERT_RELEASE(-INT8_MAX == INT8_MIN || x > INT8_MIN); return -x;} +// static inline int16_t guf_abs_i16(int16_t x) {if (x >= 0) {return x;} GUF_ASSERT_RELEASE(-INT16_MAX == INT16_MIN || x > INT16_MIN); return -x;} +// static inline int32_t guf_abs_i32(int32_t x) {if (x >= 0) {return x;} GUF_ASSERT_RELEASE(-INT32_MAX == INT32_MIN || x > INT32_MIN); return -x;} +// static inline int64_t guf_abs_i64(int64_t x) {if (x >= 0) {return x;} GUF_ASSERT_RELEASE(-INT64_MAX == INT64_MIN || x > INT64_MIN); return -x;} +// static inline ptrdiff_t guf_abs_ptrdiff(ptrdiff_t x) {if (x >= 0) {return x;} GUF_ASSERT_RELEASE(-PTRDIFF_MAX == PTRDIFF_MIN || x > PTRDIFF_MIN); return -x;} // abs functions with unsigned result functions (cannot fail) -static inline unsigned guf_uabs_int(int x) {if (x >= 0) {return x;} else if (x == INT_MIN && -INT_MAX != INT_MIN) {return (unsigned)INT_MAX + 1u;} else {return -x;}} -static inline uint8_t guf_uabs_i8(int8_t x) {if (x >= 0) {return x;} else if (x == INT8_MIN && -INT8_MAX != INT8_MIN) {return (uint8_t)INT8_MAX + 1u;} else {return -x;}} -static inline uint16_t guf_uabs_i16(int16_t x) {if (x >= 0) {return x;} else if (x == INT16_MIN && -INT16_MAX != INT16_MIN) {return (uint16_t)INT16_MAX + 1u;} else {return -x;}} -static inline uint32_t guf_uabs_i32(int32_t x) {if (x >= 0) {return x;} else if (x == INT32_MIN && -INT32_MAX != INT32_MIN) {return (uint32_t)INT32_MAX + 1u;} else {return -x;}} -static inline uint64_t guf_uabs_i64(int64_t x) {if (x >= 0) {return x;} else if (x == INT64_MIN && -INT64_MAX != INT64_MIN) {return (uint64_t)INT64_MAX + 1u;} else {return -x;}} -static inline size_t guf_uabs_ptrdiff_t(ptrdiff_t x) {if (x >= 0) {return x;} else if (x == PTRDIFF_MIN && -PTRDIFF_MAX != PTRDIFF_MIN) {return (size_t)PTRDIFF_MAX + 1u;} else {return -x;}} +static inline unsigned guf_uabs_int(int x) {if (x >= 0) {return x;} else if (x == INT_MIN && -INT_MAX != INT_MIN) {return (unsigned)INT_MAX + 1u;} else {return -x;}} +static inline unsigned long guf_uabs_long(long x) {if (x >= 0) {return x;} else if (x == LONG_MIN && -LONG_MAX != LONG_MIN) {return (unsigned long)LONG_MAX + 1u;} else {return -x;}} +static inline unsigned long long guf_uabs_long_long(long long x) {if (x >= 0) {return x;} else if (x == LLONG_MIN && -LLONG_MAX != LONG_MIN) {return (unsigned long long)LLONG_MAX + 1u;} else {return -x;}} +static inline size_t guf_uabs_ptrdiff_t(ptrdiff_t x) {if (x >= 0) {return x;} else if (x == PTRDIFF_MIN && -PTRDIFF_MAX != PTRDIFF_MIN) {return (size_t)PTRDIFF_MAX + 1u;} else {return -x;}} + +#if defined(UINT8_MAX) && defined(INT8_MAX) + static inline uint8_t guf_uabs_i8(int8_t x) {if (x >= 0) {return x;} else if (x == INT8_MIN && -INT8_MAX != INT8_MIN) {return (uint8_t)INT8_MAX + 1u;} else {return -x;}} +#endif +#if defined(UINT16_MAX) && defined(INT16_MAX) + static inline uint16_t guf_uabs_i16(int16_t x) {if (x >= 0) {return x;} else if (x == INT16_MIN && -INT16_MAX != INT16_MIN) {return (uint16_t)INT16_MAX + 1u;} else {return -x;}} +#endif +#if defined(UINT32_MAX) && defined(INT32_MAX) + static inline uint32_t guf_uabs_i32(int32_t x) {if (x >= 0) {return x;} else if (x == INT32_MIN && -INT32_MAX != INT32_MIN) {return (uint32_t)INT32_MAX + 1u;} else {return -x;}} +#endif +#if defined(UINT64_MAX) && defined(INT64_MAX) + static inline uint64_t guf_uabs_i64(int64_t x) {if (x >= 0) {return x;} else if (x == INT64_MIN && -INT64_MAX != INT64_MIN) {return (uint64_t)INT64_MAX + 1u;} else {return -x;}} +#endif // absdiff functions with unsigned result (cannot fail) -static inline unsigned char guf_absdiff_char(char a, char b) {return a > b ? (unsigned char)a - (unsigned char)b : (unsigned char)b - (unsigned char)a;} -static inline unsigned guf_absdiff_int(int a, int b) {return a > b ? (unsigned)a - (unsigned)b : (unsigned)b - (unsigned)a;} -static inline uint8_t guf_absdiff_i8(int8_t a, int8_t b) {return a > b ? (uint8_t)a - (uint8_t)b : (uint8_t)b - (uint8_t)a;} -static inline uint16_t guf_absdiff_i16(int16_t a, int16_t b) {return a > b ? (uint16_t)a - (uint16_t)b : (uint16_t)b - (uint16_t)a;} -static inline uint32_t guf_absdiff_i32(int32_t a, int32_t b) {return a > b ? (uint32_t)a - (uint32_t)b : (uint32_t)b - (uint32_t)a;} -static inline uint64_t guf_absdiff_i64(int64_t a, int64_t b) {return a > b ? (uint64_t)a - (uint64_t)b : (uint64_t)b - (uint64_t)a;} -static inline size_t guf_absdiff_ptrdiff_t(ptrdiff_t a, ptrdiff_t b) {return a > b ? (size_t)a - (size_t)b : (size_t)b - (size_t)a;} +static inline unsigned char guf_absdiff_char(char a, char b) {return a > b ? (unsigned char)a - (unsigned char)b : (unsigned char)b - (unsigned char)a;} +static inline unsigned short guf_absdiff_short(short a, short b) {return a > b ? (unsigned short)a - (unsigned short)b : (unsigned short)b - (unsigned short)a;} +static inline unsigned guf_absdiff_int(int a, int b) {return a > b ? (unsigned)a - (unsigned)b : (unsigned)b - (unsigned)a;} +static inline unsigned long guf_absdiff_long(long a, long b) {return a > b ? (unsigned long)a - (unsigned long)b : (unsigned long)b - (unsigned long)a;} +static inline unsigned long long guf_absdiff_long_long(long long a, long long b) {return a > b ? (unsigned long long)a - (unsigned long long)b : (unsigned long long)b - (unsigned long long)a;} +static inline size_t guf_absdiff_ptrdiff_t(ptrdiff_t a, ptrdiff_t b) {return a > b ? (size_t)a - (size_t)b : (size_t)b - (size_t)a;} + +static inline uint_fast8_t guf_absdiff_int_fast8_t(int_fast8_t a, int_fast8_t b) {return a > b ? GUF_UWRAP_8( (uint_fast8_t)a - (uint_fast8_t)b) : GUF_UWRAP_8( (uint_fast8_t)b - (uint_fast8_t)a);} +static inline uint_fast16_t guf_absdiff_int_fast16_t(int_fast16_t a, int_fast16_t b) {return a > b ? GUF_UWRAP_16((uint_fast16_t)a - (uint_fast16_t)b) : GUF_UWRAP_16((uint_fast16_t)b - (uint_fast16_t)a);} +static inline uint_fast32_t guf_absdiff_int_fast32_t(int_fast32_t a, int_fast32_t b) {return a > b ? GUF_UWRAP_32((uint_fast32_t)a - (uint_fast32_t)b) : GUF_UWRAP_32((uint_fast32_t)b - (uint_fast32_t)a);} +static inline uint_fast64_t guf_absdiff_int_fast64_t(int_fast64_t a, int_fast64_t b) {return a > b ? GUF_UWRAP_64((uint_fast64_t)a - (uint_fast64_t)b) : GUF_UWRAP_64((uint_fast64_t)b - (uint_fast64_t)a);} + +#if defined(UINT8_MAX) && defined(INT8_MAX) + static inline uint8_t guf_absdiff_i8(int8_t a, int8_t b) {return a > b ? (uint8_t)a - (uint8_t)b : (uint8_t)b - (uint8_t)a;} +#endif +#if defined(UINT16_MAX) && defined(INT16_MAX) + static inline uint16_t guf_absdiff_i16(int16_t a, int16_t b) {return a > b ? (uint16_t)a - (uint16_t)b : (uint16_t)b - (uint16_t)a;} +#endif +#if defined(UINT32_MAX) && defined(INT32_MAX) + static inline uint32_t guf_absdiff_i32(int32_t a, int32_t b) {return a > b ? (uint32_t)a - (uint32_t)b : (uint32_t)b - (uint32_t)a;} +#endif +#if defined(UINT64_MAX) && defined(INT64_MAX) + static inline uint64_t guf_absdiff_i64(int64_t a, int64_t b) {return a > b ? (uint64_t)a - (uint64_t)b : (uint64_t)b - (uint64_t)a;} +#endif static inline bool guf_add_is_overflow_size_t(size_t a, size_t b) @@ -186,12 +294,24 @@ static inline bool guf_size_calc_safe(ptrdiff_t count, ptrdiff_t sizeof_elem, pt // cf. https://graphics.stanford.edu/~seander/bithacks.html#DetermineIfPowerOf2 (last-retrieved 2025-03-19) -static inline bool guf_is_pow2_u8(uint8_t x) { return x && !(x & (x - 1)); } -static inline bool guf_is_pow2_u16(uint16_t x) { return x && !(x & (x - 1)); } -static inline bool guf_is_pow2_u32(uint32_t x) { return x && !(x & (x - 1)); } -static inline bool guf_is_pow2_u64(uint64_t x) { return x && !(x & (x - 1)); } -static inline bool guf_is_pow2_size_t(size_t x) { return x && !(x & (x - 1)); } - +static inline bool guf_is_pow2_uchar(unsigned char x) { return x && !(x & (x - 1)); } +static inline bool guf_is_pow2_ushort(unsigned short x) { return x && !(x & (x - 1)); } +static inline bool guf_is_pow2_unsigned(unsigned x) { return x && !(x & (x - 1)); } +static inline bool guf_is_pow2_ulong(unsigned long x) { return x && !(x & (x - 1)); } +static inline bool guf_is_pow2_ulong_long(unsigned long long x) { return x && !(x & (x - 1)); } +static inline bool guf_is_pow2_size_t(size_t x) { return x && !(x & (x - 1)); } +#ifdef UINT8_MAX + static inline bool guf_is_pow2_u8(uint8_t x) { return x && !(x & (x - 1)); } +#endif +#ifdef UINT16_MAX + static inline bool guf_is_pow2_u16(uint16_t x) { return x && !(x & (x - 1)); } +#endif +#ifdef UINT32_MAX + static inline bool guf_is_pow2_u32(uint32_t x) { return x && !(x & (x - 1)); } +#endif +#if UINT64_MAX + static inline bool guf_is_pow2_u64(uint64_t x) { return x && !(x & (x - 1)); } +#endif static bool guf_nearly_zero_f32(float x, float eps) {return fabsf(x) <= eps;} static bool guf_nearly_one_f32(float x, float eps) {return fabsf(x - 1) <= eps;} diff --git a/src/guf_math_ckdint.h b/src/guf_math_ckdint.h index 3cdd37e..ed55000 100644 --- a/src/guf_math_ckdint.h +++ b/src/guf_math_ckdint.h @@ -83,7 +83,6 @@ typedef enum guf_math_ckd_result {GUF_MATH_CKD_SUCCESS = 0, GUF_MATH_CKD_OVERFLO #if !defined(GUF_MATH_CKDINT_IMPL_STATIC) && !defined(GUF_MATH_CKDINT_IMPL) // Signed integer arithmetic checks (generated with libguf/tools/ckdint-gen.py) - GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_int(int a, int b); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_int(int a, int b); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_int(int a, int b); @@ -96,28 +95,52 @@ GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_long_long(long long a, lon GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_long_long(long long a, long long b); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_long_long(long long a, long long b); -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_i8(int8_t a, int8_t b); -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_i8(int8_t a, int8_t b); -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_i8(int8_t a, int8_t b); - -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_i16(int16_t a, int16_t b); -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_i16(int16_t a, int16_t b); -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_i16(int16_t a, int16_t b); - -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_i32(int32_t a, int32_t b); -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_i32(int32_t a, int32_t b); -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_i32(int32_t a, int32_t b); - -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_i64(int64_t a, int64_t b); -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_i64(int64_t a, int64_t b); -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_i64(int64_t a, int64_t b); - GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_ptrdiff_t(ptrdiff_t a, ptrdiff_t b); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_ptrdiff_t(ptrdiff_t a, ptrdiff_t b); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_ptrdiff_t(ptrdiff_t a, ptrdiff_t b); -// Unsigned integer arithmetic checks (generated with libguf/tools/ckdint-gen.py) +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_int_fast8_t(int_fast8_t a, int_fast8_t b); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_int_fast8_t(int_fast8_t a, int_fast8_t b); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_int_fast8_t(int_fast8_t a, int_fast8_t b); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_int_fast16_t(int_fast16_t a, int_fast16_t b); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_int_fast16_t(int_fast16_t a, int_fast16_t b); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_int_fast16_t(int_fast16_t a, int_fast16_t b); + +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_int_fast32_t(int_fast32_t a, int_fast32_t b); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_int_fast32_t(int_fast32_t a, int_fast32_t b); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_int_fast32_t(int_fast32_t a, int_fast32_t b); + +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_int_fast64_t(int_fast64_t a, int_fast64_t b); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_int_fast64_t(int_fast64_t a, int_fast64_t b); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_int_fast64_t(int_fast64_t a, int_fast64_t b); + +#ifdef INT8_MAX +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_i8(int8_t a, int8_t b); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_i8(int8_t a, int8_t b); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_i8(int8_t a, int8_t b); +#endif + +#ifdef INT16_MAX +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_i16(int16_t a, int16_t b); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_i16(int16_t a, int16_t b); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_i16(int16_t a, int16_t b); +#endif + +#ifdef INT32_MAX +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_i32(int32_t a, int32_t b); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_i32(int32_t a, int32_t b); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_i32(int32_t a, int32_t b); +#endif + +#ifdef INT64_MAX +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_i64(int64_t a, int64_t b); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_i64(int64_t a, int64_t b); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_i64(int64_t a, int64_t b); +#endif + + +// Unsigned integer arithmetic checks (generated with libguf/tools/ckdint-gen.py) GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_uchar(unsigned char a, unsigned char b); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_uchar(unsigned char a, unsigned char b); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_uchar(unsigned char a, unsigned char b); @@ -134,29 +157,53 @@ GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_ulong_long(unsigned long l GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_ulong_long(unsigned long long a, unsigned long long b); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_ulong_long(unsigned long long a, unsigned long long b); -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_u8(uint8_t a, uint8_t b); -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_u8(uint8_t a, uint8_t b); -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_u8(uint8_t a, uint8_t b); - -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_u16(uint16_t a, uint16_t b); -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_u16(uint16_t a, uint16_t b); -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_u16(uint16_t a, uint16_t b); - -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_u32(uint32_t a, uint32_t b); -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_u32(uint32_t a, uint32_t b); -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_u32(uint32_t a, uint32_t b); - -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_u64(uint64_t a, uint64_t b); -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_u64(uint64_t a, uint64_t b); -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_u64(uint64_t a, uint64_t b); - GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_size_t(size_t a, size_t b); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_size_t(size_t a, size_t b); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_size_t(size_t a, size_t b); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_uint_fast8_t(uint_fast8_t a, uint_fast8_t b); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_uint_fast8_t(uint_fast8_t a, uint_fast8_t b); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_uint_fast8_t(uint_fast8_t a, uint_fast8_t b); + +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_uint_fast16_t(uint_fast16_t a, uint_fast16_t b); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_uint_fast16_t(uint_fast16_t a, uint_fast16_t b); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_uint_fast16_t(uint_fast16_t a, uint_fast16_t b); + +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_uint_fast32_t(uint_fast32_t a, uint_fast32_t b); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_uint_fast32_t(uint_fast32_t a, uint_fast32_t b); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_uint_fast32_t(uint_fast32_t a, uint_fast32_t b); + +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_uint_fast64_t(uint_fast64_t a, uint_fast64_t b); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_uint_fast64_t(uint_fast64_t a, uint_fast64_t b); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_uint_fast64_t(uint_fast64_t a, uint_fast64_t b); + +#ifdef UINT8_MAX +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_u8(uint8_t a, uint8_t b); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_u8(uint8_t a, uint8_t b); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_u8(uint8_t a, uint8_t b); +#endif + +#ifdef UINT16_MAX +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_u16(uint16_t a, uint16_t b); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_u16(uint16_t a, uint16_t b); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_u16(uint16_t a, uint16_t b); +#endif + +#ifdef UINT32_MAX +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_u32(uint32_t a, uint32_t b); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_u32(uint32_t a, uint32_t b); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_u32(uint32_t a, uint32_t b); +#endif + +#ifdef UINT64_MAX +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_u64(uint64_t a, uint64_t b); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_u64(uint64_t a, uint64_t b); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_u64(uint64_t a, uint64_t b); +#endif + + // Signed saturating/wrapping arithmetic (generated with libguf/tools/ckdint-gen.py) - GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_int(int a, int b, int *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_int(int a, int b, int *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_int(int a, int b, int *result); @@ -165,7 +212,6 @@ GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_int(int a, int b, int GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_int(int a, int b, int *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_int(int a, int b, int *result); - GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_long(long a, long b, long *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_long(long a, long b, long *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_long(long a, long b, long *result); @@ -174,7 +220,6 @@ GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_long(long a, long b, GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_long(long a, long b, long *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_long(long a, long b, long *result); - GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_long_long(long long a, long long b, long long *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_long_long(long long a, long long b, long long *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_long_long(long long a, long long b, long long *result); @@ -183,43 +228,6 @@ GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_long_long(long long a GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_long_long(long long a, long long b, long long *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_long_long(long long a, long long b, long long *result); - -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_i8(int8_t a, int8_t b, int8_t *result); -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_i8(int8_t a, int8_t b, int8_t *result); -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_i8(int8_t a, int8_t b, int8_t *result); - -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_i8(int8_t a, int8_t b, int8_t *result); -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_i8(int8_t a, int8_t b, int8_t *result); -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_i8(int8_t a, int8_t b, int8_t *result); - - -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_i16(int16_t a, int16_t b, int16_t *result); -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_i16(int16_t a, int16_t b, int16_t *result); -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_i16(int16_t a, int16_t b, int16_t *result); - -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_i16(int16_t a, int16_t b, int16_t *result); -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_i16(int16_t a, int16_t b, int16_t *result); -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_i16(int16_t a, int16_t b, int16_t *result); - - -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_i32(int32_t a, int32_t b, int32_t *result); -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_i32(int32_t a, int32_t b, int32_t *result); -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_i32(int32_t a, int32_t b, int32_t *result); - -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_i32(int32_t a, int32_t b, int32_t *result); -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_i32(int32_t a, int32_t b, int32_t *result); -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_i32(int32_t a, int32_t b, int32_t *result); - - -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_i64(int64_t a, int64_t b, int64_t *result); -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_i64(int64_t a, int64_t b, int64_t *result); -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_i64(int64_t a, int64_t b, int64_t *result); - -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_i64(int64_t a, int64_t b, int64_t *result); -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_i64(int64_t a, int64_t b, int64_t *result); -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_i64(int64_t a, int64_t b, int64_t *result); - - GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_ptrdiff_t(ptrdiff_t a, ptrdiff_t b, ptrdiff_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_ptrdiff_t(ptrdiff_t a, ptrdiff_t b, ptrdiff_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_ptrdiff_t(ptrdiff_t a, ptrdiff_t b, ptrdiff_t *result); @@ -228,9 +236,80 @@ GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_ptrdiff_t(ptrdiff_t a GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_ptrdiff_t(ptrdiff_t a, ptrdiff_t b, ptrdiff_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_ptrdiff_t(ptrdiff_t a, ptrdiff_t b, ptrdiff_t *result); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_int_fast8_t(int_fast8_t a, int_fast8_t b, int_fast8_t *result); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_int_fast8_t(int_fast8_t a, int_fast8_t b, int_fast8_t *result); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_int_fast8_t(int_fast8_t a, int_fast8_t b, int_fast8_t *result); + +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_int_fast8_t(int_fast8_t a, int_fast8_t b, int_fast8_t *result); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_int_fast8_t(int_fast8_t a, int_fast8_t b, int_fast8_t *result); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_int_fast8_t(int_fast8_t a, int_fast8_t b, int_fast8_t *result); + +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_int_fast16_t(int_fast16_t a, int_fast16_t b, int_fast16_t *result); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_int_fast16_t(int_fast16_t a, int_fast16_t b, int_fast16_t *result); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_int_fast16_t(int_fast16_t a, int_fast16_t b, int_fast16_t *result); + +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_int_fast16_t(int_fast16_t a, int_fast16_t b, int_fast16_t *result); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_int_fast16_t(int_fast16_t a, int_fast16_t b, int_fast16_t *result); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_int_fast16_t(int_fast16_t a, int_fast16_t b, int_fast16_t *result); + +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_int_fast32_t(int_fast32_t a, int_fast32_t b, int_fast32_t *result); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_int_fast32_t(int_fast32_t a, int_fast32_t b, int_fast32_t *result); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_int_fast32_t(int_fast32_t a, int_fast32_t b, int_fast32_t *result); + +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_int_fast32_t(int_fast32_t a, int_fast32_t b, int_fast32_t *result); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_int_fast32_t(int_fast32_t a, int_fast32_t b, int_fast32_t *result); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_int_fast32_t(int_fast32_t a, int_fast32_t b, int_fast32_t *result); + +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_int_fast64_t(int_fast64_t a, int_fast64_t b, int_fast64_t *result); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_int_fast64_t(int_fast64_t a, int_fast64_t b, int_fast64_t *result); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_int_fast64_t(int_fast64_t a, int_fast64_t b, int_fast64_t *result); + +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_int_fast64_t(int_fast64_t a, int_fast64_t b, int_fast64_t *result); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_int_fast64_t(int_fast64_t a, int_fast64_t b, int_fast64_t *result); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_int_fast64_t(int_fast64_t a, int_fast64_t b, int_fast64_t *result); + +#ifdef INT8_MAX +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_i8(int8_t a, int8_t b, int8_t *result); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_i8(int8_t a, int8_t b, int8_t *result); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_i8(int8_t a, int8_t b, int8_t *result); + +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_i8(int8_t a, int8_t b, int8_t *result); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_i8(int8_t a, int8_t b, int8_t *result); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_i8(int8_t a, int8_t b, int8_t *result); +#endif + +#ifdef INT16_MAX +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_i16(int16_t a, int16_t b, int16_t *result); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_i16(int16_t a, int16_t b, int16_t *result); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_i16(int16_t a, int16_t b, int16_t *result); + +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_i16(int16_t a, int16_t b, int16_t *result); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_i16(int16_t a, int16_t b, int16_t *result); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_i16(int16_t a, int16_t b, int16_t *result); +#endif + +#ifdef INT32_MAX +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_i32(int32_t a, int32_t b, int32_t *result); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_i32(int32_t a, int32_t b, int32_t *result); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_i32(int32_t a, int32_t b, int32_t *result); + +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_i32(int32_t a, int32_t b, int32_t *result); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_i32(int32_t a, int32_t b, int32_t *result); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_i32(int32_t a, int32_t b, int32_t *result); +#endif + +#ifdef INT64_MAX +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_i64(int64_t a, int64_t b, int64_t *result); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_i64(int64_t a, int64_t b, int64_t *result); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_i64(int64_t a, int64_t b, int64_t *result); + +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_i64(int64_t a, int64_t b, int64_t *result); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_i64(int64_t a, int64_t b, int64_t *result); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_i64(int64_t a, int64_t b, int64_t *result); +#endif + // Unsigned saturating/wrapping arithmetic (generated with libguf/tools/ckdint-gen.py) - GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_uchar(unsigned char a, unsigned char b, unsigned char *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_uchar(unsigned char a, unsigned char b, unsigned char *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_uchar(unsigned char a, unsigned char b, unsigned char *result); @@ -239,7 +318,6 @@ GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_uchar(unsigned char a GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_uchar(unsigned char a, unsigned char b, unsigned char *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_uchar(unsigned char a, unsigned char b, unsigned char *result); - GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_unsigned(unsigned a, unsigned b, unsigned *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_unsigned(unsigned a, unsigned b, unsigned *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_unsigned(unsigned a, unsigned b, unsigned *result); @@ -248,7 +326,6 @@ GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_unsigned(unsigned a, GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_unsigned(unsigned a, unsigned b, unsigned *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_unsigned(unsigned a, unsigned b, unsigned *result); - GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_ulong(unsigned long a, unsigned long b, unsigned long *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_ulong(unsigned long a, unsigned long b, unsigned long *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_ulong(unsigned long a, unsigned long b, unsigned long *result); @@ -257,7 +334,6 @@ GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_ulong(unsigned long a GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_ulong(unsigned long a, unsigned long b, unsigned long *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_ulong(unsigned long a, unsigned long b, unsigned long *result); - GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_ulong_long(unsigned long long a, unsigned long long b, unsigned long long *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_ulong_long(unsigned long long a, unsigned long long b, unsigned long long *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_ulong_long(unsigned long long a, unsigned long long b, unsigned long long *result); @@ -266,43 +342,6 @@ GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_ulong_long(unsigned l GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_ulong_long(unsigned long long a, unsigned long long b, unsigned long long *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_ulong_long(unsigned long long a, unsigned long long b, unsigned long long *result); - -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_u8(uint8_t a, uint8_t b, uint8_t *result); -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_u8(uint8_t a, uint8_t b, uint8_t *result); -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_u8(uint8_t a, uint8_t b, uint8_t *result); - -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_u8(uint8_t a, uint8_t b, uint8_t *result); -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_u8(uint8_t a, uint8_t b, uint8_t *result); -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_u8(uint8_t a, uint8_t b, uint8_t *result); - - -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_u16(uint16_t a, uint16_t b, uint16_t *result); -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_u16(uint16_t a, uint16_t b, uint16_t *result); -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_u16(uint16_t a, uint16_t b, uint16_t *result); - -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_u16(uint16_t a, uint16_t b, uint16_t *result); -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_u16(uint16_t a, uint16_t b, uint16_t *result); -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_u16(uint16_t a, uint16_t b, uint16_t *result); - - -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_u32(uint32_t a, uint32_t b, uint32_t *result); -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_u32(uint32_t a, uint32_t b, uint32_t *result); -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_u32(uint32_t a, uint32_t b, uint32_t *result); - -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_u32(uint32_t a, uint32_t b, uint32_t *result); -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_u32(uint32_t a, uint32_t b, uint32_t *result); -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_u32(uint32_t a, uint32_t b, uint32_t *result); - - -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_u64(uint64_t a, uint64_t b, uint64_t *result); -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_u64(uint64_t a, uint64_t b, uint64_t *result); -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_u64(uint64_t a, uint64_t b, uint64_t *result); - -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_u64(uint64_t a, uint64_t b, uint64_t *result); -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_u64(uint64_t a, uint64_t b, uint64_t *result); -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_u64(uint64_t a, uint64_t b, uint64_t *result); - - GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_size_t(size_t a, size_t b, size_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_size_t(size_t a, size_t b, size_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_size_t(size_t a, size_t b, size_t *result); @@ -311,12 +350,83 @@ GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_size_t(size_t a, size GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_size_t(size_t a, size_t b, size_t *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_size_t(size_t a, size_t b, size_t *result); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_uint_fast8_t(uint_fast8_t a, uint_fast8_t b, uint_fast8_t *result); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_uint_fast8_t(uint_fast8_t a, uint_fast8_t b, uint_fast8_t *result); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_uint_fast8_t(uint_fast8_t a, uint_fast8_t b, uint_fast8_t *result); + +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_uint_fast8_t(uint_fast8_t a, uint_fast8_t b, uint_fast8_t *result); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_uint_fast8_t(uint_fast8_t a, uint_fast8_t b, uint_fast8_t *result); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_uint_fast8_t(uint_fast8_t a, uint_fast8_t b, uint_fast8_t *result); + +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_uint_fast16_t(uint_fast16_t a, uint_fast16_t b, uint_fast16_t *result); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_uint_fast16_t(uint_fast16_t a, uint_fast16_t b, uint_fast16_t *result); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_uint_fast16_t(uint_fast16_t a, uint_fast16_t b, uint_fast16_t *result); + +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_uint_fast16_t(uint_fast16_t a, uint_fast16_t b, uint_fast16_t *result); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_uint_fast16_t(uint_fast16_t a, uint_fast16_t b, uint_fast16_t *result); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_uint_fast16_t(uint_fast16_t a, uint_fast16_t b, uint_fast16_t *result); + +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_uint_fast32_t(uint_fast32_t a, uint_fast32_t b, uint_fast32_t *result); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_uint_fast32_t(uint_fast32_t a, uint_fast32_t b, uint_fast32_t *result); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_uint_fast32_t(uint_fast32_t a, uint_fast32_t b, uint_fast32_t *result); + +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_uint_fast32_t(uint_fast32_t a, uint_fast32_t b, uint_fast32_t *result); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_uint_fast32_t(uint_fast32_t a, uint_fast32_t b, uint_fast32_t *result); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_uint_fast32_t(uint_fast32_t a, uint_fast32_t b, uint_fast32_t *result); + +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_uint_fast64_t(uint_fast64_t a, uint_fast64_t b, uint_fast64_t *result); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_uint_fast64_t(uint_fast64_t a, uint_fast64_t b, uint_fast64_t *result); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_uint_fast64_t(uint_fast64_t a, uint_fast64_t b, uint_fast64_t *result); + +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_uint_fast64_t(uint_fast64_t a, uint_fast64_t b, uint_fast64_t *result); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_uint_fast64_t(uint_fast64_t a, uint_fast64_t b, uint_fast64_t *result); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_uint_fast64_t(uint_fast64_t a, uint_fast64_t b, uint_fast64_t *result); + +#ifdef UINT8_MAX +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_u8(uint8_t a, uint8_t b, uint8_t *result); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_u8(uint8_t a, uint8_t b, uint8_t *result); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_u8(uint8_t a, uint8_t b, uint8_t *result); + +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_u8(uint8_t a, uint8_t b, uint8_t *result); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_u8(uint8_t a, uint8_t b, uint8_t *result); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_u8(uint8_t a, uint8_t b, uint8_t *result); +#endif + +#ifdef UINT16_MAX +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_u16(uint16_t a, uint16_t b, uint16_t *result); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_u16(uint16_t a, uint16_t b, uint16_t *result); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_u16(uint16_t a, uint16_t b, uint16_t *result); + +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_u16(uint16_t a, uint16_t b, uint16_t *result); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_u16(uint16_t a, uint16_t b, uint16_t *result); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_u16(uint16_t a, uint16_t b, uint16_t *result); +#endif + +#ifdef UINT32_MAX +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_u32(uint32_t a, uint32_t b, uint32_t *result); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_u32(uint32_t a, uint32_t b, uint32_t *result); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_u32(uint32_t a, uint32_t b, uint32_t *result); + +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_u32(uint32_t a, uint32_t b, uint32_t *result); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_u32(uint32_t a, uint32_t b, uint32_t *result); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_u32(uint32_t a, uint32_t b, uint32_t *result); +#endif + +#ifdef UINT64_MAX +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_u64(uint64_t a, uint64_t b, uint64_t *result); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_u64(uint64_t a, uint64_t b, uint64_t *result); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_u64(uint64_t a, uint64_t b, uint64_t *result); + +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_u64(uint64_t a, uint64_t b, uint64_t *result); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_u64(uint64_t a, uint64_t b, uint64_t *result); +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_u64(uint64_t a, uint64_t b, uint64_t *result); +#endif #endif + #if defined(GUF_MATH_CKDINT_IMPL) || defined(GUF_MATH_CKDINT_IMPL_STATIC) #include "guf_assert.h" // Signed integer arithmetic checks (generated with libguf/tools/ckdint-gen.py) - GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_int(int a, int b) { if (b > 0 && a > INT_MAX - b) { @@ -452,186 +562,6 @@ GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_long_long(long long a, lon } } -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_i8(int8_t a, int8_t b) -{ - if (b > 0 && a > INT8_MAX - b) { - return GUF_MATH_CKD_OVERFLOW_POS; - } else if (b < 0 && a < INT8_MIN - b) { - return GUF_MATH_CKD_OVERFLOW_NEG; - } else { - return GUF_MATH_CKD_SUCCESS; - } -} -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_i8(int8_t a, int8_t b) -{ - if (b < 0 && a > INT8_MAX + b) { - return GUF_MATH_CKD_OVERFLOW_POS; - } else if (b > 0 && a < INT8_MIN + b) { - return GUF_MATH_CKD_OVERFLOW_NEG; - } else { - return GUF_MATH_CKD_SUCCESS; - } -} -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_i8(int8_t a, int8_t b) -{ - if (b > 0) { - if (a > INT8_MAX / b) { - return GUF_MATH_CKD_OVERFLOW_POS; - } else if (a < INT8_MIN / b) { - return GUF_MATH_CKD_OVERFLOW_NEG; - } else { - return GUF_MATH_CKD_SUCCESS; - } - } else if (b < 0) { - if (INT8_MIN != -INT8_MAX && b == -1) { // Prevent potential (INT8_MIN / b) overflow for b == -1 - return a == INT8_MIN ? GUF_MATH_CKD_OVERFLOW_POS : GUF_MATH_CKD_SUCCESS; - } else if (a < INT8_MAX / b) { - return GUF_MATH_CKD_OVERFLOW_POS; - } else if (a > INT8_MIN / b) { - return GUF_MATH_CKD_OVERFLOW_NEG; - } else { - return GUF_MATH_CKD_SUCCESS; - } - } else { - return GUF_MATH_CKD_SUCCESS; - } -} - -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_i16(int16_t a, int16_t b) -{ - if (b > 0 && a > INT16_MAX - b) { - return GUF_MATH_CKD_OVERFLOW_POS; - } else if (b < 0 && a < INT16_MIN - b) { - return GUF_MATH_CKD_OVERFLOW_NEG; - } else { - return GUF_MATH_CKD_SUCCESS; - } -} -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_i16(int16_t a, int16_t b) -{ - if (b < 0 && a > INT16_MAX + b) { - return GUF_MATH_CKD_OVERFLOW_POS; - } else if (b > 0 && a < INT16_MIN + b) { - return GUF_MATH_CKD_OVERFLOW_NEG; - } else { - return GUF_MATH_CKD_SUCCESS; - } -} -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_i16(int16_t a, int16_t b) -{ - if (b > 0) { - if (a > INT16_MAX / b) { - return GUF_MATH_CKD_OVERFLOW_POS; - } else if (a < INT16_MIN / b) { - return GUF_MATH_CKD_OVERFLOW_NEG; - } else { - return GUF_MATH_CKD_SUCCESS; - } - } else if (b < 0) { - if (INT16_MIN != -INT16_MAX && b == -1) { // Prevent potential (INT16_MIN / b) overflow for b == -1 - return a == INT16_MIN ? GUF_MATH_CKD_OVERFLOW_POS : GUF_MATH_CKD_SUCCESS; - } else if (a < INT16_MAX / b) { - return GUF_MATH_CKD_OVERFLOW_POS; - } else if (a > INT16_MIN / b) { - return GUF_MATH_CKD_OVERFLOW_NEG; - } else { - return GUF_MATH_CKD_SUCCESS; - } - } else { - return GUF_MATH_CKD_SUCCESS; - } -} - -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_i32(int32_t a, int32_t b) -{ - if (b > 0 && a > INT32_MAX - b) { - return GUF_MATH_CKD_OVERFLOW_POS; - } else if (b < 0 && a < INT32_MIN - b) { - return GUF_MATH_CKD_OVERFLOW_NEG; - } else { - return GUF_MATH_CKD_SUCCESS; - } -} -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_i32(int32_t a, int32_t b) -{ - if (b < 0 && a > INT32_MAX + b) { - return GUF_MATH_CKD_OVERFLOW_POS; - } else if (b > 0 && a < INT32_MIN + b) { - return GUF_MATH_CKD_OVERFLOW_NEG; - } else { - return GUF_MATH_CKD_SUCCESS; - } -} -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_i32(int32_t a, int32_t b) -{ - if (b > 0) { - if (a > INT32_MAX / b) { - return GUF_MATH_CKD_OVERFLOW_POS; - } else if (a < INT32_MIN / b) { - return GUF_MATH_CKD_OVERFLOW_NEG; - } else { - return GUF_MATH_CKD_SUCCESS; - } - } else if (b < 0) { - if (INT32_MIN != -INT32_MAX && b == -1) { // Prevent potential (INT32_MIN / b) overflow for b == -1 - return a == INT32_MIN ? GUF_MATH_CKD_OVERFLOW_POS : GUF_MATH_CKD_SUCCESS; - } else if (a < INT32_MAX / b) { - return GUF_MATH_CKD_OVERFLOW_POS; - } else if (a > INT32_MIN / b) { - return GUF_MATH_CKD_OVERFLOW_NEG; - } else { - return GUF_MATH_CKD_SUCCESS; - } - } else { - return GUF_MATH_CKD_SUCCESS; - } -} - -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_i64(int64_t a, int64_t b) -{ - if (b > 0 && a > INT64_MAX - b) { - return GUF_MATH_CKD_OVERFLOW_POS; - } else if (b < 0 && a < INT64_MIN - b) { - return GUF_MATH_CKD_OVERFLOW_NEG; - } else { - return GUF_MATH_CKD_SUCCESS; - } -} -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_i64(int64_t a, int64_t b) -{ - if (b < 0 && a > INT64_MAX + b) { - return GUF_MATH_CKD_OVERFLOW_POS; - } else if (b > 0 && a < INT64_MIN + b) { - return GUF_MATH_CKD_OVERFLOW_NEG; - } else { - return GUF_MATH_CKD_SUCCESS; - } -} -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_i64(int64_t a, int64_t b) -{ - if (b > 0) { - if (a > INT64_MAX / b) { - return GUF_MATH_CKD_OVERFLOW_POS; - } else if (a < INT64_MIN / b) { - return GUF_MATH_CKD_OVERFLOW_NEG; - } else { - return GUF_MATH_CKD_SUCCESS; - } - } else if (b < 0) { - if (INT64_MIN != -INT64_MAX && b == -1) { // Prevent potential (INT64_MIN / b) overflow for b == -1 - return a == INT64_MIN ? GUF_MATH_CKD_OVERFLOW_POS : GUF_MATH_CKD_SUCCESS; - } else if (a < INT64_MAX / b) { - return GUF_MATH_CKD_OVERFLOW_POS; - } else if (a > INT64_MIN / b) { - return GUF_MATH_CKD_OVERFLOW_NEG; - } else { - return GUF_MATH_CKD_SUCCESS; - } - } else { - return GUF_MATH_CKD_SUCCESS; - } -} - GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_ptrdiff_t(ptrdiff_t a, ptrdiff_t b) { if (b > 0 && a > PTRDIFF_MAX - b) { @@ -677,8 +607,376 @@ GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_ptrdiff_t(ptrdiff_t a, ptr } } -// Unsigned integer arithmetic checks (generated with libguf/tools/ckdint-gen.py) +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_int_fast8_t(int_fast8_t a, int_fast8_t b) +{ + if (b > 0 && a > GUF_INT8_MAX - b) { + return GUF_MATH_CKD_OVERFLOW_POS; + } else if (b < 0 && a < GUF_INT8_MIN - b) { + return GUF_MATH_CKD_OVERFLOW_NEG; + } else { + return GUF_MATH_CKD_SUCCESS; + } +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_int_fast8_t(int_fast8_t a, int_fast8_t b) +{ + if (b < 0 && a > GUF_INT8_MAX + b) { + return GUF_MATH_CKD_OVERFLOW_POS; + } else if (b > 0 && a < GUF_INT8_MIN + b) { + return GUF_MATH_CKD_OVERFLOW_NEG; + } else { + return GUF_MATH_CKD_SUCCESS; + } +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_int_fast8_t(int_fast8_t a, int_fast8_t b) +{ + if (b > 0) { + if (a > GUF_INT8_MAX / b) { + return GUF_MATH_CKD_OVERFLOW_POS; + } else if (a < GUF_INT8_MIN / b) { + return GUF_MATH_CKD_OVERFLOW_NEG; + } else { + return GUF_MATH_CKD_SUCCESS; + } + } else if (b < 0) { + if (GUF_INT8_MIN != -GUF_INT8_MAX && b == -1) { // Prevent potential (GUF_INT8_MIN / b) overflow for b == -1 + return a == GUF_INT8_MIN ? GUF_MATH_CKD_OVERFLOW_POS : GUF_MATH_CKD_SUCCESS; + } else if (a < GUF_INT8_MAX / b) { + return GUF_MATH_CKD_OVERFLOW_POS; + } else if (a > GUF_INT8_MIN / b) { + return GUF_MATH_CKD_OVERFLOW_NEG; + } else { + return GUF_MATH_CKD_SUCCESS; + } + } else { + return GUF_MATH_CKD_SUCCESS; + } +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_int_fast16_t(int_fast16_t a, int_fast16_t b) +{ + if (b > 0 && a > GUF_INT16_MAX - b) { + return GUF_MATH_CKD_OVERFLOW_POS; + } else if (b < 0 && a < GUF_INT16_MIN - b) { + return GUF_MATH_CKD_OVERFLOW_NEG; + } else { + return GUF_MATH_CKD_SUCCESS; + } +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_int_fast16_t(int_fast16_t a, int_fast16_t b) +{ + if (b < 0 && a > GUF_INT16_MAX + b) { + return GUF_MATH_CKD_OVERFLOW_POS; + } else if (b > 0 && a < GUF_INT16_MIN + b) { + return GUF_MATH_CKD_OVERFLOW_NEG; + } else { + return GUF_MATH_CKD_SUCCESS; + } +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_int_fast16_t(int_fast16_t a, int_fast16_t b) +{ + if (b > 0) { + if (a > GUF_INT16_MAX / b) { + return GUF_MATH_CKD_OVERFLOW_POS; + } else if (a < GUF_INT16_MIN / b) { + return GUF_MATH_CKD_OVERFLOW_NEG; + } else { + return GUF_MATH_CKD_SUCCESS; + } + } else if (b < 0) { + if (GUF_INT16_MIN != -GUF_INT16_MAX && b == -1) { // Prevent potential (GUF_INT16_MIN / b) overflow for b == -1 + return a == GUF_INT16_MIN ? GUF_MATH_CKD_OVERFLOW_POS : GUF_MATH_CKD_SUCCESS; + } else if (a < GUF_INT16_MAX / b) { + return GUF_MATH_CKD_OVERFLOW_POS; + } else if (a > GUF_INT16_MIN / b) { + return GUF_MATH_CKD_OVERFLOW_NEG; + } else { + return GUF_MATH_CKD_SUCCESS; + } + } else { + return GUF_MATH_CKD_SUCCESS; + } +} + +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_int_fast32_t(int_fast32_t a, int_fast32_t b) +{ + if (b > 0 && a > GUF_INT32_MAX - b) { + return GUF_MATH_CKD_OVERFLOW_POS; + } else if (b < 0 && a < GUF_INT32_MIN - b) { + return GUF_MATH_CKD_OVERFLOW_NEG; + } else { + return GUF_MATH_CKD_SUCCESS; + } +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_int_fast32_t(int_fast32_t a, int_fast32_t b) +{ + if (b < 0 && a > GUF_INT32_MAX + b) { + return GUF_MATH_CKD_OVERFLOW_POS; + } else if (b > 0 && a < GUF_INT32_MIN + b) { + return GUF_MATH_CKD_OVERFLOW_NEG; + } else { + return GUF_MATH_CKD_SUCCESS; + } +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_int_fast32_t(int_fast32_t a, int_fast32_t b) +{ + if (b > 0) { + if (a > GUF_INT32_MAX / b) { + return GUF_MATH_CKD_OVERFLOW_POS; + } else if (a < GUF_INT32_MIN / b) { + return GUF_MATH_CKD_OVERFLOW_NEG; + } else { + return GUF_MATH_CKD_SUCCESS; + } + } else if (b < 0) { + if (GUF_INT32_MIN != -GUF_INT32_MAX && b == -1) { // Prevent potential (GUF_INT32_MIN / b) overflow for b == -1 + return a == GUF_INT32_MIN ? GUF_MATH_CKD_OVERFLOW_POS : GUF_MATH_CKD_SUCCESS; + } else if (a < GUF_INT32_MAX / b) { + return GUF_MATH_CKD_OVERFLOW_POS; + } else if (a > GUF_INT32_MIN / b) { + return GUF_MATH_CKD_OVERFLOW_NEG; + } else { + return GUF_MATH_CKD_SUCCESS; + } + } else { + return GUF_MATH_CKD_SUCCESS; + } +} + +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_int_fast64_t(int_fast64_t a, int_fast64_t b) +{ + if (b > 0 && a > GUF_INT64_MAX - b) { + return GUF_MATH_CKD_OVERFLOW_POS; + } else if (b < 0 && a < GUF_INT64_MIN - b) { + return GUF_MATH_CKD_OVERFLOW_NEG; + } else { + return GUF_MATH_CKD_SUCCESS; + } +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_int_fast64_t(int_fast64_t a, int_fast64_t b) +{ + if (b < 0 && a > GUF_INT64_MAX + b) { + return GUF_MATH_CKD_OVERFLOW_POS; + } else if (b > 0 && a < GUF_INT64_MIN + b) { + return GUF_MATH_CKD_OVERFLOW_NEG; + } else { + return GUF_MATH_CKD_SUCCESS; + } +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_int_fast64_t(int_fast64_t a, int_fast64_t b) +{ + if (b > 0) { + if (a > GUF_INT64_MAX / b) { + return GUF_MATH_CKD_OVERFLOW_POS; + } else if (a < GUF_INT64_MIN / b) { + return GUF_MATH_CKD_OVERFLOW_NEG; + } else { + return GUF_MATH_CKD_SUCCESS; + } + } else if (b < 0) { + if (GUF_INT64_MIN != -GUF_INT64_MAX && b == -1) { // Prevent potential (GUF_INT64_MIN / b) overflow for b == -1 + return a == GUF_INT64_MIN ? GUF_MATH_CKD_OVERFLOW_POS : GUF_MATH_CKD_SUCCESS; + } else if (a < GUF_INT64_MAX / b) { + return GUF_MATH_CKD_OVERFLOW_POS; + } else if (a > GUF_INT64_MIN / b) { + return GUF_MATH_CKD_OVERFLOW_NEG; + } else { + return GUF_MATH_CKD_SUCCESS; + } + } else { + return GUF_MATH_CKD_SUCCESS; + } +} + +#ifdef INT8_MAX +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_i8(int8_t a, int8_t b) +{ + if (b > 0 && a > INT8_MAX - b) { + return GUF_MATH_CKD_OVERFLOW_POS; + } else if (b < 0 && a < INT8_MIN - b) { + return GUF_MATH_CKD_OVERFLOW_NEG; + } else { + return GUF_MATH_CKD_SUCCESS; + } +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_i8(int8_t a, int8_t b) +{ + if (b < 0 && a > INT8_MAX + b) { + return GUF_MATH_CKD_OVERFLOW_POS; + } else if (b > 0 && a < INT8_MIN + b) { + return GUF_MATH_CKD_OVERFLOW_NEG; + } else { + return GUF_MATH_CKD_SUCCESS; + } +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_i8(int8_t a, int8_t b) +{ + if (b > 0) { + if (a > INT8_MAX / b) { + return GUF_MATH_CKD_OVERFLOW_POS; + } else if (a < INT8_MIN / b) { + return GUF_MATH_CKD_OVERFLOW_NEG; + } else { + return GUF_MATH_CKD_SUCCESS; + } + } else if (b < 0) { + if (INT8_MIN != -INT8_MAX && b == -1) { // Prevent potential (INT8_MIN / b) overflow for b == -1 + return a == INT8_MIN ? GUF_MATH_CKD_OVERFLOW_POS : GUF_MATH_CKD_SUCCESS; + } else if (a < INT8_MAX / b) { + return GUF_MATH_CKD_OVERFLOW_POS; + } else if (a > INT8_MIN / b) { + return GUF_MATH_CKD_OVERFLOW_NEG; + } else { + return GUF_MATH_CKD_SUCCESS; + } + } else { + return GUF_MATH_CKD_SUCCESS; + } +} +#endif + +#ifdef INT16_MAX +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_i16(int16_t a, int16_t b) +{ + if (b > 0 && a > INT16_MAX - b) { + return GUF_MATH_CKD_OVERFLOW_POS; + } else if (b < 0 && a < INT16_MIN - b) { + return GUF_MATH_CKD_OVERFLOW_NEG; + } else { + return GUF_MATH_CKD_SUCCESS; + } +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_i16(int16_t a, int16_t b) +{ + if (b < 0 && a > INT16_MAX + b) { + return GUF_MATH_CKD_OVERFLOW_POS; + } else if (b > 0 && a < INT16_MIN + b) { + return GUF_MATH_CKD_OVERFLOW_NEG; + } else { + return GUF_MATH_CKD_SUCCESS; + } +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_i16(int16_t a, int16_t b) +{ + if (b > 0) { + if (a > INT16_MAX / b) { + return GUF_MATH_CKD_OVERFLOW_POS; + } else if (a < INT16_MIN / b) { + return GUF_MATH_CKD_OVERFLOW_NEG; + } else { + return GUF_MATH_CKD_SUCCESS; + } + } else if (b < 0) { + if (INT16_MIN != -INT16_MAX && b == -1) { // Prevent potential (INT16_MIN / b) overflow for b == -1 + return a == INT16_MIN ? GUF_MATH_CKD_OVERFLOW_POS : GUF_MATH_CKD_SUCCESS; + } else if (a < INT16_MAX / b) { + return GUF_MATH_CKD_OVERFLOW_POS; + } else if (a > INT16_MIN / b) { + return GUF_MATH_CKD_OVERFLOW_NEG; + } else { + return GUF_MATH_CKD_SUCCESS; + } + } else { + return GUF_MATH_CKD_SUCCESS; + } +} +#endif + +#ifdef INT32_MAX +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_i32(int32_t a, int32_t b) +{ + if (b > 0 && a > INT32_MAX - b) { + return GUF_MATH_CKD_OVERFLOW_POS; + } else if (b < 0 && a < INT32_MIN - b) { + return GUF_MATH_CKD_OVERFLOW_NEG; + } else { + return GUF_MATH_CKD_SUCCESS; + } +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_i32(int32_t a, int32_t b) +{ + if (b < 0 && a > INT32_MAX + b) { + return GUF_MATH_CKD_OVERFLOW_POS; + } else if (b > 0 && a < INT32_MIN + b) { + return GUF_MATH_CKD_OVERFLOW_NEG; + } else { + return GUF_MATH_CKD_SUCCESS; + } +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_i32(int32_t a, int32_t b) +{ + if (b > 0) { + if (a > INT32_MAX / b) { + return GUF_MATH_CKD_OVERFLOW_POS; + } else if (a < INT32_MIN / b) { + return GUF_MATH_CKD_OVERFLOW_NEG; + } else { + return GUF_MATH_CKD_SUCCESS; + } + } else if (b < 0) { + if (INT32_MIN != -INT32_MAX && b == -1) { // Prevent potential (INT32_MIN / b) overflow for b == -1 + return a == INT32_MIN ? GUF_MATH_CKD_OVERFLOW_POS : GUF_MATH_CKD_SUCCESS; + } else if (a < INT32_MAX / b) { + return GUF_MATH_CKD_OVERFLOW_POS; + } else if (a > INT32_MIN / b) { + return GUF_MATH_CKD_OVERFLOW_NEG; + } else { + return GUF_MATH_CKD_SUCCESS; + } + } else { + return GUF_MATH_CKD_SUCCESS; + } +} +#endif + +#ifdef INT64_MAX +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_i64(int64_t a, int64_t b) +{ + if (b > 0 && a > INT64_MAX - b) { + return GUF_MATH_CKD_OVERFLOW_POS; + } else if (b < 0 && a < INT64_MIN - b) { + return GUF_MATH_CKD_OVERFLOW_NEG; + } else { + return GUF_MATH_CKD_SUCCESS; + } +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_i64(int64_t a, int64_t b) +{ + if (b < 0 && a > INT64_MAX + b) { + return GUF_MATH_CKD_OVERFLOW_POS; + } else if (b > 0 && a < INT64_MIN + b) { + return GUF_MATH_CKD_OVERFLOW_NEG; + } else { + return GUF_MATH_CKD_SUCCESS; + } +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_i64(int64_t a, int64_t b) +{ + if (b > 0) { + if (a > INT64_MAX / b) { + return GUF_MATH_CKD_OVERFLOW_POS; + } else if (a < INT64_MIN / b) { + return GUF_MATH_CKD_OVERFLOW_NEG; + } else { + return GUF_MATH_CKD_SUCCESS; + } + } else if (b < 0) { + if (INT64_MIN != -INT64_MAX && b == -1) { // Prevent potential (INT64_MIN / b) overflow for b == -1 + return a == INT64_MIN ? GUF_MATH_CKD_OVERFLOW_POS : GUF_MATH_CKD_SUCCESS; + } else if (a < INT64_MAX / b) { + return GUF_MATH_CKD_OVERFLOW_POS; + } else if (a > INT64_MIN / b) { + return GUF_MATH_CKD_OVERFLOW_NEG; + } else { + return GUF_MATH_CKD_SUCCESS; + } + } else { + return GUF_MATH_CKD_SUCCESS; + } +} +#endif + + +// Unsigned integer arithmetic checks (generated with libguf/tools/ckdint-gen.py) GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_uchar(unsigned char a, unsigned char b) { if (b > 0 && a > UCHAR_MAX - b) { @@ -767,94 +1065,6 @@ GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_ulong_long(unsigned long l return a != 0 && ((1u * c / a) != b) ? GUF_MATH_CKD_OVERFLOW_POS : GUF_MATH_CKD_SUCCESS; } -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_u8(uint8_t a, uint8_t b) -{ - if (b > 0 && a > UINT8_MAX - b) { - return GUF_MATH_CKD_OVERFLOW_POS; - } else { - return GUF_MATH_CKD_SUCCESS; - } -} -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_u8(uint8_t a, uint8_t b) -{ - if (b > a) { - return GUF_MATH_CKD_OVERFLOW_NEG; - } else { - return GUF_MATH_CKD_SUCCESS; - } -} -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_u8(uint8_t a, uint8_t b) -{ - const uint8_t c = 1u * a * b; - return a != 0 && ((1u * c / a) != b) ? GUF_MATH_CKD_OVERFLOW_POS : GUF_MATH_CKD_SUCCESS; -} - -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_u16(uint16_t a, uint16_t b) -{ - if (b > 0 && a > UINT16_MAX - b) { - return GUF_MATH_CKD_OVERFLOW_POS; - } else { - return GUF_MATH_CKD_SUCCESS; - } -} -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_u16(uint16_t a, uint16_t b) -{ - if (b > a) { - return GUF_MATH_CKD_OVERFLOW_NEG; - } else { - return GUF_MATH_CKD_SUCCESS; - } -} -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_u16(uint16_t a, uint16_t b) -{ - const uint16_t c = 1u * a * b; - return a != 0 && ((1u * c / a) != b) ? GUF_MATH_CKD_OVERFLOW_POS : GUF_MATH_CKD_SUCCESS; -} - -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_u32(uint32_t a, uint32_t b) -{ - if (b > 0 && a > UINT32_MAX - b) { - return GUF_MATH_CKD_OVERFLOW_POS; - } else { - return GUF_MATH_CKD_SUCCESS; - } -} -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_u32(uint32_t a, uint32_t b) -{ - if (b > a) { - return GUF_MATH_CKD_OVERFLOW_NEG; - } else { - return GUF_MATH_CKD_SUCCESS; - } -} -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_u32(uint32_t a, uint32_t b) -{ - const uint32_t c = 1u * a * b; - return a != 0 && ((1u * c / a) != b) ? GUF_MATH_CKD_OVERFLOW_POS : GUF_MATH_CKD_SUCCESS; -} - -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_u64(uint64_t a, uint64_t b) -{ - if (b > 0 && a > UINT64_MAX - b) { - return GUF_MATH_CKD_OVERFLOW_POS; - } else { - return GUF_MATH_CKD_SUCCESS; - } -} -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_u64(uint64_t a, uint64_t b) -{ - if (b > a) { - return GUF_MATH_CKD_OVERFLOW_NEG; - } else { - return GUF_MATH_CKD_SUCCESS; - } -} -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_u64(uint64_t a, uint64_t b) -{ - const uint64_t c = 1u * a * b; - return a != 0 && ((1u * c / a) != b) ? GUF_MATH_CKD_OVERFLOW_POS : GUF_MATH_CKD_SUCCESS; -} - GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_size_t(size_t a, size_t b) { if (b > 0 && a > SIZE_MAX - b) { @@ -877,9 +1087,213 @@ GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_size_t(size_t a, size_t b) return a != 0 && ((1u * c / a) != b) ? GUF_MATH_CKD_OVERFLOW_POS : GUF_MATH_CKD_SUCCESS; } +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_uint_fast8_t(uint_fast8_t a, uint_fast8_t b) +{ + a = GUF_UWRAP_8(a); + b = GUF_UWRAP_8(b); + if (b > 0 && a > GUF_UINT8_MAX - b) { + return GUF_MATH_CKD_OVERFLOW_POS; + } else { + return GUF_MATH_CKD_SUCCESS; + } +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_uint_fast8_t(uint_fast8_t a, uint_fast8_t b) +{ + a = GUF_UWRAP_8(a); + b = GUF_UWRAP_8(b); + if (b > a) { + return GUF_MATH_CKD_OVERFLOW_NEG; + } else { + return GUF_MATH_CKD_SUCCESS; + } +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_uint_fast8_t(uint_fast8_t a, uint_fast8_t b) +{ + a = GUF_UWRAP_8(a); + b = GUF_UWRAP_8(b); + const uint_fast8_t c = GUF_UWRAP_8( 1u * a * b ); + return a != 0 && ((1u * c / a) != b) ? GUF_MATH_CKD_OVERFLOW_POS : GUF_MATH_CKD_SUCCESS; +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_uint_fast16_t(uint_fast16_t a, uint_fast16_t b) +{ + a = GUF_UWRAP_16(a); + b = GUF_UWRAP_16(b); + if (b > 0 && a > GUF_UINT16_MAX - b) { + return GUF_MATH_CKD_OVERFLOW_POS; + } else { + return GUF_MATH_CKD_SUCCESS; + } +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_uint_fast16_t(uint_fast16_t a, uint_fast16_t b) +{ + a = GUF_UWRAP_16(a); + b = GUF_UWRAP_16(b); + if (b > a) { + return GUF_MATH_CKD_OVERFLOW_NEG; + } else { + return GUF_MATH_CKD_SUCCESS; + } +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_uint_fast16_t(uint_fast16_t a, uint_fast16_t b) +{ + a = GUF_UWRAP_16(a); + b = GUF_UWRAP_16(b); + const uint_fast16_t c = GUF_UWRAP_16( 1u * a * b ); + return a != 0 && ((1u * c / a) != b) ? GUF_MATH_CKD_OVERFLOW_POS : GUF_MATH_CKD_SUCCESS; +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_uint_fast32_t(uint_fast32_t a, uint_fast32_t b) +{ + a = GUF_UWRAP_32(a); + b = GUF_UWRAP_32(b); + if (b > 0 && a > GUF_UINT32_MAX - b) { + return GUF_MATH_CKD_OVERFLOW_POS; + } else { + return GUF_MATH_CKD_SUCCESS; + } +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_uint_fast32_t(uint_fast32_t a, uint_fast32_t b) +{ + a = GUF_UWRAP_32(a); + b = GUF_UWRAP_32(b); + if (b > a) { + return GUF_MATH_CKD_OVERFLOW_NEG; + } else { + return GUF_MATH_CKD_SUCCESS; + } +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_uint_fast32_t(uint_fast32_t a, uint_fast32_t b) +{ + a = GUF_UWRAP_32(a); + b = GUF_UWRAP_32(b); + const uint_fast32_t c = GUF_UWRAP_32( 1u * a * b ); + return a != 0 && ((1u * c / a) != b) ? GUF_MATH_CKD_OVERFLOW_POS : GUF_MATH_CKD_SUCCESS; +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_uint_fast64_t(uint_fast64_t a, uint_fast64_t b) +{ + a = GUF_UWRAP_64(a); + b = GUF_UWRAP_64(b); + if (b > 0 && a > GUF_UINT64_MAX - b) { + return GUF_MATH_CKD_OVERFLOW_POS; + } else { + return GUF_MATH_CKD_SUCCESS; + } +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_uint_fast64_t(uint_fast64_t a, uint_fast64_t b) +{ + a = GUF_UWRAP_64(a); + b = GUF_UWRAP_64(b); + if (b > a) { + return GUF_MATH_CKD_OVERFLOW_NEG; + } else { + return GUF_MATH_CKD_SUCCESS; + } +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_uint_fast64_t(uint_fast64_t a, uint_fast64_t b) +{ + a = GUF_UWRAP_64(a); + b = GUF_UWRAP_64(b); + const uint_fast64_t c = GUF_UWRAP_64( 1u * a * b ); + return a != 0 && ((1u * c / a) != b) ? GUF_MATH_CKD_OVERFLOW_POS : GUF_MATH_CKD_SUCCESS; +} +#ifdef UINT8_MAX +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_u8(uint8_t a, uint8_t b) +{ + if (b > 0 && a > UINT8_MAX - b) { + return GUF_MATH_CKD_OVERFLOW_POS; + } else { + return GUF_MATH_CKD_SUCCESS; + } +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_u8(uint8_t a, uint8_t b) +{ + if (b > a) { + return GUF_MATH_CKD_OVERFLOW_NEG; + } else { + return GUF_MATH_CKD_SUCCESS; + } +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_u8(uint8_t a, uint8_t b) +{ + const uint8_t c = 1u * a * b; + return a != 0 && ((1u * c / a) != b) ? GUF_MATH_CKD_OVERFLOW_POS : GUF_MATH_CKD_SUCCESS; +} +#endif + +#ifdef UINT16_MAX +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_u16(uint16_t a, uint16_t b) +{ + if (b > 0 && a > UINT16_MAX - b) { + return GUF_MATH_CKD_OVERFLOW_POS; + } else { + return GUF_MATH_CKD_SUCCESS; + } +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_u16(uint16_t a, uint16_t b) +{ + if (b > a) { + return GUF_MATH_CKD_OVERFLOW_NEG; + } else { + return GUF_MATH_CKD_SUCCESS; + } +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_u16(uint16_t a, uint16_t b) +{ + const uint16_t c = 1u * a * b; + return a != 0 && ((1u * c / a) != b) ? GUF_MATH_CKD_OVERFLOW_POS : GUF_MATH_CKD_SUCCESS; +} +#endif + +#ifdef UINT32_MAX +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_u32(uint32_t a, uint32_t b) +{ + if (b > 0 && a > UINT32_MAX - b) { + return GUF_MATH_CKD_OVERFLOW_POS; + } else { + return GUF_MATH_CKD_SUCCESS; + } +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_u32(uint32_t a, uint32_t b) +{ + if (b > a) { + return GUF_MATH_CKD_OVERFLOW_NEG; + } else { + return GUF_MATH_CKD_SUCCESS; + } +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_u32(uint32_t a, uint32_t b) +{ + const uint32_t c = 1u * a * b; + return a != 0 && ((1u * c / a) != b) ? GUF_MATH_CKD_OVERFLOW_POS : GUF_MATH_CKD_SUCCESS; +} +#endif + +#ifdef UINT64_MAX +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_u64(uint64_t a, uint64_t b) +{ + if (b > 0 && a > UINT64_MAX - b) { + return GUF_MATH_CKD_OVERFLOW_POS; + } else { + return GUF_MATH_CKD_SUCCESS; + } +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_u64(uint64_t a, uint64_t b) +{ + if (b > a) { + return GUF_MATH_CKD_OVERFLOW_NEG; + } else { + return GUF_MATH_CKD_SUCCESS; + } +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_u64(uint64_t a, uint64_t b) +{ + const uint64_t c = 1u * a * b; + return a != 0 && ((1u * c / a) != b) ? GUF_MATH_CKD_OVERFLOW_POS : GUF_MATH_CKD_SUCCESS; +} +#endif + + // Signed saturating/wrapping arithmetic (generated with libguf/tools/ckdint-gen.py) - GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_int(int a, int b, int *result) { const guf_math_ckd_result check = guf_ckd_add_int(a, b); @@ -995,8 +1409,9 @@ GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_int(int a, int b, int case GUF_MATH_CKD_OVERFLOW_NEG: { unsigned res = 1u * (unsigned)a * (unsigned)b; if (res > INT_MAX) { // This is the fix for implementation defined conversion from unsigned to signed. - const unsigned mod = (1u + (unsigned)INT_MAX); - res = mod > 0 ? (1u * res % mod) : res; + const unsigned mod = (unsigned)INT_MAX + 1u; + GUF_ASSERT(mod > 0); + res = 1u * res % mod; *result = INT_MIN + (int)res; } else { *result = (int)res; @@ -1010,7 +1425,6 @@ GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_int(int a, int b, int return check; } - GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_long(long a, long b, long *result) { const guf_math_ckd_result check = guf_ckd_add_long(a, b); @@ -1126,8 +1540,9 @@ GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_long(long a, long b, case GUF_MATH_CKD_OVERFLOW_NEG: { unsigned long res = 1u * (unsigned long)a * (unsigned long)b; if (res > LONG_MAX) { // This is the fix for implementation defined conversion from unsigned to signed. - const unsigned long mod = (1u + (unsigned long)LONG_MAX); - res = mod > 0 ? (1u * res % mod) : res; + const unsigned long mod = (unsigned long)LONG_MAX + 1u; + GUF_ASSERT(mod > 0); + res = 1u * res % mod; *result = LONG_MIN + (long)res; } else { *result = (long)res; @@ -1141,7 +1556,6 @@ GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_long(long a, long b, return check; } - GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_long_long(long long a, long long b, long long *result) { const guf_math_ckd_result check = guf_ckd_add_long_long(a, b); @@ -1257,8 +1671,9 @@ GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_long_long(long long a case GUF_MATH_CKD_OVERFLOW_NEG: { unsigned long long res = 1u * (unsigned long long)a * (unsigned long long)b; if (res > LLONG_MAX) { // This is the fix for implementation defined conversion from unsigned to signed. - const unsigned long long mod = (1u + (unsigned long long)LLONG_MAX); - res = mod > 0 ? (1u * res % mod) : res; + const unsigned long long mod = (unsigned long long)LLONG_MAX + 1u; + GUF_ASSERT(mod > 0); + res = 1u * res % mod; *result = LLONG_MIN + (long long)res; } else { *result = (long long)res; @@ -1272,531 +1687,6 @@ GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_long_long(long long a return check; } - -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_i8(int8_t a, int8_t b, int8_t *result) -{ - const guf_math_ckd_result check = guf_ckd_add_i8(a, b); - if (result) { - switch (check) { - case GUF_MATH_CKD_SUCCESS: - *result = a + b; - break; - case GUF_MATH_CKD_OVERFLOW_POS: - *result = INT8_MAX; - break; - case GUF_MATH_CKD_OVERFLOW_NEG: - *result = INT8_MIN; - break; - default: - GUF_ASSERT(false); - } - } - return check; -} -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_i8(int8_t a, int8_t b, int8_t *result) -{ - const guf_math_ckd_result check = guf_ckd_sub_i8(a, b); - if (result) { - switch (check) { - case GUF_MATH_CKD_SUCCESS: - *result = a - b; - break; - case GUF_MATH_CKD_OVERFLOW_POS: - *result = INT8_MAX; - break; - case GUF_MATH_CKD_OVERFLOW_NEG: - *result = INT8_MIN; - break; - default: - GUF_ASSERT(false); - } - } - return check; -} -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_i8(int8_t a, int8_t b, int8_t *result) -{ - const guf_math_ckd_result check = guf_ckd_mul_i8(a, b); - if (result) { - switch (check) { - case GUF_MATH_CKD_SUCCESS: - *result = a * b; - break; - case GUF_MATH_CKD_OVERFLOW_POS: - *result = INT8_MAX; - break; - case GUF_MATH_CKD_OVERFLOW_NEG: - *result = INT8_MIN; - break; - default: - GUF_ASSERT(false); - } - } - return check; -} - -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_i8(int8_t a, int8_t b, int8_t *result) -{ - const guf_math_ckd_result check = guf_ckd_add_i8(a, b); - if (result) { - switch (check) { - case GUF_MATH_CKD_SUCCESS: - *result = a + b; - break; - case GUF_MATH_CKD_OVERFLOW_POS: - *result = (a + INT8_MIN) + (b + INT8_MIN); - break; - case GUF_MATH_CKD_OVERFLOW_NEG: - *result = (a - INT8_MIN) + (b - INT8_MIN); - break; - default: - GUF_ASSERT(false); - } - } - return check; -} -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_i8(int8_t a, int8_t b, int8_t *result) -{ - const guf_math_ckd_result check = guf_ckd_sub_i8(a, b); - if (result) { - switch (check) { - case GUF_MATH_CKD_SUCCESS: - *result = a - b; - break; - case GUF_MATH_CKD_OVERFLOW_POS: - GUF_ASSERT(b < 0); - *result = (a + INT8_MIN) - (b - INT8_MIN); // TODO: not sure - break; - case GUF_MATH_CKD_OVERFLOW_NEG: - GUF_ASSERT(b > 0); - *result = (a - INT8_MIN) - (b + INT8_MIN); // TODO: not sure - break; - default: - GUF_ASSERT(false); - } - } - return check; -} -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_i8(int8_t a, int8_t b, int8_t *result) -{ - const guf_math_ckd_result check = guf_ckd_mul_i8(a, b); - if (result) { - switch (check) { - case GUF_MATH_CKD_SUCCESS: - *result = a * b; - break; - case GUF_MATH_CKD_OVERFLOW_POS: - case GUF_MATH_CKD_OVERFLOW_NEG: { - uint8_t res = 1u * (uint8_t)a * (uint8_t)b; - if (res > INT8_MAX) { // This is the fix for implementation defined conversion from unsigned to signed. - const uint8_t mod = (1u + (uint8_t)INT8_MAX); - res = mod > 0 ? (1u * res % mod) : res; - *result = INT8_MIN + (int8_t)res; - } else { - *result = (int8_t)res; - } - break; - } - default: - GUF_ASSERT(false); - } - } - return check; -} - - -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_i16(int16_t a, int16_t b, int16_t *result) -{ - const guf_math_ckd_result check = guf_ckd_add_i16(a, b); - if (result) { - switch (check) { - case GUF_MATH_CKD_SUCCESS: - *result = a + b; - break; - case GUF_MATH_CKD_OVERFLOW_POS: - *result = INT16_MAX; - break; - case GUF_MATH_CKD_OVERFLOW_NEG: - *result = INT16_MIN; - break; - default: - GUF_ASSERT(false); - } - } - return check; -} -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_i16(int16_t a, int16_t b, int16_t *result) -{ - const guf_math_ckd_result check = guf_ckd_sub_i16(a, b); - if (result) { - switch (check) { - case GUF_MATH_CKD_SUCCESS: - *result = a - b; - break; - case GUF_MATH_CKD_OVERFLOW_POS: - *result = INT16_MAX; - break; - case GUF_MATH_CKD_OVERFLOW_NEG: - *result = INT16_MIN; - break; - default: - GUF_ASSERT(false); - } - } - return check; -} -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_i16(int16_t a, int16_t b, int16_t *result) -{ - const guf_math_ckd_result check = guf_ckd_mul_i16(a, b); - if (result) { - switch (check) { - case GUF_MATH_CKD_SUCCESS: - *result = a * b; - break; - case GUF_MATH_CKD_OVERFLOW_POS: - *result = INT16_MAX; - break; - case GUF_MATH_CKD_OVERFLOW_NEG: - *result = INT16_MIN; - break; - default: - GUF_ASSERT(false); - } - } - return check; -} - -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_i16(int16_t a, int16_t b, int16_t *result) -{ - const guf_math_ckd_result check = guf_ckd_add_i16(a, b); - if (result) { - switch (check) { - case GUF_MATH_CKD_SUCCESS: - *result = a + b; - break; - case GUF_MATH_CKD_OVERFLOW_POS: - *result = (a + INT16_MIN) + (b + INT16_MIN); - break; - case GUF_MATH_CKD_OVERFLOW_NEG: - *result = (a - INT16_MIN) + (b - INT16_MIN); - break; - default: - GUF_ASSERT(false); - } - } - return check; -} -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_i16(int16_t a, int16_t b, int16_t *result) -{ - const guf_math_ckd_result check = guf_ckd_sub_i16(a, b); - if (result) { - switch (check) { - case GUF_MATH_CKD_SUCCESS: - *result = a - b; - break; - case GUF_MATH_CKD_OVERFLOW_POS: - GUF_ASSERT(b < 0); - *result = (a + INT16_MIN) - (b - INT16_MIN); // TODO: not sure - break; - case GUF_MATH_CKD_OVERFLOW_NEG: - GUF_ASSERT(b > 0); - *result = (a - INT16_MIN) - (b + INT16_MIN); // TODO: not sure - break; - default: - GUF_ASSERT(false); - } - } - return check; -} -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_i16(int16_t a, int16_t b, int16_t *result) -{ - const guf_math_ckd_result check = guf_ckd_mul_i16(a, b); - if (result) { - switch (check) { - case GUF_MATH_CKD_SUCCESS: - *result = a * b; - break; - case GUF_MATH_CKD_OVERFLOW_POS: - case GUF_MATH_CKD_OVERFLOW_NEG: { - uint16_t res = 1u * (uint16_t)a * (uint16_t)b; - if (res > INT16_MAX) { // This is the fix for implementation defined conversion from unsigned to signed. - const uint16_t mod = (1u + (uint16_t)INT16_MAX); - res = mod > 0 ? (1u * res % mod) : res; - *result = INT16_MIN + (int16_t)res; - } else { - *result = (int16_t)res; - } - break; - } - default: - GUF_ASSERT(false); - } - } - return check; -} - - -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_i32(int32_t a, int32_t b, int32_t *result) -{ - const guf_math_ckd_result check = guf_ckd_add_i32(a, b); - if (result) { - switch (check) { - case GUF_MATH_CKD_SUCCESS: - *result = a + b; - break; - case GUF_MATH_CKD_OVERFLOW_POS: - *result = INT32_MAX; - break; - case GUF_MATH_CKD_OVERFLOW_NEG: - *result = INT32_MIN; - break; - default: - GUF_ASSERT(false); - } - } - return check; -} -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_i32(int32_t a, int32_t b, int32_t *result) -{ - const guf_math_ckd_result check = guf_ckd_sub_i32(a, b); - if (result) { - switch (check) { - case GUF_MATH_CKD_SUCCESS: - *result = a - b; - break; - case GUF_MATH_CKD_OVERFLOW_POS: - *result = INT32_MAX; - break; - case GUF_MATH_CKD_OVERFLOW_NEG: - *result = INT32_MIN; - break; - default: - GUF_ASSERT(false); - } - } - return check; -} -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_i32(int32_t a, int32_t b, int32_t *result) -{ - const guf_math_ckd_result check = guf_ckd_mul_i32(a, b); - if (result) { - switch (check) { - case GUF_MATH_CKD_SUCCESS: - *result = a * b; - break; - case GUF_MATH_CKD_OVERFLOW_POS: - *result = INT32_MAX; - break; - case GUF_MATH_CKD_OVERFLOW_NEG: - *result = INT32_MIN; - break; - default: - GUF_ASSERT(false); - } - } - return check; -} - -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_i32(int32_t a, int32_t b, int32_t *result) -{ - const guf_math_ckd_result check = guf_ckd_add_i32(a, b); - if (result) { - switch (check) { - case GUF_MATH_CKD_SUCCESS: - *result = a + b; - break; - case GUF_MATH_CKD_OVERFLOW_POS: - *result = (a + INT32_MIN) + (b + INT32_MIN); - break; - case GUF_MATH_CKD_OVERFLOW_NEG: - *result = (a - INT32_MIN) + (b - INT32_MIN); - break; - default: - GUF_ASSERT(false); - } - } - return check; -} -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_i32(int32_t a, int32_t b, int32_t *result) -{ - const guf_math_ckd_result check = guf_ckd_sub_i32(a, b); - if (result) { - switch (check) { - case GUF_MATH_CKD_SUCCESS: - *result = a - b; - break; - case GUF_MATH_CKD_OVERFLOW_POS: - GUF_ASSERT(b < 0); - *result = (a + INT32_MIN) - (b - INT32_MIN); // TODO: not sure - break; - case GUF_MATH_CKD_OVERFLOW_NEG: - GUF_ASSERT(b > 0); - *result = (a - INT32_MIN) - (b + INT32_MIN); // TODO: not sure - break; - default: - GUF_ASSERT(false); - } - } - return check; -} -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_i32(int32_t a, int32_t b, int32_t *result) -{ - const guf_math_ckd_result check = guf_ckd_mul_i32(a, b); - if (result) { - switch (check) { - case GUF_MATH_CKD_SUCCESS: - *result = a * b; - break; - case GUF_MATH_CKD_OVERFLOW_POS: - case GUF_MATH_CKD_OVERFLOW_NEG: { - uint32_t res = 1u * (uint32_t)a * (uint32_t)b; - if (res > INT32_MAX) { // This is the fix for implementation defined conversion from unsigned to signed. - const uint32_t mod = (1u + (uint32_t)INT32_MAX); - res = mod > 0 ? (1u * res % mod) : res; - *result = INT32_MIN + (int32_t)res; - } else { - *result = (int32_t)res; - } - break; - } - default: - GUF_ASSERT(false); - } - } - return check; -} - - -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_i64(int64_t a, int64_t b, int64_t *result) -{ - const guf_math_ckd_result check = guf_ckd_add_i64(a, b); - if (result) { - switch (check) { - case GUF_MATH_CKD_SUCCESS: - *result = a + b; - break; - case GUF_MATH_CKD_OVERFLOW_POS: - *result = INT64_MAX; - break; - case GUF_MATH_CKD_OVERFLOW_NEG: - *result = INT64_MIN; - break; - default: - GUF_ASSERT(false); - } - } - return check; -} -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_i64(int64_t a, int64_t b, int64_t *result) -{ - const guf_math_ckd_result check = guf_ckd_sub_i64(a, b); - if (result) { - switch (check) { - case GUF_MATH_CKD_SUCCESS: - *result = a - b; - break; - case GUF_MATH_CKD_OVERFLOW_POS: - *result = INT64_MAX; - break; - case GUF_MATH_CKD_OVERFLOW_NEG: - *result = INT64_MIN; - break; - default: - GUF_ASSERT(false); - } - } - return check; -} -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_i64(int64_t a, int64_t b, int64_t *result) -{ - const guf_math_ckd_result check = guf_ckd_mul_i64(a, b); - if (result) { - switch (check) { - case GUF_MATH_CKD_SUCCESS: - *result = a * b; - break; - case GUF_MATH_CKD_OVERFLOW_POS: - *result = INT64_MAX; - break; - case GUF_MATH_CKD_OVERFLOW_NEG: - *result = INT64_MIN; - break; - default: - GUF_ASSERT(false); - } - } - return check; -} - -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_i64(int64_t a, int64_t b, int64_t *result) -{ - const guf_math_ckd_result check = guf_ckd_add_i64(a, b); - if (result) { - switch (check) { - case GUF_MATH_CKD_SUCCESS: - *result = a + b; - break; - case GUF_MATH_CKD_OVERFLOW_POS: - *result = (a + INT64_MIN) + (b + INT64_MIN); - break; - case GUF_MATH_CKD_OVERFLOW_NEG: - *result = (a - INT64_MIN) + (b - INT64_MIN); - break; - default: - GUF_ASSERT(false); - } - } - return check; -} -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_i64(int64_t a, int64_t b, int64_t *result) -{ - const guf_math_ckd_result check = guf_ckd_sub_i64(a, b); - if (result) { - switch (check) { - case GUF_MATH_CKD_SUCCESS: - *result = a - b; - break; - case GUF_MATH_CKD_OVERFLOW_POS: - GUF_ASSERT(b < 0); - *result = (a + INT64_MIN) - (b - INT64_MIN); // TODO: not sure - break; - case GUF_MATH_CKD_OVERFLOW_NEG: - GUF_ASSERT(b > 0); - *result = (a - INT64_MIN) - (b + INT64_MIN); // TODO: not sure - break; - default: - GUF_ASSERT(false); - } - } - return check; -} -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_i64(int64_t a, int64_t b, int64_t *result) -{ - const guf_math_ckd_result check = guf_ckd_mul_i64(a, b); - if (result) { - switch (check) { - case GUF_MATH_CKD_SUCCESS: - *result = a * b; - break; - case GUF_MATH_CKD_OVERFLOW_POS: - case GUF_MATH_CKD_OVERFLOW_NEG: { - uint64_t res = 1u * (uint64_t)a * (uint64_t)b; - if (res > INT64_MAX) { // This is the fix for implementation defined conversion from unsigned to signed. - const uint64_t mod = (1u + (uint64_t)INT64_MAX); - res = mod > 0 ? (1u * res % mod) : res; - *result = INT64_MIN + (int64_t)res; - } else { - *result = (int64_t)res; - } - break; - } - default: - GUF_ASSERT(false); - } - } - return check; -} - - GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_ptrdiff_t(ptrdiff_t a, ptrdiff_t b, ptrdiff_t *result) { const guf_math_ckd_result check = guf_ckd_add_ptrdiff_t(a, b); @@ -1912,8 +1802,9 @@ GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_ptrdiff_t(ptrdiff_t a case GUF_MATH_CKD_OVERFLOW_NEG: { size_t res = 1u * (size_t)a * (size_t)b; if (res > PTRDIFF_MAX) { // This is the fix for implementation defined conversion from unsigned to signed. - const size_t mod = (1u + (size_t)PTRDIFF_MAX); - res = mod > 0 ? (1u * res % mod) : res; + const size_t mod = (size_t)PTRDIFF_MAX + 1u; + GUF_ASSERT(mod > 0); + res = 1u * res % mod; *result = PTRDIFF_MIN + (ptrdiff_t)res; } else { *result = (ptrdiff_t)res; @@ -1927,9 +1818,1064 @@ GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_ptrdiff_t(ptrdiff_t a return check; } +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_int_fast8_t(int_fast8_t a, int_fast8_t b, int_fast8_t *result) +{ + const guf_math_ckd_result check = guf_ckd_add_int_fast8_t(a, b); + if (result) { + switch (check) { + case GUF_MATH_CKD_SUCCESS: + *result = a + b; + break; + case GUF_MATH_CKD_OVERFLOW_POS: + *result = GUF_INT8_MAX; + break; + case GUF_MATH_CKD_OVERFLOW_NEG: + *result = GUF_INT8_MIN; + break; + default: + GUF_ASSERT(false); + } + } + return check; +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_int_fast8_t(int_fast8_t a, int_fast8_t b, int_fast8_t *result) +{ + const guf_math_ckd_result check = guf_ckd_sub_int_fast8_t(a, b); + if (result) { + switch (check) { + case GUF_MATH_CKD_SUCCESS: + *result = a - b; + break; + case GUF_MATH_CKD_OVERFLOW_POS: + *result = GUF_INT8_MAX; + break; + case GUF_MATH_CKD_OVERFLOW_NEG: + *result = GUF_INT8_MIN; + break; + default: + GUF_ASSERT(false); + } + } + return check; +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_int_fast8_t(int_fast8_t a, int_fast8_t b, int_fast8_t *result) +{ + const guf_math_ckd_result check = guf_ckd_mul_int_fast8_t(a, b); + if (result) { + switch (check) { + case GUF_MATH_CKD_SUCCESS: + *result = a * b; + break; + case GUF_MATH_CKD_OVERFLOW_POS: + *result = GUF_INT8_MAX; + break; + case GUF_MATH_CKD_OVERFLOW_NEG: + *result = GUF_INT8_MIN; + break; + default: + GUF_ASSERT(false); + } + } + return check; +} + +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_int_fast8_t(int_fast8_t a, int_fast8_t b, int_fast8_t *result) +{ + const guf_math_ckd_result check = guf_ckd_add_int_fast8_t(a, b); + if (result) { + switch (check) { + case GUF_MATH_CKD_SUCCESS: + *result = a + b; + break; + case GUF_MATH_CKD_OVERFLOW_POS: + *result = (a + GUF_INT8_MIN) + (b + GUF_INT8_MIN); + break; + case GUF_MATH_CKD_OVERFLOW_NEG: + *result = (a - GUF_INT8_MIN) + (b - GUF_INT8_MIN); + break; + default: + GUF_ASSERT(false); + } + } + return check; +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_int_fast8_t(int_fast8_t a, int_fast8_t b, int_fast8_t *result) +{ + const guf_math_ckd_result check = guf_ckd_sub_int_fast8_t(a, b); + if (result) { + switch (check) { + case GUF_MATH_CKD_SUCCESS: + *result = a - b; + break; + case GUF_MATH_CKD_OVERFLOW_POS: + GUF_ASSERT(b < 0); + *result = (a + GUF_INT8_MIN) - (b - GUF_INT8_MIN); // TODO: not sure + break; + case GUF_MATH_CKD_OVERFLOW_NEG: + GUF_ASSERT(b > 0); + *result = (a - GUF_INT8_MIN) - (b + GUF_INT8_MIN); // TODO: not sure + break; + default: + GUF_ASSERT(false); + } + } + return check; +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_int_fast8_t(int_fast8_t a, int_fast8_t b, int_fast8_t *result) +{ + const guf_math_ckd_result check = guf_ckd_mul_int_fast8_t(a, b); + if (result) { + switch (check) { + case GUF_MATH_CKD_SUCCESS: + *result = a * b; + break; + case GUF_MATH_CKD_OVERFLOW_POS: + case GUF_MATH_CKD_OVERFLOW_NEG: { + uint_fast8_t res = 1u * (uint_fast8_t)a * (uint_fast8_t)b; + if (res > GUF_INT8_MAX) { // This is the fix for implementation defined conversion from unsigned to signed. + const uint_fast8_t mod = (uint_fast8_t)GUF_INT8_MAX + 1u; + GUF_ASSERT(mod > 0); + res = 1u * res % mod; + *result = GUF_INT8_MIN + (int_fast8_t)res; + } else { + *result = (int_fast8_t)res; + } + break; + } + default: + GUF_ASSERT(false); + } + } + return check; +} + +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_int_fast16_t(int_fast16_t a, int_fast16_t b, int_fast16_t *result) +{ + const guf_math_ckd_result check = guf_ckd_add_int_fast16_t(a, b); + if (result) { + switch (check) { + case GUF_MATH_CKD_SUCCESS: + *result = a + b; + break; + case GUF_MATH_CKD_OVERFLOW_POS: + *result = GUF_INT16_MAX; + break; + case GUF_MATH_CKD_OVERFLOW_NEG: + *result = GUF_INT16_MIN; + break; + default: + GUF_ASSERT(false); + } + } + return check; +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_int_fast16_t(int_fast16_t a, int_fast16_t b, int_fast16_t *result) +{ + const guf_math_ckd_result check = guf_ckd_sub_int_fast16_t(a, b); + if (result) { + switch (check) { + case GUF_MATH_CKD_SUCCESS: + *result = a - b; + break; + case GUF_MATH_CKD_OVERFLOW_POS: + *result = GUF_INT16_MAX; + break; + case GUF_MATH_CKD_OVERFLOW_NEG: + *result = GUF_INT16_MIN; + break; + default: + GUF_ASSERT(false); + } + } + return check; +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_int_fast16_t(int_fast16_t a, int_fast16_t b, int_fast16_t *result) +{ + const guf_math_ckd_result check = guf_ckd_mul_int_fast16_t(a, b); + if (result) { + switch (check) { + case GUF_MATH_CKD_SUCCESS: + *result = a * b; + break; + case GUF_MATH_CKD_OVERFLOW_POS: + *result = GUF_INT16_MAX; + break; + case GUF_MATH_CKD_OVERFLOW_NEG: + *result = GUF_INT16_MIN; + break; + default: + GUF_ASSERT(false); + } + } + return check; +} + +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_int_fast16_t(int_fast16_t a, int_fast16_t b, int_fast16_t *result) +{ + const guf_math_ckd_result check = guf_ckd_add_int_fast16_t(a, b); + if (result) { + switch (check) { + case GUF_MATH_CKD_SUCCESS: + *result = a + b; + break; + case GUF_MATH_CKD_OVERFLOW_POS: + *result = (a + GUF_INT16_MIN) + (b + GUF_INT16_MIN); + break; + case GUF_MATH_CKD_OVERFLOW_NEG: + *result = (a - GUF_INT16_MIN) + (b - GUF_INT16_MIN); + break; + default: + GUF_ASSERT(false); + } + } + return check; +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_int_fast16_t(int_fast16_t a, int_fast16_t b, int_fast16_t *result) +{ + const guf_math_ckd_result check = guf_ckd_sub_int_fast16_t(a, b); + if (result) { + switch (check) { + case GUF_MATH_CKD_SUCCESS: + *result = a - b; + break; + case GUF_MATH_CKD_OVERFLOW_POS: + GUF_ASSERT(b < 0); + *result = (a + GUF_INT16_MIN) - (b - GUF_INT16_MIN); // TODO: not sure + break; + case GUF_MATH_CKD_OVERFLOW_NEG: + GUF_ASSERT(b > 0); + *result = (a - GUF_INT16_MIN) - (b + GUF_INT16_MIN); // TODO: not sure + break; + default: + GUF_ASSERT(false); + } + } + return check; +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_int_fast16_t(int_fast16_t a, int_fast16_t b, int_fast16_t *result) +{ + const guf_math_ckd_result check = guf_ckd_mul_int_fast16_t(a, b); + if (result) { + switch (check) { + case GUF_MATH_CKD_SUCCESS: + *result = a * b; + break; + case GUF_MATH_CKD_OVERFLOW_POS: + case GUF_MATH_CKD_OVERFLOW_NEG: { + uint_fast16_t res = 1u * (uint_fast16_t)a * (uint_fast16_t)b; + if (res > GUF_INT16_MAX) { // This is the fix for implementation defined conversion from unsigned to signed. + const uint_fast16_t mod = (uint_fast16_t)GUF_INT16_MAX + 1u; + GUF_ASSERT(mod > 0); + res = 1u * res % mod; + *result = GUF_INT16_MIN + (int_fast16_t)res; + } else { + *result = (int_fast16_t)res; + } + break; + } + default: + GUF_ASSERT(false); + } + } + return check; +} + +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_int_fast32_t(int_fast32_t a, int_fast32_t b, int_fast32_t *result) +{ + const guf_math_ckd_result check = guf_ckd_add_int_fast32_t(a, b); + if (result) { + switch (check) { + case GUF_MATH_CKD_SUCCESS: + *result = a + b; + break; + case GUF_MATH_CKD_OVERFLOW_POS: + *result = GUF_INT32_MAX; + break; + case GUF_MATH_CKD_OVERFLOW_NEG: + *result = GUF_INT32_MIN; + break; + default: + GUF_ASSERT(false); + } + } + return check; +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_int_fast32_t(int_fast32_t a, int_fast32_t b, int_fast32_t *result) +{ + const guf_math_ckd_result check = guf_ckd_sub_int_fast32_t(a, b); + if (result) { + switch (check) { + case GUF_MATH_CKD_SUCCESS: + *result = a - b; + break; + case GUF_MATH_CKD_OVERFLOW_POS: + *result = GUF_INT32_MAX; + break; + case GUF_MATH_CKD_OVERFLOW_NEG: + *result = GUF_INT32_MIN; + break; + default: + GUF_ASSERT(false); + } + } + return check; +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_int_fast32_t(int_fast32_t a, int_fast32_t b, int_fast32_t *result) +{ + const guf_math_ckd_result check = guf_ckd_mul_int_fast32_t(a, b); + if (result) { + switch (check) { + case GUF_MATH_CKD_SUCCESS: + *result = a * b; + break; + case GUF_MATH_CKD_OVERFLOW_POS: + *result = GUF_INT32_MAX; + break; + case GUF_MATH_CKD_OVERFLOW_NEG: + *result = GUF_INT32_MIN; + break; + default: + GUF_ASSERT(false); + } + } + return check; +} + +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_int_fast32_t(int_fast32_t a, int_fast32_t b, int_fast32_t *result) +{ + const guf_math_ckd_result check = guf_ckd_add_int_fast32_t(a, b); + if (result) { + switch (check) { + case GUF_MATH_CKD_SUCCESS: + *result = a + b; + break; + case GUF_MATH_CKD_OVERFLOW_POS: + *result = (a + GUF_INT32_MIN) + (b + GUF_INT32_MIN); + break; + case GUF_MATH_CKD_OVERFLOW_NEG: + *result = (a - GUF_INT32_MIN) + (b - GUF_INT32_MIN); + break; + default: + GUF_ASSERT(false); + } + } + return check; +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_int_fast32_t(int_fast32_t a, int_fast32_t b, int_fast32_t *result) +{ + const guf_math_ckd_result check = guf_ckd_sub_int_fast32_t(a, b); + if (result) { + switch (check) { + case GUF_MATH_CKD_SUCCESS: + *result = a - b; + break; + case GUF_MATH_CKD_OVERFLOW_POS: + GUF_ASSERT(b < 0); + *result = (a + GUF_INT32_MIN) - (b - GUF_INT32_MIN); // TODO: not sure + break; + case GUF_MATH_CKD_OVERFLOW_NEG: + GUF_ASSERT(b > 0); + *result = (a - GUF_INT32_MIN) - (b + GUF_INT32_MIN); // TODO: not sure + break; + default: + GUF_ASSERT(false); + } + } + return check; +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_int_fast32_t(int_fast32_t a, int_fast32_t b, int_fast32_t *result) +{ + const guf_math_ckd_result check = guf_ckd_mul_int_fast32_t(a, b); + if (result) { + switch (check) { + case GUF_MATH_CKD_SUCCESS: + *result = a * b; + break; + case GUF_MATH_CKD_OVERFLOW_POS: + case GUF_MATH_CKD_OVERFLOW_NEG: { + uint_fast32_t res = 1u * (uint_fast32_t)a * (uint_fast32_t)b; + if (res > GUF_INT32_MAX) { // This is the fix for implementation defined conversion from unsigned to signed. + const uint_fast32_t mod = (uint_fast32_t)GUF_INT32_MAX + 1u; + GUF_ASSERT(mod > 0); + res = 1u * res % mod; + *result = GUF_INT32_MIN + (int_fast32_t)res; + } else { + *result = (int_fast32_t)res; + } + break; + } + default: + GUF_ASSERT(false); + } + } + return check; +} + +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_int_fast64_t(int_fast64_t a, int_fast64_t b, int_fast64_t *result) +{ + const guf_math_ckd_result check = guf_ckd_add_int_fast64_t(a, b); + if (result) { + switch (check) { + case GUF_MATH_CKD_SUCCESS: + *result = a + b; + break; + case GUF_MATH_CKD_OVERFLOW_POS: + *result = GUF_INT64_MAX; + break; + case GUF_MATH_CKD_OVERFLOW_NEG: + *result = GUF_INT64_MIN; + break; + default: + GUF_ASSERT(false); + } + } + return check; +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_int_fast64_t(int_fast64_t a, int_fast64_t b, int_fast64_t *result) +{ + const guf_math_ckd_result check = guf_ckd_sub_int_fast64_t(a, b); + if (result) { + switch (check) { + case GUF_MATH_CKD_SUCCESS: + *result = a - b; + break; + case GUF_MATH_CKD_OVERFLOW_POS: + *result = GUF_INT64_MAX; + break; + case GUF_MATH_CKD_OVERFLOW_NEG: + *result = GUF_INT64_MIN; + break; + default: + GUF_ASSERT(false); + } + } + return check; +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_int_fast64_t(int_fast64_t a, int_fast64_t b, int_fast64_t *result) +{ + const guf_math_ckd_result check = guf_ckd_mul_int_fast64_t(a, b); + if (result) { + switch (check) { + case GUF_MATH_CKD_SUCCESS: + *result = a * b; + break; + case GUF_MATH_CKD_OVERFLOW_POS: + *result = GUF_INT64_MAX; + break; + case GUF_MATH_CKD_OVERFLOW_NEG: + *result = GUF_INT64_MIN; + break; + default: + GUF_ASSERT(false); + } + } + return check; +} + +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_int_fast64_t(int_fast64_t a, int_fast64_t b, int_fast64_t *result) +{ + const guf_math_ckd_result check = guf_ckd_add_int_fast64_t(a, b); + if (result) { + switch (check) { + case GUF_MATH_CKD_SUCCESS: + *result = a + b; + break; + case GUF_MATH_CKD_OVERFLOW_POS: + *result = (a + GUF_INT64_MIN) + (b + GUF_INT64_MIN); + break; + case GUF_MATH_CKD_OVERFLOW_NEG: + *result = (a - GUF_INT64_MIN) + (b - GUF_INT64_MIN); + break; + default: + GUF_ASSERT(false); + } + } + return check; +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_int_fast64_t(int_fast64_t a, int_fast64_t b, int_fast64_t *result) +{ + const guf_math_ckd_result check = guf_ckd_sub_int_fast64_t(a, b); + if (result) { + switch (check) { + case GUF_MATH_CKD_SUCCESS: + *result = a - b; + break; + case GUF_MATH_CKD_OVERFLOW_POS: + GUF_ASSERT(b < 0); + *result = (a + GUF_INT64_MIN) - (b - GUF_INT64_MIN); // TODO: not sure + break; + case GUF_MATH_CKD_OVERFLOW_NEG: + GUF_ASSERT(b > 0); + *result = (a - GUF_INT64_MIN) - (b + GUF_INT64_MIN); // TODO: not sure + break; + default: + GUF_ASSERT(false); + } + } + return check; +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_int_fast64_t(int_fast64_t a, int_fast64_t b, int_fast64_t *result) +{ + const guf_math_ckd_result check = guf_ckd_mul_int_fast64_t(a, b); + if (result) { + switch (check) { + case GUF_MATH_CKD_SUCCESS: + *result = a * b; + break; + case GUF_MATH_CKD_OVERFLOW_POS: + case GUF_MATH_CKD_OVERFLOW_NEG: { + uint_fast64_t res = 1u * (uint_fast64_t)a * (uint_fast64_t)b; + if (res > GUF_INT64_MAX) { // This is the fix for implementation defined conversion from unsigned to signed. + const uint_fast64_t mod = (uint_fast64_t)GUF_INT64_MAX + 1u; + GUF_ASSERT(mod > 0); + res = 1u * res % mod; + *result = GUF_INT64_MIN + (int_fast64_t)res; + } else { + *result = (int_fast64_t)res; + } + break; + } + default: + GUF_ASSERT(false); + } + } + return check; +} + +#ifdef INT8_MAX +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_i8(int8_t a, int8_t b, int8_t *result) +{ + const guf_math_ckd_result check = guf_ckd_add_i8(a, b); + if (result) { + switch (check) { + case GUF_MATH_CKD_SUCCESS: + *result = a + b; + break; + case GUF_MATH_CKD_OVERFLOW_POS: + *result = INT8_MAX; + break; + case GUF_MATH_CKD_OVERFLOW_NEG: + *result = INT8_MIN; + break; + default: + GUF_ASSERT(false); + } + } + return check; +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_i8(int8_t a, int8_t b, int8_t *result) +{ + const guf_math_ckd_result check = guf_ckd_sub_i8(a, b); + if (result) { + switch (check) { + case GUF_MATH_CKD_SUCCESS: + *result = a - b; + break; + case GUF_MATH_CKD_OVERFLOW_POS: + *result = INT8_MAX; + break; + case GUF_MATH_CKD_OVERFLOW_NEG: + *result = INT8_MIN; + break; + default: + GUF_ASSERT(false); + } + } + return check; +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_i8(int8_t a, int8_t b, int8_t *result) +{ + const guf_math_ckd_result check = guf_ckd_mul_i8(a, b); + if (result) { + switch (check) { + case GUF_MATH_CKD_SUCCESS: + *result = a * b; + break; + case GUF_MATH_CKD_OVERFLOW_POS: + *result = INT8_MAX; + break; + case GUF_MATH_CKD_OVERFLOW_NEG: + *result = INT8_MIN; + break; + default: + GUF_ASSERT(false); + } + } + return check; +} + +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_i8(int8_t a, int8_t b, int8_t *result) +{ + const guf_math_ckd_result check = guf_ckd_add_i8(a, b); + if (result) { + switch (check) { + case GUF_MATH_CKD_SUCCESS: + *result = a + b; + break; + case GUF_MATH_CKD_OVERFLOW_POS: + *result = (a + INT8_MIN) + (b + INT8_MIN); + break; + case GUF_MATH_CKD_OVERFLOW_NEG: + *result = (a - INT8_MIN) + (b - INT8_MIN); + break; + default: + GUF_ASSERT(false); + } + } + return check; +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_i8(int8_t a, int8_t b, int8_t *result) +{ + const guf_math_ckd_result check = guf_ckd_sub_i8(a, b); + if (result) { + switch (check) { + case GUF_MATH_CKD_SUCCESS: + *result = a - b; + break; + case GUF_MATH_CKD_OVERFLOW_POS: + GUF_ASSERT(b < 0); + *result = (a + INT8_MIN) - (b - INT8_MIN); // TODO: not sure + break; + case GUF_MATH_CKD_OVERFLOW_NEG: + GUF_ASSERT(b > 0); + *result = (a - INT8_MIN) - (b + INT8_MIN); // TODO: not sure + break; + default: + GUF_ASSERT(false); + } + } + return check; +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_i8(int8_t a, int8_t b, int8_t *result) +{ + const guf_math_ckd_result check = guf_ckd_mul_i8(a, b); + if (result) { + switch (check) { + case GUF_MATH_CKD_SUCCESS: + *result = a * b; + break; + case GUF_MATH_CKD_OVERFLOW_POS: + case GUF_MATH_CKD_OVERFLOW_NEG: { + uint8_t res = 1u * (uint8_t)a * (uint8_t)b; + if (res > INT8_MAX) { // This is the fix for implementation defined conversion from unsigned to signed. + const uint8_t mod = (uint8_t)INT8_MAX + 1u; + GUF_ASSERT(mod > 0); + res = 1u * res % mod; + *result = INT8_MIN + (int8_t)res; + } else { + *result = (int8_t)res; + } + break; + } + default: + GUF_ASSERT(false); + } + } + return check; +} +#endif + +#ifdef INT16_MAX +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_i16(int16_t a, int16_t b, int16_t *result) +{ + const guf_math_ckd_result check = guf_ckd_add_i16(a, b); + if (result) { + switch (check) { + case GUF_MATH_CKD_SUCCESS: + *result = a + b; + break; + case GUF_MATH_CKD_OVERFLOW_POS: + *result = INT16_MAX; + break; + case GUF_MATH_CKD_OVERFLOW_NEG: + *result = INT16_MIN; + break; + default: + GUF_ASSERT(false); + } + } + return check; +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_i16(int16_t a, int16_t b, int16_t *result) +{ + const guf_math_ckd_result check = guf_ckd_sub_i16(a, b); + if (result) { + switch (check) { + case GUF_MATH_CKD_SUCCESS: + *result = a - b; + break; + case GUF_MATH_CKD_OVERFLOW_POS: + *result = INT16_MAX; + break; + case GUF_MATH_CKD_OVERFLOW_NEG: + *result = INT16_MIN; + break; + default: + GUF_ASSERT(false); + } + } + return check; +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_i16(int16_t a, int16_t b, int16_t *result) +{ + const guf_math_ckd_result check = guf_ckd_mul_i16(a, b); + if (result) { + switch (check) { + case GUF_MATH_CKD_SUCCESS: + *result = a * b; + break; + case GUF_MATH_CKD_OVERFLOW_POS: + *result = INT16_MAX; + break; + case GUF_MATH_CKD_OVERFLOW_NEG: + *result = INT16_MIN; + break; + default: + GUF_ASSERT(false); + } + } + return check; +} + +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_i16(int16_t a, int16_t b, int16_t *result) +{ + const guf_math_ckd_result check = guf_ckd_add_i16(a, b); + if (result) { + switch (check) { + case GUF_MATH_CKD_SUCCESS: + *result = a + b; + break; + case GUF_MATH_CKD_OVERFLOW_POS: + *result = (a + INT16_MIN) + (b + INT16_MIN); + break; + case GUF_MATH_CKD_OVERFLOW_NEG: + *result = (a - INT16_MIN) + (b - INT16_MIN); + break; + default: + GUF_ASSERT(false); + } + } + return check; +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_i16(int16_t a, int16_t b, int16_t *result) +{ + const guf_math_ckd_result check = guf_ckd_sub_i16(a, b); + if (result) { + switch (check) { + case GUF_MATH_CKD_SUCCESS: + *result = a - b; + break; + case GUF_MATH_CKD_OVERFLOW_POS: + GUF_ASSERT(b < 0); + *result = (a + INT16_MIN) - (b - INT16_MIN); // TODO: not sure + break; + case GUF_MATH_CKD_OVERFLOW_NEG: + GUF_ASSERT(b > 0); + *result = (a - INT16_MIN) - (b + INT16_MIN); // TODO: not sure + break; + default: + GUF_ASSERT(false); + } + } + return check; +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_i16(int16_t a, int16_t b, int16_t *result) +{ + const guf_math_ckd_result check = guf_ckd_mul_i16(a, b); + if (result) { + switch (check) { + case GUF_MATH_CKD_SUCCESS: + *result = a * b; + break; + case GUF_MATH_CKD_OVERFLOW_POS: + case GUF_MATH_CKD_OVERFLOW_NEG: { + uint16_t res = 1u * (uint16_t)a * (uint16_t)b; + if (res > INT16_MAX) { // This is the fix for implementation defined conversion from unsigned to signed. + const uint16_t mod = (uint16_t)INT16_MAX + 1u; + GUF_ASSERT(mod > 0); + res = 1u * res % mod; + *result = INT16_MIN + (int16_t)res; + } else { + *result = (int16_t)res; + } + break; + } + default: + GUF_ASSERT(false); + } + } + return check; +} +#endif + +#ifdef INT32_MAX +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_i32(int32_t a, int32_t b, int32_t *result) +{ + const guf_math_ckd_result check = guf_ckd_add_i32(a, b); + if (result) { + switch (check) { + case GUF_MATH_CKD_SUCCESS: + *result = a + b; + break; + case GUF_MATH_CKD_OVERFLOW_POS: + *result = INT32_MAX; + break; + case GUF_MATH_CKD_OVERFLOW_NEG: + *result = INT32_MIN; + break; + default: + GUF_ASSERT(false); + } + } + return check; +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_i32(int32_t a, int32_t b, int32_t *result) +{ + const guf_math_ckd_result check = guf_ckd_sub_i32(a, b); + if (result) { + switch (check) { + case GUF_MATH_CKD_SUCCESS: + *result = a - b; + break; + case GUF_MATH_CKD_OVERFLOW_POS: + *result = INT32_MAX; + break; + case GUF_MATH_CKD_OVERFLOW_NEG: + *result = INT32_MIN; + break; + default: + GUF_ASSERT(false); + } + } + return check; +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_i32(int32_t a, int32_t b, int32_t *result) +{ + const guf_math_ckd_result check = guf_ckd_mul_i32(a, b); + if (result) { + switch (check) { + case GUF_MATH_CKD_SUCCESS: + *result = a * b; + break; + case GUF_MATH_CKD_OVERFLOW_POS: + *result = INT32_MAX; + break; + case GUF_MATH_CKD_OVERFLOW_NEG: + *result = INT32_MIN; + break; + default: + GUF_ASSERT(false); + } + } + return check; +} + +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_i32(int32_t a, int32_t b, int32_t *result) +{ + const guf_math_ckd_result check = guf_ckd_add_i32(a, b); + if (result) { + switch (check) { + case GUF_MATH_CKD_SUCCESS: + *result = a + b; + break; + case GUF_MATH_CKD_OVERFLOW_POS: + *result = (a + INT32_MIN) + (b + INT32_MIN); + break; + case GUF_MATH_CKD_OVERFLOW_NEG: + *result = (a - INT32_MIN) + (b - INT32_MIN); + break; + default: + GUF_ASSERT(false); + } + } + return check; +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_i32(int32_t a, int32_t b, int32_t *result) +{ + const guf_math_ckd_result check = guf_ckd_sub_i32(a, b); + if (result) { + switch (check) { + case GUF_MATH_CKD_SUCCESS: + *result = a - b; + break; + case GUF_MATH_CKD_OVERFLOW_POS: + GUF_ASSERT(b < 0); + *result = (a + INT32_MIN) - (b - INT32_MIN); // TODO: not sure + break; + case GUF_MATH_CKD_OVERFLOW_NEG: + GUF_ASSERT(b > 0); + *result = (a - INT32_MIN) - (b + INT32_MIN); // TODO: not sure + break; + default: + GUF_ASSERT(false); + } + } + return check; +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_i32(int32_t a, int32_t b, int32_t *result) +{ + const guf_math_ckd_result check = guf_ckd_mul_i32(a, b); + if (result) { + switch (check) { + case GUF_MATH_CKD_SUCCESS: + *result = a * b; + break; + case GUF_MATH_CKD_OVERFLOW_POS: + case GUF_MATH_CKD_OVERFLOW_NEG: { + uint32_t res = 1u * (uint32_t)a * (uint32_t)b; + if (res > INT32_MAX) { // This is the fix for implementation defined conversion from unsigned to signed. + const uint32_t mod = (uint32_t)INT32_MAX + 1u; + GUF_ASSERT(mod > 0); + res = 1u * res % mod; + *result = INT32_MIN + (int32_t)res; + } else { + *result = (int32_t)res; + } + break; + } + default: + GUF_ASSERT(false); + } + } + return check; +} +#endif + +#ifdef INT64_MAX +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_i64(int64_t a, int64_t b, int64_t *result) +{ + const guf_math_ckd_result check = guf_ckd_add_i64(a, b); + if (result) { + switch (check) { + case GUF_MATH_CKD_SUCCESS: + *result = a + b; + break; + case GUF_MATH_CKD_OVERFLOW_POS: + *result = INT64_MAX; + break; + case GUF_MATH_CKD_OVERFLOW_NEG: + *result = INT64_MIN; + break; + default: + GUF_ASSERT(false); + } + } + return check; +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_i64(int64_t a, int64_t b, int64_t *result) +{ + const guf_math_ckd_result check = guf_ckd_sub_i64(a, b); + if (result) { + switch (check) { + case GUF_MATH_CKD_SUCCESS: + *result = a - b; + break; + case GUF_MATH_CKD_OVERFLOW_POS: + *result = INT64_MAX; + break; + case GUF_MATH_CKD_OVERFLOW_NEG: + *result = INT64_MIN; + break; + default: + GUF_ASSERT(false); + } + } + return check; +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_i64(int64_t a, int64_t b, int64_t *result) +{ + const guf_math_ckd_result check = guf_ckd_mul_i64(a, b); + if (result) { + switch (check) { + case GUF_MATH_CKD_SUCCESS: + *result = a * b; + break; + case GUF_MATH_CKD_OVERFLOW_POS: + *result = INT64_MAX; + break; + case GUF_MATH_CKD_OVERFLOW_NEG: + *result = INT64_MIN; + break; + default: + GUF_ASSERT(false); + } + } + return check; +} + +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_i64(int64_t a, int64_t b, int64_t *result) +{ + const guf_math_ckd_result check = guf_ckd_add_i64(a, b); + if (result) { + switch (check) { + case GUF_MATH_CKD_SUCCESS: + *result = a + b; + break; + case GUF_MATH_CKD_OVERFLOW_POS: + *result = (a + INT64_MIN) + (b + INT64_MIN); + break; + case GUF_MATH_CKD_OVERFLOW_NEG: + *result = (a - INT64_MIN) + (b - INT64_MIN); + break; + default: + GUF_ASSERT(false); + } + } + return check; +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_i64(int64_t a, int64_t b, int64_t *result) +{ + const guf_math_ckd_result check = guf_ckd_sub_i64(a, b); + if (result) { + switch (check) { + case GUF_MATH_CKD_SUCCESS: + *result = a - b; + break; + case GUF_MATH_CKD_OVERFLOW_POS: + GUF_ASSERT(b < 0); + *result = (a + INT64_MIN) - (b - INT64_MIN); // TODO: not sure + break; + case GUF_MATH_CKD_OVERFLOW_NEG: + GUF_ASSERT(b > 0); + *result = (a - INT64_MIN) - (b + INT64_MIN); // TODO: not sure + break; + default: + GUF_ASSERT(false); + } + } + return check; +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_i64(int64_t a, int64_t b, int64_t *result) +{ + const guf_math_ckd_result check = guf_ckd_mul_i64(a, b); + if (result) { + switch (check) { + case GUF_MATH_CKD_SUCCESS: + *result = a * b; + break; + case GUF_MATH_CKD_OVERFLOW_POS: + case GUF_MATH_CKD_OVERFLOW_NEG: { + uint64_t res = 1u * (uint64_t)a * (uint64_t)b; + if (res > INT64_MAX) { // This is the fix for implementation defined conversion from unsigned to signed. + const uint64_t mod = (uint64_t)INT64_MAX + 1u; + GUF_ASSERT(mod > 0); + res = 1u * res % mod; + *result = INT64_MIN + (int64_t)res; + } else { + *result = (int64_t)res; + } + break; + } + default: + GUF_ASSERT(false); + } + } + return check; +} +#endif + // Unsigned saturating/wrapping arithmetic (generated with libguf/tools/ckdint-gen.py) - GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_uchar(unsigned char a, unsigned char b, unsigned char *result) { const guf_math_ckd_result check = guf_ckd_add_uchar(a, b); @@ -2010,7 +2956,6 @@ GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_uchar(unsigned char a return check; } - GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_unsigned(unsigned a, unsigned b, unsigned *result) { const guf_math_ckd_result check = guf_ckd_add_unsigned(a, b); @@ -2091,7 +3036,6 @@ GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_unsigned(unsigned a, return check; } - GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_ulong(unsigned long a, unsigned long b, unsigned long *result) { const guf_math_ckd_result check = guf_ckd_add_ulong(a, b); @@ -2172,7 +3116,6 @@ GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_ulong(unsigned long a return check; } - GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_ulong_long(unsigned long long a, unsigned long long b, unsigned long long *result) { const guf_math_ckd_result check = guf_ckd_add_ulong_long(a, b); @@ -2253,331 +3196,6 @@ GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_ulong_long(unsigned l return check; } - -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_u8(uint8_t a, uint8_t b, uint8_t *result) -{ - const guf_math_ckd_result check = guf_ckd_add_u8(a, b); - GUF_ASSERT(check == GUF_MATH_CKD_SUCCESS || check == GUF_MATH_CKD_OVERFLOW_POS); - if (result) { - switch (check) { - case GUF_MATH_CKD_SUCCESS: - *result = a + b; - break; - case GUF_MATH_CKD_OVERFLOW_POS: - *result = UINT8_MAX; - break; - default: - GUF_ASSERT(false); - } - } - return check; -} -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_u8(uint8_t a, uint8_t b, uint8_t *result) -{ - const guf_math_ckd_result check = guf_ckd_sub_u8(a, b); - GUF_ASSERT(check == GUF_MATH_CKD_SUCCESS || check == GUF_MATH_CKD_OVERFLOW_NEG); - if (result) { - switch (check) { - case GUF_MATH_CKD_SUCCESS: - *result = a - b; - break; - case GUF_MATH_CKD_OVERFLOW_NEG: - *result = 0; - break; - default: - GUF_ASSERT(false); - } - } - return check; -} -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_u8(uint8_t a, uint8_t b, uint8_t *result) -{ - const guf_math_ckd_result check = guf_ckd_mul_u8(a, b); - GUF_ASSERT(check == GUF_MATH_CKD_SUCCESS || check == GUF_MATH_CKD_OVERFLOW_POS); - if (result) { - switch (check) { - case GUF_MATH_CKD_SUCCESS: - *result = a * b; - break; - case GUF_MATH_CKD_OVERFLOW_POS: - *result = UINT8_MAX; - break; - default: - GUF_ASSERT(false); - } - } - return check; -} - -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_u8(uint8_t a, uint8_t b, uint8_t *result) -{ - const guf_math_ckd_result check = guf_ckd_add_u8(a, b); - if (result) { - *result = 1u * a + b; - } - return check; -} -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_u8(uint8_t a, uint8_t b, uint8_t *result) -{ - const guf_math_ckd_result check = guf_ckd_sub_u8(a, b); - if (result) { - *result = 1u * a - b; - } - return check; -} -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_u8(uint8_t a, uint8_t b, uint8_t *result) -{ - const guf_math_ckd_result check = guf_ckd_mul_u8(a, b); - if (result) { - *result = 1u * a * b; - } - return check; -} - - -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_u16(uint16_t a, uint16_t b, uint16_t *result) -{ - const guf_math_ckd_result check = guf_ckd_add_u16(a, b); - GUF_ASSERT(check == GUF_MATH_CKD_SUCCESS || check == GUF_MATH_CKD_OVERFLOW_POS); - if (result) { - switch (check) { - case GUF_MATH_CKD_SUCCESS: - *result = a + b; - break; - case GUF_MATH_CKD_OVERFLOW_POS: - *result = UINT16_MAX; - break; - default: - GUF_ASSERT(false); - } - } - return check; -} -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_u16(uint16_t a, uint16_t b, uint16_t *result) -{ - const guf_math_ckd_result check = guf_ckd_sub_u16(a, b); - GUF_ASSERT(check == GUF_MATH_CKD_SUCCESS || check == GUF_MATH_CKD_OVERFLOW_NEG); - if (result) { - switch (check) { - case GUF_MATH_CKD_SUCCESS: - *result = a - b; - break; - case GUF_MATH_CKD_OVERFLOW_NEG: - *result = 0; - break; - default: - GUF_ASSERT(false); - } - } - return check; -} -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_u16(uint16_t a, uint16_t b, uint16_t *result) -{ - const guf_math_ckd_result check = guf_ckd_mul_u16(a, b); - GUF_ASSERT(check == GUF_MATH_CKD_SUCCESS || check == GUF_MATH_CKD_OVERFLOW_POS); - if (result) { - switch (check) { - case GUF_MATH_CKD_SUCCESS: - *result = a * b; - break; - case GUF_MATH_CKD_OVERFLOW_POS: - *result = UINT16_MAX; - break; - default: - GUF_ASSERT(false); - } - } - return check; -} - -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_u16(uint16_t a, uint16_t b, uint16_t *result) -{ - const guf_math_ckd_result check = guf_ckd_add_u16(a, b); - if (result) { - *result = 1u * a + b; - } - return check; -} -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_u16(uint16_t a, uint16_t b, uint16_t *result) -{ - const guf_math_ckd_result check = guf_ckd_sub_u16(a, b); - if (result) { - *result = 1u * a - b; - } - return check; -} -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_u16(uint16_t a, uint16_t b, uint16_t *result) -{ - const guf_math_ckd_result check = guf_ckd_mul_u16(a, b); - if (result) { - *result = 1u * a * b; - } - return check; -} - - -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_u32(uint32_t a, uint32_t b, uint32_t *result) -{ - const guf_math_ckd_result check = guf_ckd_add_u32(a, b); - GUF_ASSERT(check == GUF_MATH_CKD_SUCCESS || check == GUF_MATH_CKD_OVERFLOW_POS); - if (result) { - switch (check) { - case GUF_MATH_CKD_SUCCESS: - *result = a + b; - break; - case GUF_MATH_CKD_OVERFLOW_POS: - *result = UINT32_MAX; - break; - default: - GUF_ASSERT(false); - } - } - return check; -} -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_u32(uint32_t a, uint32_t b, uint32_t *result) -{ - const guf_math_ckd_result check = guf_ckd_sub_u32(a, b); - GUF_ASSERT(check == GUF_MATH_CKD_SUCCESS || check == GUF_MATH_CKD_OVERFLOW_NEG); - if (result) { - switch (check) { - case GUF_MATH_CKD_SUCCESS: - *result = a - b; - break; - case GUF_MATH_CKD_OVERFLOW_NEG: - *result = 0; - break; - default: - GUF_ASSERT(false); - } - } - return check; -} -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_u32(uint32_t a, uint32_t b, uint32_t *result) -{ - const guf_math_ckd_result check = guf_ckd_mul_u32(a, b); - GUF_ASSERT(check == GUF_MATH_CKD_SUCCESS || check == GUF_MATH_CKD_OVERFLOW_POS); - if (result) { - switch (check) { - case GUF_MATH_CKD_SUCCESS: - *result = a * b; - break; - case GUF_MATH_CKD_OVERFLOW_POS: - *result = UINT32_MAX; - break; - default: - GUF_ASSERT(false); - } - } - return check; -} - -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_u32(uint32_t a, uint32_t b, uint32_t *result) -{ - const guf_math_ckd_result check = guf_ckd_add_u32(a, b); - if (result) { - *result = 1u * a + b; - } - return check; -} -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_u32(uint32_t a, uint32_t b, uint32_t *result) -{ - const guf_math_ckd_result check = guf_ckd_sub_u32(a, b); - if (result) { - *result = 1u * a - b; - } - return check; -} -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_u32(uint32_t a, uint32_t b, uint32_t *result) -{ - const guf_math_ckd_result check = guf_ckd_mul_u32(a, b); - if (result) { - *result = 1u * a * b; - } - return check; -} - - -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_u64(uint64_t a, uint64_t b, uint64_t *result) -{ - const guf_math_ckd_result check = guf_ckd_add_u64(a, b); - GUF_ASSERT(check == GUF_MATH_CKD_SUCCESS || check == GUF_MATH_CKD_OVERFLOW_POS); - if (result) { - switch (check) { - case GUF_MATH_CKD_SUCCESS: - *result = a + b; - break; - case GUF_MATH_CKD_OVERFLOW_POS: - *result = UINT64_MAX; - break; - default: - GUF_ASSERT(false); - } - } - return check; -} -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_u64(uint64_t a, uint64_t b, uint64_t *result) -{ - const guf_math_ckd_result check = guf_ckd_sub_u64(a, b); - GUF_ASSERT(check == GUF_MATH_CKD_SUCCESS || check == GUF_MATH_CKD_OVERFLOW_NEG); - if (result) { - switch (check) { - case GUF_MATH_CKD_SUCCESS: - *result = a - b; - break; - case GUF_MATH_CKD_OVERFLOW_NEG: - *result = 0; - break; - default: - GUF_ASSERT(false); - } - } - return check; -} -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_u64(uint64_t a, uint64_t b, uint64_t *result) -{ - const guf_math_ckd_result check = guf_ckd_mul_u64(a, b); - GUF_ASSERT(check == GUF_MATH_CKD_SUCCESS || check == GUF_MATH_CKD_OVERFLOW_POS); - if (result) { - switch (check) { - case GUF_MATH_CKD_SUCCESS: - *result = a * b; - break; - case GUF_MATH_CKD_OVERFLOW_POS: - *result = UINT64_MAX; - break; - default: - GUF_ASSERT(false); - } - } - return check; -} - -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_u64(uint64_t a, uint64_t b, uint64_t *result) -{ - const guf_math_ckd_result check = guf_ckd_add_u64(a, b); - if (result) { - *result = 1u * a + b; - } - return check; -} -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_u64(uint64_t a, uint64_t b, uint64_t *result) -{ - const guf_math_ckd_result check = guf_ckd_sub_u64(a, b); - if (result) { - *result = 1u * a - b; - } - return check; -} -GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_u64(uint64_t a, uint64_t b, uint64_t *result) -{ - const guf_math_ckd_result check = guf_ckd_mul_u64(a, b); - if (result) { - *result = 1u * a * b; - } - return check; -} - - GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_size_t(size_t a, size_t b, size_t *result) { const guf_math_ckd_result check = guf_ckd_add_size_t(a, b); @@ -2658,6 +3276,678 @@ GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_size_t(size_t a, size return check; } +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_uint_fast8_t(uint_fast8_t a, uint_fast8_t b, uint_fast8_t *result) +{ + const guf_math_ckd_result check = guf_ckd_add_uint_fast8_t(a, b); + GUF_ASSERT(check == GUF_MATH_CKD_SUCCESS || check == GUF_MATH_CKD_OVERFLOW_POS); + if (result) { + switch (check) { + case GUF_MATH_CKD_SUCCESS: + *result = a + b; + break; + case GUF_MATH_CKD_OVERFLOW_POS: + *result = GUF_UINT8_MAX; + break; + default: + GUF_ASSERT(false); + } + } + return check; +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_uint_fast8_t(uint_fast8_t a, uint_fast8_t b, uint_fast8_t *result) +{ + const guf_math_ckd_result check = guf_ckd_sub_uint_fast8_t(a, b); + GUF_ASSERT(check == GUF_MATH_CKD_SUCCESS || check == GUF_MATH_CKD_OVERFLOW_NEG); + if (result) { + switch (check) { + case GUF_MATH_CKD_SUCCESS: + *result = a - b; + break; + case GUF_MATH_CKD_OVERFLOW_NEG: + *result = 0; + break; + default: + GUF_ASSERT(false); + } + } + return check; +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_uint_fast8_t(uint_fast8_t a, uint_fast8_t b, uint_fast8_t *result) +{ + const guf_math_ckd_result check = guf_ckd_mul_uint_fast8_t(a, b); + GUF_ASSERT(check == GUF_MATH_CKD_SUCCESS || check == GUF_MATH_CKD_OVERFLOW_POS); + if (result) { + switch (check) { + case GUF_MATH_CKD_SUCCESS: + *result = a * b; + break; + case GUF_MATH_CKD_OVERFLOW_POS: + *result = GUF_UINT8_MAX; + break; + default: + GUF_ASSERT(false); + } + } + return check; +} + +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_uint_fast8_t(uint_fast8_t a, uint_fast8_t b, uint_fast8_t *result) +{ + a = GUF_UWRAP_8(a); + b = GUF_UWRAP_8(b); + const guf_math_ckd_result check = guf_ckd_add_uint_fast8_t(a, b); + if (result) { + *result = GUF_UWRAP_8( 1u * a + b ); + } + return check; +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_uint_fast8_t(uint_fast8_t a, uint_fast8_t b, uint_fast8_t *result) +{ + a = GUF_UWRAP_8(a); + b = GUF_UWRAP_8(b); + const guf_math_ckd_result check = guf_ckd_sub_uint_fast8_t(a, b); + if (result) { + *result = GUF_UWRAP_8( 1u * a - b ); + } + return check; +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_uint_fast8_t(uint_fast8_t a, uint_fast8_t b, uint_fast8_t *result) +{ + a = GUF_UWRAP_8(a); + b = GUF_UWRAP_8(b); + const guf_math_ckd_result check = guf_ckd_mul_uint_fast8_t(a, b); + if (result) { + *result = GUF_UWRAP_8( 1u * a * b ); + } + return check; +} + +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_uint_fast16_t(uint_fast16_t a, uint_fast16_t b, uint_fast16_t *result) +{ + const guf_math_ckd_result check = guf_ckd_add_uint_fast16_t(a, b); + GUF_ASSERT(check == GUF_MATH_CKD_SUCCESS || check == GUF_MATH_CKD_OVERFLOW_POS); + if (result) { + switch (check) { + case GUF_MATH_CKD_SUCCESS: + *result = a + b; + break; + case GUF_MATH_CKD_OVERFLOW_POS: + *result = GUF_UINT16_MAX; + break; + default: + GUF_ASSERT(false); + } + } + return check; +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_uint_fast16_t(uint_fast16_t a, uint_fast16_t b, uint_fast16_t *result) +{ + const guf_math_ckd_result check = guf_ckd_sub_uint_fast16_t(a, b); + GUF_ASSERT(check == GUF_MATH_CKD_SUCCESS || check == GUF_MATH_CKD_OVERFLOW_NEG); + if (result) { + switch (check) { + case GUF_MATH_CKD_SUCCESS: + *result = a - b; + break; + case GUF_MATH_CKD_OVERFLOW_NEG: + *result = 0; + break; + default: + GUF_ASSERT(false); + } + } + return check; +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_uint_fast16_t(uint_fast16_t a, uint_fast16_t b, uint_fast16_t *result) +{ + const guf_math_ckd_result check = guf_ckd_mul_uint_fast16_t(a, b); + GUF_ASSERT(check == GUF_MATH_CKD_SUCCESS || check == GUF_MATH_CKD_OVERFLOW_POS); + if (result) { + switch (check) { + case GUF_MATH_CKD_SUCCESS: + *result = a * b; + break; + case GUF_MATH_CKD_OVERFLOW_POS: + *result = GUF_UINT16_MAX; + break; + default: + GUF_ASSERT(false); + } + } + return check; +} + +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_uint_fast16_t(uint_fast16_t a, uint_fast16_t b, uint_fast16_t *result) +{ + a = GUF_UWRAP_16(a); + b = GUF_UWRAP_16(b); + const guf_math_ckd_result check = guf_ckd_add_uint_fast16_t(a, b); + if (result) { + *result = GUF_UWRAP_16( 1u * a + b ); + } + return check; +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_uint_fast16_t(uint_fast16_t a, uint_fast16_t b, uint_fast16_t *result) +{ + a = GUF_UWRAP_16(a); + b = GUF_UWRAP_16(b); + const guf_math_ckd_result check = guf_ckd_sub_uint_fast16_t(a, b); + if (result) { + *result = GUF_UWRAP_16( 1u * a - b ); + } + return check; +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_uint_fast16_t(uint_fast16_t a, uint_fast16_t b, uint_fast16_t *result) +{ + a = GUF_UWRAP_16(a); + b = GUF_UWRAP_16(b); + const guf_math_ckd_result check = guf_ckd_mul_uint_fast16_t(a, b); + if (result) { + *result = GUF_UWRAP_16( 1u * a * b ); + } + return check; +} + +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_uint_fast32_t(uint_fast32_t a, uint_fast32_t b, uint_fast32_t *result) +{ + const guf_math_ckd_result check = guf_ckd_add_uint_fast32_t(a, b); + GUF_ASSERT(check == GUF_MATH_CKD_SUCCESS || check == GUF_MATH_CKD_OVERFLOW_POS); + if (result) { + switch (check) { + case GUF_MATH_CKD_SUCCESS: + *result = a + b; + break; + case GUF_MATH_CKD_OVERFLOW_POS: + *result = GUF_UINT32_MAX; + break; + default: + GUF_ASSERT(false); + } + } + return check; +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_uint_fast32_t(uint_fast32_t a, uint_fast32_t b, uint_fast32_t *result) +{ + const guf_math_ckd_result check = guf_ckd_sub_uint_fast32_t(a, b); + GUF_ASSERT(check == GUF_MATH_CKD_SUCCESS || check == GUF_MATH_CKD_OVERFLOW_NEG); + if (result) { + switch (check) { + case GUF_MATH_CKD_SUCCESS: + *result = a - b; + break; + case GUF_MATH_CKD_OVERFLOW_NEG: + *result = 0; + break; + default: + GUF_ASSERT(false); + } + } + return check; +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_uint_fast32_t(uint_fast32_t a, uint_fast32_t b, uint_fast32_t *result) +{ + const guf_math_ckd_result check = guf_ckd_mul_uint_fast32_t(a, b); + GUF_ASSERT(check == GUF_MATH_CKD_SUCCESS || check == GUF_MATH_CKD_OVERFLOW_POS); + if (result) { + switch (check) { + case GUF_MATH_CKD_SUCCESS: + *result = a * b; + break; + case GUF_MATH_CKD_OVERFLOW_POS: + *result = GUF_UINT32_MAX; + break; + default: + GUF_ASSERT(false); + } + } + return check; +} + +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_uint_fast32_t(uint_fast32_t a, uint_fast32_t b, uint_fast32_t *result) +{ + a = GUF_UWRAP_32(a); + b = GUF_UWRAP_32(b); + const guf_math_ckd_result check = guf_ckd_add_uint_fast32_t(a, b); + if (result) { + *result = GUF_UWRAP_32( 1u * a + b ); + } + return check; +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_uint_fast32_t(uint_fast32_t a, uint_fast32_t b, uint_fast32_t *result) +{ + a = GUF_UWRAP_32(a); + b = GUF_UWRAP_32(b); + const guf_math_ckd_result check = guf_ckd_sub_uint_fast32_t(a, b); + if (result) { + *result = GUF_UWRAP_32( 1u * a - b ); + } + return check; +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_uint_fast32_t(uint_fast32_t a, uint_fast32_t b, uint_fast32_t *result) +{ + a = GUF_UWRAP_32(a); + b = GUF_UWRAP_32(b); + const guf_math_ckd_result check = guf_ckd_mul_uint_fast32_t(a, b); + if (result) { + *result = GUF_UWRAP_32( 1u * a * b ); + } + return check; +} + +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_uint_fast64_t(uint_fast64_t a, uint_fast64_t b, uint_fast64_t *result) +{ + const guf_math_ckd_result check = guf_ckd_add_uint_fast64_t(a, b); + GUF_ASSERT(check == GUF_MATH_CKD_SUCCESS || check == GUF_MATH_CKD_OVERFLOW_POS); + if (result) { + switch (check) { + case GUF_MATH_CKD_SUCCESS: + *result = a + b; + break; + case GUF_MATH_CKD_OVERFLOW_POS: + *result = GUF_UINT64_MAX; + break; + default: + GUF_ASSERT(false); + } + } + return check; +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_uint_fast64_t(uint_fast64_t a, uint_fast64_t b, uint_fast64_t *result) +{ + const guf_math_ckd_result check = guf_ckd_sub_uint_fast64_t(a, b); + GUF_ASSERT(check == GUF_MATH_CKD_SUCCESS || check == GUF_MATH_CKD_OVERFLOW_NEG); + if (result) { + switch (check) { + case GUF_MATH_CKD_SUCCESS: + *result = a - b; + break; + case GUF_MATH_CKD_OVERFLOW_NEG: + *result = 0; + break; + default: + GUF_ASSERT(false); + } + } + return check; +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_uint_fast64_t(uint_fast64_t a, uint_fast64_t b, uint_fast64_t *result) +{ + const guf_math_ckd_result check = guf_ckd_mul_uint_fast64_t(a, b); + GUF_ASSERT(check == GUF_MATH_CKD_SUCCESS || check == GUF_MATH_CKD_OVERFLOW_POS); + if (result) { + switch (check) { + case GUF_MATH_CKD_SUCCESS: + *result = a * b; + break; + case GUF_MATH_CKD_OVERFLOW_POS: + *result = GUF_UINT64_MAX; + break; + default: + GUF_ASSERT(false); + } + } + return check; +} + +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_uint_fast64_t(uint_fast64_t a, uint_fast64_t b, uint_fast64_t *result) +{ + a = GUF_UWRAP_64(a); + b = GUF_UWRAP_64(b); + const guf_math_ckd_result check = guf_ckd_add_uint_fast64_t(a, b); + if (result) { + *result = GUF_UWRAP_64( 1u * a + b ); + } + return check; +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_uint_fast64_t(uint_fast64_t a, uint_fast64_t b, uint_fast64_t *result) +{ + a = GUF_UWRAP_64(a); + b = GUF_UWRAP_64(b); + const guf_math_ckd_result check = guf_ckd_sub_uint_fast64_t(a, b); + if (result) { + *result = GUF_UWRAP_64( 1u * a - b ); + } + return check; +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_uint_fast64_t(uint_fast64_t a, uint_fast64_t b, uint_fast64_t *result) +{ + a = GUF_UWRAP_64(a); + b = GUF_UWRAP_64(b); + const guf_math_ckd_result check = guf_ckd_mul_uint_fast64_t(a, b); + if (result) { + *result = GUF_UWRAP_64( 1u * a * b ); + } + return check; +} + +#ifdef UINT8_MAX +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_u8(uint8_t a, uint8_t b, uint8_t *result) +{ + const guf_math_ckd_result check = guf_ckd_add_u8(a, b); + GUF_ASSERT(check == GUF_MATH_CKD_SUCCESS || check == GUF_MATH_CKD_OVERFLOW_POS); + if (result) { + switch (check) { + case GUF_MATH_CKD_SUCCESS: + *result = a + b; + break; + case GUF_MATH_CKD_OVERFLOW_POS: + *result = UINT8_MAX; + break; + default: + GUF_ASSERT(false); + } + } + return check; +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_u8(uint8_t a, uint8_t b, uint8_t *result) +{ + const guf_math_ckd_result check = guf_ckd_sub_u8(a, b); + GUF_ASSERT(check == GUF_MATH_CKD_SUCCESS || check == GUF_MATH_CKD_OVERFLOW_NEG); + if (result) { + switch (check) { + case GUF_MATH_CKD_SUCCESS: + *result = a - b; + break; + case GUF_MATH_CKD_OVERFLOW_NEG: + *result = 0; + break; + default: + GUF_ASSERT(false); + } + } + return check; +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_u8(uint8_t a, uint8_t b, uint8_t *result) +{ + const guf_math_ckd_result check = guf_ckd_mul_u8(a, b); + GUF_ASSERT(check == GUF_MATH_CKD_SUCCESS || check == GUF_MATH_CKD_OVERFLOW_POS); + if (result) { + switch (check) { + case GUF_MATH_CKD_SUCCESS: + *result = a * b; + break; + case GUF_MATH_CKD_OVERFLOW_POS: + *result = UINT8_MAX; + break; + default: + GUF_ASSERT(false); + } + } + return check; +} + +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_u8(uint8_t a, uint8_t b, uint8_t *result) +{ + const guf_math_ckd_result check = guf_ckd_add_u8(a, b); + if (result) { + *result = 1u * a + b; + } + return check; +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_u8(uint8_t a, uint8_t b, uint8_t *result) +{ + const guf_math_ckd_result check = guf_ckd_sub_u8(a, b); + if (result) { + *result = 1u * a - b; + } + return check; +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_u8(uint8_t a, uint8_t b, uint8_t *result) +{ + const guf_math_ckd_result check = guf_ckd_mul_u8(a, b); + if (result) { + *result = 1u * a * b; + } + return check; +} +#endif + +#ifdef UINT16_MAX +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_u16(uint16_t a, uint16_t b, uint16_t *result) +{ + const guf_math_ckd_result check = guf_ckd_add_u16(a, b); + GUF_ASSERT(check == GUF_MATH_CKD_SUCCESS || check == GUF_MATH_CKD_OVERFLOW_POS); + if (result) { + switch (check) { + case GUF_MATH_CKD_SUCCESS: + *result = a + b; + break; + case GUF_MATH_CKD_OVERFLOW_POS: + *result = UINT16_MAX; + break; + default: + GUF_ASSERT(false); + } + } + return check; +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_u16(uint16_t a, uint16_t b, uint16_t *result) +{ + const guf_math_ckd_result check = guf_ckd_sub_u16(a, b); + GUF_ASSERT(check == GUF_MATH_CKD_SUCCESS || check == GUF_MATH_CKD_OVERFLOW_NEG); + if (result) { + switch (check) { + case GUF_MATH_CKD_SUCCESS: + *result = a - b; + break; + case GUF_MATH_CKD_OVERFLOW_NEG: + *result = 0; + break; + default: + GUF_ASSERT(false); + } + } + return check; +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_u16(uint16_t a, uint16_t b, uint16_t *result) +{ + const guf_math_ckd_result check = guf_ckd_mul_u16(a, b); + GUF_ASSERT(check == GUF_MATH_CKD_SUCCESS || check == GUF_MATH_CKD_OVERFLOW_POS); + if (result) { + switch (check) { + case GUF_MATH_CKD_SUCCESS: + *result = a * b; + break; + case GUF_MATH_CKD_OVERFLOW_POS: + *result = UINT16_MAX; + break; + default: + GUF_ASSERT(false); + } + } + return check; +} + +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_u16(uint16_t a, uint16_t b, uint16_t *result) +{ + const guf_math_ckd_result check = guf_ckd_add_u16(a, b); + if (result) { + *result = 1u * a + b; + } + return check; +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_u16(uint16_t a, uint16_t b, uint16_t *result) +{ + const guf_math_ckd_result check = guf_ckd_sub_u16(a, b); + if (result) { + *result = 1u * a - b; + } + return check; +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_u16(uint16_t a, uint16_t b, uint16_t *result) +{ + const guf_math_ckd_result check = guf_ckd_mul_u16(a, b); + if (result) { + *result = 1u * a * b; + } + return check; +} +#endif + +#ifdef UINT32_MAX +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_u32(uint32_t a, uint32_t b, uint32_t *result) +{ + const guf_math_ckd_result check = guf_ckd_add_u32(a, b); + GUF_ASSERT(check == GUF_MATH_CKD_SUCCESS || check == GUF_MATH_CKD_OVERFLOW_POS); + if (result) { + switch (check) { + case GUF_MATH_CKD_SUCCESS: + *result = a + b; + break; + case GUF_MATH_CKD_OVERFLOW_POS: + *result = UINT32_MAX; + break; + default: + GUF_ASSERT(false); + } + } + return check; +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_u32(uint32_t a, uint32_t b, uint32_t *result) +{ + const guf_math_ckd_result check = guf_ckd_sub_u32(a, b); + GUF_ASSERT(check == GUF_MATH_CKD_SUCCESS || check == GUF_MATH_CKD_OVERFLOW_NEG); + if (result) { + switch (check) { + case GUF_MATH_CKD_SUCCESS: + *result = a - b; + break; + case GUF_MATH_CKD_OVERFLOW_NEG: + *result = 0; + break; + default: + GUF_ASSERT(false); + } + } + return check; +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_u32(uint32_t a, uint32_t b, uint32_t *result) +{ + const guf_math_ckd_result check = guf_ckd_mul_u32(a, b); + GUF_ASSERT(check == GUF_MATH_CKD_SUCCESS || check == GUF_MATH_CKD_OVERFLOW_POS); + if (result) { + switch (check) { + case GUF_MATH_CKD_SUCCESS: + *result = a * b; + break; + case GUF_MATH_CKD_OVERFLOW_POS: + *result = UINT32_MAX; + break; + default: + GUF_ASSERT(false); + } + } + return check; +} + +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_u32(uint32_t a, uint32_t b, uint32_t *result) +{ + const guf_math_ckd_result check = guf_ckd_add_u32(a, b); + if (result) { + *result = 1u * a + b; + } + return check; +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_u32(uint32_t a, uint32_t b, uint32_t *result) +{ + const guf_math_ckd_result check = guf_ckd_sub_u32(a, b); + if (result) { + *result = 1u * a - b; + } + return check; +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_u32(uint32_t a, uint32_t b, uint32_t *result) +{ + const guf_math_ckd_result check = guf_ckd_mul_u32(a, b); + if (result) { + *result = 1u * a * b; + } + return check; +} +#endif + +#ifdef UINT64_MAX +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_u64(uint64_t a, uint64_t b, uint64_t *result) +{ + const guf_math_ckd_result check = guf_ckd_add_u64(a, b); + GUF_ASSERT(check == GUF_MATH_CKD_SUCCESS || check == GUF_MATH_CKD_OVERFLOW_POS); + if (result) { + switch (check) { + case GUF_MATH_CKD_SUCCESS: + *result = a + b; + break; + case GUF_MATH_CKD_OVERFLOW_POS: + *result = UINT64_MAX; + break; + default: + GUF_ASSERT(false); + } + } + return check; +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_u64(uint64_t a, uint64_t b, uint64_t *result) +{ + const guf_math_ckd_result check = guf_ckd_sub_u64(a, b); + GUF_ASSERT(check == GUF_MATH_CKD_SUCCESS || check == GUF_MATH_CKD_OVERFLOW_NEG); + if (result) { + switch (check) { + case GUF_MATH_CKD_SUCCESS: + *result = a - b; + break; + case GUF_MATH_CKD_OVERFLOW_NEG: + *result = 0; + break; + default: + GUF_ASSERT(false); + } + } + return check; +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_u64(uint64_t a, uint64_t b, uint64_t *result) +{ + const guf_math_ckd_result check = guf_ckd_mul_u64(a, b); + GUF_ASSERT(check == GUF_MATH_CKD_SUCCESS || check == GUF_MATH_CKD_OVERFLOW_POS); + if (result) { + switch (check) { + case GUF_MATH_CKD_SUCCESS: + *result = a * b; + break; + case GUF_MATH_CKD_OVERFLOW_POS: + *result = UINT64_MAX; + break; + default: + GUF_ASSERT(false); + } + } + return check; +} + +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_u64(uint64_t a, uint64_t b, uint64_t *result) +{ + const guf_math_ckd_result check = guf_ckd_add_u64(a, b); + if (result) { + *result = 1u * a + b; + } + return check; +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_u64(uint64_t a, uint64_t b, uint64_t *result) +{ + const guf_math_ckd_result check = guf_ckd_sub_u64(a, b); + if (result) { + *result = 1u * a - b; + } + return check; +} +GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_u64(uint64_t a, uint64_t b, uint64_t *result) +{ + const guf_math_ckd_result check = guf_ckd_mul_u64(a, b); + if (result) { + *result = 1u * a * b; + } + return check; +} +#endif + #endif /* End impl */ diff --git a/src/guf_rand.h b/src/guf_rand.h index e3c1177..63036fd 100644 --- a/src/guf_rand.h +++ b/src/guf_rand.h @@ -26,29 +26,24 @@ // State for xoshiro128** 1.1 typedef struct guf_rand32_state { - uint32_t s[4]; // Must not be all zero. + uint_fast32_t s[4]; // Must not be all zero. } guf_rand32_state; // State for xoshiro256** 1.0 -#ifdef UINT64_MAX - typedef struct guf_rand64_state { - uint64_t s[4]; // Must not be all zero. - } guf_rand64_state; -#endif +typedef struct guf_rand64_state { + uint_fast64_t s[4]; // Must not be all zero. +} guf_rand64_state; #ifdef GUF_RAND_32_BIT // Use guf_rand32_state (i.e. xoshiro128** 1.1) as default. - #define GUF_RAND_MAX UINT32_MAX + #define GUF_RAND_MAX GUF_UINT32_MAX typedef guf_rand32_state guf_randstate; - typedef uint32_t guf_rand_seed_t; + typedef uint_fast32_t guf_rand_seed_t; #else // Use guf_rand64_state (i.e. xoshiro256** 1.0) as default. - #ifndef UINT64_MAX - #error "guf_rand.h: Platform does not support uint64_t (define GUF_RAND_32_BIT to fix)" - #endif - #define GUF_RAND_MAX UINT64_MAX + #define GUF_RAND_MAX GUF_UINT64_MAX typedef guf_rand64_state guf_randstate; - typedef uint64_t guf_rand_seed_t; + typedef uint_fast64_t guf_rand_seed_t; #endif /* @@ -60,76 +55,59 @@ typedef struct guf_rand32_state { (If you want to initialise the guf_randstate struct manually, you have to ensure yourself the four state-integers aren't all zero.) */ GUF_RAND_KWRDS void guf_randstate_init(guf_randstate *state, guf_rand_seed_t seed); -#ifdef UINT64_MAX - GUF_RAND_KWRDS void guf_rand64_state_init(guf_rand64_state *state, uint64_t seed); -#endif -GUF_RAND_KWRDS void guf_rand32_state_init(guf_rand32_state *state, uint32_t seed); +GUF_RAND_KWRDS void guf_rand64_state_init(guf_rand64_state *state, uint_fast64_t seed); +GUF_RAND_KWRDS void guf_rand32_state_init(guf_rand32_state *state, uint_fast32_t seed); /* - guf_randstate_jump(state) -> void; advance the rng-state as if 2^128 (or 2^64 for rand32_state) calls to guf_rand_u32 had occured. Can be used to generate 2^128 (or 2^64 for rand32_state) non-overlapping subsequences for parallel computations. */ -GUF_RAND_KWRDS void guf_randstate_jump(guf_randstate *state); // Equivalent to 2^128 (or 2^64) calls to guf_rand_u32 -#ifdef UINT64_MAX - GUF_RAND_KWRDS void guf_rand64_state_jump(guf_rand64_state *state); // Equivalent to 2^128 calls to guf_rand64_u64 -#endif +GUF_RAND_KWRDS void guf_randstate_jump(guf_randstate *state); // Equivalent to 2^128 (or 2^64) calls to guf_rand_u32/u64 +GUF_RAND_KWRDS void guf_rand64_state_jump(guf_rand64_state *state); // Equivalent to 2^128 calls to guf_rand64_u64 GUF_RAND_KWRDS void guf_rand32_state_jump(guf_rand32_state *state); // Equivalent to 2^64 calls to guf_rand32_u32 // Uniform distributions in default ranges: /* - - guf_rand_splitmix64(state) -> uint64_t in range [0, UINT64_MAX] + - guf_rand_splitmix64(state) -> u64 in range [0, UINT64_MAX] (Very simple rng with only 64-bits of state; used for "scrambling" 64-bit seeds in guf_randstate_init.) - - guf_rand_splitmix32(state) -> uint32_t in range [0, UINT32_MAX] + - guf_rand_splitmix32(state) -> u32 in range [0, UINT32_MAX] (Very simple rng with only 32-bits of state; used for "scrambling" 32-bit seeds in guf_randstate_init.) */ -#ifdef UINT64_MAX - GUF_RAND_KWRDS uint64_t guf_rand_splitmix64(uint64_t *state); -#endif -GUF_RAND_KWRDS uint32_t guf_rand_splitmix32(uint32_t *state); +GUF_RAND_KWRDS uint_fast64_t guf_rand_splitmix64(uint_fast64_t *state); +GUF_RAND_KWRDS uint_fast32_t guf_rand_splitmix32(uint_fast32_t *state); /* - - guf_rand_u32(state) -> uint32_t in range [0, UINT32_MAX] + - guf_rand_u32(state) -> u32 in range [0, UINT32_MAX] */ -GUF_RAND_KWRDS uint32_t guf_rand_u32(guf_randstate *state); -#ifdef UINT64_MAX - GUF_RAND_KWRDS uint32_t guf_rand64_u32(guf_rand64_state *state); -#endif -GUF_RAND_KWRDS uint32_t guf_rand32_u32(guf_rand32_state *state); +GUF_RAND_KWRDS uint_fast32_t guf_rand_u32(guf_randstate *state); +GUF_RAND_KWRDS uint_fast32_t guf_rand64_u32(guf_rand64_state *state); +GUF_RAND_KWRDS uint_fast32_t guf_rand32_u32(guf_rand32_state *state); /* - guf_rand_u64(state) -> uint64_t (or uint_least64_t) in range [0, UINT64_MAX] NOTE: May be slow on 32-bit platforms. NOTE: If uint64_t is not available (optional according to the standards), use uint_least64_t (always available in C99 and above). */ -#ifdef UINT64_MAX - GUF_RAND_KWRDS uint64_t guf_rand_u64(guf_randstate *state); - GUF_RAND_KWRDS uint64_t guf_rand32_u64(guf_rand32_state *state); - GUF_RAND_KWRDS uint64_t guf_rand64_u64(guf_rand64_state *state); -#else - GUF_RAND_KWRDS uint_least64_t guf_rand_u64(guf_randstate *state) - GUF_RAND_KWRDS uint_least64_t guf_rand32_u64(guf_rand32_state *state); -#endif +GUF_RAND_KWRDS uint_fast64_t guf_rand_u64(guf_randstate *state); +GUF_RAND_KWRDS uint_fast64_t guf_rand32_u64(guf_rand32_state *state); +GUF_RAND_KWRDS uint_fast64_t guf_rand64_u64(guf_rand64_state *state); /* - guf_rand_f64(state) -> double in range [0.0, 1.0) NOTE: May be slow on 32-bit platforms (as it calls guf_rand_u64) */ GUF_RAND_KWRDS double guf_rand_f64(guf_randstate *state); -#ifdef UINT64_MAX - GUF_RAND_KWRDS double guf_rand64_f64(guf_rand64_state *state); -#endif +GUF_RAND_KWRDS double guf_rand64_f64(guf_rand64_state *state); GUF_RAND_KWRDS double guf_rand32_f64(guf_rand32_state *state); /* - guf_rand_f32(state) -> float in range [0.f, 1.f) */ GUF_RAND_KWRDS float guf_rand_f32(guf_randstate *state); -#ifdef UINT64_MAX - GUF_RAND_KWRDS float guf_rand64_f32(guf_rand64_state *state); -#endif +GUF_RAND_KWRDS float guf_rand64_f32(guf_rand64_state *state); GUF_RAND_KWRDS float guf_rand32_f32(guf_rand32_state *state); @@ -142,39 +120,34 @@ GUF_RAND_KWRDS float guf_rand32_f32(guf_rand32_state *state); */ GUF_RAND_KWRDS float guf_randrange_f32(guf_randstate *state, float min, float end); GUF_RAND_KWRDS double guf_randrange_f64(guf_randstate *state, double min, double end); -#ifdef UINT64_MAX - GUF_RAND_KWRDS float guf_rand64_range_f32(guf_rand64_state *state, float min, float end); - GUF_RAND_KWRDS double guf_rand64_range_f64(guf_rand64_state *state, double min, double end); -#endif + +GUF_RAND_KWRDS float guf_rand64_range_f32(guf_rand64_state *state, float min, float end); +GUF_RAND_KWRDS double guf_rand64_range_f64(guf_rand64_state *state, double min, double end); + GUF_RAND_KWRDS float guf_rand32_range_f32(guf_rand32_state *state, float min, float end); GUF_RAND_KWRDS double guf_rand32_range_f64(guf_rand32_state *state, double min, double end); /* - - guf_randrange_i32(state, min, max) -> int32_t in range [min, max] (contrary to the float equivalents, max *is* inclusive) - - guf_randrange_u32(state, min, max) -> uint32_t in range [min, max] (contrary to the float equivalents, max *is* inclusive) + - guf_randrange_i32(state, min, max) -> i32 in range [min, max] (contrary to the float equivalents, max *is* inclusive) + - guf_randrange_u32(state, min, max) -> u32 in range [min, max] (contrary to the float equivalents, max *is* inclusive) NOTE: guf_randrange_u32 may be slow on 32-bit platforms (as it calls guf_rand_f64). This does not apply to guf_randrange_i32 (as it doesn't call guf_rand_f64). */ -GUF_RAND_KWRDS int32_t guf_randrange_i32(guf_randstate *state, int32_t min, int32_t max); -GUF_RAND_KWRDS uint32_t guf_randrange_u32(guf_randstate *state, uint32_t min, uint32_t max); // NOTE: may be slow on 32-bit platforms. -#ifdef UINT64_MAX - GUF_RAND_KWRDS int32_t guf_rand64_range_i32(guf_rand64_state *state, int32_t min, int32_t max); - GUF_RAND_KWRDS uint32_t guf_rand64_range_u32(guf_rand64_state *state, uint32_t min, uint32_t max); -#endif -GUF_RAND_KWRDS int32_t guf_rand32_range_i32(guf_rand32_state *state, int32_t min, int32_t max); -GUF_RAND_KWRDS uint32_t guf_rand32_range_u32(guf_rand32_state *state, uint32_t min, uint32_t max); // NOTE: may be slow on 32-bit platforms. +GUF_RAND_KWRDS int_fast32_t guf_randrange_i32(guf_randstate *state, int_fast32_t min, int_fast32_t max); +GUF_RAND_KWRDS uint_fast32_t guf_randrange_u32(guf_randstate *state, uint_fast32_t min, uint_fast32_t max); // NOTE: may be slow on 32-bit platforms (as it calls guf_rand_f64). + +GUF_RAND_KWRDS int_fast32_t guf_rand64_range_i32(guf_rand64_state *state, int_fast32_t min, int_fast32_t max); +GUF_RAND_KWRDS uint_fast32_t guf_rand64_range_u32(guf_rand64_state *state, uint_fast32_t min, uint_fast32_t max); + +GUF_RAND_KWRDS int_fast32_t guf_rand32_range_i32(guf_rand32_state *state, int_fast32_t min, int_fast32_t max); +GUF_RAND_KWRDS uint_fast32_t guf_rand32_range_u32(guf_rand32_state *state, uint_fast32_t min, uint_fast32_t max); // NOTE: may be slow on 32-bit platforms (as it calls guf_rand_f64). /* - guf_randrange_i64(state, min, max) -> int64_t in range [min, max] (contrary to the float equivalents, max *is* inclusive) - NOTE: The Generic version is only available if GUF_RAND_32_BIT is undefined and the platform supports uint64_t. - (The specific guf_rand64_range_i64 version is available as long as the platform supports uint64_t.) */ -#if defined(UINT64_MAX) && !defined(GUF_RAND_32_BIT) - GUF_RAND_KWRDS int64_t guf_randrange_i64(guf_randstate *state, int64_t min, int64_t max); -#endif -#ifdef UINT64_MAX - GUF_RAND_KWRDS int64_t guf_rand64_range_i64(guf_rand64_state *state, int64_t min, int64_t max); -#endif +GUF_RAND_KWRDS int_fast64_t guf_randrange_i64(guf_randstate *state, int_fast64_t min, int_fast64_t max); +GUF_RAND_KWRDS int_fast64_t guf_rand64_range_i64(guf_rand64_state *state, int_fast64_t min, int_fast64_t max); +GUF_RAND_KWRDS int_fast64_t guf_rand32_range_i64(guf_rand32_state *state, int_fast64_t min, int_fast64_t max); // Bernoulli-trials: @@ -187,11 +160,11 @@ GUF_RAND_KWRDS uint32_t guf_rand32_range_u32(guf_rand32_state *state, uint32_t m GUF_RAND_KWRDS bool guf_rand_bernoulli_trial_f32(guf_randstate *state, float p); GUF_RAND_KWRDS bool guf_rand_bernoulli_trial_f64(guf_randstate *state, double p); GUF_RAND_KWRDS bool guf_rand_flip(guf_randstate *state); -#ifdef UINT64_MAX - GUF_RAND_KWRDS bool guf_rand64_bernoulli_trial_f32(guf_rand64_state *state, float p); - GUF_RAND_KWRDS bool guf_rand64_bernoulli_trial_f64(guf_rand64_state *state, double p); - GUF_RAND_KWRDS bool guf_rand64_flip(guf_rand64_state *state); -#endif + +GUF_RAND_KWRDS bool guf_rand64_bernoulli_trial_f32(guf_rand64_state *state, float p); +GUF_RAND_KWRDS bool guf_rand64_bernoulli_trial_f64(guf_rand64_state *state, double p); +GUF_RAND_KWRDS bool guf_rand64_flip(guf_rand64_state *state); + GUF_RAND_KWRDS bool guf_rand32_bernoulli_trial_f32(guf_rand32_state *state, float p); GUF_RAND_KWRDS bool guf_rand32_bernoulli_trial_f64(guf_rand32_state *state, double p); GUF_RAND_KWRDS bool guf_rand32_flip(guf_rand32_state *state); @@ -209,12 +182,12 @@ GUF_RAND_KWRDS void guf_rand_normal_sample_f64(guf_randstate *state, double mean GUF_RAND_KWRDS void guf_rand_normal_sample_f32(guf_randstate *state, float mean, float std_dev, float *result, ptrdiff_t n); GUF_RAND_KWRDS double guf_rand_normal_sample_one_f64(guf_randstate *state, double mean, double std_dev); GUF_RAND_KWRDS float guf_rand_normal_sample_one_f32(guf_randstate *state, float mean, float std_dev); -#ifdef UINT64_MAX - GUF_RAND_KWRDS void guf_rand64_normal_sample_f32(guf_rand64_state *state, float mean, float std_dev, float *result, ptrdiff_t n); - GUF_RAND_KWRDS void guf_rand64_normal_sample_f64(guf_rand64_state *state, double mean, double std_dev, double *result, ptrdiff_t n); - GUF_RAND_KWRDS float guf_rand64_normal_sample_one_f32(guf_rand64_state *state, float mean, float std_dev); - GUF_RAND_KWRDS double guf_rand64_normal_sample_one_f64(guf_rand64_state *state, double mean, double std_dev); -#endif + +GUF_RAND_KWRDS void guf_rand64_normal_sample_f32(guf_rand64_state *state, float mean, float std_dev, float *result, ptrdiff_t n); +GUF_RAND_KWRDS void guf_rand64_normal_sample_f64(guf_rand64_state *state, double mean, double std_dev, double *result, ptrdiff_t n); +GUF_RAND_KWRDS float guf_rand64_normal_sample_one_f32(guf_rand64_state *state, float mean, float std_dev); +GUF_RAND_KWRDS double guf_rand64_normal_sample_one_f64(guf_rand64_state *state, double mean, double std_dev); + GUF_RAND_KWRDS void guf_rand32_normal_sample_f32(guf_rand32_state *state, float mean, float std_dev, float *result, ptrdiff_t n); GUF_RAND_KWRDS void guf_rand32_normal_sample_f64(guf_rand32_state *state, double mean, double std_dev, double *result, ptrdiff_t n); GUF_RAND_KWRDS float guf_rand32_normal_sample_one_f32(guf_rand32_state *state, float mean, float std_dev); @@ -222,6 +195,8 @@ GUF_RAND_KWRDS double guf_rand32_normal_sample_one_f64(guf_rand32_state *state, #endif +// #define GUF_RAND_IMPL_STATIC /* DEBUG */ + #if defined(GUF_RAND_IMPL) || defined(GUF_RAND_IMPL_STATIC) #include #include @@ -231,35 +206,34 @@ GUF_RAND_KWRDS double guf_rand32_normal_sample_one_f64(guf_rand32_state *state, #define GUF_MATH_CKDINT_IMPL_STATIC #include "guf_math_ckdint.h" -#ifdef UINT64_MAX - /* - splitmix64 written in 2015 by Sebastiano Vigna (vigna@acm.org) (released as public domain) - cf. https://prng.di.unimi.it/splitmix64.c (last-retrieved 2025-02-11) - */ - GUF_RAND_KWRDS uint64_t guf_rand_splitmix64(uint64_t *state) - { - GUF_ASSERT(state); - uint64_t z = ((*state) += 1u * 0x9e3779b97f4a7c15); - z = (z ^ (z >> 30u)) * 0xbf58476d1ce4e5b9; - z = (z ^ (z >> 27u)) * 0x94d049bb133111eb; - return z ^ (z >> 31u); - } -#endif +/* + splitmix64 written in 2015 by Sebastiano Vigna (vigna@acm.org) (released as public domain) + cf. https://prng.di.unimi.it/splitmix64.c (last-retrieved 2025-02-11) +*/ +GUF_RAND_KWRDS uint_fast64_t guf_rand_splitmix64(uint_fast64_t *state) +{ + GUF_ASSERT(state); + *state = GUF_UWRAP_64(*state); + uint_fast64_t z = ( *state = GUF_UWRAP_64(*state + 0x9e3779b97f4a7c15ull) ); + z = GUF_UWRAP_64( GUF_UWRAP_64(z ^ (z >> 30u)) * 0xbf58476d1ce4e5b9ull ); + z = GUF_UWRAP_64( GUF_UWRAP_64(z ^ (z >> 27u)) * 0x94d049bb133111ebull ); + return GUF_UWRAP_64(z ^ (z >> 31u)); +} /* splitmix32 written in 2016 by Kaito Udagawa (released under CC0 ) cf. https://github.com/umireon/my-random-stuff/blob/master/xorshift/splitmix32.c (last-retrieved 2025-03-28) */ -GUF_RAND_KWRDS uint32_t guf_rand_splitmix32(uint32_t *state) +GUF_RAND_KWRDS uint_fast32_t guf_rand_splitmix32(uint_fast32_t *state) { GUF_ASSERT(state); - uint32_t z = (*state += 1u * 0x9e3779b9); - z = (z ^ (z >> 16u)) * 0x85ebca6b; - z = (z ^ (z >> 13u)) * 0xc2b2ae35; - return z ^ (z >> 16u); + uint_fast32_t z = ( *state = GUF_UWRAP_32(*state + 0x9e3779b9ul) ); + z = GUF_UWRAP_32( GUF_UWRAP_32(z ^ (z >> 16u)) * 0x85ebca6bul ); + z = GUF_UWRAP_32( GUF_UWRAP_32(z ^ (z >> 13u)) * 0xc2b2ae35ul ); + return GUF_UWRAP_32(z ^ (z >> 16u)); } -GUF_RAND_KWRDS void guf_rand32_state_init(guf_rand32_state *state, uint32_t seed) +GUF_RAND_KWRDS void guf_rand32_state_init(guf_rand32_state *state, uint_fast32_t seed) { for (size_t i = 0; i < GUF_ARR_SIZE(state->s); ++i) { state->s[i] = guf_rand_splitmix32(&seed); @@ -273,21 +247,19 @@ GUF_RAND_KWRDS void guf_rand32_state_init(guf_rand32_state *state, uint32_t seed } } -#ifdef UINT64_MAX - GUF_RAND_KWRDS void guf_rand64_state_init(guf_rand64_state *state, uint64_t seed) - { - for (size_t i = 0; i < GUF_ARR_SIZE(state->s); ++i) { +GUF_RAND_KWRDS void guf_rand64_state_init(guf_rand64_state *state, uint_fast64_t seed) +{ + for (size_t i = 0; i < GUF_ARR_SIZE(state->s); ++i) { + state->s[i] = guf_rand_splitmix64(&seed); + } + if (!state->s[0] && !state->s[1] && !state->s[2] && !state->s[3]) { // State must not be only zeroes: + state->s[0] = 0x9e3779b97f4a7c15; // arbitrary constant != 0 + seed = state->s[0]; + for (size_t i = 1; i < GUF_ARR_SIZE(state->s); ++i) { state->s[i] = guf_rand_splitmix64(&seed); } - if (!state->s[0] && !state->s[1] && !state->s[2] && !state->s[3]) { // State must not be only zeroes: - state->s[0] = 0x9e3779b97f4a7c15; // arbitrary constant != 0 - seed = state->s[0]; - for (size_t i = 1; i < GUF_ARR_SIZE(state->s); ++i) { - state->s[i] = guf_rand_splitmix64(&seed); - } - } } -#endif +} GUF_RAND_KWRDS void guf_randstate_init(guf_randstate *state, guf_rand_seed_t seed) { @@ -298,7 +270,7 @@ GUF_RAND_KWRDS void guf_randstate_init(guf_randstate *state, guf_rand_seed_t see #endif } -GUF_RAND_KWRDS uint32_t guf_rand32_u32(guf_rand32_state *state) +GUF_RAND_KWRDS uint_fast32_t guf_rand32_u32(guf_rand32_state *state) { GUF_ASSERT(state); GUF_ASSERT(state->s[0] || state->s[1] || state->s[2] || state->s[3]); @@ -306,25 +278,30 @@ GUF_RAND_KWRDS uint32_t guf_rand32_u32(guf_rand32_state *state) xoshiro128** 1.1 (public domain) written in 2018 by David Blackman and Sebastiano Vigna (vigna@acm.org) cf. https://prng.di.unimi.it/xoshiro128starstar.c (last-retrieved 2025-02-11) */ - const uint32_t result = guf_rotl_u32(state->s[1] * 5u, 7) * 9u; - const uint32_t t = state->s[1] << 9u; + const uint_fast32_t result = GUF_UWRAP_32( guf_rotl32_uint_fast32_t(state->s[1] * 5u, 7) * 9u ); + const uint_fast32_t t = GUF_UWRAP_32( state->s[1] << 9u ); + state->s[2] ^= state->s[0]; state->s[3] ^= state->s[1]; state->s[1] ^= state->s[2]; state->s[0] ^= state->s[3]; state->s[2] ^= t; - state->s[3] = guf_rotl_u32(state->s[3], 11); + state->s[3] = guf_rotl32_uint_fast32_t(state->s[3], 11); + + state->s[0] = GUF_UWRAP_32(state->s[0]); + state->s[1] = GUF_UWRAP_32(state->s[1]); + state->s[2] = GUF_UWRAP_32(state->s[2]); + state->s[3] = GUF_UWRAP_32(state->s[3]); + return result; } -#ifdef UINT64_MAX - GUF_RAND_KWRDS uint32_t guf_rand64_u32(guf_rand64_state *state) - { - return (uint32_t)(guf_rand64_u64(state) >> 32u); - } -#endif +GUF_RAND_KWRDS uint_fast32_t guf_rand64_u32(guf_rand64_state *state) +{ + return (uint_fast32_t)GUF_UWRAP_32( (guf_rand64_u64(state) >> 32u) ); +} -GUF_RAND_KWRDS uint32_t guf_rand_u32(guf_randstate *state) +GUF_RAND_KWRDS uint_fast32_t guf_rand_u32(guf_randstate *state) { GUF_ASSERT(state); GUF_ASSERT(state->s[0] || state->s[1] || state->s[2] || state->s[3]); @@ -336,50 +313,45 @@ GUF_RAND_KWRDS uint32_t guf_rand_u32(guf_randstate *state) } -#ifdef UINT64_MAX - GUF_RAND_KWRDS uint64_t guf_rand64_u64(guf_rand64_state *state) - { - GUF_ASSERT(state); - GUF_ASSERT(state->s[0] || state->s[1] || state->s[2] || state->s[3]); - /* - xoshiro256** 1.0 (public domain) written in 2018 by David Blackman and Sebastiano Vigna (vigna@acm.org) - cf. https://prng.di.unimi.it/xoshiro256starstar.c (last-retrieved 2025-02-11) - */ - const uint64_t result = guf_rotl_u64(state->s[1] * 5u, 7) * 9u; - const uint64_t t = state->s[1] << 17u; - state->s[2] ^= state->s[0]; - state->s[3] ^= state->s[1]; - state->s[1] ^= state->s[2]; - state->s[0] ^= state->s[3]; - state->s[2] ^= t; - state->s[3] = guf_rotl_u64(state->s[3], 45); - return result; - } -#endif - -#ifdef UINT64_MAX -GUF_RAND_KWRDS uint64_t guf_rand32_u64(guf_rand32_state *state) -#else -GUF_RAND_KWRDS uint_least64_t guf_rand32_u64(guf_rand32_state *state) -#endif +GUF_RAND_KWRDS uint_fast64_t guf_rand64_u64(guf_rand64_state *state) { GUF_ASSERT(state); GUF_ASSERT(state->s[0] || state->s[1] || state->s[2] || state->s[3]); - const uint32_t lower_bits = guf_rand32_u32(state); - const uint32_t upper_bits = guf_rand32_u32(state); - #ifdef UINT64_MAX - return ((uint64_t)upper_bits << 32u) | (uint64_t)lower_bits; // TODO: not sure if that's a good idea... - #else - return ((uint_least64_t)upper_bits << 32u) | (uint_least64_t)lower_bits; // TODO: not sure if that's a good idea... - #endif + /* + xoshiro256** 1.0 (public domain) written in 2018 by David Blackman and Sebastiano Vigna (vigna@acm.org) + cf. https://prng.di.unimi.it/xoshiro256starstar.c (last-retrieved 2025-02-11) + */ + const uint_fast64_t result = GUF_UWRAP_64( guf_rotl64_uint_fast64_t(state->s[1] * 5u, 7) * 9u ); + const uint_fast64_t t = GUF_UWRAP_64( state->s[1] << 17u ); + + state->s[2] ^= state->s[0]; + state->s[3] ^= state->s[1]; + state->s[1] ^= state->s[2]; + state->s[0] ^= state->s[3]; + state->s[2] ^= t; + state->s[3] = guf_rotl64_uint_fast64_t(state->s[3], 45); + + state->s[0] = GUF_UWRAP_64(state->s[0]); + state->s[1] = GUF_UWRAP_64(state->s[1]); + state->s[2] = GUF_UWRAP_64(state->s[2]); + state->s[3] = GUF_UWRAP_64(state->s[3]); + + return result; } +GUF_RAND_KWRDS uint_fast64_t guf_rand32_u64(guf_rand32_state *state) +{ + GUF_ASSERT(state); + GUF_ASSERT(state->s[0] || state->s[1] || state->s[2] || state->s[3]); + const uint_fast32_t lower_bits = guf_rand32_u32(state); + const uint_fast32_t upper_bits = guf_rand32_u32(state); + GUF_ASSERT( lower_bits <= GUF_UINT32_MAX && upper_bits <= GUF_UINT32_MAX ); + GUF_ASSERT( ( ((uint_fast64_t)upper_bits << 32u) | (uint_fast64_t)lower_bits ) <= GUF_UINT32_MAX); + return ((uint_fast64_t)upper_bits << 32u) | (uint_fast64_t)lower_bits; // TODO: not sure if that's a good idea... + +} -#ifdef UINT64_MAX -GUF_RAND_KWRDS uint64_t guf_rand_u64(guf_randstate *state) -#else -GUF_RAND_KWRDS uint_least64_t guf_rand_u64(guf_randstate *state) -#endif +GUF_RAND_KWRDS uint_fast64_t guf_rand_u64(guf_randstate *state) { #ifdef GUF_RAND_32_BIT return guf_rand32_u64(state); @@ -395,59 +367,63 @@ GUF_RAND_KWRDS uint_least64_t guf_rand_u64(guf_randstate *state) GUF_RAND_KWRDS void guf_rand32_state_jump(guf_rand32_state *state) { GUF_ASSERT(state); - static const uint32_t JUMP[] = { 0x8764000b, 0xf542d2d3, 0x6fa035c3, 0x77f2db5b }; - uint32_t s0 = 0; - uint32_t s1 = 0; - uint32_t s2 = 0; - uint32_t s3 = 0; + static const uint_fast32_t JUMP[] = { 0x8764000b, 0xf542d2d3, 0x6fa035c3, 0x77f2db5b }; + uint_fast32_t s0 = 0; + uint_fast32_t s1 = 0; + uint_fast32_t s2 = 0; + uint_fast32_t s3 = 0; for (size_t i = 0; i < sizeof JUMP / sizeof *JUMP; ++i) { for (int b = 0; b < 32; ++b) { - if (JUMP[i] & UINT32_C(1) << b) { + if (1u * JUMP[i] & UINT32_C(1) << b) { s0 ^= state->s[0]; s1 ^= state->s[1]; s2 ^= state->s[2]; s3 ^= state->s[3]; + s0 = GUF_UWRAP_32(s0); + s1 = GUF_UWRAP_32(s1); + s2 = GUF_UWRAP_32(s2); + s3 = GUF_UWRAP_32(s3); } guf_rand32_u32(state); } } - state->s[0] = s0; - state->s[1] = s1; - state->s[2] = s2; - state->s[3] = s3; + state->s[0] = GUF_UWRAP_32(s0); + state->s[1] = GUF_UWRAP_32(s1); + state->s[2] = GUF_UWRAP_32(s2); + state->s[3] = GUF_UWRAP_32(s3); } - - -#ifdef UINT64_MAX - /* - Equivalent to 2^128 calls to guf_rand64_u64(); can be used to generate 2^128 - non-overlapping subsequences for parallel computations. - */ - GUF_RAND_KWRDS void guf_rand64_state_jump(guf_rand64_state *state) - { - static const uint64_t JUMP[] = { 0x180ec6d33cfd0aba, 0xd5a61266f0c9392c, 0xa9582618e03fc9aa, 0x39abdc4529b1661c }; - uint64_t s0 = 0; - uint64_t s1 = 0; - uint64_t s2 = 0; - uint64_t s3 = 0; - for (size_t i = 0; i < sizeof JUMP / sizeof *JUMP; ++i) { - for (int b = 0; b < 64; ++b) { - if (JUMP[i] & UINT64_C(1) << b) { - s0 ^= state->s[0]; - s1 ^= state->s[1]; - s2 ^= state->s[2]; - s3 ^= state->s[3]; - } - guf_rand64_u64(state); +/* + Equivalent to 2^128 calls to guf_rand64_u64(); can be used to generate 2^128 + non-overlapping subsequences for parallel computations. +*/ +GUF_RAND_KWRDS void guf_rand64_state_jump(guf_rand64_state *state) +{ + static const uint_fast64_t JUMP[] = { 0x180ec6d33cfd0aba, 0xd5a61266f0c9392c, 0xa9582618e03fc9aa, 0x39abdc4529b1661c }; + uint_fast64_t s0 = 0; + uint_fast64_t s1 = 0; + uint_fast64_t s2 = 0; + uint_fast64_t s3 = 0; + for (size_t i = 0; i < sizeof JUMP / sizeof *JUMP; ++i) { + for (int b = 0; b < 64; ++b) { + if (1u * JUMP[i] & UINT64_C(1) << b) { + s0 ^= state->s[0]; + s1 ^= state->s[1]; + s2 ^= state->s[2]; + s3 ^= state->s[3]; + s0 = GUF_UWRAP_64(s0); + s1 = GUF_UWRAP_64(s1); + s2 = GUF_UWRAP_64(s2); + s3 = GUF_UWRAP_64(s3); } + guf_rand64_u64(state); } - state->s[0] = s0; - state->s[1] = s1; - state->s[2] = s2; - state->s[3] = s3; } -#endif + state->s[0] = GUF_UWRAP_64(s0); + state->s[1] = GUF_UWRAP_64(s1); + state->s[2] = GUF_UWRAP_64(s2); + state->s[3] = GUF_UWRAP_64(s3); +} /* Equivalent to 2^128 calls to guf_rand() (or 2^64 calls if GUF_RAND_32_BIT); it can be used to generate 2^128 (or 2^64) @@ -463,13 +439,12 @@ GUF_RAND_KWRDS void guf_randstate_jump(guf_randstate *state) #endif } -#ifdef UINT64_MAX - GUF_RAND_KWRDS double guf_rand64_f64(guf_rand64_state *state) - { - // cf. https://prng.di.unimi.it/ and https://dotat.at/@/2023-06-23-random-double.html (last-retrieved 2025-02-11) - return (guf_rand64_u64(state) >> 11u) * 0x1.0p-53; // 11 == 64 - 53 (double has a 53-bit mantissa/significand) - } -#endif + +GUF_RAND_KWRDS double guf_rand64_f64(guf_rand64_state *state) +{ + // cf. https://prng.di.unimi.it/ and https://dotat.at/@/2023-06-23-random-double.html (last-retrieved 2025-02-11) + return (guf_rand64_u64(state) >> 11u) * 0x1.0p-53; // 11 == 64 - 53 (double has a 53-bit mantissa/significand) +} GUF_RAND_KWRDS double guf_rand32_f64(guf_rand32_state *state) { @@ -484,12 +459,11 @@ GUF_RAND_KWRDS double guf_rand_f64(guf_randstate *state) return (guf_rand_u64(state) >> 11u) * 0x1.0p-53; // 11 == 64 - 53 (double has a 53-bit mantissa/significand) } -#ifdef UINT64_MAX - GUF_RAND_KWRDS float guf_rand64_f32(guf_rand64_state *state) - { - return (guf_rand64_u64(state) >> 40u) * 0x1.0p-24f; // 40 == 64 - 24; (float has a 24-bit mantissa/significand) - } -#endif + +GUF_RAND_KWRDS float guf_rand64_f32(guf_rand64_state *state) +{ + return (guf_rand64_u64(state) >> 40u) * 0x1.0p-24f; // 40 == 64 - 24; (float has a 24-bit mantissa/significand) +} GUF_RAND_KWRDS float guf_rand32_f32(guf_rand32_state *state) { @@ -512,13 +486,12 @@ GUF_RAND_KWRDS bool guf_rand32_bernoulli_trial_f32(guf_rand32_state *state, floa p = guf_clamp_f32(p, 0, 1); return guf_rand32_f32(state) < p; // never true for p = 0, always true for p = 1 since guf_rand_f64 is in range [0, 1) } -#ifdef UINT64_MAX - GUF_RAND_KWRDS bool guf_rand64_bernoulli_trial_f32(guf_rand64_state *state, float p) - { - p = guf_clamp_f32(p, 0, 1); - return guf_rand64_f32(state) < p; // never true for p = 0, always true for p = 1 since guf_rand_f64 is in range [0, 1) - } -#endif + +GUF_RAND_KWRDS bool guf_rand64_bernoulli_trial_f32(guf_rand64_state *state, float p) +{ + p = guf_clamp_f32(p, 0, 1); + return guf_rand64_f32(state) < p; // never true for p = 0, always true for p = 1 since guf_rand_f64 is in range [0, 1) +} GUF_RAND_KWRDS bool guf_rand_bernoulli_trial_f32(guf_randstate *state, float p) { @@ -532,13 +505,11 @@ GUF_RAND_KWRDS bool guf_rand32_bernoulli_trial_f64(guf_rand32_state *state, doub return guf_rand32_f64(state) < p; // never true for p = 0, always true for p = 1 since guf_rand_f64 is in range [0, 1) } -#ifdef UINT64_MAX - GUF_RAND_KWRDS bool guf_rand64_bernoulli_trial_f64(guf_rand64_state *state, double p) - { - p = guf_clamp_f64(p, 0, 1); - return guf_rand64_f64(state) < p; // never true for p = 0, always true for p = 1 since guf_rand_f64 is in range [0, 1) - } -#endif +GUF_RAND_KWRDS bool guf_rand64_bernoulli_trial_f64(guf_rand64_state *state, double p) +{ + p = guf_clamp_f64(p, 0, 1); + return guf_rand64_f64(state) < p; // never true for p = 0, always true for p = 1 since guf_rand_f64 is in range [0, 1) +} GUF_RAND_KWRDS bool guf_rand_bernoulli_trial_f64(guf_randstate *state, double p) { @@ -546,17 +517,16 @@ GUF_RAND_KWRDS bool guf_rand_bernoulli_trial_f64(guf_randstate *state, double p) return guf_rand_f64(state) < p; // never true for p = 0, always true for p = 1 since guf_rand_f64 is in range [0, 1) } + GUF_RAND_KWRDS bool guf_rand32_flip(guf_rand32_state *state) { return guf_rand32_bernoulli_trial_f32(state, 0.5f); } -#ifdef UINT64_MAX - GUF_RAND_KWRDS bool guf_rand64_flip(guf_rand64_state *state) - { - return guf_rand64_bernoulli_trial_f64(state, 0.5); - } -#endif +GUF_RAND_KWRDS bool guf_rand64_flip(guf_rand64_state *state) +{ + return guf_rand64_bernoulli_trial_f64(state, 0.5); +} GUF_RAND_KWRDS bool guf_rand_flip(guf_randstate *state) { @@ -567,6 +537,7 @@ GUF_RAND_KWRDS bool guf_rand_flip(guf_randstate *state) #endif } + GUF_RAND_KWRDS double guf_rand32_range_f64(guf_rand32_state *state, double min, double end) { if (min == (double)INFINITY) { @@ -583,23 +554,21 @@ GUF_RAND_KWRDS double guf_rand32_range_f64(guf_rand32_state *state, double min, return guf_rand32_f64(state) * (end - min) + min; } -#ifdef UINT64_MAX - GUF_RAND_KWRDS double guf_rand64_range_f64(guf_rand64_state *state, double min, double end) - { - if (min == (double)INFINITY) { - min = DBL_MAX; - } else if (min == (double)-INFINITY) { - min = -DBL_MAX; - } - if (end == (double)INFINITY) { - end = DBL_MAX; - } else if (end == (double)-INFINITY) { - end = -DBL_MAX; - } - GUF_ASSERT_RELEASE(end >= min); - return guf_rand64_f64(state) * (end - min) + min; +GUF_RAND_KWRDS double guf_rand64_range_f64(guf_rand64_state *state, double min, double end) +{ + if (min == (double)INFINITY) { + min = DBL_MAX; + } else if (min == (double)-INFINITY) { + min = -DBL_MAX; } -#endif + if (end == (double)INFINITY) { + end = DBL_MAX; + } else if (end == (double)-INFINITY) { + end = -DBL_MAX; + } + GUF_ASSERT_RELEASE(end >= min); + return guf_rand64_f64(state) * (end - min) + min; +} // returns uniformly-distributed random double in range [min, end) (or min if min == end) GUF_RAND_KWRDS double guf_randrange_f64(guf_randstate *state, double min, double end) @@ -611,6 +580,7 @@ GUF_RAND_KWRDS double guf_randrange_f64(guf_randstate *state, double min, double #endif } + // returns uniformly-distributed random float in range [min, end) (or min if min == end) GUF_RAND_KWRDS float guf_rand32_range_f32(guf_rand32_state *state, float min, float end) { @@ -628,24 +598,22 @@ GUF_RAND_KWRDS float guf_rand32_range_f32(guf_rand32_state *state, float min, fl return guf_rand32_f32(state) * (end - min) + min; } -#ifdef UINT64_MAX - // returns uniformly-distributed random float in range [min, end) (or min if min == end) - GUF_RAND_KWRDS float guf_rand64_range_f32(guf_rand64_state *state, float min, float end) - { - if (min == INFINITY) { - min = FLT_MAX; - } else if (min == -INFINITY) { - min = -FLT_MAX; - } - if (end == INFINITY) { - end = FLT_MAX; - } else if (end == -INFINITY) { - end = -FLT_MAX; - } - GUF_ASSERT_RELEASE(end >= min); - return guf_rand64_f32(state) * (end - min) + min; +// returns uniformly-distributed random float in range [min, end) (or min if min == end) +GUF_RAND_KWRDS float guf_rand64_range_f32(guf_rand64_state *state, float min, float end) +{ + if (min == INFINITY) { + min = FLT_MAX; + } else if (min == -INFINITY) { + min = -FLT_MAX; } -#endif + if (end == INFINITY) { + end = FLT_MAX; + } else if (end == -INFINITY) { + end = -FLT_MAX; + } + GUF_ASSERT_RELEASE(end >= min); + return guf_rand64_f32(state) * (end - min) + min; +} // returns uniformly-distributed random float in range [min, end) (or min if min == end) GUF_RAND_KWRDS float guf_randrange_f32(guf_randstate *state, float min, float end) @@ -658,35 +626,36 @@ GUF_RAND_KWRDS float guf_randrange_f32(guf_randstate *state, float min, float en } -#ifdef UINT64_MAX - // returns uniformly-distributed random int32_t in range [min, max] (max is inclusive as opposed to the f32/f64 versions) - GUF_RAND_KWRDS int32_t guf_rand64_range_i32(guf_rand64_state *state, int32_t min, int32_t max) - { - GUF_ASSERT_RELEASE(max >= min); - if (min == max) { - return min; - } - const double delta = (double)max - (double)min; - // cf. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/random (last-retrieved 2025-02-12) - const double result = floor(guf_rand64_f64(state) * (delta + 1.0) + min); - GUF_ASSERT(result >= min && result <= max); - return (int32_t)result; +// returns uniformly-distributed random i32 in range [min, max] (max is inclusive as opposed to the f32/f64 versions) +GUF_RAND_KWRDS int_fast32_t guf_rand64_range_i32(guf_rand64_state *state, int_fast32_t min, int_fast32_t max) +{ + GUF_ASSERT_RELEASE(max >= min); + if (min == max) { + return min; } -#endif + const double delta = (double)max - (double)min; + // cf. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/random (last-retrieved 2025-02-12) + const double result = floor(guf_rand64_f64(state) * (delta + 1.0) + min); + GUF_ASSERT(result >= min && result <= max); + #ifdef INT32_MAX + GUF_ASSERT((int_fast32_t)result <= INT32_MAX && (int_fast32_t)result >= INT32_MIN); + #endif + return (int_fast32_t)result; +} -// returns uniformly-distributed random int32_t in range [min, max] (max is inclusive as opposed to the f32/f64 versions) -GUF_RAND_KWRDS int32_t guf_rand32_range_i32(guf_rand32_state *state, int32_t min, int32_t max) +// returns uniformly-distributed random i32 in range [min, max] (max is inclusive as opposed to the f32/f64 versions) +GUF_RAND_KWRDS int_fast32_t guf_rand32_range_i32(guf_rand32_state *state, int_fast32_t min, int_fast32_t max) { GUF_ASSERT_RELEASE(max >= min); if (min == max) { return min; } - const uint32_t rand_max_i32 = UINT32_MAX >> 1u; // 2^31 - 1 (== INT32_MAX) + const uint_fast32_t rand_max_i32 = GUF_UWRAP_32(GUF_UINT32_MAX >> 1u); // 2^31 - 1 (== INT32_MAX) - const uint32_t delta = guf_absdiff_i32(max, min); + const uint_fast32_t delta = guf_absdiff_int_fast32_t(max, min); if (delta > rand_max_i32) { - guf_panic(GUF_ERR_INT_OVERFLOW, GUF_ERR_MSG("in function guf_rand32_range_i32: interval [min, max] larger than INT32_MAX")); + guf_panic(GUF_ERR_INT_OVERFLOW, GUF_ERR_MSG("in function guf_rand32_range_i32: interval [min, max] larger than 2^31 - 1")); return -1; } /* @@ -696,32 +665,36 @@ GUF_RAND_KWRDS int32_t guf_rand32_range_i32(guf_rand32_state *state, int32_t min cf. https://c-faq.com/lib/randrange.html (last-retrieved 2025-02-11) https://stackoverflow.com/a/6852396 (last-retrieved 2025-02-11) */ - const uint32_t num_rand_vals = rand_max_i32 + 1u; // 2^31 - const uint32_t num_bins = (delta + 1u); + const uint_fast32_t num_rand_vals = GUF_UWRAP_32(rand_max_i32 + 1u); // 2^31 + const uint_fast32_t num_bins = GUF_UWRAP_32(delta + 1u); - const uint32_t bin_size = num_rand_vals / num_bins; // bin_size = floor(num_rand_vals / num_bins) - const uint32_t limit = num_rand_vals - (num_rand_vals % num_bins); // limit == bin_size * num_bins - GUF_ASSERT(limit == bin_size * num_bins); + const uint_fast32_t bin_size = GUF_UWRAP_32(num_rand_vals / num_bins); // bin_size = floor(num_rand_vals / num_bins) + const uint_fast32_t limit = GUF_UWRAP_32(num_rand_vals - (num_rand_vals % num_bins)); // limit == bin_size * num_bins + GUF_ASSERT(limit == 1u * GUF_UWRAP_32(bin_size * num_bins)); /* since (num_rand_vals % num_bins) is at most 2^30 + 1 (I think...), the minimum limit is 2^31 - (2^30 + 1), which means in the worst case, the chance of having to iterate (i.e. step >= limit) is 1 - (2^31 - (2^30 + 1)) / 2^31 == 0.5 */ - uint32_t step; + uint_fast32_t step; do { - step = guf_rand32_u32(state) >> 1u; // [0, 2^31 - 1] + step = GUF_UWRAP_32(guf_rand32_u32(state) >> 1u); // [0, 2^31 - 1] } while (step >= limit); - step = step / bin_size; + step = GUF_UWRAP_32(step / bin_size); - - GUF_ASSERT(guf_ckd_add_i32(min, step) == GUF_MATH_CKD_SUCCESS); - const int32_t rnd = min + (int32_t)step; + #ifdef INT32_MAX + GUF_ASSERT(guf_ckd_add_i32(min, step) == GUF_MATH_CKD_SUCCESS); + #endif + const int_fast32_t rnd = min + (int_fast32_t)step; GUF_ASSERT(rnd >= min && rnd <= max); + #ifdef INT32_MAX + GUF_ASSERT(rnd <= INT32_MAX && rnd >= INT32_MIN); + #endif return rnd; } -// returns uniformly-distributed random int32_t in range [min, max] (max is inclusive as opposed to the f32/f64 versions) -GUF_RAND_KWRDS int32_t guf_randrange_i32(guf_randstate *state, int32_t min, int32_t max) +// returns uniformly-distributed random i32 in range [min, max] (max is inclusive as opposed to the f32/f64 versions) +GUF_RAND_KWRDS int_fast32_t guf_randrange_i32(guf_randstate *state, int_fast32_t min, int_fast32_t max) { #ifdef GUF_RAND_32_BIT return guf_rand32_range_i32(state, min, max); @@ -730,38 +703,45 @@ GUF_RAND_KWRDS int32_t guf_randrange_i32(guf_randstate *state, int32_t min, int3 #endif } -GUF_RAND_KWRDS uint32_t guf_rand32_range_u32(guf_rand32_state *state, uint32_t min, uint32_t max) +GUF_RAND_KWRDS uint_fast32_t guf_rand32_range_u32(guf_rand32_state *state, uint_fast32_t min, uint_fast32_t max) { /* The method used in guf_rand32_range_i32 above (which uses only 32-bit integer arithmetic) could overflow here, so we use the floating-point method since we have to use 64-bit arithmetic anyways. */ + min = GUF_UWRAP_32(min); + max = GUF_UWRAP_32(max); GUF_ASSERT_RELEASE(max >= min); + if (min == max) { return min; } const double delta = (double)max - (double)min; const double result = floor(guf_rand32_f64(state) * (delta + 1.0) + min); // NOTE: guf_rand32_f64 is slow for 32-bit platforms... GUF_ASSERT(result >= min && result <= max); - return (uint32_t)result; + GUF_ASSERT((uint_fast32_t)result <= GUF_UINT32_MAX); + return (uint_fast32_t)result; } -#ifdef UINT64_MAX - GUF_RAND_KWRDS uint32_t guf_rand64_range_u32(guf_rand64_state *state, uint32_t min, uint32_t max) - { - GUF_ASSERT_RELEASE(max >= min); - if (min == max) { - return min; - } - const double delta = (double)max - (double)min; - const double result = floor(guf_rand64_f64(state) * (delta + 1.0) + min); - GUF_ASSERT(result >= min && result <= max); - return (uint32_t)result; - } -#endif +GUF_RAND_KWRDS uint_fast32_t guf_rand64_range_u32(guf_rand64_state *state, uint_fast32_t min, uint_fast32_t max) +{ + min = GUF_UWRAP_32(min); + max = GUF_UWRAP_32(max); -GUF_RAND_KWRDS uint32_t guf_randrange_u32(guf_randstate *state, uint32_t min, uint32_t max) + GUF_ASSERT_RELEASE(max >= min); + + if (min == max) { + return min; + } + const double delta = (double)max - (double)min; + const double result = floor(guf_rand64_f64(state) * (delta + 1.0) + min); + GUF_ASSERT(result >= min && result <= max); + GUF_ASSERT((uint_fast32_t)result <= GUF_UINT32_MAX); + return (uint_fast32_t)result; +} + +GUF_RAND_KWRDS uint_fast32_t guf_randrange_u32(guf_randstate *state, uint_fast32_t min, uint_fast32_t max) { #ifdef GUF_RAND_32_BIT return guf_rand32_range_u32(state, min, max); @@ -770,58 +750,106 @@ GUF_RAND_KWRDS uint32_t guf_randrange_u32(guf_randstate *state, uint32_t min, ui #endif } -#ifdef UINT64_MAX - GUF_RAND_KWRDS int64_t guf_rand64_range_i64(guf_rand64_state *state, int64_t min, int64_t max) - { - GUF_ASSERT_RELEASE(max >= min); - if (min == max) { - return min; - } +GUF_RAND_KWRDS int_fast64_t guf_rand64_range_i64(guf_rand64_state *state, int_fast64_t min, int_fast64_t max) +{ + GUF_ASSERT_RELEASE(max >= min); + if (min == max) { + return min; + } - const uint64_t rand_max_i64 = UINT64_MAX >> 1u; // 2^63 - 1 (== INT64_MAX) - - const uint64_t delta = guf_absdiff_i64(max, min); - if (delta > rand_max_i64) { - guf_panic(GUF_ERR_INT_OVERFLOW, GUF_ERR_MSG("in function guf_randrange_i64: interval [min, max] larger than INT64_MAX")); - return -1; - } - /* - We should not use the same approach as in guf_rand64_range_i32 because (max - min) might be close to 2^63 - 1 + const uint_fast64_t rand_max_i64 = GUF_UWRAP_64(GUF_UINT64_MAX >> 1u); // 2^63 - 1 (== INT64_MAX) + + const uint_fast64_t delta = guf_absdiff_int_fast64_t(max, min); + if (delta > rand_max_i64) { + guf_panic(GUF_ERR_INT_OVERFLOW, GUF_ERR_MSG("in function guf_randrange_i64: interval [min, max] larger than 2^63 - 1")); + return -1; + } + /* + We should not use the same approach as in guf_rand64_range_i32 because (max - min) might be close to 2^63 - 1 - cf. https://c-faq.com/lib/randrange.html (last-retrieved 2025-02-11) - https://stackoverflow.com/a/6852396 (last-retrieved 2025-02-11) - */ - const uint64_t num_rand_vals = rand_max_i64 + 1u; // 2^63 - const uint64_t num_bins = (delta + 1u); + cf. https://c-faq.com/lib/randrange.html (last-retrieved 2025-02-11) + https://stackoverflow.com/a/6852396 (last-retrieved 2025-02-11) + */ + const uint_fast64_t num_rand_vals = GUF_UWRAP_64(rand_max_i64 + 1u); // 2^63 + const uint_fast64_t num_bins = GUF_UWRAP_64(delta + 1u); - const uint64_t bin_size = num_rand_vals / num_bins; // bin_size = floor(num_rand_vals / num_bins) - const uint64_t limit = num_rand_vals - (num_rand_vals % num_bins); // limit == bin_size * num_bins - GUF_ASSERT(limit == bin_size * num_bins); - /* - since (num_rand_vals % num_bins) is at most 2^62 + 1 (I think...), the minimum limit is 2^63 - (2^62 + 1), - which means in the worst case, the chance of having to iterate (i.e. step >= limit) - is 1 - (2^63 - (2^62 + 1)) / 2^63 == 0.5 - */ - uint64_t step; - do { - step = guf_rand64_u64(state) >> 1; // [0, 2^63 - 1] - } while (step >= limit); - step = step / bin_size; + const uint_fast64_t bin_size = GUF_UWRAP_64(num_rand_vals / num_bins); // bin_size = floor(num_rand_vals / num_bins) + const uint_fast64_t limit = GUF_UWRAP_64(num_rand_vals - (num_rand_vals % num_bins)); // limit == bin_size * num_bins + GUF_ASSERT(limit == 1u * GUF_UWRAP_64(bin_size * num_bins)); + /* + since (num_rand_vals % num_bins) is at most 2^62 + 1 (I think...), the minimum limit is 2^63 - (2^62 + 1), + which means in the worst case, the chance of having to iterate (i.e. step >= limit) + is 1 - (2^63 - (2^62 + 1)) / 2^63 == 0.5 + */ + uint_fast64_t step; + do { + step = GUF_UWRAP_64(guf_rand64_u64(state) >> 1); // [0, 2^63 - 1] + } while (step >= limit); + step = GUF_UWRAP_64(step / bin_size); + #ifdef INT64_MAX GUF_ASSERT(guf_ckd_add_i64(min, step) == GUF_MATH_CKD_SUCCESS); - const int64_t rnd = min + (int64_t)step; - GUF_ASSERT(rnd >= min && rnd <= max); - return rnd; - } -#endif + #endif + const int_fast64_t rnd = min + (int_fast64_t)step; + GUF_ASSERT(rnd >= min && rnd <= max); + return rnd; +} -#if !defined(GUF_RAND_32_BIT) && defined(UINT64_MAX) - // returns uniformly-distributed random int64_t in range [min, max] (max is inclusive as opposed to the f32/f64 versions) - GUF_RAND_KWRDS int64_t guf_randrange_i64(guf_randstate *state, int64_t min, int64_t max) - { - return guf_rand64_range_i64(state, min, max); +GUF_RAND_KWRDS int_fast64_t guf_rand32_range_i64(guf_rand32_state *state, int_fast64_t min, int_fast64_t max) +{ + GUF_ASSERT_RELEASE(max >= min); + if (min == max) { + return min; } -#endif + + const uint_fast64_t rand_max_i64 = GUF_UWRAP_64(GUF_UINT64_MAX >> 1u); // 2^63 - 1 (== INT64_MAX) + + const uint_fast64_t delta = guf_absdiff_int_fast64_t(max, min); + if (delta > rand_max_i64) { + guf_panic(GUF_ERR_INT_OVERFLOW, GUF_ERR_MSG("in function guf_randrange_i64: interval [min, max] larger than 2^63 - 1")); + return -1; + } + /* + We should not use the same approach as in guf_rand64_range_i32 because (max - min) might be close to 2^63 - 1 + + cf. https://c-faq.com/lib/randrange.html (last-retrieved 2025-02-11) + https://stackoverflow.com/a/6852396 (last-retrieved 2025-02-11) + */ + const uint_fast64_t num_rand_vals = GUF_UWRAP_64(rand_max_i64 + 1u); // 2^63 + const uint_fast64_t num_bins = GUF_UWRAP_64(delta + 1u); + + const uint_fast64_t bin_size = GUF_UWRAP_64(num_rand_vals / num_bins); // bin_size = floor(num_rand_vals / num_bins) + const uint_fast64_t limit = GUF_UWRAP_64(num_rand_vals - (num_rand_vals % num_bins)); // limit == bin_size * num_bins + GUF_ASSERT(limit == 1u * GUF_UWRAP_64(bin_size * num_bins)); + /* + since (num_rand_vals % num_bins) is at most 2^62 + 1 (I think...), the minimum limit is 2^63 - (2^62 + 1), + which means in the worst case, the chance of having to iterate (i.e. step >= limit) + is 1 - (2^63 - (2^62 + 1)) / 2^63 == 0.5 + */ + uint_fast64_t step; + do { + step = GUF_UWRAP_64(guf_rand32_u64(state) >> 1); // [0, 2^63 - 1] + } while (step >= limit); + step = GUF_UWRAP_64(step / bin_size); + + #ifdef INT64_MAX + GUF_ASSERT(guf_ckd_add_i64(min, step) == GUF_MATH_CKD_SUCCESS); + #endif + const int_fast64_t rnd = min + (int_fast64_t)step; + GUF_ASSERT(rnd >= min && rnd <= max); + return rnd; +} + +// returns uniformly-distributed random int64_t in range [min, max] (max is inclusive as opposed to the f32/f64 versions) +GUF_RAND_KWRDS int_fast64_t guf_randrange_i64(guf_randstate *state, int_fast64_t min, int_fast64_t max) +{ + #ifdef GUF_RAND_32_BIT + return guf_rand32_range_i64(state, min, max); + #else + return guf_rand64_range_i64(state, min, max); + #endif +} + // Box-Müller-transform transcribed from wikipedia, cf. https://en.wikipedia.org/wiki/Box%E2%80%93Muller_transform (last-retrieved 2025-02-12) GUF_RAND_KWRDS void guf_rand32_normal_sample_f64(guf_rand32_state *state, double mean, double std_dev, double *result, ptrdiff_t n) @@ -846,30 +874,28 @@ GUF_RAND_KWRDS void guf_rand32_normal_sample_f64(guf_rand32_state *state, double } } -#ifdef UINT64_MAX - // Box-Müller-transform transcribed from wikipedia, cf. https://en.wikipedia.org/wiki/Box%E2%80%93Muller_transform (last-retrieved 2025-02-12) - GUF_RAND_KWRDS void guf_rand64_normal_sample_f64(guf_rand64_state *state, double mean, double std_dev, double *result, ptrdiff_t n) - { - GUF_ASSERT_RELEASE(result); - GUF_ASSERT_RELEASE(n >= 0); - const double TAU = 2.0 * GUF_PI; +// Box-Müller-transform transcribed from wikipedia, cf. https://en.wikipedia.org/wiki/Box%E2%80%93Muller_transform (last-retrieved 2025-02-12) +GUF_RAND_KWRDS void guf_rand64_normal_sample_f64(guf_rand64_state *state, double mean, double std_dev, double *result, ptrdiff_t n) +{ + GUF_ASSERT_RELEASE(result); + GUF_ASSERT_RELEASE(n >= 0); + const double TAU = 2.0 * GUF_PI; - ptrdiff_t i = 0; - while (i < n) { - double u1, u2; - do { - u1 = guf_rand64_f64(state); - } while (u1 == 0); - u2 = guf_rand64_f64(state); + ptrdiff_t i = 0; + while (i < n) { + double u1, u2; + do { + u1 = guf_rand64_f64(state); + } while (u1 == 0); + u2 = guf_rand64_f64(state); - const double mag = std_dev * sqrt(-2.0 * log(u1)); - result[i++] = mag * cos(TAU * u2) + mean; - if (i < n) { - result[i++] = mag * sin(TAU * u2) + mean; - } - } + const double mag = std_dev * sqrt(-2.0 * log(u1)); + result[i++] = mag * cos(TAU * u2) + mean; + if (i < n) { + result[i++] = mag * sin(TAU * u2) + mean; + } } -#endif +} // Box-Müller-transform transcribed from wikipedia, cf. https://en.wikipedia.org/wiki/Box%E2%80%93Muller_transform (last-retrieved 2025-02-12) GUF_RAND_KWRDS void guf_rand_normal_sample_f64(guf_randstate *state, double mean, double std_dev, double *result, ptrdiff_t n) @@ -903,29 +929,27 @@ GUF_RAND_KWRDS void guf_rand32_normal_sample_f32(guf_rand32_state *state, float } } -#ifdef UINT64_MAX - GUF_RAND_KWRDS void guf_rand64_normal_sample_f32(guf_rand64_state *state, float mean, float std_dev, float *result, ptrdiff_t n) - { - GUF_ASSERT_RELEASE(result); - GUF_ASSERT_RELEASE(n >= 0); - const float TAU = 2.f * (float)GUF_PI; +GUF_RAND_KWRDS void guf_rand64_normal_sample_f32(guf_rand64_state *state, float mean, float std_dev, float *result, ptrdiff_t n) +{ + GUF_ASSERT_RELEASE(result); + GUF_ASSERT_RELEASE(n >= 0); + const float TAU = 2.f * (float)GUF_PI; - ptrdiff_t i = 0; - while (i < n) { - float u1, u2; - do { - u1 = guf_rand64_f32(state); - } while (u1 == 0); - u2 = guf_rand64_f32(state); + ptrdiff_t i = 0; + while (i < n) { + float u1, u2; + do { + u1 = guf_rand64_f32(state); + } while (u1 == 0); + u2 = guf_rand64_f32(state); - const float mag = std_dev * sqrtf(-2.f * logf(u1)); - result[i++] = mag * cosf(TAU * u2) + mean; - if (i < n) { - result[i++] = mag * sinf(TAU * u2) + mean; - } - } + const float mag = std_dev * sqrtf(-2.f * logf(u1)); + result[i++] = mag * cosf(TAU * u2) + mean; + if (i < n) { + result[i++] = mag * sinf(TAU * u2) + mean; + } } -#endif +} GUF_RAND_KWRDS void guf_rand_normal_sample_f32(guf_randstate *state, float mean, float std_dev, float *result, ptrdiff_t n) { @@ -943,14 +967,12 @@ GUF_RAND_KWRDS double guf_rand32_normal_sample_one_f64(guf_rand32_state *state, return result; } -#ifdef UINT64_MAX - GUF_RAND_KWRDS double guf_rand64_normal_sample_one_f64(guf_rand64_state *state, double mean, double std_dev) - { - double result; - guf_rand64_normal_sample_f64(state, mean, std_dev, &result, 1); - return result; - } -#endif +GUF_RAND_KWRDS double guf_rand64_normal_sample_one_f64(guf_rand64_state *state, double mean, double std_dev) +{ + double result; + guf_rand64_normal_sample_f64(state, mean, std_dev, &result, 1); + return result; +} GUF_RAND_KWRDS double guf_rand_normal_sample_one_f64(guf_randstate *state, double mean, double std_dev) { @@ -968,14 +990,12 @@ GUF_RAND_KWRDS float guf_rand32_normal_sample_one_f32(guf_rand32_state *state, f return result; } -#ifdef UINT64_MAX - GUF_RAND_KWRDS float guf_rand64_normal_sample_one_f32(guf_rand64_state *state, float mean, float std_dev) - { - float result; - guf_rand64_normal_sample_f32(state, mean, std_dev, &result, 1); - return result; - } -#endif +GUF_RAND_KWRDS float guf_rand64_normal_sample_one_f32(guf_rand64_state *state, float mean, float std_dev) +{ + float result; + guf_rand64_normal_sample_f32(state, mean, std_dev, &result, 1); + return result; +} GUF_RAND_KWRDS float guf_rand_normal_sample_one_f32(guf_randstate *state, float mean, float std_dev) { diff --git a/src/guf_str.h b/src/guf_str.h index a135671..1f8c118 100644 --- a/src/guf_str.h +++ b/src/guf_str.h @@ -94,8 +94,8 @@ GUF_STR_KWRDS int guf_str_view_cmp(const void *str_view_a, const void *str_view_ // Hash functions. GUF_STR_KWRDS guf_hash_size_t guf_str_view_hash(const guf_str_view *sv); -GUF_STR_KWRDS uint64_t guf_str_view_hash64(const guf_str_view *sv); -GUF_STR_KWRDS uint32_t guf_str_view_hash32(const guf_str_view *sv); +GUF_STR_KWRDS uint_fast64_t guf_str_view_hash64(const guf_str_view *sv); +GUF_STR_KWRDS uint_fast32_t guf_str_view_hash32(const guf_str_view *sv); // Return a new guf_str_view corresponding to the substring with leading/trailing ascii-whitespace chars removed from the left/right GUF_STR_KWRDS guf_str_view guf_str_view_trim_left_ascii(guf_str_view sv); @@ -151,8 +151,8 @@ GUF_STR_KWRDS int guf_str_cmp(const guf_str *a, const guf_str *b); // Hash-functions. GUF_STR_KWRDS guf_hash_size_t guf_str_hash(const guf_str *str); -GUF_STR_KWRDS uint64_t guf_str_hash64(const guf_str *str); -GUF_STR_KWRDS uint32_t guf_str_hash32(const guf_str *str); +GUF_STR_KWRDS uint_fast64_t guf_str_hash64(const guf_str *str); +GUF_STR_KWRDS uint_fast32_t guf_str_hash32(const guf_str *str); // Reserve at least min_capacity characters (excluding the null-terminator) (try to double the current capacity first; if that's not at least min_capacity, set the new capacity to min_capacity instead). GUF_STR_KWRDS guf_str *guf_str_try_reserve(guf_str *str, ptrdiff_t min_capacity, guf_err *err); @@ -1196,13 +1196,13 @@ GUF_STR_KWRDS guf_hash_size_t guf_str_hash(const guf_str *str) return guf_str_view_hash(&(guf_str_view){.str = guf_str_const_cstr(str), .len = guf_str_len(str)}); } -GUF_STR_KWRDS uint64_t guf_str_hash64(const guf_str *str) +GUF_STR_KWRDS uint_fast64_t guf_str_hash64(const guf_str *str) { GUF_ASSERT(guf_str_is_valid(str)); return guf_str_view_hash64(&(guf_str_view){.str = guf_str_const_cstr(str), .len = guf_str_len(str)}); } -GUF_STR_KWRDS uint32_t guf_str_hash32(const guf_str *str) +GUF_STR_KWRDS uint_fast32_t guf_str_hash32(const guf_str *str) { GUF_ASSERT(guf_str_is_valid(str)); return guf_str_view_hash32(&(guf_str_view){.str = guf_str_const_cstr(str), .len = guf_str_len(str)}); @@ -1457,7 +1457,7 @@ GUF_STR_KWRDS guf_hash_size_t guf_str_view_hash(const guf_str_view *sv) return guf_hash(sv->str, sv->len, GUF_HASH_INIT); } -GUF_STR_KWRDS uint64_t guf_str_view_hash64(const guf_str_view *sv) +GUF_STR_KWRDS uint_fast64_t guf_str_view_hash64(const guf_str_view *sv) { GUF_ASSERT(sv); if (!sv->str || sv->len <= 0) { @@ -1466,7 +1466,7 @@ GUF_STR_KWRDS uint64_t guf_str_view_hash64(const guf_str_view *sv) return guf_hash64(sv->str, sv->len, GUF_HASH64_INIT); } -GUF_STR_KWRDS uint32_t guf_str_view_hash32(const guf_str_view *sv) +GUF_STR_KWRDS uint_fast32_t guf_str_view_hash32(const guf_str_view *sv) { GUF_ASSERT(sv); if (!sv->str || sv->len <= 0) { diff --git a/src/guf_utf8.h b/src/guf_utf8.h index 66743d6..66f8c14 100644 --- a/src/guf_utf8.h +++ b/src/guf_utf8.h @@ -35,9 +35,9 @@ GUF_UTF8_KWRDS int guf_utf8_char_num_bytes(const guf_utf8_char *c); GUF_UTF8_KWRDS bool guf_utf8_char_is_valid(const guf_utf8_char *c); GUF_UTF8_KWRDS bool guf_utf8_char_is_whitespace(const guf_utf8_char *c); -GUF_UTF8_KWRDS guf_utf8_char guf_utf8_char_new(uint32_t codepoint); // Returns GUF_UTF8_REPLACEMENT_CHAR for invalid codepoints (and for GUF_UTF8_REPLACEMENT_CHAR_CODEPOINT). -GUF_UTF8_KWRDS bool guf_utf8_encode(guf_utf8_char *result, uint32_t codepoint); // Returns false for invalid codepoints. -GUF_UTF8_KWRDS int32_t guf_utf8_decode(const guf_utf8_char *utf8); // Returns -1 for invalid utf-8. +GUF_UTF8_KWRDS guf_utf8_char guf_utf8_char_new(uint_fast32_t codepoint); // Returns GUF_UTF8_REPLACEMENT_CHAR for invalid codepoints (and for GUF_UTF8_REPLACEMENT_CHAR_CODEPOINT). +GUF_UTF8_KWRDS bool guf_utf8_encode(guf_utf8_char *result, uint_fast32_t codepoint); // Returns false for invalid codepoints. +GUF_UTF8_KWRDS int_fast32_t guf_utf8_decode(const guf_utf8_char *utf8); // Returns -1 for invalid utf-8. GUF_UTF8_KWRDS bool guf_utf8_equal(const guf_utf8_char *a, const guf_utf8_char *b); @@ -93,7 +93,7 @@ GUF_UTF8_KWRDS bool guf_utf8_equal(const guf_utf8_char *a, const guf_utf8_char * } // cf. https://datatracker.ietf.org/doc/html/rfc3629#section-3 (last-retrieved 2025-03-02) -GUF_UTF8_KWRDS bool guf_utf8_encode(guf_utf8_char *result, uint32_t cp) +GUF_UTF8_KWRDS bool guf_utf8_encode(guf_utf8_char *result, uint_fast32_t cp) { GUF_ASSERT(result); @@ -138,8 +138,8 @@ GUF_UTF8_KWRDS bool guf_utf8_encode(guf_utf8_char *result, uint32_t cp) int cp_bits = 0; for (int byte_n = num_bytes - 1; byte_n >= 0 && cp > 0; --byte_n) { const int bits = (byte_n == 0) ? first_byte_bits : tail_byte_bits; - const uint32_t cp_mask = (UINT32_C(1) << bits) - 1; - result->bytes[byte_n] = (char)((unsigned char)result->bytes[byte_n] | (cp & cp_mask)); + const uint_fast32_t cp_mask = GUF_UWRAP_32( (UINT32_C(1) << bits) - 1 ); + result->bytes[byte_n] = (char)(1u * (unsigned char)result->bytes[byte_n] | (cp & cp_mask)); cp = cp >> bits; cp_bits += bits; } @@ -155,7 +155,7 @@ GUF_UTF8_KWRDS bool guf_utf8_encode(guf_utf8_char *result, uint32_t cp) } } -GUF_UTF8_KWRDS guf_utf8_char guf_utf8_char_new(uint32_t codepoint) +GUF_UTF8_KWRDS guf_utf8_char guf_utf8_char_new(uint_fast32_t codepoint) { guf_utf8_char result = GUF_UTF8_REPLACEMENT_CHAR; guf_utf8_encode(&result, codepoint); @@ -163,7 +163,7 @@ GUF_UTF8_KWRDS guf_utf8_char guf_utf8_char_new(uint32_t codepoint) } // cf. https://datatracker.ietf.org/doc/html/rfc3629#section-3 (last-retrieved 2025-03-02) -GUF_UTF8_KWRDS int32_t guf_utf8_decode(const guf_utf8_char *c) +GUF_UTF8_KWRDS int_fast32_t guf_utf8_decode(const guf_utf8_char *c) { if (!guf_utf8_char_is_valid(c)) { return -1; @@ -189,12 +189,12 @@ GUF_UTF8_KWRDS int32_t guf_utf8_decode(const guf_utf8_char *c) return -1; } - uint32_t cp = 0; + uint_fast32_t cp = 0; int cp_bits = 0; for (int byte_n = num_bytes - 1; byte_n >= 0; --byte_n) { const int bits = (byte_n == 0) ? first_byte_bits : tail_byte_bits; - const uint32_t byte_mask = (UINT32_C(1) << bits) - 1; - cp |= ((uint32_t)c->bytes[byte_n] & byte_mask) << cp_bits; + const uint_fast32_t byte_mask = GUF_UWRAP_32( (UINT32_C(1) << bits) - 1 ); + cp = GUF_UWRAP_32( cp | GUF_UWRAP_32( 1u * ((uint_fast32_t)c->bytes[byte_n] & byte_mask) << cp_bits ) ); cp_bits += bits; } GUF_ASSERT(cp_bits == first_byte_bits + (num_bytes - 1) * tail_byte_bits); @@ -204,8 +204,11 @@ GUF_UTF8_KWRDS int32_t guf_utf8_decode(const guf_utf8_char *c) if (!valid) { return -1; } else { - GUF_ASSERT(cp <= INT32_MAX); - return (int32_t)cp; + #ifdef INT32_MAX + GUF_ASSERT(cp <= INT32_MAX); + #endif + GUF_ASSERT(cp <= INT_FAST32_MAX); + return (int_fast32_t)cp; } } diff --git a/src/test/test_ckdint.cpp b/src/test/test_ckdint.cpp index 69b85de..72e541c 100644 --- a/src/test/test_ckdint.cpp +++ b/src/test/test_ckdint.cpp @@ -27,6 +27,7 @@ void CkdIntTest::test_ckd() const int32_t add_res = a + b; const guf_math_ckd_result ckd_add = guf_ckd_add_i8((int8_t)a, (int8_t)b); TEST_CHECK(ckd_add == guf_ckd_add_i8((int8_t)b, (int8_t)a)); + TEST_CHECK(ckd_add == guf_ckd_add_int_fast8_t((int_fast8_t)a, (int_fast8_t)b)); if (add_res > INT8_MAX) { TEST_CHECK(ckd_add == GUF_MATH_CKD_OVERFLOW_POS); int8_t saturated, saturated2; @@ -72,6 +73,7 @@ void CkdIntTest::test_ckd() const int32_t sub_res = a - b; const guf_math_ckd_result ckd_sub = guf_ckd_sub_i8((int8_t)a, (int8_t)b); + TEST_CHECK(ckd_sub == guf_ckd_sub_int_fast8_t((int_fast8_t)a, (int_fast8_t)b)); if (sub_res > INT8_MAX) { TEST_CHECK(ckd_sub == GUF_MATH_CKD_OVERFLOW_POS); int8_t saturated; @@ -100,6 +102,7 @@ void CkdIntTest::test_ckd() const int32_t mul_res = a * b; const guf_math_ckd_result ckd_mul = guf_ckd_mul_i8((int8_t)a, (int8_t)b); + TEST_CHECK(ckd_mul == guf_ckd_mul_int_fast8_t((int_fast8_t)a, (int_fast8_t)b)); TEST_CHECK(ckd_mul == guf_ckd_mul_i8((int8_t)b, (int8_t)a)); if (mul_res > INT8_MAX) { TEST_CHECK(ckd_mul == GUF_MATH_CKD_OVERFLOW_POS); @@ -220,6 +223,57 @@ void CkdIntTest::test_ckd() guf_wrapping_mul_i32(4096, -314159265, &mul_i32_res); TEST_CHECK(mul_i32_res == 1693839360); + + int_fast32_t mul_i32fast_res = -12345; + TEST_CHECK(guf_wrapping_mul_int_fast32_t(INT32_MAX, 2, &mul_i32fast_res) == GUF_MATH_CKD_OVERFLOW_POS); + TEST_CHECK(mul_i32fast_res == -2); + mul_i32fast_res = -12345; + TEST_CHECK(guf_wrapping_mul_int_fast32_t(2, INT32_MAX, &mul_i32fast_res) == GUF_MATH_CKD_OVERFLOW_POS); + TEST_CHECK(mul_i32fast_res == -2); + + mul_i32fast_res = -12345; + TEST_CHECK(guf_wrapping_mul_int_fast32_t(INT32_MAX, -2, &mul_i32fast_res) == GUF_MATH_CKD_OVERFLOW_NEG); + TEST_CHECK(mul_i32fast_res == 2); + mul_i32fast_res = -12345; + TEST_CHECK(guf_wrapping_mul_int_fast32_t(-2, INT32_MAX, &mul_i32fast_res) == GUF_MATH_CKD_OVERFLOW_NEG); + TEST_CHECK(mul_i32fast_res == 2); + + TEST_CHECK(guf_wrapping_mul_int_fast32_t(42002718, 314159265, &mul_i32fast_res) == GUF_MATH_CKD_OVERFLOW_POS); + TEST_CHECK(mul_i32fast_res == -972735522); + mul_i32fast_res = -12345; + TEST_CHECK(guf_wrapping_mul_int_fast32_t(314159265, 42002718, &mul_i32fast_res) == GUF_MATH_CKD_OVERFLOW_POS); + TEST_CHECK(mul_i32fast_res == -972735522); + + mul_i32fast_res = 12345; + guf_wrapping_mul_int_fast32_t(42002718, 314159265, &mul_i32fast_res); + TEST_CHECK(mul_i32fast_res == -972735522); + + mul_i32fast_res = 12345; + guf_wrapping_mul_int_fast32_t(-42002718, 314159265, &mul_i32fast_res); + TEST_CHECK(mul_i32fast_res == 972735522); + + mul_i32fast_res = 12345; + guf_wrapping_mul_int_fast32_t(-88888888, 99999999, &mul_i32fast_res); + TEST_CHECK(mul_i32fast_res == 1374494264); + + mul_i32fast_res = 12345; + guf_wrapping_mul_int_fast32_t(INT32_MIN, -1, &mul_i32fast_res); + TEST_CHECK(mul_i32fast_res == INT32_MIN); + + mul_i32fast_res = 12345; + guf_wrapping_mul_int_fast32_t(-2147483648, 2147483640, &mul_i32fast_res); + TEST_CHECK(mul_i32fast_res == 0); + + mul_i32fast_res = 12345; + guf_wrapping_mul_int_fast32_t(-2048, -314159265, &mul_i32fast_res); + TEST_CHECK(mul_i32fast_res == -846919680); + + mul_i32fast_res = 12345; + guf_wrapping_mul_int_fast32_t(4096, -314159265, &mul_i32fast_res); + TEST_CHECK(mul_i32fast_res == 1693839360); + + + ptrdiff_t ptrdiff_res = -1234; TEST_CHECK(guf_saturating_add_ptrdiff_t(PTRDIFF_MAX, 1, &ptrdiff_res) == GUF_MATH_CKD_OVERFLOW_POS); TEST_CHECK(ptrdiff_res == PTRDIFF_MAX); @@ -241,6 +295,7 @@ void CkdIntTest::test_ckd_uint() for (int32_t b = 0; b <= UINT8_MAX; ++b) { const int32_t add_res = a + b; const guf_math_ckd_result ckd_add = guf_ckd_add_u8((uint8_t)a, (uint8_t)b); + GUF_ASSERT(ckd_add == guf_ckd_add_uint_fast8_t((uint_fast8_t)a, (uint_fast8_t)b)); if (add_res > UINT8_MAX) { TEST_CHECK(ckd_add == GUF_MATH_CKD_OVERFLOW_POS); uint8_t saturated; @@ -262,6 +317,7 @@ void CkdIntTest::test_ckd_uint() const int32_t sub_res = a - b; const guf_math_ckd_result ckd_sub = guf_ckd_sub_u8((uint8_t)a, (uint8_t)b); + GUF_ASSERT(ckd_sub == guf_ckd_sub_uint_fast8_t((uint_fast8_t)a, (uint_fast8_t)b)); if (sub_res < 0) { TEST_CHECK(ckd_sub == GUF_MATH_CKD_OVERFLOW_NEG); uint8_t saturated; @@ -282,6 +338,7 @@ void CkdIntTest::test_ckd_uint() const int32_t mul_res = a * b; const guf_math_ckd_result ckd_mul = guf_ckd_mul_u8((uint8_t)a, (uint8_t)b); + GUF_ASSERT(ckd_mul == guf_ckd_mul_uint_fast8_t((uint_fast8_t)a, (uint_fast8_t)b)); if (mul_res > UINT8_MAX) { TEST_CHECK(ckd_mul == GUF_MATH_CKD_OVERFLOW_POS); uint8_t saturated; diff --git a/todo.txt b/todo.txt index 9a1a0e1..3f9a0e1 100644 --- a/todo.txt +++ b/todo.txt @@ -1,3 +1,6 @@ + +- make guf_utf8_char 4 bytes (non-null terminated) + - guf_stack, guf_queue, guf_dqueue, guf_prio_queue (using a heap), guf_ringbuf - sort: add cpp #ifdef to remove restrict from declaration diff --git a/tools/ckdint-gen.py b/tools/ckdint-gen.py index 6ce4c92..940f4d7 100644 --- a/tools/ckdint-gen.py +++ b/tools/ckdint-gen.py @@ -12,7 +12,10 @@ class IntType: INT_TYPE_ABBR: str INT_MIN: str INT_MAX: str - UINT_TYPE: str = "size_t" + UINT_TYPE: str + UINT_MAX: str + is_optional: bool = False + @dataclass class UintType: @@ -20,15 +23,17 @@ class UintType: INT_TYPE_ABBR: str INT_MIN: str INT_MAX: str + is_optional: bool = False def generate_ckdint_functions(int_types: list, uint_types: list) -> Tuple[str, str]: - ckd_add_sub_uint_header = textwrap.dedent(""" + ckd_add_sub_uint_header = textwrap.dedent("""\ GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_{type_abbr}({type} a, {type} b); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_{type_abbr}({type} a, {type} b); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_{type_abbr}({type} a, {type} b); """) - ckd_add_sub_uint = textwrap.dedent(""" + + ckd_add_sub_uint = textwrap.dedent("""\ GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_{type_abbr}({type} a, {type} b) {{ if (b > 0 && a > {int_max} - b) {{ @@ -52,13 +57,43 @@ def generate_ckdint_functions(int_types: list, uint_types: list) -> Tuple[str, s }} """) + ckd_add_sub_uint_FAST = textwrap.dedent("""\ + GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_{type_abbr}({type} a, {type} b) + {{ + a = GUF_UWRAP_{bits}(a); + b = GUF_UWRAP_{bits}(b); + if (b > 0 && a > {int_max} - b) {{ + return GUF_MATH_CKD_OVERFLOW_POS; + }} else {{ + return GUF_MATH_CKD_SUCCESS; + }} + }} + GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_{type_abbr}({type} a, {type} b) + {{ + a = GUF_UWRAP_{bits}(a); + b = GUF_UWRAP_{bits}(b); + if (b > a) {{ + return GUF_MATH_CKD_OVERFLOW_NEG; + }} else {{ + return GUF_MATH_CKD_SUCCESS; + }} + }} + GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_{type_abbr}({type} a, {type} b) + {{ + a = GUF_UWRAP_{bits}(a); + b = GUF_UWRAP_{bits}(b); + const {type} c = GUF_UWRAP_{bits}( 1u * a * b ); + return a != 0 && ((1u * c / a) != b) ? GUF_MATH_CKD_OVERFLOW_POS : GUF_MATH_CKD_SUCCESS; + }} + """) - ckd_add_sub_int_header = textwrap.dedent(""" + ckd_add_sub_int_header = textwrap.dedent("""\ GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_{type_abbr}({type} a, {type} b); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_sub_{type_abbr}({type} a, {type} b); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_mul_{type_abbr}({type} a, {type} b); """) - ckd_add_sub_int = textwrap.dedent(""" + + ckd_add_sub_int = textwrap.dedent("""\ GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_ckd_add_{type_abbr}({type} a, {type} b) {{ if (b > 0 && a > {int_max} - b) {{ @@ -107,7 +142,7 @@ def generate_ckdint_functions(int_types: list, uint_types: list) -> Tuple[str, s - saturating_wrapping_int_header = textwrap.dedent(""" + saturating_wrapping_int_header = textwrap.dedent("""\ GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_{type_abbr}({type} a, {type} b, {type} *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_{type_abbr}({type} a, {type} b, {type} *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_{type_abbr}({type} a, {type} b, {type} *result); @@ -116,7 +151,8 @@ def generate_ckdint_functions(int_types: list, uint_types: list) -> Tuple[str, s GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_{type_abbr}({type} a, {type} b, {type} *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_{type_abbr}({type} a, {type} b, {type} *result); """) - saturating_wrapping_int = textwrap.dedent(""" + + saturating_wrapping_int = textwrap.dedent("""\ GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_{type_abbr}({type} a, {type} b, {type} *result) {{ const guf_math_ckd_result check = guf_ckd_add_{type_abbr}(a, b); @@ -232,8 +268,9 @@ def generate_ckdint_functions(int_types: list, uint_types: list) -> Tuple[str, s case GUF_MATH_CKD_OVERFLOW_NEG: {{ {uint_type} res = 1u * ({uint_type})a * ({uint_type})b; if (res > {int_max}) {{ // This is the fix for implementation defined conversion from unsigned to signed. - const {uint_type} mod = (1u + ({uint_type}){int_max}); - res = mod > 0 ? (1u * res % mod) : res; + const {uint_type} mod = ({uint_type}){int_max} + 1u; + GUF_ASSERT(mod > 0); + res = 1u * res % mod; *result = {int_min} + ({type})res; }} else {{ *result = ({type})res; @@ -248,7 +285,8 @@ def generate_ckdint_functions(int_types: list, uint_types: list) -> Tuple[str, s }} """) - saturating_wrapping_uint_header = textwrap.dedent(""" + + saturating_wrapping_uint_header = textwrap.dedent("""\ GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_{type_abbr}({type} a, {type} b, {type} *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_{type_abbr}({type} a, {type} b, {type} *result); GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_{type_abbr}({type} a, {type} b, {type} *result); @@ -258,7 +296,7 @@ def generate_ckdint_functions(int_types: list, uint_types: list) -> Tuple[str, s GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_{type_abbr}({type} a, {type} b, {type} *result); """) - saturating_wrapping_uint = textwrap.dedent(""" + saturating_wrapping_uint = textwrap.dedent("""\ GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_{type_abbr}({type} a, {type} b, {type} *result) {{ const guf_math_ckd_result check = guf_ckd_add_{type_abbr}(a, b); @@ -340,29 +378,190 @@ def generate_ckdint_functions(int_types: list, uint_types: list) -> Tuple[str, s }} """) + saturating_wrapping_uint_FAST = textwrap.dedent("""\ + GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_add_{type_abbr}({type} a, {type} b, {type} *result) + {{ + const guf_math_ckd_result check = guf_ckd_add_{type_abbr}(a, b); + GUF_ASSERT(check == GUF_MATH_CKD_SUCCESS || check == GUF_MATH_CKD_OVERFLOW_POS); + if (result) {{ + switch (check) {{ + case GUF_MATH_CKD_SUCCESS: + *result = a + b; + break; + case GUF_MATH_CKD_OVERFLOW_POS: + *result = {int_max}; + break; + default: + GUF_ASSERT(false); + }} + }} + return check; + }} + GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_sub_{type_abbr}({type} a, {type} b, {type} *result) + {{ + const guf_math_ckd_result check = guf_ckd_sub_{type_abbr}(a, b); + GUF_ASSERT(check == GUF_MATH_CKD_SUCCESS || check == GUF_MATH_CKD_OVERFLOW_NEG); + if (result) {{ + switch (check) {{ + case GUF_MATH_CKD_SUCCESS: + *result = a - b; + break; + case GUF_MATH_CKD_OVERFLOW_NEG: + *result = 0; + break; + default: + GUF_ASSERT(false); + }} + }} + return check; + }} + GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_saturating_mul_{type_abbr}({type} a, {type} b, {type} *result) + {{ + const guf_math_ckd_result check = guf_ckd_mul_{type_abbr}(a, b); + GUF_ASSERT(check == GUF_MATH_CKD_SUCCESS || check == GUF_MATH_CKD_OVERFLOW_POS); + if (result) {{ + switch (check) {{ + case GUF_MATH_CKD_SUCCESS: + *result = a * b; + break; + case GUF_MATH_CKD_OVERFLOW_POS: + *result = {int_max}; + break; + default: + GUF_ASSERT(false); + }} + }} + return check; + }} + + GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_add_{type_abbr}({type} a, {type} b, {type} *result) + {{ + a = GUF_UWRAP_{bits}(a); + b = GUF_UWRAP_{bits}(b); + const guf_math_ckd_result check = guf_ckd_add_{type_abbr}(a, b); + if (result) {{ + *result = GUF_UWRAP_{bits}( 1u * a + b ); + }} + return check; + }} + GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_sub_{type_abbr}({type} a, {type} b, {type} *result) + {{ + a = GUF_UWRAP_{bits}(a); + b = GUF_UWRAP_{bits}(b); + const guf_math_ckd_result check = guf_ckd_sub_{type_abbr}(a, b); + if (result) {{ + *result = GUF_UWRAP_{bits}( 1u * a - b ); + }} + return check; + }} + GUF_MATH_CKDINT_KWRDS guf_math_ckd_result guf_wrapping_mul_{type_abbr}({type} a, {type} b, {type} *result) + {{ + a = GUF_UWRAP_{bits}(a); + b = GUF_UWRAP_{bits}(b); + const guf_math_ckd_result check = guf_ckd_mul_{type_abbr}(a, b); + if (result) {{ + *result = GUF_UWRAP_{bits}( 1u * a * b ); + }} + return check; + }} + """) + text_result = "// Signed integer arithmetic checks (generated with libguf/tools/ckdint-gen.py)\n" text_result_header = text_result - for type in int_types: - text_result += ckd_add_sub_int.format(type = type.INT_TYPE, type_abbr = type.INT_TYPE_ABBR, int_min = type.INT_MIN, int_max = type.INT_MAX) - text_result_header += ckd_add_sub_int_header.format(type = type.INT_TYPE, type_abbr = type.INT_TYPE_ABBR, int_min = type.INT_MIN, int_max = type.INT_MAX) + for type in int_types: + end = "\n" + if type.is_optional: + text_result += f"#ifdef {type.INT_MAX}\n" + text_result_header += f"#ifdef {type.INT_MAX}\n" + end = "" + + text_result += ckd_add_sub_int.format(type = type.INT_TYPE, type_abbr = type.INT_TYPE_ABBR, int_min = type.INT_MIN, int_max = type.INT_MAX, uint_max = type.UINT_MAX) + end + text_result_header += ckd_add_sub_int_header.format(type = type.INT_TYPE, type_abbr = type.INT_TYPE_ABBR, int_min = type.INT_MIN, int_max = type.INT_MAX, uint_max = type.UINT_MAX) + end + + if type.is_optional: + text_result += "#endif\n\n" + text_result_header += "#endif\n\n" + text_result += "\n// Unsigned integer arithmetic checks (generated with libguf/tools/ckdint-gen.py) \n" text_result_header += "\n// Unsigned integer arithmetic checks (generated with libguf/tools/ckdint-gen.py) \n" for type in uint_types: - text_result += ckd_add_sub_uint.format(type = type.INT_TYPE, type_abbr = type.INT_TYPE_ABBR, int_min = type.INT_MIN, int_max = type.INT_MAX) - text_result_header += ckd_add_sub_uint_header.format(type = type.INT_TYPE, type_abbr = type.INT_TYPE_ABBR, int_min = type.INT_MIN, int_max = type.INT_MAX) + end = "\n" + if type.is_optional: + text_result += f"#ifdef {type.INT_MAX}\n" + text_result_header += f"#ifdef {type.INT_MAX}\n" + end = "" + + if "uint_fast" in type.INT_TYPE: + bits = 0 + if "fast8" in type.INT_TYPE: + bits = 8 + elif "fast16" in type.INT_TYPE: + bits = 16 + elif "fast32" in type.INT_TYPE: + bits = 32 + elif "fast64" in type.INT_TYPE: + bits = 64 + else: + assert(False) + text_result += ckd_add_sub_uint_FAST.format(type = type.INT_TYPE, type_abbr = type.INT_TYPE_ABBR, int_min = type.INT_MIN, int_max = type.INT_MAX, bits = str(bits)) + else: + text_result += ckd_add_sub_uint.format(type = type.INT_TYPE, type_abbr = type.INT_TYPE_ABBR, int_min = type.INT_MIN, int_max = type.INT_MAX) + end + text_result_header += ckd_add_sub_uint_header.format(type = type.INT_TYPE, type_abbr = type.INT_TYPE_ABBR, int_min = type.INT_MIN, int_max = type.INT_MAX) + end + + if type.is_optional: + text_result += "#endif\n\n" + text_result_header += "#endif\n\n" + text_result += "\n\n// Signed saturating/wrapping arithmetic (generated with libguf/tools/ckdint-gen.py)\n" text_result_header += "\n\n// Signed saturating/wrapping arithmetic (generated with libguf/tools/ckdint-gen.py)\n" for type in int_types: - text_result += saturating_wrapping_int.format(type = type.INT_TYPE, type_abbr = type.INT_TYPE_ABBR, int_min = type.INT_MIN, int_max = type.INT_MAX, uint_type = type.UINT_TYPE) + "\n" - text_result_header += saturating_wrapping_int_header.format(type = type.INT_TYPE, type_abbr = type.INT_TYPE_ABBR, int_min = type.INT_MIN, int_max = type.INT_MAX, uint_type = type.UINT_TYPE) + "\n" + end = "\n" + if type.is_optional: + text_result += f"#ifdef {type.INT_MAX}\n" + text_result_header += f"#ifdef {type.INT_MAX}\n" + end = "" + + text_result += saturating_wrapping_int.format(type = type.INT_TYPE, type_abbr = type.INT_TYPE_ABBR, int_min = type.INT_MIN, int_max = type.INT_MAX, uint_type = type.UINT_TYPE, uint_max = type.UINT_MAX) + end + text_result_header += saturating_wrapping_int_header.format(type = type.INT_TYPE, type_abbr = type.INT_TYPE_ABBR, int_min = type.INT_MIN, int_max = type.INT_MAX, uint_type = type.UINT_TYPE, uint_max = type.UINT_MAX) + end + + if type.is_optional: + text_result += "#endif\n\n" + text_result_header += "#endif\n\n" + text_result += "\n// Unsigned saturating/wrapping arithmetic (generated with libguf/tools/ckdint-gen.py)\n" text_result_header += "\n// Unsigned saturating/wrapping arithmetic (generated with libguf/tools/ckdint-gen.py)\n" for type in uint_types: - text_result += saturating_wrapping_uint.format(type = type.INT_TYPE, type_abbr = type.INT_TYPE_ABBR, int_min = type.INT_MIN, int_max = type.INT_MAX) + "\n" - text_result_header += saturating_wrapping_uint_header.format(type = type.INT_TYPE, type_abbr = type.INT_TYPE_ABBR, int_min = type.INT_MIN, int_max = type.INT_MAX) + "\n" + end = "\n" + if type.is_optional: + text_result += f"#ifdef {type.INT_MAX}\n" + text_result_header += f"#ifdef {type.INT_MAX}\n" + end = "" + + if "uint_fast" in type.INT_TYPE: + bits = 0 + if "fast8" in type.INT_TYPE: + bits = 8 + elif "fast16" in type.INT_TYPE: + bits = 16 + elif "fast32" in type.INT_TYPE: + bits = 32 + elif "fast64" in type.INT_TYPE: + bits = 64 + else: + assert(False) + text_result += saturating_wrapping_uint_FAST.format(type = type.INT_TYPE, type_abbr = type.INT_TYPE_ABBR, int_min = type.INT_MIN, int_max = type.INT_MAX, bits = str(bits)) + end + else: + text_result += saturating_wrapping_uint.format(type = type.INT_TYPE, type_abbr = type.INT_TYPE_ABBR, int_min = type.INT_MIN, int_max = type.INT_MAX) + end + + text_result_header += saturating_wrapping_uint_header.format(type = type.INT_TYPE, type_abbr = type.INT_TYPE_ABBR, int_min = type.INT_MIN, int_max = type.INT_MAX) + end + + if type.is_optional: + text_result += "#endif\n\n" + text_result_header += "#endif\n\n" + return (text_result_header, text_result) @@ -371,28 +570,41 @@ def generate_ckdint_functions(int_types: list, uint_types: list) -> Tuple[str, s if __name__ == "__main__": int_types = [ - IntType(INT_TYPE = "int", INT_TYPE_ABBR = "int", INT_MIN = "INT_MIN", INT_MAX = "INT_MAX", UINT_TYPE = "unsigned"), - IntType(INT_TYPE = "long", INT_TYPE_ABBR = "long", INT_MIN = "LONG_MIN", INT_MAX = "LONG_MAX", UINT_TYPE = "unsigned long"), - IntType(INT_TYPE = "long long", INT_TYPE_ABBR = "long_long", INT_MIN = "LLONG_MIN", INT_MAX = "LLONG_MAX", UINT_TYPE = "unsigned long long"), + IntType(INT_TYPE = "int", INT_TYPE_ABBR = "int", INT_MIN = "INT_MIN", INT_MAX = "INT_MAX", UINT_TYPE = "unsigned", UINT_MAX = "UINT_MAX"), + IntType(INT_TYPE = "long", INT_TYPE_ABBR = "long", INT_MIN = "LONG_MIN", INT_MAX = "LONG_MAX", UINT_TYPE = "unsigned long", UINT_MAX = "ULONG_MAX"), + IntType(INT_TYPE = "long long", INT_TYPE_ABBR = "long_long", INT_MIN = "LLONG_MIN", INT_MAX = "LLONG_MAX", UINT_TYPE = "unsigned long long", UINT_MAX = "ULLONG_MAX"), - IntType(INT_TYPE = "int8_t", INT_TYPE_ABBR = "i8", INT_MIN = "INT8_MIN", INT_MAX = "INT8_MAX", UINT_TYPE = "uint8_t"), - IntType(INT_TYPE = "int16_t", INT_TYPE_ABBR = "i16", INT_MIN = "INT16_MIN", INT_MAX = "INT16_MAX", UINT_TYPE = "uint16_t"), - IntType(INT_TYPE = "int32_t", INT_TYPE_ABBR = "i32", INT_MIN = "INT32_MIN", INT_MAX = "INT32_MAX", UINT_TYPE = "uint32_t"), - IntType(INT_TYPE = "int64_t", INT_TYPE_ABBR = "i64", INT_MIN = "INT64_MIN", INT_MAX = "INT64_MAX", UINT_TYPE = "uint64_t"), - IntType(INT_TYPE = "ptrdiff_t", INT_TYPE_ABBR = "ptrdiff_t", INT_MIN = "PTRDIFF_MIN", INT_MAX = "PTRDIFF_MAX", UINT_TYPE = "size_t"), # TODO: size_t is not necessarily the unsigned ptrdiff_t equivalent + # TODO: size_t is not necessarily the unsigned ptrdiff_t equivalent + IntType(INT_TYPE = "ptrdiff_t", INT_TYPE_ABBR = "ptrdiff_t", INT_MIN = "PTRDIFF_MIN", INT_MAX = "PTRDIFF_MAX", UINT_TYPE = "size_t", UINT_MAX = "SIZE_MAX"), + + IntType(INT_TYPE = "int_fast8_t", INT_TYPE_ABBR = "int_fast8_t", INT_MIN = "GUF_INT8_MIN", INT_MAX = "GUF_INT8_MAX", UINT_TYPE = "uint_fast8_t", UINT_MAX = "GUF_UINT8_MAX"), + IntType(INT_TYPE = "int_fast16_t", INT_TYPE_ABBR = "int_fast16_t", INT_MIN = "GUF_INT16_MIN", INT_MAX = "GUF_INT16_MAX", UINT_TYPE = "uint_fast16_t", UINT_MAX = "GUF_UINT16_MAX"), + IntType(INT_TYPE = "int_fast32_t", INT_TYPE_ABBR = "int_fast32_t", INT_MIN = "GUF_INT32_MIN", INT_MAX = "GUF_INT32_MAX", UINT_TYPE = "uint_fast32_t", UINT_MAX = "GUF_UINT32_MAX"), + IntType(INT_TYPE = "int_fast64_t", INT_TYPE_ABBR = "int_fast64_t", INT_MIN = "GUF_INT64_MIN", INT_MAX = "GUF_INT64_MAX", UINT_TYPE = "uint_fast64_t", UINT_MAX = "GUF_UINT64_MAX"), + + IntType(INT_TYPE = "int8_t", INT_TYPE_ABBR = "i8", INT_MIN = "INT8_MIN", INT_MAX = "INT8_MAX", UINT_TYPE = "uint8_t", UINT_MAX = "GUF_UINT8_MAX", is_optional = True), + IntType(INT_TYPE = "int16_t", INT_TYPE_ABBR = "i16", INT_MIN = "INT16_MIN", INT_MAX = "INT16_MAX", UINT_TYPE = "uint16_t", UINT_MAX = "GUF_UINT16_MAX", is_optional = True), + IntType(INT_TYPE = "int32_t", INT_TYPE_ABBR = "i32", INT_MIN = "INT32_MIN", INT_MAX = "INT32_MAX", UINT_TYPE = "uint32_t", UINT_MAX = "GUF_UINT32_MAX", is_optional = True), + IntType(INT_TYPE = "int64_t", INT_TYPE_ABBR = "i64", INT_MIN = "INT64_MIN", INT_MAX = "INT64_MAX", UINT_TYPE = "uint64_t", UINT_MAX = "GUF_UINT64_MAX", is_optional = True), ] uint_types = [ UintType(INT_TYPE = "unsigned char", INT_TYPE_ABBR = "uchar", INT_MIN = "0", INT_MAX = "UCHAR_MAX"), UintType(INT_TYPE = "unsigned", INT_TYPE_ABBR = "unsigned", INT_MIN = "0", INT_MAX = "UINT_MAX"), - UintType(INT_TYPE = "unsigned long", INT_TYPE_ABBR = "ulong", INT_MIN = "ULONG_MIN", INT_MAX = "ULONG_MAX"), - UintType(INT_TYPE = "unsigned long long", INT_TYPE_ABBR = "ulong_long", INT_MIN = "ULLONG_MIN", INT_MAX = "ULLONG_MAX"), + UintType(INT_TYPE = "unsigned long", INT_TYPE_ABBR = "ulong", INT_MIN = "0", INT_MAX = "ULONG_MAX"), + UintType(INT_TYPE = "unsigned long long", INT_TYPE_ABBR = "ulong_long", INT_MIN = "0", INT_MAX = "ULLONG_MAX"), - UintType(INT_TYPE = "uint8_t", INT_TYPE_ABBR = "u8", INT_MIN = "0", INT_MAX = "UINT8_MAX"), - UintType(INT_TYPE = "uint16_t", INT_TYPE_ABBR = "u16", INT_MIN = "0", INT_MAX = "UINT16_MAX"), - UintType(INT_TYPE = "uint32_t", INT_TYPE_ABBR = "u32", INT_MIN = "0", INT_MAX = "UINT32_MAX"), - UintType(INT_TYPE = "uint64_t", INT_TYPE_ABBR = "u64", INT_MIN = "0", INT_MAX = "UINT64_MAX"), UintType(INT_TYPE = "size_t", INT_TYPE_ABBR = "size_t", INT_MIN = "0", INT_MAX = "SIZE_MAX"), + + UintType(INT_TYPE = "uint_fast8_t", INT_TYPE_ABBR = "uint_fast8_t", INT_MIN = "0", INT_MAX = "GUF_UINT8_MAX"), + UintType(INT_TYPE = "uint_fast16_t", INT_TYPE_ABBR = "uint_fast16_t", INT_MIN = "0", INT_MAX = "GUF_UINT16_MAX"), + UintType(INT_TYPE = "uint_fast32_t", INT_TYPE_ABBR = "uint_fast32_t", INT_MIN = "0", INT_MAX = "GUF_UINT32_MAX"), + UintType(INT_TYPE = "uint_fast64_t", INT_TYPE_ABBR = "uint_fast64_t", INT_MIN = "0", INT_MAX = "GUF_UINT64_MAX"), + + UintType(INT_TYPE = "uint8_t", INT_TYPE_ABBR = "u8", INT_MIN = "0", INT_MAX = "UINT8_MAX", is_optional = True), + UintType(INT_TYPE = "uint16_t", INT_TYPE_ABBR = "u16", INT_MIN = "0", INT_MAX = "UINT16_MAX", is_optional = True), + UintType(INT_TYPE = "uint32_t", INT_TYPE_ABBR = "u32", INT_MIN = "0", INT_MAX = "UINT32_MAX", is_optional = True), + UintType(INT_TYPE = "uint64_t", INT_TYPE_ABBR = "u64", INT_MIN = "0", INT_MAX = "UINT64_MAX", is_optional = True), ] code_header, code_impl = generate_ckdint_functions(int_types = int_types, uint_types= uint_types) diff --git a/tools/min_max_clamp-gen.py b/tools/min_max_clamp-gen.py index ecfa11a..a02e9cc 100644 --- a/tools/min_max_clamp-gen.py +++ b/tools/min_max_clamp-gen.py @@ -11,6 +11,7 @@ class IntType: INT_TYPE_ABBR: str INT_MIN: str INT_MAX: str + is_optional: bool = False @dataclass class UintType: @@ -18,10 +19,11 @@ class UintType: INT_TYPE_ABBR: str INT_MIN: str INT_MAX: str + is_optional: bool = False def gen_min_max_clamp(int_types: list, uint_types: list) -> str: - template = textwrap.dedent(""" + template = textwrap.dedent("""\ static inline {type} guf_min_{type_abbr}({type} a, {type} b) {{ return a < b ? a : b; }} static inline {type} guf_max_{type_abbr}({type} a, {type} b) {{ return a > b ? a : b; }} static inline {type} guf_clamp_{type_abbr}({type} x, {type} min, {type} max) {{ if (x < min) {{return min;}} if (x > max) {{return max;}} return x; }} @@ -29,12 +31,21 @@ def gen_min_max_clamp(int_types: list, uint_types: list) -> str: result = "\n// Signed min, max, clamp functions (generated with libguf/tools/min_max_clamp-gen.py)\n" for t in int_types: + if t.is_optional: + result += "#ifdef {int_max}\n".format(int_max = t.INT_MAX) result += template.format(type = t.INT_TYPE, type_abbr = t.INT_TYPE_ABBR) + if t.is_optional: + result += "#endif\n" + result += "\n" result += "\n// Unsigned min, max, clamp functions (generated with libguf/tools/min_max_clamp-gen.py)\n" for t in uint_types: + if t.is_optional: + result +="#ifdef {int_max}\n".format(int_max = t.INT_MAX) result += template.format(type = t.INT_TYPE, type_abbr = t.INT_TYPE_ABBR) - + if t.is_optional: + result += "#endif\n" + result += "\n" return result @@ -45,15 +56,23 @@ if __name__ == "__main__": IntType(INT_TYPE = "int", INT_TYPE_ABBR = "int", INT_MIN = "INT_MIN", INT_MAX = "INT_MAX"), IntType(INT_TYPE = "long", INT_TYPE_ABBR = "long", INT_MIN = "LONG_MIN", INT_MAX = "LONG_MAX"), IntType(INT_TYPE = "long long", INT_TYPE_ABBR = "long_long", INT_MIN = "LLONG_MIN", INT_MAX = "LLONG_MAX"), - - IntType(INT_TYPE = "int8_t", INT_TYPE_ABBR = "i8", INT_MIN = "INT8_MIN", INT_MAX = "INT8_MAX"), - IntType(INT_TYPE = "int16_t", INT_TYPE_ABBR = "i16", INT_MIN = "INT16_MIN", INT_MAX = "INT16_MAX"), - IntType(INT_TYPE = "int32_t", INT_TYPE_ABBR = "i32", INT_MIN = "INT32_MIN", INT_MAX = "INT32_MAX"), - IntType(INT_TYPE = "int64_t", INT_TYPE_ABBR = "i64", INT_MIN = "INT64_MIN", INT_MAX = "INT64_MAX"), + IntType(INT_TYPE = "ptrdiff_t", INT_TYPE_ABBR = "ptrdiff_t", INT_MIN = "PTRDIFF_MIN", INT_MAX = "PTRDIFF_MAX"), + IntType(INT_TYPE = "int_fast8_t", INT_TYPE_ABBR = "i8_fast", INT_MIN = "GUF_INT8_MIN", INT_MAX = "GUF_INT8_MAX"), + IntType(INT_TYPE = "int_fast16_t", INT_TYPE_ABBR = "i16_fast", INT_MIN = "GUF_INT16_MIN", INT_MAX = "GUF_INT16_MAX"), + IntType(INT_TYPE = "int_fast32_t", INT_TYPE_ABBR = "i32_fast", INT_MIN = "GUF_INT32_MIN", INT_MAX = "GUF_INT32_MAX"), + IntType(INT_TYPE = "int_fast64_t", INT_TYPE_ABBR = "i64_fast", INT_MIN = "GUF_INT64_MIN", INT_MAX = "GUF_INT64_MAX"), + IntType(INT_TYPE = "float", INT_TYPE_ABBR = "f32", INT_MIN = "-FLT_MAX", INT_MAX = "FLT_MAX"), IntType(INT_TYPE = "double", INT_TYPE_ABBR = "f64", INT_MIN = "-DBL_MAX", INT_MAX = "DBL_MAX"), + + IntType(INT_TYPE = "int8_t", INT_TYPE_ABBR = "i8", INT_MIN = "INT8_MIN", INT_MAX = "INT8_MAX", is_optional=True), + IntType(INT_TYPE = "int16_t", INT_TYPE_ABBR = "i16", INT_MIN = "INT16_MIN", INT_MAX = "INT16_MAX", is_optional=True), + IntType(INT_TYPE = "int32_t", INT_TYPE_ABBR = "i32", INT_MIN = "INT32_MIN", INT_MAX = "INT32_MAX", is_optional=True), + IntType(INT_TYPE = "int64_t", INT_TYPE_ABBR = "i64", INT_MIN = "INT64_MIN", INT_MAX = "INT64_MAX", is_optional=True), + + ] uint_types = [ @@ -62,11 +81,17 @@ if __name__ == "__main__": UintType(INT_TYPE = "unsigned long", INT_TYPE_ABBR = "ulong", INT_MIN = "0", INT_MAX = "ULONG_MAX"), UintType(INT_TYPE = "unsigned long long", INT_TYPE_ABBR = "ulong_long", INT_MIN = "0", INT_MAX = "ULLONG_MAX"), - UintType(INT_TYPE = "uint8_t", INT_TYPE_ABBR = "u8", INT_MIN = "0", INT_MAX = "UINT8_MAX"), - UintType(INT_TYPE = "uint16_t", INT_TYPE_ABBR = "u16", INT_MIN = "0", INT_MAX = "UINT16_MAX"), - UintType(INT_TYPE = "uint32_t", INT_TYPE_ABBR = "u32", INT_MIN = "0", INT_MAX = "UINT32_MAX"), - UintType(INT_TYPE = "uint64_t", INT_TYPE_ABBR = "u64", INT_MIN = "0", INT_MAX = "UINT64_MAX"), UintType(INT_TYPE = "size_t", INT_TYPE_ABBR = "size_t", INT_MIN = "0", INT_MAX = "SIZE_MAX"), + + UintType(INT_TYPE = "uint_fast8_t", INT_TYPE_ABBR = "u8_fast", INT_MIN = "0", INT_MAX = "GUF_UINT8_MAX"), + UintType(INT_TYPE = "uint_fast16_t", INT_TYPE_ABBR = "u16_fast", INT_MIN = "0", INT_MAX = "GUF_UINT16_MAX"), + UintType(INT_TYPE = "uint_fast32_t", INT_TYPE_ABBR = "u32_fast", INT_MIN = "0", INT_MAX = "GUF_UINT32_MAX"), + UintType(INT_TYPE = "uint_fast64_t", INT_TYPE_ABBR = "u64_fast", INT_MIN = "0", INT_MAX = "GUF_UINT64_MAX"), + + UintType(INT_TYPE = "uint8_t", INT_TYPE_ABBR = "u8", INT_MIN = "0", INT_MAX = "UINT8_MAX", is_optional=True), + UintType(INT_TYPE = "uint16_t", INT_TYPE_ABBR = "u16", INT_MIN = "0", INT_MAX = "UINT16_MAX", is_optional=True), + UintType(INT_TYPE = "uint32_t", INT_TYPE_ABBR = "u32", INT_MIN = "0", INT_MAX = "UINT32_MAX", is_optional=True), + UintType(INT_TYPE = "uint64_t", INT_TYPE_ABBR = "u64", INT_MIN = "0", INT_MAX = "UINT64_MAX", is_optional=True), ]