mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
mruby-random: split 64-bit state into two 32-bit values on 32-bit platforms
on 32-bit systems, the rand_state struct with uint64_t state (8 bytes, 8-byte aligned) followed by uint32_t seed_value (4 bytes) resulted in 16 bytes due to padding, exceeding the 12-byte ISTRUCT_DATA_SIZE limit. this caused the static_assert at line 540 to fail. split the state field into state_lo and state_hi on MRB_32BIT platforms to achieve perfect 12-byte alignment (4+4+4) without padding. add GET_STATE/SET_STATE macros to provide uniform access across platforms. Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -38,14 +38,33 @@
|
||||
#define PCG_INCREMENT 1442695040888963407ULL
|
||||
|
||||
typedef struct rand_state {
|
||||
#ifdef MRB_32BIT
|
||||
/* On 32-bit platforms, split state to avoid alignment padding */
|
||||
uint32_t state_lo;
|
||||
uint32_t state_hi;
|
||||
#else
|
||||
uint64_t state;
|
||||
#endif
|
||||
uint32_t seed_value; /* Track last seed for srand compatibility */
|
||||
} rand_state;
|
||||
|
||||
/* Helper macros for 64-bit state access */
|
||||
#ifdef MRB_32BIT
|
||||
# define GET_STATE(t) (((uint64_t)(t)->state_hi << 32) | (t)->state_lo)
|
||||
# define SET_STATE(t, val) do { \
|
||||
uint64_t v_ = (val); \
|
||||
(t)->state_lo = (uint32_t)v_; \
|
||||
(t)->state_hi = (uint32_t)(v_ >> 32); \
|
||||
} while (0)
|
||||
#else
|
||||
# define GET_STATE(t) ((t)->state)
|
||||
# define SET_STATE(t, val) ((t)->state = (val))
|
||||
#endif
|
||||
|
||||
static void
|
||||
rand_init(rand_state *t)
|
||||
{
|
||||
t->state = 0x853c49e6748fea9bULL;
|
||||
SET_STATE(t, 0x853c49e6748fea9bULL);
|
||||
t->seed_value = 521288629;
|
||||
}
|
||||
|
||||
@@ -57,9 +76,9 @@ rand_seed(rand_state *t, uint32_t seed)
|
||||
uint32_t old_seed = t->seed_value;
|
||||
|
||||
/* PCG initialization: state=0, step, add seed, step, then mix */
|
||||
t->state = 0;
|
||||
SET_STATE(t, 0);
|
||||
rand_uint32(t);
|
||||
t->state += seed;
|
||||
SET_STATE(t, GET_STATE(t) + seed);
|
||||
for (int i = 0; i < 10; i++) {
|
||||
rand_uint32(t);
|
||||
}
|
||||
@@ -72,10 +91,10 @@ static uint32_t
|
||||
rand_uint32(rand_state *rng)
|
||||
{
|
||||
/* PCG-XSH-RR: XorShift High (xorshift), then Random Rotate */
|
||||
uint64_t oldstate = rng->state;
|
||||
uint64_t oldstate = GET_STATE(rng);
|
||||
|
||||
/* LCG step: advance internal state */
|
||||
rng->state = oldstate * PCG_MULTIPLIER + PCG_INCREMENT;
|
||||
SET_STATE(rng, oldstate * PCG_MULTIPLIER + PCG_INCREMENT);
|
||||
|
||||
/* Output function: xorshift, then rotate by top bits */
|
||||
uint32_t xorshifted = (uint32_t)(((oldstate >> 18u) ^ oldstate) >> 27u);
|
||||
|
||||
Reference in New Issue
Block a user