[4019] | 1 | #ifndef TINYMT32_H
|
---|
| 2 | #define TINYMT32_H
|
---|
| 3 | /**
|
---|
| 4 | * @file tinymt32.h
|
---|
| 5 | *
|
---|
| 6 | * @brief Tiny Mersenne Twister only 127 bit internal state
|
---|
| 7 | *
|
---|
| 8 | * @author Mutsuo Saito (Hiroshima University)
|
---|
| 9 | * @author Makoto Matsumoto (University of Tokyo)
|
---|
| 10 | *
|
---|
| 11 | * Copyright (C) 2011 Mutsuo Saito, Makoto Matsumoto,
|
---|
| 12 | * Hiroshima University and The University of Tokyo.
|
---|
| 13 | * All rights reserved.
|
---|
| 14 | *
|
---|
| 15 | * The 3-clause BSD License is applied to this software, see
|
---|
| 16 | * LICENSE.txt
|
---|
| 17 | */
|
---|
| 18 |
|
---|
| 19 | #include <stdint.h>
|
---|
| 20 | #include <inttypes.h>
|
---|
| 21 |
|
---|
| 22 | #define TINYMT32_MEXP 127
|
---|
| 23 | #define TINYMT32_SH0 1
|
---|
| 24 | #define TINYMT32_SH1 10
|
---|
| 25 | #define TINYMT32_SH8 8
|
---|
| 26 | #define TINYMT32_MASK UINT32_C(0x7fffffff)
|
---|
| 27 | #define TINYMT32_MUL (1.0f / 4294967296.0f)
|
---|
| 28 |
|
---|
| 29 | /**
|
---|
| 30 | * tinymt32 internal state vector and parameters
|
---|
| 31 | */
|
---|
| 32 | struct TINYMT32_T {
|
---|
| 33 | uint32_t status[4];
|
---|
| 34 | uint32_t mat1;
|
---|
| 35 | uint32_t mat2;
|
---|
| 36 | uint32_t tmat;
|
---|
| 37 | };
|
---|
| 38 |
|
---|
| 39 | typedef struct TINYMT32_T tinymt32_t;
|
---|
| 40 |
|
---|
| 41 | /* --- Ajout par cmv / Compilation C++ --- */
|
---|
| 42 | #ifdef __cplusplus
|
---|
| 43 | extern "C" {
|
---|
| 44 | #endif
|
---|
| 45 |
|
---|
| 46 | void tinymt32_init(tinymt32_t * random, uint32_t seed);
|
---|
| 47 | void tinymt32_init_by_array(tinymt32_t * random, uint32_t init_key[],
|
---|
| 48 | int key_length);
|
---|
| 49 |
|
---|
| 50 | /* --- Ajout par cmv / Compilation C++ --- */
|
---|
| 51 | #ifdef __cplusplus
|
---|
| 52 | }
|
---|
| 53 | #endif
|
---|
| 54 |
|
---|
| 55 | #if defined(__GNUC__)
|
---|
| 56 | /**
|
---|
| 57 | * This function always returns 127
|
---|
| 58 | * @param random not used
|
---|
| 59 | * @return always 127
|
---|
| 60 | */
|
---|
| 61 | inline static int tinymt32_get_mexp(
|
---|
| 62 | tinymt32_t * random __attribute__((unused))) {
|
---|
| 63 | return TINYMT32_MEXP;
|
---|
| 64 | }
|
---|
| 65 | #else
|
---|
| 66 | inline static int tinymt32_get_mexp(tinymt32_t * random) {
|
---|
| 67 | return TINYMT32_MEXP;
|
---|
| 68 | }
|
---|
| 69 | #endif
|
---|
| 70 |
|
---|
| 71 | /**
|
---|
| 72 | * This function changes internal state of tinymt32.
|
---|
| 73 | * Users should not call this function directly.
|
---|
| 74 | * @param random tinymt internal status
|
---|
| 75 | */
|
---|
| 76 | inline static void tinymt32_next_state(tinymt32_t * random) {
|
---|
| 77 | uint32_t x;
|
---|
| 78 | uint32_t y;
|
---|
| 79 |
|
---|
| 80 | y = random->status[3];
|
---|
| 81 | x = (random->status[0] & TINYMT32_MASK)
|
---|
| 82 | ^ random->status[1]
|
---|
| 83 | ^ random->status[2];
|
---|
| 84 | x ^= (x << TINYMT32_SH0);
|
---|
| 85 | y ^= (y >> TINYMT32_SH0) ^ x;
|
---|
| 86 | random->status[0] = random->status[1];
|
---|
| 87 | random->status[1] = random->status[2];
|
---|
| 88 | random->status[2] = x ^ (y << TINYMT32_SH1);
|
---|
| 89 | random->status[3] = y;
|
---|
| 90 | random->status[1] ^= -((int32_t)(y & 1)) & random->mat1;
|
---|
| 91 | random->status[2] ^= -((int32_t)(y & 1)) & random->mat2;
|
---|
| 92 | }
|
---|
| 93 |
|
---|
| 94 | /**
|
---|
| 95 | * This function outputs 32-bit unsigned integer from internal state.
|
---|
| 96 | * Users should not call this function directly.
|
---|
| 97 | * @param random tinymt internal status
|
---|
| 98 | * @return 32-bit unsigned pseudorandom number
|
---|
| 99 | */
|
---|
| 100 | inline static uint32_t tinymt32_temper(tinymt32_t * random) {
|
---|
| 101 | uint32_t t0, t1;
|
---|
| 102 | t0 = random->status[3];
|
---|
| 103 | #if defined(LINEARITY_CHECK)
|
---|
| 104 | t1 = random->status[0]
|
---|
| 105 | ^ (random->status[2] >> TINYMT32_SH8);
|
---|
| 106 | #else
|
---|
| 107 | t1 = random->status[0]
|
---|
| 108 | + (random->status[2] >> TINYMT32_SH8);
|
---|
| 109 | #endif
|
---|
| 110 | t0 ^= t1;
|
---|
| 111 | t0 ^= -((int32_t)(t1 & 1)) & random->tmat;
|
---|
| 112 | return t0;
|
---|
| 113 | }
|
---|
| 114 |
|
---|
| 115 | /**
|
---|
| 116 | * This function outputs floating point number from internal state.
|
---|
| 117 | * Users should not call this function directly.
|
---|
| 118 | * @param random tinymt internal status
|
---|
| 119 | * @return floating point number r (1.0 <= r < 2.0)
|
---|
| 120 | */
|
---|
| 121 | inline static float tinymt32_temper_conv(tinymt32_t * random) {
|
---|
| 122 | uint32_t t0, t1;
|
---|
| 123 | union {
|
---|
| 124 | uint32_t u;
|
---|
| 125 | float f;
|
---|
| 126 | } conv;
|
---|
| 127 |
|
---|
| 128 | t0 = random->status[3];
|
---|
| 129 | #if defined(LINEARITY_CHECK)
|
---|
| 130 | t1 = random->status[0]
|
---|
| 131 | ^ (random->status[2] >> TINYMT32_SH8);
|
---|
| 132 | #else
|
---|
| 133 | t1 = random->status[0]
|
---|
| 134 | + (random->status[2] >> TINYMT32_SH8);
|
---|
| 135 | #endif
|
---|
| 136 | t0 ^= t1;
|
---|
| 137 | conv.u = ((t0 ^ (-((int32_t)(t1 & 1)) & random->tmat)) >> 9)
|
---|
| 138 | | UINT32_C(0x3f800000);
|
---|
| 139 | return conv.f;
|
---|
| 140 | }
|
---|
| 141 |
|
---|
| 142 | /**
|
---|
| 143 | * This function outputs floating point number from internal state.
|
---|
| 144 | * Users should not call this function directly.
|
---|
| 145 | * @param random tinymt internal status
|
---|
| 146 | * @return floating point number r (1.0 < r < 2.0)
|
---|
| 147 | */
|
---|
| 148 | inline static float tinymt32_temper_conv_open(tinymt32_t * random) {
|
---|
| 149 | uint32_t t0, t1;
|
---|
| 150 | union {
|
---|
| 151 | uint32_t u;
|
---|
| 152 | float f;
|
---|
| 153 | } conv;
|
---|
| 154 |
|
---|
| 155 | t0 = random->status[3];
|
---|
| 156 | #if defined(LINEARITY_CHECK)
|
---|
| 157 | t1 = random->status[0]
|
---|
| 158 | ^ (random->status[2] >> TINYMT32_SH8);
|
---|
| 159 | #else
|
---|
| 160 | t1 = random->status[0]
|
---|
| 161 | + (random->status[2] >> TINYMT32_SH8);
|
---|
| 162 | #endif
|
---|
| 163 | t0 ^= t1;
|
---|
| 164 | conv.u = ((t0 ^ (-((int32_t)(t1 & 1)) & random->tmat)) >> 9)
|
---|
| 165 | | UINT32_C(0x3f800001);
|
---|
| 166 | return conv.f;
|
---|
| 167 | }
|
---|
| 168 |
|
---|
| 169 | /**
|
---|
| 170 | * This function outputs 32-bit unsigned integer from internal state.
|
---|
| 171 | * @param random tinymt internal status
|
---|
| 172 | * @return 32-bit unsigned integer r (0 <= r < 2^32)
|
---|
| 173 | */
|
---|
| 174 | inline static uint32_t tinymt32_generate_uint32(tinymt32_t * random) {
|
---|
| 175 | tinymt32_next_state(random);
|
---|
| 176 | return tinymt32_temper(random);
|
---|
| 177 | }
|
---|
| 178 |
|
---|
| 179 | /**
|
---|
| 180 | * This function outputs floating point number from internal state.
|
---|
| 181 | * This function is implemented using multiplying by 1 / 2^32.
|
---|
| 182 | * floating point multiplication is faster than using union trick in
|
---|
| 183 | * my Intel CPU.
|
---|
| 184 | * @param random tinymt internal status
|
---|
| 185 | * @return floating point number r (0.0 <= r < 1.0)
|
---|
| 186 | */
|
---|
| 187 | inline static float tinymt32_generate_float(tinymt32_t * random) {
|
---|
| 188 | tinymt32_next_state(random);
|
---|
| 189 | return tinymt32_temper(random) * TINYMT32_MUL;
|
---|
| 190 | }
|
---|
| 191 |
|
---|
| 192 | /**
|
---|
| 193 | * This function outputs floating point number from internal state.
|
---|
| 194 | * This function is implemented using union trick.
|
---|
| 195 | * @param random tinymt internal status
|
---|
| 196 | * @return floating point number r (1.0 <= r < 2.0)
|
---|
| 197 | */
|
---|
| 198 | inline static float tinymt32_generate_float12(tinymt32_t * random) {
|
---|
| 199 | tinymt32_next_state(random);
|
---|
| 200 | return tinymt32_temper_conv(random);
|
---|
| 201 | }
|
---|
| 202 |
|
---|
| 203 | /**
|
---|
| 204 | * This function outputs floating point number from internal state.
|
---|
| 205 | * This function is implemented using union trick.
|
---|
| 206 | * @param random tinymt internal status
|
---|
| 207 | * @return floating point number r (0.0 <= r < 1.0)
|
---|
| 208 | */
|
---|
| 209 | inline static float tinymt32_generate_float01(tinymt32_t * random) {
|
---|
| 210 | tinymt32_next_state(random);
|
---|
| 211 | return tinymt32_temper_conv(random) - 1.0f;
|
---|
| 212 | }
|
---|
| 213 |
|
---|
| 214 | /**
|
---|
| 215 | * This function outputs floating point number from internal state.
|
---|
| 216 | * This function may return 1.0 and never returns 0.0.
|
---|
| 217 | * @param random tinymt internal status
|
---|
| 218 | * @return floating point number r (0.0 < r <= 1.0)
|
---|
| 219 | */
|
---|
| 220 | inline static float tinymt32_generate_floatOC(tinymt32_t * random) {
|
---|
| 221 | tinymt32_next_state(random);
|
---|
| 222 | return 1.0f - tinymt32_generate_float(random);
|
---|
| 223 | }
|
---|
| 224 |
|
---|
| 225 | /**
|
---|
| 226 | * This function outputs floating point number from internal state.
|
---|
| 227 | * This function returns neither 0.0 nor 1.0.
|
---|
| 228 | * @param random tinymt internal status
|
---|
| 229 | * @return floating point number r (0.0 < r < 0.0)
|
---|
| 230 | */
|
---|
| 231 | inline static float tinymt32_generate_floatOO(tinymt32_t * random) {
|
---|
| 232 | tinymt32_next_state(random);
|
---|
| 233 | return tinymt32_temper_conv_open(random) - 1.0f;
|
---|
| 234 | }
|
---|
| 235 |
|
---|
| 236 | /**
|
---|
| 237 | * This function outputs double precision floating point number from
|
---|
| 238 | * internal state. The returned value has 32-bit precision.
|
---|
| 239 | * In other words, this function makes one double precision floating point
|
---|
| 240 | * number from one 32-bit unsigned integer.
|
---|
| 241 | * @param random tinymt internal status
|
---|
| 242 | * @return floating point number r (1.0 < r < 2.0)
|
---|
| 243 | */
|
---|
| 244 | inline static double tinymt32_generate_32double(tinymt32_t * random) {
|
---|
| 245 | tinymt32_next_state(random);
|
---|
| 246 | return tinymt32_temper(random) * (1.0 / 4294967296.0);
|
---|
| 247 | }
|
---|
| 248 | #endif
|
---|