/** * @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 (unsigned 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 (unsigned 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 unsigned int lag = 1; const unsigned int mid = 1; const unsigned int size = 4; unsigned int i, j; unsigned 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 = (unsigned int)key_length + 1; } else { count = MIN_LOOP; } r = ini_func1(st[0] ^ st[mid % size] ^ st[(size - 1) % size]); st[mid % size] += r; r += (unsigned int)key_length; st[(mid + lag) % size] += r; st[0] = r; count--; for (i = 1, j = 0; (j < count) && (j < (unsigned int)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); } }