aboutsummaryrefslogtreecommitdiff
path: root/src/rnd.c
diff options
context:
space:
mode:
authorDavid Timber <mieabby@gmail.com>2020-01-01 09:50:34 +1100
committerDavid Timber <mieabby@gmail.com>2020-01-01 09:50:34 +1100
commited809a51fdd1c313cd256301ef6f7211e8394cb1 (patch)
tree81a3054ce0d42976f80c973e2b6ebf9c1b8b7476 /src/rnd.c
parent6e456edb2757cf9d28d306afb836aa16780fb912 (diff)
checkpoint
Diffstat (limited to 'src/rnd.c')
-rw-r--r--src/rnd.c93
1 files changed, 93 insertions, 0 deletions
diff --git a/src/rnd.c b/src/rnd.c
new file mode 100644
index 0000000..8fff675
--- /dev/null
+++ b/src/rnd.c
@@ -0,0 +1,93 @@
+#include "rnd.h"
+
+#include <stdlib.h>
+
+#define N ((size_t)624)
+
+
+struct prne_rnd_engine {
+ size_t mti;
+ uint32_t mt[N];
+};
+
+
+void prne_init_alloc_rnd_engine_result (prne_rnd_engnie_alloc_result_t *r) {
+ r->engine = NULL;
+ r->result = PRNE_RND_ENGINE_ALLOC_OK;
+}
+
+prne_rnd_engnie_alloc_result_t prne_alloc_rnd_engine (const uint32_t *s) {
+ prne_rnd_engnie_alloc_result_t ret;
+ uint32_t seed;
+
+ prne_init_alloc_rnd_engine_result(&ret);
+
+ if (s == NULL) {
+ seed = 4357;
+ }
+ else {
+ if (*s == 0) {
+ ret.result = PRNE_RND_ENGINE_ALLOC_INVALID_SEED;
+ return ret;
+ }
+ seed = *s;
+ }
+
+ ret.engine = (prne_rnd_engine_t*)malloc(sizeof(prne_rnd_engine_t));
+ if (ret.engine == NULL) {
+ ret.result = PRNE_RND_ENGINE_ALLOC_MEM_ERR;
+ return ret;
+ }
+
+ ret.engine->mt[0] = seed;
+ for (ret.engine->mti = 1; ret.engine->mti < N; ret.engine->mti += 1) {
+ ret.engine->mt[ret.engine->mti] = 69069 * ret.engine->mt[ret.engine->mti - 1];
+ }
+
+ return ret;
+}
+
+void prne_free_rnd_engine (prne_rnd_engine_t *engine) {
+ free(engine);
+}
+
+uint32_t prne_rnd_gen_int (prne_rnd_engine_t *engine) {
+ static const size_t M = 397;
+ static const uint32_t
+ UPPER_MASK = 0x80000000,
+ LOWER_MASK = 0x7fffffff,
+ TEMPERING_MASK_B = 0x9d2c5680,
+ TEMPERING_MASK_C = 0xefc60000;
+ static const uint32_t mag01[2] = {0, 0x9908b0df};
+ uint32_t y;
+
+ if (engine->mti >= N) {
+ size_t kk;
+
+ for (kk = 0; kk < N - M; kk += 1) {
+ y = (engine->mt[kk] & UPPER_MASK) | (engine->mt[kk + 1] & LOWER_MASK);
+ engine->mt[kk] = engine->mt[kk + M] ^ (y >> 1) ^ mag01[y & 1];
+ }
+ for (; kk < N - 1; kk += 1) {
+ y = (engine->mt[kk] & UPPER_MASK) | (engine->mt[kk + 1] & LOWER_MASK);
+ engine->mt[kk] = engine->mt[kk + (M - N)] ^ (y >> 1) ^ mag01[y & 1];
+ }
+ y = (engine->mt[N - 1] & UPPER_MASK) | (engine->mt[0] & LOWER_MASK);
+ engine->mt[N - 1] = engine->mt[M - 1] ^ (y >> 1) ^ mag01[y & 1];
+
+ engine->mti = 0;
+ }
+
+ y = engine->mt[engine->mti];
+ engine->mti += 1;
+ y ^= y >> 11;
+ y ^= (y << 7) & TEMPERING_MASK_B;
+ y ^= (y << 15) & TEMPERING_MASK_C;
+ y ^= y >> 18;
+
+ return y;
+}
+
+double prne_rnd_gen_double (prne_rnd_engine_t *engine) {
+ return (double)prne_rnd_gen_int(engine) * 2.3283064370807974e-10;
+}