diff --git a/src/guf_math.h b/src/guf_math.h index 46e1029..5d1b03b 100644 --- a/src/guf_math.h +++ b/src/guf_math.h @@ -62,4 +62,10 @@ static inline int32_t guf_abs_i32(int32_t x) {if (x >= 0) {return x;} static inline int64_t guf_abs_i64(int64_t x) {if (x >= 0) {return x;} GUF_ASSERT_RELEASE(x > INT64_MIN); return -x;} static inline ptrdiff_t guf_abs_ptrdiff(ptrdiff_t x) {if (x >= 0) {return x;} GUF_ASSERT_RELEASE(x > PTRDIFF_MIN); return -x;} +static inline uint32_t guf_uabs_i32(int32_t x) {if (x >= 0) {return x;} else if (x == INT32_MIN) {return (uint32_t)INT32_MAX + 1;} else {return -x;}} +static inline uint64_t guf_uabs_i64(int64_t x) {if (x >= 0) {return x;} else if (x == INT64_MIN) {return (uint64_t)INT64_MAX + 1;} else {return -x;}} + +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;} + #endif diff --git a/src/guf_rand.h b/src/guf_rand.h index 39cb20b..9bd1feb 100644 --- a/src/guf_rand.h +++ b/src/guf_rand.h @@ -223,7 +223,7 @@ GUF_FN_KEYWORDS int64_t guf_randrange_i64(guf_randstate *state, int64_t min, int const unsigned rand_max_shift = 1; const uint64_t rand_max = GUF_RAND_MAX >> rand_max_shift; // 2^63 - 1 - const uint64_t delta = max - min; + const uint64_t delta = guf_absdiff_i64(max, min); if (delta > rand_max) { guf_panic(GUF_ERR_INT_OVERFLOW, GUF_ERR_MSG("in function guf_randrange_i64: interval [min, max] larger than INT64_MAX")); return -1; diff --git a/src/guf_rand32.h b/src/guf_rand32.h index 3b1108a..17af1d1 100644 --- a/src/guf_rand32.h +++ b/src/guf_rand32.h @@ -8,7 +8,7 @@ #define GUF_RAND32_MAX UINT32_MAX -typedef struct guf_randstate32 { // State for xoshiro256** 1.0 +typedef struct guf_randstate32 { // State for xoshiro128** 1.1 uint32_t s[4]; } guf_randstate32; @@ -66,7 +66,6 @@ GUF_FN_KEYWORDS void guf_randstate32_init(guf_randstate32 *state, uint64_t seed) if (!state->s[0] && !state->s[1] && !state->s[2] && !state->s[3]) { // State must not be only zeroes: state->s[0] = 0x9e3779b9; // arbitrary constant != 0 - seed = 0x9e3779b97f4a7c15; split = guf_rand32_splitmix64(&seed); state->s[0] = (uint32_t)split; // lower 32-bits @@ -174,18 +173,19 @@ GUF_FN_KEYWORDS int32_t guf_rand32range_i32(guf_randstate32 *state, int32_t min, const unsigned rand_max_shift = 1; const uint32_t rand_max = GUF_RAND32_MAX >> rand_max_shift; // 2^32 - 1 - const uint32_t delta = max - min; + const uint32_t delta = guf_absdiff_i32(max, min); if (delta > rand_max) { guf_panic(GUF_ERR_INT_OVERFLOW, GUF_ERR_MSG("in function guf_randrange32_i32: interval [min, max] larger than INT32_MAX")); return -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 uint32_t num_rand_vals = rand_max + 1u; // 2^31 const uint32_t num_bins = (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);