#ifndef TINYMT32_H #define TINYMT32_H /** * @file tinymt32.h * * @brief Tiny Mersenne Twister only 127 bit internal state * * @author Mutsuo Saito (Hiroshima University) * @author Makoto Matsumoto (University of Tokyo) * * Copyright (C) 2011 Mutsuo Saito, Makoto Matsumoto, * Hiroshima University and The University of Tokyo. * All rights reserved. * * The 3-clause BSD License is applied to this software, see * LICENSE.txt */ #include #include #define TINYMT32_MEXP 127 #define TINYMT32_SH0 1 #define TINYMT32_SH1 10 #define TINYMT32_SH8 8 #define TINYMT32_MASK UINT32_C(0x7fffffff) #define TINYMT32_MUL (1.0f / 16777216.0f) #ifdef __cplusplus extern "C" { #endif /** * tinymt32 internal state vector and parameters */ struct TINYMT32_T { uint32_t status[4]; uint32_t mat1; uint32_t mat2; uint32_t tmat; }; typedef struct TINYMT32_T tinymt32_t; void tinymt32_init(tinymt32_t *random, uint32_t seed); void tinymt32_init_by_array(tinymt32_t *random, uint32_t init_key[], int key_length); inline static int tinymt32_get_mexp(tinymt32_t *random) { (void) random; return TINYMT32_MEXP; } /** * This function changes internal state of tinymt32. * Users should not call this function directly. * @param random tinymt internal status */ inline static void tinymt32_next_state(tinymt32_t *random) { uint32_t x; uint32_t y; y = random->status[3]; x = (random->status[0] & TINYMT32_MASK) ^ random->status[1] ^ random->status[2]; x ^= (x << TINYMT32_SH0); y ^= (y >> TINYMT32_SH0) ^ x; random->status[0] = random->status[1]; random->status[1] = random->status[2]; random->status[2] = x ^ (y << TINYMT32_SH1); random->status[3] = y; random->status[1] ^= -((int32_t)(y & 1)) & random->mat1; random->status[2] ^= -((int32_t)(y & 1)) & random->mat2; } /** * This function outputs 32-bit unsigned integer from internal state. * Users should not call this function directly. * @param random tinymt internal status * @return 32-bit unsigned pseudorandom number */ inline static uint32_t tinymt32_temper(tinymt32_t *random) { uint32_t t0, t1; t0 = random->status[3]; t1 = random->status[0] + (random->status[2] >> TINYMT32_SH8); t0 ^= t1; t0 ^= -((int32_t)(t1 & 1)) & random->tmat; return t0; } /** * This function outputs floating point number from internal state. * Users should not call this function directly. * @param random tinymt internal status * @return floating point number r (1.0 <= r < 2.0) */ inline static float tinymt32_temper_conv(tinymt32_t *random) { uint32_t t0, t1; union { uint32_t u; float f; } conv; t0 = random->status[3]; t1 = random->status[0] + (random->status[2] >> TINYMT32_SH8); t0 ^= t1; conv.u = ((t0 ^ (-((int32_t)(t1 & 1)) & random->tmat)) >> 9) | UINT32_C(0x3f800000); return conv.f; } /** * This function outputs floating point number from internal state. * Users should not call this function directly. * @param random tinymt internal status * @return floating point number r (1.0 < r < 2.0) */ inline static float tinymt32_temper_conv_open(tinymt32_t *random) { uint32_t t0, t1; union { uint32_t u; float f; } conv; t0 = random->status[3]; t1 = random->status[0] + (random->status[2] >> TINYMT32_SH8); t0 ^= t1; conv.u = ((t0 ^ (-((int32_t)(t1 & 1)) & random->tmat)) >> 9) | UINT32_C(0x3f800001); return conv.f; } /** * This function outputs 32-bit unsigned integer from internal state. * @param random tinymt internal status * @return 32-bit unsigned integer r (0 <= r < 2^32) */ inline static uint32_t tinymt32_generate_uint32(tinymt32_t *random) { tinymt32_next_state(random); return tinymt32_temper(random); } /** * This function outputs floating point number from internal state. * This function is implemented using multiplying by (1 / 2^24). * floating point multiplication is faster than using union trick in * my Intel CPU. * @param random tinymt internal status * @return floating point number r (0.0 <= r < 1.0) */ inline static float tinymt32_generate_float(tinymt32_t *random) { tinymt32_next_state(random); return (tinymt32_temper(random) >> 8) * TINYMT32_MUL; } /** * This function outputs floating point number from internal state. * This function is implemented using union trick. * @param random tinymt internal status * @return floating point number r (1.0 <= r < 2.0) */ inline static float tinymt32_generate_float12(tinymt32_t *random) { tinymt32_next_state(random); return tinymt32_temper_conv(random); } /** * This function outputs floating point number from internal state. * This function is implemented using union trick. * @param random tinymt internal status * @return floating point number r (0.0 <= r < 1.0) */ inline static float tinymt32_generate_float01(tinymt32_t *random) { tinymt32_next_state(random); return tinymt32_temper_conv(random) - 1.0f; } /** * This function outputs floating point number from internal state. * This function may return 1.0 and never returns 0.0. * @param random tinymt internal status * @return floating point number r (0.0 < r <= 1.0) */ inline static float tinymt32_generate_floatOC(tinymt32_t *random) { tinymt32_next_state(random); return 1.0f - tinymt32_generate_float(random); } /** * This function outputs floating point number from internal state. * This function returns neither 0.0 nor 1.0. * @param random tinymt internal status * @return floating point number r (0.0 < r < 1.0) */ inline static float tinymt32_generate_floatOO(tinymt32_t *random) { tinymt32_next_state(random); return tinymt32_temper_conv_open(random) - 1.0f; } /** * This function outputs double precision floating point number from * internal state. The returned value has 32-bit precision. * In other words, this function makes one double precision floating point * number from one 32-bit unsigned integer. * @param random tinymt internal status * @return floating point number r (0.0 < r <= 1.0) */ inline static double tinymt32_generate_32double(tinymt32_t *random) { tinymt32_next_state(random); return tinymt32_temper(random) * (1.0 / 4294967296.0); } #ifdef __cplusplus } #endif #endif