138 lines
4.4 KiB
C
138 lines
4.4 KiB
C
/*
|
|
* This software is licensed under the terms of the MIT License.
|
|
* See COPYING for further information.
|
|
* ---
|
|
* Copyright (c) 2011-2019, Lukas Weber <laochailan@web.de>.
|
|
* Copyright (c) 2012-2019, Andrei Alexeyev <akari@taisei-project.org>.
|
|
*/
|
|
|
|
#pragma once
|
|
#include "taisei.h"
|
|
|
|
#include "util/crap.h"
|
|
#include "util/miscmath.h"
|
|
|
|
typedef struct RandomState {
|
|
uint64_t state[4];
|
|
#ifdef DEBUG
|
|
bool locked;
|
|
#endif
|
|
} RandomState;
|
|
|
|
typedef struct rng_val {
|
|
uint64_t _value;
|
|
} rng_val_t;
|
|
|
|
uint64_t splitmix64(uint64_t *state) attr_nonnull(1);
|
|
uint32_t splitmix32(uint32_t *state) attr_nonnull(1);
|
|
uint64_t makeseed(void);
|
|
|
|
void rng_init(RandomState *rng, uint64_t seed) attr_nonnull(1);
|
|
void rng_seed(RandomState *rng, uint64_t seed) attr_nonnull(1);
|
|
void rng_make_active(RandomState *rng) attr_nonnull(1);
|
|
rng_val_t rng_next_p(RandomState *rng) attr_nonnull(1);
|
|
|
|
#ifdef DEBUG
|
|
INLINE void rng_lock(RandomState *rng) { rng->locked = true; }
|
|
INLINE void rng_unlock(RandomState *rng) { rng->locked = false; }
|
|
INLINE bool rng_is_locked(RandomState *rng) { return rng->locked; }
|
|
#else
|
|
#define rng_lock(rng) ((void)(rng), (void)0)
|
|
#define rng_unlock(rng) ((void)(rng), (void)0)
|
|
#define rng_is_locked(rng) (false)
|
|
#endif
|
|
|
|
// NOTE: if you rename this, also update scripts/upkeep/check-rng-usage.py!
|
|
rng_val_t rng_next(void);
|
|
void rng_nextn(size_t n, rng_val_t v[n]) attr_nonnull(2);
|
|
|
|
#define RNG_ARRAY(name, size) rng_val_t name[size]; RNG_NEXT(name)
|
|
|
|
#define RNG_NEXT(_val) \
|
|
rng_nextn(sizeof(_val)/sizeof(rng_val_t), _Generic((_val), \
|
|
rng_val_t: &(_val), \
|
|
rng_val_t*: (_val) \
|
|
))
|
|
|
|
uint64_t vrng_u64(rng_val_t v) attr_pure;
|
|
#define rng_u64() vrng_u64(rng_next())
|
|
int64_t vrng_i64(rng_val_t v) attr_pure;
|
|
#define rng_i64() vrng_i64(rng_next())
|
|
|
|
uint32_t vrng_u32(rng_val_t v) attr_pure;
|
|
#define rng_u32() vrng_u32(rng_next())
|
|
int32_t vrng_i32(rng_val_t v) attr_pure;
|
|
#define rng_i32() vrng_i32(rng_next())
|
|
|
|
double vrng_f64(rng_val_t v) attr_pure;
|
|
#define rng_f64() vrng_f64(rng_next())
|
|
double vrng_f64s(rng_val_t v) attr_pure;
|
|
#define rng_f64s() vrng_f64s(rng_next())
|
|
|
|
float vrng_f32(rng_val_t v) attr_pure;
|
|
#define rng_f32() vrng_f32(rng_next())
|
|
float vrng_f32s(rng_val_t v) attr_pure;
|
|
#define rng_f32s() vrng_f32s(rng_next())
|
|
|
|
#define vrng_real(v) vrng_f64(v)
|
|
#define rng_real() vrng_real(rng_next())
|
|
#define vrng_sreal(v) vrng_f64s(v)
|
|
#define rng_sreal() vrng_sreal(rng_next())
|
|
|
|
bool vrng_bool(rng_val_t v);
|
|
#define rng_bool() vrng_bool(rng_next())
|
|
|
|
double vrng_f64_sign(rng_val_t v) attr_pure;
|
|
#define rng_f64_sign() vrng_f64_sign(rng_next())
|
|
float vrng_f32_sign(rng_val_t v) attr_pure;
|
|
#define rng_f32_sign() vrng_f32_sign(rng_next())
|
|
|
|
#define vrng_sign(v) vrng_f64_sign(v)
|
|
#define rng_sign() vrng_sign(rng_next())
|
|
|
|
double vrng_f64_range(rng_val_t v, double rmin, double rmax) attr_pure;
|
|
#define rng_f64_range(rmin, rmax) vrng_f64_range(rng_next(), rmin, rmax)
|
|
float vrng_f32_range(rng_val_t v, float rmin, float rmax) attr_pure;
|
|
#define rng_f32_range(rmin, rmax) vrng_f32_range(rng_next(), rmin, rmax)
|
|
|
|
#define vrng_range(v, rmin, rmax) _Generic((rmin), \
|
|
float: \
|
|
_Generic((rmax), \
|
|
float: vrng_f32_range, \
|
|
default: vrng_f64_range \
|
|
), \
|
|
default: vrng_f64_range \
|
|
)(v, rmin, rmax)
|
|
|
|
#define rng_range(rmin, rmax) vrng_range(rng_next(), rmin, rmax)
|
|
|
|
int64_t vrng_i64_range(rng_val_t v, int64_t rmin, int64_t rmax) attr_pure;
|
|
#define rng_i64_range(rmin, rmax) vrng_i64_range(rng_next(), rmin, rmax)
|
|
int32_t vrng_i32_range(rng_val_t v, int32_t rmin, int32_t rmax) attr_pure;
|
|
#define rng_i32_range(rmin, rmax) vrng_i32_range(rng_next(), rmin, rmax)
|
|
|
|
#define vrng_irange(v, rmin, rmax) vrng_i32_range(v, rmin, rmax)
|
|
#define rng_irange(rmin, rmax) vrng_irange(rng_next(), rmin, rmax)
|
|
|
|
double vrng_f64_angle(rng_val_t v) attr_pure;
|
|
#define rng_f64_angle() vrng_f64_angle(rng_next())
|
|
float vrng_f32_angle(rng_val_t v) attr_pure;
|
|
#define rng_f32_angle() vrng_f32_angle(rng_next())
|
|
|
|
#define vrng_angle(v) vrng_f64_angle(v)
|
|
#define rng_angle() vrng_angle(rng_next())
|
|
|
|
cmplx vrng_dir(rng_val_t v) attr_pure;
|
|
#define rng_dir() vrng_dir(rng_next())
|
|
|
|
bool vrng_f64_chance(rng_val_t v, double chance) attr_pure;
|
|
#define rng_f64_chance(chance) vrng_f64_chance(rng_next(), chance)
|
|
bool vrng_f32_chance(rng_val_t v, float chance) attr_pure;
|
|
#define rng_f32_chance(chance) vrng_f32_chance(rng_next(), chance)
|
|
|
|
#define vrng_chance(v, chance) _Generic((chance), \
|
|
float: vrng_f32_chance, \
|
|
default: vrng_f64_chance \
|
|
)(v, chance)
|
|
|
|
#define rng_chance(chance) vrng_chance(rng_next(), chance)
|