/** * @file tinymt64.c * * @brief 64-bit 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 "tinymt64.h" #define MIN_LOOP 8 /** * This function represents a function used in the initialization * by init_by_array * @param[in] x 64-bit integer * @return 64-bit integer */ static uint64_t ini_func1(uint64_t x) { return (x ^ (x >> 59)) * UINT64_C(2173292883993); } /** * This function represents a function used in the initialization * by init_by_array * @param[in] x 64-bit integer * @return 64-bit integer */ static uint64_t ini_func2(uint64_t x) { return (x ^ (x >> 59)) * UINT64_C(58885565329898161); } /** * This function certificate the period of 2^127-1. * @param random tinymt state vector. */ static void period_certification(tinymt64_t * random) { if ((random->status[0] & TINYMT64_MASK) == 0 && random->status[1] == 0) { random->status[0] = 'T'; random->status[1] = 'M'; } } /** * This function initializes the internal state array with a 64-bit * unsigned integer seed. * @param random tinymt state vector. * @param seed a 64-bit unsigned integer used as a seed. */ void tinymt64_init(tinymt64_t * random, uint64_t seed) { random->status[0] = seed ^ ((uint64_t)random->mat1 << 32); random->status[1] = random->mat2 ^ random->tmat; for (int i = 1; i < MIN_LOOP; i++) { random->status[i & 1] ^= i + UINT64_C(6364136223846793005) * (random->status[(i - 1) & 1] ^ (random->status[(i - 1) & 1] >> 62)); } period_certification(random); } /** * This function initializes the internal state array, * with an array of 64-bit unsigned integers used as seeds * @param random tinymt state vector. * @param init_key the array of 64-bit integers, used as a seed. * @param key_length the length of init_key. */ void tinymt64_init_by_array(tinymt64_t * random, const uint64_t init_key[], int key_length) { const int lag = 1; const int mid = 1; const int size = 4; int i, j; int count; uint64_t r; uint64_t st[4]; 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] ^ 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] = r; i = (i + 1) % size; } for (; j < count; j++) { r = ini_func1(st[i] ^ st[(i + mid) % size] ^ st[(i + size - 1) % size]); st[(i + mid) % size] += r; r += i; st[(i + mid + lag) % size] += r; st[i] = r; i = (i + 1) % size; } for (j = 0; j < size; j++) { r = ini_func2(st[i] + st[(i + mid) % size] + st[(i + size - 1) % size]); st[(i + mid) % size] ^= r; r -= i; st[(i + mid + lag) % size] ^= r; st[i] = r; i = (i + 1) % size; } random->status[0] = st[0] ^ st[1]; random->status[1] = st[2] ^ st[3]; period_certification(random); }