57#include <hdrl_random.h>
65struct hdrl_random_state_{
81static uint32_t hdrl_random_uniform_uint32(hdrl_random_state * rng)
86 uint64_t oldstate = rng->state;
88 rng->state = oldstate * 6364136223846793005ULL + (rng->inc|1);
90 uint32_t xorshifted = ((oldstate >> 18u) ^ oldstate) >> 27u;
91 uint32_t rot = oldstate >> 59u;
92 return (xorshifted >> rot) | (xorshifted << ((-rot) & 31));
108hdrl_random_state * hdrl_random_state_new(
int type, uint64_t * seed)
110 cpl_error_ensure(type == 1, CPL_ERROR_UNSUPPORTED_MODE,
111 return NULL,
"type needs to be 1");
112 hdrl_random_state * state = cpl_calloc(
sizeof(*state), 1);
113 uint64_t s1 = seed ? seed[0] : (uint64_t)rand();
114 uint64_t s2 = seed ? seed[1] : (uint64_t)rand();
117 hdrl_random_uniform_uint32(state);
119 hdrl_random_uniform_uint32(state);
130void hdrl_random_state_delete(hdrl_random_state * state)
135static uint64_t hdrl_random_uniform_uint64_full(hdrl_random_state * state)
137 return ((uint64_t)hdrl_random_uniform_uint32(state) << 32) |
138 (uint64_t)hdrl_random_uniform_uint32(state);
153hdrl_random_uniform_int64(hdrl_random_state * state,
154 int64_t minval, int64_t maxval)
157 if (maxval < minval) {
158 cpl_error_set_message(cpl_func, CPL_ERROR_ILLEGAL_INPUT,
159 "maximum value smaller than minimum value");
162 uint64_t umaxval = (uint64_t)maxval - (uint64_t)minval;
178 res = hdrl_random_uniform_uint64_full(state) & mask;
179 if (res <= umaxval) {
183 return (int64_t)((uint64_t)minval + res);
186static double hdrl_random_uniform_double_one(hdrl_random_state * state)
189 uint64_t a = hdrl_random_uniform_uint32(state) >> 5;
190 uint64_t b = hdrl_random_uniform_uint32(state) >> 6;
191 return (a * 67108864.0 + b) / 9007199254740992.0;
206double hdrl_random_uniform_double(hdrl_random_state * state,
207 double minval,
double maxval)
209 double scale = fabs(maxval - minval);
210 return minval + scale * hdrl_random_uniform_double_one(state);
213static uint64_t hdrl_random_poisson_low(hdrl_random_state * state,
double lam)
215 const double explam = exp(-lam);
216 double prod = hdrl_random_uniform_double_one(state);
219 while (prod > explam) {
221 prod *= hdrl_random_uniform_double_one(state);
232static uint64_t hdrl_random_poisson_ptrs(hdrl_random_state * state,
double lam)
234 const double slam = sqrt(lam);
235 const double loglam = log(lam);
236 const double b = 0.931 + 2.53 * slam;
237 const double a = -0.059 + 0.02483 * b;
238 const double invalpha = 1.1239 + 1.1328 / (b - 3.4);
239 const double vr = 0.9277 - 3.6224 / (b - 2. );
243 double U = hdrl_random_uniform_double_one(state) - 0.5;
244 double V = hdrl_random_uniform_double_one(state);
246 double us = 0.5 - fabs(U);
247 cpl_boolean eval = (us >= 0.07);
249 double aux = 2 * a / us;
250 int64_t k = (long)floor((aux + b) * U + lam + 0.43);
252 if(eval && V <= vr) {
256 if (k < 0 || (us < 0.013 && V > us) ) {
260 double lgamk = lgamma(k + 1);
262 if ((log(V) + log(invalpha) - log(a/(us*us)+b)) <=
263 (-lam + k * loglam - lgamk)) {
279uint64_t hdrl_random_poisson(hdrl_random_state * state,
double lam)
282 return hdrl_random_poisson_ptrs(state, lam);
284 else if (lam == 0.) {
288 cpl_error_set_message(cpl_func, CPL_ERROR_ILLEGAL_INPUT,
289 "lam must not be negative");
293 return hdrl_random_poisson_low(state, lam);
308double hdrl_random_normal(hdrl_random_state * state,
double mean,
double sigma)
311 cpl_error_set_message(cpl_func, CPL_ERROR_ILLEGAL_INPUT,
312 "sigma must not be negative");
315 if (state->has_normal) {
316 state->has_normal = 0;
317 return mean + sigma * state->normal;
323 x1 = 2.0 * hdrl_random_uniform_double_one(state) - 1.0;
324 x2 = 2.0 * hdrl_random_uniform_double_one(state) - 1.0;
325 r = x1 * x1 + x2 * x2;
327 while (r >= 1.0 || r == 0.0);
330 f = sqrt(-2.0*log(r)/r);
332 state->normal = f * x1;
333 state->has_normal = 1;
334 return mean + sigma * f * x2;