RNG improvements (replay-breaking)
This commit is contained in:
parent
14a2d50edf
commit
35c1a90912
3 changed files with 58 additions and 15 deletions
35
src/random.c
35
src/random.c
|
@ -87,17 +87,38 @@ uint64_t tsrand64(void) {
|
|||
return tsrand64_p(tsrand_current);
|
||||
}
|
||||
|
||||
static inline double makedouble(uint64_t x) {
|
||||
// Range: [0..1)
|
||||
return (x >> 11) * (1.0 / (UINT64_C(1) << 53));
|
||||
static inline double make_unsigned_double(uint64_t x) {
|
||||
// Range: [0.0; 1.0)
|
||||
return (x >> 11) * 0x1.0p-53;
|
||||
}
|
||||
|
||||
static inline double make_signed_double(uint64_t x) {
|
||||
// Range: (-1.0; 1.0)
|
||||
// NOTE: slight bias towards 0, because -0 exists
|
||||
DoubleBits db;
|
||||
db.val = make_unsigned_double(x << 1);
|
||||
db.bits |= x & (UINT64_C(1) << 63);
|
||||
return db.val;
|
||||
}
|
||||
|
||||
double frand(void) {
|
||||
return makedouble(tsrand64());
|
||||
return make_unsigned_double(tsrand64());
|
||||
}
|
||||
|
||||
double nfrand(void) {
|
||||
return frand() * 2.0 - 1.0;
|
||||
return make_signed_double(tsrand64());
|
||||
}
|
||||
|
||||
bool rand_bool(void) {
|
||||
return tsrand64() >> 63;
|
||||
}
|
||||
|
||||
double rand_sign(void) {
|
||||
return bits_to_double((UINT64_C(0x3FF) << 52) | (tsrand64() & (UINT64_C(1) << 63)));
|
||||
}
|
||||
|
||||
float rand_signf(void) {
|
||||
return bits_to_float((0x7f << 23) | (tsrand() & (1 << 31)));
|
||||
}
|
||||
|
||||
// we use this to support multiple rands in a single statement without breaking replays across different builds
|
||||
|
@ -157,11 +178,11 @@ uint32_t _tsrand_a(int idx, const char *file, uint line) {
|
|||
}
|
||||
|
||||
double _afrand(int idx, const char *file, uint line) {
|
||||
return makedouble(_tsrand64_a(idx, file, line));
|
||||
return make_unsigned_double(_tsrand64_a(idx, file, line));
|
||||
}
|
||||
|
||||
double _anfrand(int idx, const char *file, uint line) {
|
||||
return _afrand(idx, file, line) * 2 - 1;
|
||||
return make_signed_double(_tsrand64_a(idx, file, line));
|
||||
}
|
||||
|
||||
void tsrand_lock(RandomState *rnd) {
|
||||
|
|
12
src/random.h
12
src/random.h
|
@ -32,8 +32,11 @@ uint64_t tsrand64(void);
|
|||
void tsrand_lock(RandomState *rnd);
|
||||
void tsrand_unlock(RandomState *rnd);
|
||||
|
||||
double frand(void);
|
||||
double nfrand(void);
|
||||
double frand(void); // Range: [0.0; 1.0)
|
||||
double nfrand(void); // Range: (-1.0; 1.0)
|
||||
bool rand_bool(void);
|
||||
double rand_sign(void); // 1.0 or -1.0
|
||||
float rand_signf(void); // 1.0f or -1.0f
|
||||
|
||||
void _tsrand_fill_p(RandomState *rnd, int amount, const char *file, uint line);
|
||||
void _tsrand_fill(int amount, const char *file, uint line);
|
||||
|
@ -50,6 +53,7 @@ double _anfrand(int idx, const char *file, uint line);
|
|||
|
||||
#define TSRAND_ARRAY_LIMIT 16
|
||||
|
||||
// Range: [rmin; rmax)
|
||||
INLINE double rand_range(double rmin, double rmax) {
|
||||
// TODO: ensure uniform distribution?
|
||||
return frand() * (rmax - rmin) + rmin;
|
||||
|
@ -60,4 +64,8 @@ INLINE double rand_angle(void) {
|
|||
return frand() * (M_PI * 2);
|
||||
}
|
||||
|
||||
INLINE bool rand_chance(double chance) {
|
||||
return frand() < chance;
|
||||
}
|
||||
|
||||
#endif // IGUARD_random_h
|
||||
|
|
|
@ -17,16 +17,30 @@ void* memdup(const void *src, size_t size) attr_returns_allocated attr_nonnull(1
|
|||
void inherit_missing_pointers(uint num, void *dest[num], void *const base[num]) attr_nonnull(2, 3);
|
||||
bool is_main_thread(void);
|
||||
|
||||
typedef union FloatBits {
|
||||
float val;
|
||||
uint32_t bits;
|
||||
} FloatBits;
|
||||
|
||||
typedef union DoubleBits {
|
||||
double val;
|
||||
uint64_t bits;
|
||||
} DoubleBits;
|
||||
|
||||
INLINE uint32_t float_to_bits(float f) {
|
||||
union { uint32_t i; float f; } u;
|
||||
u.f = f;
|
||||
return u.i;
|
||||
return ((FloatBits) { .val = f }).bits;
|
||||
}
|
||||
|
||||
INLINE float bits_to_float(uint32_t i) {
|
||||
union { uint32_t i; float f; } u;
|
||||
u.i = i;
|
||||
return u.f;
|
||||
return ((FloatBits) { .bits = i }).val;
|
||||
}
|
||||
|
||||
INLINE uint32_t double_to_bits(float f) {
|
||||
return ((DoubleBits) { .val = f }).bits;
|
||||
}
|
||||
|
||||
INLINE double bits_to_double(uint64_t i) {
|
||||
return ((DoubleBits) { .bits = i }).val;
|
||||
}
|
||||
|
||||
extern SDL_threadID main_thread_id;
|
||||
|
|
Loading…
Reference in a new issue