dbf-halloween2015

annotate src/rng.cc @ 0:50683c78264e

initial commit
author John Tsiombikas <nuclear@member.fsf.org>
date Sun, 01 Nov 2015 00:09:12 +0200
parents
children
rev   line source
nuclear@0 1 #include <stdlib.h>
nuclear@0 2 #include <string.h>
nuclear@0 3 #include "rng.h"
nuclear@0 4
nuclear@0 5 //#define USE_STD_RAND
nuclear@0 6
nuclear@0 7 // defined at the end
nuclear@0 8 /**
nuclear@0 9 * tinymt32 internal state vector and parameters
nuclear@0 10 */
nuclear@0 11 struct tinymt32_t {
nuclear@0 12 uint32_t status[4];
nuclear@0 13 uint32_t mat1;
nuclear@0 14 uint32_t mat2;
nuclear@0 15 uint32_t tmat;
nuclear@0 16 };
nuclear@0 17
nuclear@0 18 #ifndef USE_STD_RAND
nuclear@0 19 static void tinymt32_init(tinymt32_t * random, uint32_t seed);
nuclear@0 20 inline static uint32_t tinymt32_generate_uint32(tinymt32_t * random);
nuclear@0 21 inline static float tinymt32_generate_float(tinymt32_t * random);
nuclear@0 22 #endif
nuclear@0 23
nuclear@0 24 static RandGen defrng;
nuclear@0 25
nuclear@0 26 struct RandGenState {
nuclear@0 27 tinymt32_t st;
nuclear@0 28 };
nuclear@0 29
nuclear@0 30 RandGen::RandGen()
nuclear@0 31 {
nuclear@0 32 state = new RandGenState;
nuclear@0 33 memset(state, 0, sizeof *state);
nuclear@0 34 #ifndef USE_STD_RAND
nuclear@0 35 tinymt32_init(&state->st, 0);
nuclear@0 36 #endif
nuclear@0 37 }
nuclear@0 38
nuclear@0 39 RandGen::~RandGen()
nuclear@0 40 {
nuclear@0 41 delete state;
nuclear@0 42 }
nuclear@0 43
nuclear@0 44 void RandGen::seed(uint32_t s)
nuclear@0 45 {
nuclear@0 46 #ifndef USE_STD_RAND
nuclear@0 47 tinymt32_init(&state->st, s);
nuclear@0 48 #else
nuclear@0 49 srand(s);
nuclear@0 50 #endif
nuclear@0 51 }
nuclear@0 52
nuclear@0 53 uint32_t RandGen::generate()
nuclear@0 54 {
nuclear@0 55 #ifndef USE_STD_RAND
nuclear@0 56 return tinymt32_generate_uint32(&state->st);
nuclear@0 57 #else
nuclear@0 58 return rand();
nuclear@0 59 #endif
nuclear@0 60 }
nuclear@0 61
nuclear@0 62 float RandGen::generate_float()
nuclear@0 63 {
nuclear@0 64 #ifndef USE_STD_RAND
nuclear@0 65 return tinymt32_generate_float(&state->st);
nuclear@0 66 #else
nuclear@0 67 return (float)rand() / (float)RAND_MAX;
nuclear@0 68 #endif
nuclear@0 69 }
nuclear@0 70
nuclear@0 71 void rng_srand(uint32_t s)
nuclear@0 72 {
nuclear@0 73 defrng.seed(s);
nuclear@0 74 }
nuclear@0 75
nuclear@0 76 uint32_t rng_rand()
nuclear@0 77 {
nuclear@0 78 return defrng.generate();
nuclear@0 79 }
nuclear@0 80
nuclear@0 81 float rng_frand()
nuclear@0 82 {
nuclear@0 83 return defrng.generate_float();
nuclear@0 84 }
nuclear@0 85
nuclear@0 86
nuclear@0 87 #ifndef USE_STD_RAND
nuclear@0 88 /**
nuclear@0 89 * @file tinymt32.h
nuclear@0 90 *
nuclear@0 91 * @brief Tiny Mersenne Twister only 127 bit internal state
nuclear@0 92 *
nuclear@0 93 * @author Mutsuo Saito (Hiroshima University)
nuclear@0 94 * @author Makoto Matsumoto (University of Tokyo)
nuclear@0 95 *
nuclear@0 96 * Copyright (C) 2011 Mutsuo Saito, Makoto Matsumoto,
nuclear@0 97 * Hiroshima University and The University of Tokyo.
nuclear@0 98 * All rights reserved.
nuclear@0 99 *
nuclear@0 100 * The 3-clause BSD License is applied to this software, see
nuclear@0 101 * LICENSE.txt
nuclear@0 102 */
nuclear@0 103 #define TINYMT32_MEXP 127
nuclear@0 104 #define TINYMT32_SH0 1
nuclear@0 105 #define TINYMT32_SH1 10
nuclear@0 106 #define TINYMT32_SH8 8
nuclear@0 107 #define TINYMT32_MASK UINT32_C(0x7fffffff)
nuclear@0 108 #define TINYMT32_MUL (1.0f / 4294967296.0f)
nuclear@0 109
nuclear@0 110 /**
nuclear@0 111 * This function changes internal state of tinymt32.
nuclear@0 112 * Users should not call this function directly.
nuclear@0 113 * @param random tinymt internal status
nuclear@0 114 */
nuclear@0 115 inline static void tinymt32_next_state(tinymt32_t * random) {
nuclear@0 116 uint32_t x;
nuclear@0 117 uint32_t y;
nuclear@0 118
nuclear@0 119 y = random->status[3];
nuclear@0 120 x = (random->status[0] & TINYMT32_MASK)
nuclear@0 121 ^ random->status[1]
nuclear@0 122 ^ random->status[2];
nuclear@0 123 x ^= (x << TINYMT32_SH0);
nuclear@0 124 y ^= (y >> TINYMT32_SH0) ^ x;
nuclear@0 125 random->status[0] = random->status[1];
nuclear@0 126 random->status[1] = random->status[2];
nuclear@0 127 random->status[2] = x ^ (y << TINYMT32_SH1);
nuclear@0 128 random->status[3] = y;
nuclear@0 129 random->status[1] ^= -((int32_t)(y & 1)) & random->mat1;
nuclear@0 130 random->status[2] ^= -((int32_t)(y & 1)) & random->mat2;
nuclear@0 131 }
nuclear@0 132
nuclear@0 133 /**
nuclear@0 134 * This function outputs 32-bit unsigned integer from internal state.
nuclear@0 135 * Users should not call this function directly.
nuclear@0 136 * @param random tinymt internal status
nuclear@0 137 * @return 32-bit unsigned pseudorandom number
nuclear@0 138 */
nuclear@0 139 inline static uint32_t tinymt32_temper(tinymt32_t * random) {
nuclear@0 140 uint32_t t0, t1;
nuclear@0 141 t0 = random->status[3];
nuclear@0 142 #if defined(LINEARITY_CHECK)
nuclear@0 143 t1 = random->status[0]
nuclear@0 144 ^ (random->status[2] >> TINYMT32_SH8);
nuclear@0 145 #else
nuclear@0 146 t1 = random->status[0]
nuclear@0 147 + (random->status[2] >> TINYMT32_SH8);
nuclear@0 148 #endif
nuclear@0 149 t0 ^= t1;
nuclear@0 150 t0 ^= -((int32_t)(t1 & 1)) & random->tmat;
nuclear@0 151 return t0;
nuclear@0 152 }
nuclear@0 153
nuclear@0 154 /**
nuclear@0 155 * This function outputs 32-bit unsigned integer from internal state.
nuclear@0 156 * @param random tinymt internal status
nuclear@0 157 * @return 32-bit unsigned integer r (0 <= r < 2^32)
nuclear@0 158 */
nuclear@0 159 inline static uint32_t tinymt32_generate_uint32(tinymt32_t * random) {
nuclear@0 160 tinymt32_next_state(random);
nuclear@0 161 return tinymt32_temper(random);
nuclear@0 162 }
nuclear@0 163
nuclear@0 164 /**
nuclear@0 165 * This function outputs floating point number from internal state.
nuclear@0 166 * This function is implemented using multiplying by 1 / 2^32.
nuclear@0 167 * floating point multiplication is faster than using union trick in
nuclear@0 168 * my Intel CPU.
nuclear@0 169 * @param random tinymt internal status
nuclear@0 170 * @return floating point number r (0.0 <= r < 1.0)
nuclear@0 171 */
nuclear@0 172 inline static float tinymt32_generate_float(tinymt32_t * random) {
nuclear@0 173 tinymt32_next_state(random);
nuclear@0 174 return tinymt32_temper(random) * TINYMT32_MUL;
nuclear@0 175 }
nuclear@0 176
nuclear@0 177 #define MIN_LOOP 8
nuclear@0 178 #define PRE_LOOP 8
nuclear@0 179
nuclear@0 180 /**
nuclear@0 181 * This function certificate the period of 2^127-1.
nuclear@0 182 * @param random tinymt state vector.
nuclear@0 183 */
nuclear@0 184 static void period_certification(tinymt32_t * random) {
nuclear@0 185 if ((random->status[0] & TINYMT32_MASK) == 0 &&
nuclear@0 186 random->status[1] == 0 &&
nuclear@0 187 random->status[2] == 0 &&
nuclear@0 188 random->status[3] == 0) {
nuclear@0 189 random->status[0] = 'T';
nuclear@0 190 random->status[1] = 'I';
nuclear@0 191 random->status[2] = 'N';
nuclear@0 192 random->status[3] = 'Y';
nuclear@0 193 }
nuclear@0 194 }
nuclear@0 195
nuclear@0 196 /**
nuclear@0 197 * This function initializes the internal state array with a 32-bit
nuclear@0 198 * unsigned integer seed.
nuclear@0 199 * @param random tinymt state vector.
nuclear@0 200 * @param seed a 32-bit unsigned integer used as a seed.
nuclear@0 201 */
nuclear@0 202 static void tinymt32_init(tinymt32_t * random, uint32_t seed) {
nuclear@0 203 random->status[0] = seed;
nuclear@0 204 random->status[1] = random->mat1;
nuclear@0 205 random->status[2] = random->mat2;
nuclear@0 206 random->status[3] = random->tmat;
nuclear@0 207 for (int i = 1; i < MIN_LOOP; i++) {
nuclear@0 208 random->status[i & 3] ^= i + UINT32_C(1812433253)
nuclear@0 209 * (random->status[(i - 1) & 3]
nuclear@0 210 ^ (random->status[(i - 1) & 3] >> 30));
nuclear@0 211 }
nuclear@0 212 period_certification(random);
nuclear@0 213 for (int i = 0; i < PRE_LOOP; i++) {
nuclear@0 214 tinymt32_next_state(random);
nuclear@0 215 }
nuclear@0 216 }
nuclear@0 217 #endif // !defined(USE_STD_RAND)