1/** 2 * @file tinymt32.c 3 * 4 * @brief Tiny Mersenne Twister only 127 bit internal state 5 * 6 * @author Mutsuo Saito (Hiroshima University) 7 * @author Makoto Matsumoto (The University of Tokyo) 8 * 9 * Copyright (C) 2011 Mutsuo Saito, Makoto Matsumoto, 10 * Hiroshima University and The University of Tokyo. 11 * All rights reserved. 12 * 13 * The 3-clause BSD License is applied to this software, see 14 * LICENSE.txt 15 * 16 * $Id:: tinymt32.c 1306 2012-06-21 14:10:10Z jeung $: 17 * $Rev::file = 1306 : Global SVN Revision = 1306 $: 18 * 19 */ 20 21/* FILE-CSTYLED */ 22 23#include <tinymt32.h> 24 25#define MIN_LOOP 8 26#define PRE_LOOP 8 27 28/** 29 * This function represents a function used in the initialization 30 * by init_by_array 31 * @param x 32-bit integer 32 * @return 32-bit integer 33 */ 34static uint32_t ini_func1(uint32_t x) { 35 return (x ^ (x >> 27)) * (uint32_t)1664525UL; 36} 37 38/** 39 * This function represents a function used in the initialization 40 * by init_by_array 41 * @param x 32-bit integer 42 * @return 32-bit integer 43 */ 44static uint32_t ini_func2(uint32_t x) { 45 return (x ^ (x >> 27)) * (uint32_t)1566083941UL; 46} 47 48/** 49 * This function certificate the period of 2^127-1. 50 * @param random tinymt state vector. 51 */ 52static void period_certification(tinymt32_t * random) { 53 if ((random->status[0] & TINYMT32_MASK) == 0 && 54 random->status[1] == 0 && 55 random->status[2] == 0 && 56 random->status[3] == 0) { 57 random->status[0] = 'T'; 58 random->status[1] = 'I'; 59 random->status[2] = 'N'; 60 random->status[3] = 'Y'; 61 } 62} 63 64/** 65 * This function initializes the internal state array with a 32-bit 66 * unsigned integer seed. 67 * @param random tinymt state vector. 68 * @param seed a 32-bit unsigned integer used as a seed. 69 */ 70void tinymt32_init(tinymt32_t * random, uint32_t seed) { 71 int i; 72 random->status[0] = seed; 73 random->status[1] = random->mat1; 74 random->status[2] = random->mat2; 75 random->status[3] = random->tmat; 76 for ( i = 1; i < MIN_LOOP; i++) { 77 random->status[i & 3] ^= i + UINT32_C(1812433253) 78 * (random->status[(i - 1) & 3] 79 ^ (random->status[(i - 1) & 3] >> 30)); 80 } 81 period_certification(random); 82 for ( i = 0; i < PRE_LOOP; i++) { 83 tinymt32_next_state(random); 84 } 85} 86 87/** 88 * This function initializes the internal state array, 89 * with an array of 32-bit unsigned integers used as seeds 90 * @param random tinymt state vector. 91 * @param init_key the array of 32-bit integers, used as a seed. 92 * @param key_length the length of init_key. 93 */ 94void tinymt32_init_by_array(tinymt32_t * random, uint32_t init_key[], 95 int key_length) { 96 const int lag = 1; 97 const int mid = 1; 98 const int size = 4; 99 int i, j; 100 int count; 101 uint32_t r; 102 uint32_t * st = &random->status[0]; 103 104 st[0] = 0; 105 st[1] = random->mat1; 106 st[2] = random->mat2; 107 st[3] = random->tmat; 108 if (key_length + 1 > MIN_LOOP) { 109 count = key_length + 1; 110 } else { 111 count = MIN_LOOP; 112 } 113 r = ini_func1(st[0] ^ st[mid % size] 114 ^ st[(size - 1) % size]); 115 st[mid % size] += r; 116 r += key_length; 117 st[(mid + lag) % size] += r; 118 st[0] = r; 119 count--; 120 for (i = 1, j = 0; (j < count) && (j < key_length); j++) { 121 r = ini_func1(st[i] ^ st[(i + mid) % size] ^ st[(i + size - 1) % size]); 122 st[(i + mid) % size] += r; 123 r += init_key[j] + i; 124 st[(i + mid + lag) % size] += r; 125 st[i] = r; 126 i = (i + 1) % size; 127 } 128 for (; j < count; j++) { 129 r = ini_func1(st[i] ^ st[(i + mid) % size] ^ st[(i + size - 1) % size]); 130 st[(i + mid) % size] += r; 131 r += i; 132 st[(i + mid + lag) % size] += r; 133 st[i] = r; 134 i = (i + 1) % size; 135 } 136 for (j = 0; j < size; j++) { 137 r = ini_func2(st[i] + st[(i + mid) % size] + st[(i + size - 1) % size]); 138 st[(i + mid) % size] ^= r; 139 r -= i; 140 st[(i + mid + lag) % size] ^= r; 141 st[i] = r; 142 i = (i + 1) % size; 143 } 144 period_certification(random); 145 for (i = 0; i < PRE_LOOP; i++) { 146 tinymt32_next_state(random); 147 } 148} 149