summaryrefslogtreecommitdiffstats
path: root/src/civetweb/src/third_party/duktape-1.5.2/src-separate/duk_util_tinyrandom.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/civetweb/src/third_party/duktape-1.5.2/src-separate/duk_util_tinyrandom.c')
-rw-r--r--src/civetweb/src/third_party/duktape-1.5.2/src-separate/duk_util_tinyrandom.c63
1 files changed, 63 insertions, 0 deletions
diff --git a/src/civetweb/src/third_party/duktape-1.5.2/src-separate/duk_util_tinyrandom.c b/src/civetweb/src/third_party/duktape-1.5.2/src-separate/duk_util_tinyrandom.c
new file mode 100644
index 000000000..99e4223c5
--- /dev/null
+++ b/src/civetweb/src/third_party/duktape-1.5.2/src-separate/duk_util_tinyrandom.c
@@ -0,0 +1,63 @@
+/*
+ * 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;
+}