| /** |
| * @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); |
| } |