aboutsummaryrefslogtreecommitdiff
path: root/builtins
diff options
context:
space:
mode:
authorBruce Hill <bruce@bruce-hill.com>2024-08-03 16:23:28 -0400
committerBruce Hill <bruce@bruce-hill.com>2024-08-03 16:23:28 -0400
commit17be975d3afbff837ea621470f8a093c0090c5c8 (patch)
tree7e10d4d1f5aa20157985862e90dbf5276d047ab2 /builtins
parent46396646bf1ec5f19cfbe52c7a6faf6ab61086ef (diff)
Fix integer random functions so they correctly handle all representable
ranges
Diffstat (limited to 'builtins')
-rw-r--r--builtins/integers.c24
-rw-r--r--builtins/integers.h2
2 files changed, 17 insertions, 9 deletions
diff --git a/builtins/integers.c b/builtins/integers.c
index ef9b5df4..d50c6573 100644
--- a/builtins/integers.c
+++ b/builtins/integers.c
@@ -51,14 +51,22 @@
} \
return bit_array; \
} \
- public c_type KindOfInt ## $random(int64_t min, int64_t max) { \
- if (min > max) fail("Random min (%ld) is larger than max (%ld)", min, max); \
- if (min < (int64_t)min_val) fail("Random min (%ld) is smaller than the minimum "#KindOfInt" value", min); \
- if (max > (int64_t)max_val) fail("Random max (%ld) is smaller than the maximum "#KindOfInt" value", max); \
- int64_t range = max - min; \
- if (range > UINT32_MAX) fail("Random range (%ld) is larger than the maximum allowed (%ld)", range, UINT32_MAX); \
- uint32_t r = arc4random_uniform((uint32_t)range); \
- return min + (c_type)r; \
+ public c_type KindOfInt ## $random(c_type min, c_type max) { \
+ if (min > max) fail("Random minimum value (%ld) is larger than the maximum value (%ld)", min, max); \
+ if (min == max) return min; \
+ if (min == min_val && max == max_val) { \
+ c_type r; \
+ arc4random_buf(&r, sizeof(r)); \
+ return r; \
+ } \
+ uint64_t range = (uint64_t)max - (uint64_t)min + 1; \
+ uint64_t min_r = -range % range; \
+ uint64_t r; \
+ for (;;) { \
+ arc4random_buf(&r, sizeof(r)); \
+ if (r >= min_r) break; \
+ } \
+ return (c_type)((uint64_t)min + (r % range)); \
} \
public c_type KindOfInt ## $from_text(CORD text, CORD *the_rest) { \
const char *str = CORD_to_const_char_star(text); \
diff --git a/builtins/integers.h b/builtins/integers.h
index 2e8f6721..2c638a4a 100644
--- a/builtins/integers.h
+++ b/builtins/integers.h
@@ -27,7 +27,7 @@
CORD type_name ## $hex(c_type i, int64_t digits, bool uppercase, bool prefix); \
CORD type_name ## $octal(c_type i, int64_t digits, bool prefix); \
array_t type_name ## $bits(c_type x); \
- c_type type_name ## $random(int64_t min, int64_t max); \
+ c_type type_name ## $random(c_type min, c_type max); \
c_type type_name ## $from_text(CORD text, CORD *the_rest); \
extern const c_type type_name ## $min, type_name##$max; \
extern const TypeInfo $ ## type_name;