| /* |
| * A tiny random number generator. |
| * |
| * Currently used for Math.random(). |
| * |
| * http://www.woodmann.com/forum/archive/index.php/t-3100.html |
| */ |
| |
| #include "duk_internal.h" |
| |
| #define DUK__UPDATE_RND(rnd) do { \ |
| (rnd) += ((rnd) * (rnd)) | 0x05; \ |
| (rnd) = ((rnd) & 0xffffffffU); /* if duk_uint32_t is exactly 32 bits, this is a NOP */ \ |
| } while (0) |
| |
| #define DUK__RND_BIT(rnd) ((rnd) >> 31) /* only use the highest bit */ |
| |
| DUK_INTERNAL duk_uint32_t duk_util_tinyrandom_get_bits(duk_hthread *thr, duk_small_int_t n) { |
| duk_small_int_t i; |
| duk_uint32_t res = 0; |
| duk_uint32_t rnd; |
| |
| rnd = thr->heap->rnd_state; |
| |
| for (i = 0; i < n; i++) { |
| DUK__UPDATE_RND(rnd); |
| res <<= 1; |
| res += DUK__RND_BIT(rnd); |
| } |
| |
| thr->heap->rnd_state = rnd; |
| |
| return res; |
| } |
| |
| DUK_INTERNAL duk_double_t duk_util_tinyrandom_get_double(duk_hthread *thr) { |
| duk_double_t t; |
| duk_small_int_t n; |
| duk_uint32_t rnd; |
| |
| /* |
| * XXX: could make this a lot faster if we create the double memory |
| * representation directly. Feasible easily (must be uniform random). |
| */ |
| |
| rnd = thr->heap->rnd_state; |
| |
| n = 53; /* enough to cover the whole mantissa */ |
| t = 0.0; |
| |
| do { |
| DUK__UPDATE_RND(rnd); |
| t += DUK__RND_BIT(rnd); |
| t /= 2.0; |
| } while (--n); |
| |
| thr->heap->rnd_state = rnd; |
| |
| DUK_ASSERT(t >= (duk_double_t) 0.0); |
| DUK_ASSERT(t < (duk_double_t) 1.0); |
| |
| return t; |
| } |