
9 changed files with 474 additions and 3 deletions
@ -0,0 +1,36 @@
|
||||
/**
|
||||
* Copyright (C) 2015 Kaspar Schleiser <kaspar@schleiser.de> |
||||
* |
||||
* This file is subject to the terms and conditions of the GNU Lesser |
||||
* General Public License v2.1. See the file LICENSE in the top level |
||||
* directory for more details. |
||||
*/ |
||||
|
||||
/**
|
||||
* @ingroup sys_random |
||||
* @{ |
||||
* @file |
||||
* |
||||
* @brief Glue-code for tinymt32 |
||||
* |
||||
* See https://github.com/MersenneTwister-Lab/TinyMT for details.
|
||||
* |
||||
* @author Kaspar Schleiser <kaspar@schleiser.de> |
||||
* @} |
||||
*/ |
||||
|
||||
#include <stdint.h> |
||||
|
||||
#include "tinymt32/tinymt32.h" |
||||
|
||||
static tinymt32_t _random; |
||||
|
||||
void genrand_init(uint32_t seed) |
||||
{ |
||||
tinymt32_init(&_random, seed); |
||||
} |
||||
|
||||
uint32_t genrand_uint32(void) |
||||
{ |
||||
return tinymt32_generate_uint32(&_random); |
||||
} |
@ -0,0 +1,30 @@
|
||||
Copyright (c) 2011, 2013 Mutsuo Saito, Makoto Matsumoto, |
||||
Hiroshima University and The University of Tokyo. |
||||
All rights reserved. |
||||
|
||||
Redistribution and use in source and binary forms, with or without |
||||
modification, are permitted provided that the following conditions are |
||||
met: |
||||
|
||||
* Redistributions of source code must retain the above copyright |
||||
notice, this list of conditions and the following disclaimer. |
||||
* Redistributions in binary form must reproduce the above |
||||
copyright notice, this list of conditions and the following |
||||
disclaimer in the documentation and/or other materials provided |
||||
with the distribution. |
||||
* Neither the name of the Hiroshima University nor the names of |
||||
its contributors may be used to endorse or promote products |
||||
derived from this software without specific prior written |
||||
permission. |
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
@ -0,0 +1,151 @@
|
||||
/**
|
||||
* @file tinymt32.c |
||||
* |
||||
* @brief Tiny Mersenne Twister only 127 bit internal state |
||||
* |
||||
* @author Mutsuo Saito (Hiroshima University) |
||||
* @author Makoto Matsumoto (The 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 "tinymt32.h" |
||||
#define MIN_LOOP 8 |
||||
#define PRE_LOOP 8 |
||||
|
||||
/**
|
||||
* This function represents a function used in the initialization |
||||
* by init_by_array |
||||
* @param x 32-bit integer |
||||
* @return 32-bit integer |
||||
*/ |
||||
static uint32_t ini_func1(uint32_t x) |
||||
{ |
||||
return (x ^ (x >> 27)) * UINT32_C(1664525); |
||||
} |
||||
|
||||
/**
|
||||
* This function represents a function used in the initialization |
||||
* by init_by_array |
||||
* @param x 32-bit integer |
||||
* @return 32-bit integer |
||||
*/ |
||||
static uint32_t ini_func2(uint32_t x) |
||||
{ |
||||
return (x ^ (x >> 27)) * UINT32_C(1566083941); |
||||
} |
||||
|
||||
/**
|
||||
* This function certificate the period of 2^127-1. |
||||
* @param random tinymt state vector. |
||||
*/ |
||||
static void period_certification(tinymt32_t *random) |
||||
{ |
||||
if ((random->status[0] & TINYMT32_MASK) == 0 && |
||||
random->status[1] == 0 && |
||||
random->status[2] == 0 && |
||||
random->status[3] == 0) { |
||||
random->status[0] = 'T'; |
||||
random->status[1] = 'I'; |
||||
random->status[2] = 'N'; |
||||
random->status[3] = 'Y'; |
||||
} |
||||
} |
||||
|
||||
/**
|
||||
* This function initializes the internal state array with a 32-bit |
||||
* unsigned integer seed. |
||||
* @param random tinymt state vector. |
||||
* @param seed a 32-bit unsigned integer used as a seed. |
||||
*/ |
||||
void tinymt32_init(tinymt32_t *random, uint32_t seed) |
||||
{ |
||||
random->status[0] = seed; |
||||
random->status[1] = random->mat1; |
||||
random->status[2] = random->mat2; |
||||
random->status[3] = random->tmat; |
||||
for (int i = 1; i < MIN_LOOP; i++) { |
||||
random->status[i & 3] ^= i + UINT32_C(1812433253) |
||||
* (random->status[(i - 1) & 3] |
||||
^ (random->status[(i - 1) & 3] >> 30)); |
||||
} |
||||
period_certification(random); |
||||
for (int i = 0; i < PRE_LOOP; i++) { |
||||
tinymt32_next_state(random); |
||||
} |
||||
} |
||||
|
||||
/**
|
||||
* This function initializes the internal state array, |
||||
* with an array of 32-bit unsigned integers used as seeds |
||||
* @param random tinymt state vector. |
||||
* @param init_key the array of 32-bit integers, used as a seed. |
||||
* @param key_length the length of init_key. |
||||
*/ |
||||
void tinymt32_init_by_array(tinymt32_t *random, uint32_t init_key[], |
||||
int key_length) |
||||
{ |
||||
const int lag = 1; |
||||
const int mid = 1; |
||||
const int size = 4; |
||||
int i, j; |
||||
int count; |
||||
uint32_t r; |
||||
uint32_t *st = &random->status[0]; |
||||
|
||||
st[0] = 0; |
||||
st[1] = random->mat1; |
||||
st[2] = random->mat2; |
||||
st[3] = random->tmat; |
||||
if (key_length + 1 > MIN_LOOP) { |
||||
count = key_length + 1; |
||||
} |
||||
else { |
||||
count = MIN_LOOP; |
||||
} |
||||
r = ini_func1(st[0] ^ st[mid % size] |
||||
^ st[(size - 1) % size]); |
||||
st[mid % size] += r; |
||||
r += key_length; |
||||
st[(mid + lag) % size] += r; |
||||
st[0] = r; |
||||
count--; |
||||
for (i = 1, j = 0; (j < count) && (j < key_length); j++) { |
||||
r = ini_func1(st[i % size] |
||||
^ st[(i + mid) % size] |
||||
^ st[(i + size - 1) % size]); |
||||
st[(i + mid) % size] += r; |
||||
r += init_key[j] + i; |
||||
st[(i + mid + lag) % size] += r; |
||||
st[i % size] = r; |
||||
i = (i + 1) % size; |
||||
} |
||||
for (; j < count; j++) { |
||||
r = ini_func1(st[i % size] |
||||
^ st[(i + mid) % size] |
||||
^ st[(i + size - 1) % size]); |
||||
st[(i + mid) % size] += r; |
||||
r += i; |
||||
st[(i + mid + lag) % size] += r; |
||||
st[i % size] = r; |
||||
i = (i + 1) % size; |
||||
} |
||||
for (j = 0; j < size; j++) { |
||||
r = ini_func2(st[i % size] |
||||
+ st[(i + mid) % size] |
||||
+ st[(i + size - 1) % size]); |
||||
st[(i + mid) % size] ^= r; |
||||
r -= i; |
||||
st[(i + mid + lag) % size] ^= r; |
||||
st[i % size] = r; |
||||
i = (i + 1) % size; |
||||
} |
||||
period_certification(random); |
||||
for (i = 0; i < PRE_LOOP; i++) { |
||||
tinymt32_next_state(random); |
||||
} |
||||
} |
@ -0,0 +1,233 @@
|
||||
#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 <stdint.h> |
||||
#include <inttypes.h> |
||||
|
||||
#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 |
Loading…
Reference in new issue