amiga_boottest
annotate src/rng.c @ 4:995d42b33974
serial output
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Fri, 23 Feb 2018 13:29:37 +0200 |
parents | |
children |
rev | line source |
---|---|
nuclear@3 | 1 #include "rng.h" |
nuclear@3 | 2 |
nuclear@3 | 3 /** |
nuclear@3 | 4 * tinymt32 internal state vector and parameters |
nuclear@3 | 5 */ |
nuclear@3 | 6 typedef struct tinymt32 { |
nuclear@3 | 7 uint32_t status[4]; |
nuclear@3 | 8 uint32_t mat1; |
nuclear@3 | 9 uint32_t mat2; |
nuclear@3 | 10 uint32_t tmat; |
nuclear@3 | 11 } tinymt32_t; |
nuclear@3 | 12 |
nuclear@3 | 13 static tinymt32_t st; |
nuclear@3 | 14 |
nuclear@3 | 15 static void tinymt32_init(tinymt32_t * random, uint32_t seed); |
nuclear@3 | 16 inline static uint32_t tinymt32_generate_uint32(tinymt32_t * random); |
nuclear@3 | 17 /*inline static float tinymt32_generate_float(tinymt32_t * random);*/ |
nuclear@3 | 18 |
nuclear@3 | 19 void srand(unsigned int s) |
nuclear@3 | 20 { |
nuclear@3 | 21 tinymt32_init(&st, s); |
nuclear@3 | 22 } |
nuclear@3 | 23 |
nuclear@3 | 24 int32_t rand(void) |
nuclear@3 | 25 { |
nuclear@3 | 26 return tinymt32_generate_uint32(&st) & RAND_MAX; |
nuclear@3 | 27 } |
nuclear@3 | 28 |
nuclear@3 | 29 /** |
nuclear@3 | 30 * @file tinymt32.h |
nuclear@3 | 31 * |
nuclear@3 | 32 * @brief Tiny Mersenne Twister only 127 bit internal state |
nuclear@3 | 33 * |
nuclear@3 | 34 * @author Mutsuo Saito (Hiroshima University) |
nuclear@3 | 35 * @author Makoto Matsumoto (University of Tokyo) |
nuclear@3 | 36 * |
nuclear@3 | 37 * Copyright (C) 2011 Mutsuo Saito, Makoto Matsumoto, |
nuclear@3 | 38 * Hiroshima University and The University of Tokyo. |
nuclear@3 | 39 * All rights reserved. |
nuclear@3 | 40 * |
nuclear@3 | 41 * The 3-clause BSD License is applied to this software, see |
nuclear@3 | 42 * LICENSE.txt |
nuclear@3 | 43 */ |
nuclear@3 | 44 #define TINYMT32_MEXP 127 |
nuclear@3 | 45 #define TINYMT32_SH0 1 |
nuclear@3 | 46 #define TINYMT32_SH1 10 |
nuclear@3 | 47 #define TINYMT32_SH8 8 |
nuclear@3 | 48 #define TINYMT32_MASK 0x7fffffffu |
nuclear@3 | 49 /*#define TINYMT32_MUL (1.0f / 4294967296.0f)*/ |
nuclear@3 | 50 |
nuclear@3 | 51 /** |
nuclear@3 | 52 * This function changes internal state of tinymt32. |
nuclear@3 | 53 * Users should not call this function directly. |
nuclear@3 | 54 * @param random tinymt internal status |
nuclear@3 | 55 */ |
nuclear@3 | 56 inline static void tinymt32_next_state(tinymt32_t * random) { |
nuclear@3 | 57 uint32_t x; |
nuclear@3 | 58 uint32_t y; |
nuclear@3 | 59 |
nuclear@3 | 60 y = random->status[3]; |
nuclear@3 | 61 x = (random->status[0] & TINYMT32_MASK) |
nuclear@3 | 62 ^ random->status[1] |
nuclear@3 | 63 ^ random->status[2]; |
nuclear@3 | 64 x ^= (x << TINYMT32_SH0); |
nuclear@3 | 65 y ^= (y >> TINYMT32_SH0) ^ x; |
nuclear@3 | 66 random->status[0] = random->status[1]; |
nuclear@3 | 67 random->status[1] = random->status[2]; |
nuclear@3 | 68 random->status[2] = x ^ (y << TINYMT32_SH1); |
nuclear@3 | 69 random->status[3] = y; |
nuclear@3 | 70 random->status[1] ^= -((int32_t)(y & 1)) & random->mat1; |
nuclear@3 | 71 random->status[2] ^= -((int32_t)(y & 1)) & random->mat2; |
nuclear@3 | 72 } |
nuclear@3 | 73 |
nuclear@3 | 74 /** |
nuclear@3 | 75 * This function outputs 32-bit unsigned integer from internal state. |
nuclear@3 | 76 * Users should not call this function directly. |
nuclear@3 | 77 * @param random tinymt internal status |
nuclear@3 | 78 * @return 32-bit unsigned pseudorandom number |
nuclear@3 | 79 */ |
nuclear@3 | 80 inline static uint32_t tinymt32_temper(tinymt32_t * random) { |
nuclear@3 | 81 uint32_t t0, t1; |
nuclear@3 | 82 t0 = random->status[3]; |
nuclear@3 | 83 #if defined(LINEARITY_CHECK) |
nuclear@3 | 84 t1 = random->status[0] |
nuclear@3 | 85 ^ (random->status[2] >> TINYMT32_SH8); |
nuclear@3 | 86 #else |
nuclear@3 | 87 t1 = random->status[0] |
nuclear@3 | 88 + (random->status[2] >> TINYMT32_SH8); |
nuclear@3 | 89 #endif |
nuclear@3 | 90 t0 ^= t1; |
nuclear@3 | 91 t0 ^= -((int32_t)(t1 & 1)) & random->tmat; |
nuclear@3 | 92 return t0; |
nuclear@3 | 93 } |
nuclear@3 | 94 |
nuclear@3 | 95 /** |
nuclear@3 | 96 * This function outputs 32-bit unsigned integer from internal state. |
nuclear@3 | 97 * @param random tinymt internal status |
nuclear@3 | 98 * @return 32-bit unsigned integer r (0 <= r < 2^32) |
nuclear@3 | 99 */ |
nuclear@3 | 100 inline static uint32_t tinymt32_generate_uint32(tinymt32_t * random) { |
nuclear@3 | 101 tinymt32_next_state(random); |
nuclear@3 | 102 return tinymt32_temper(random); |
nuclear@3 | 103 } |
nuclear@3 | 104 |
nuclear@3 | 105 #if 0 |
nuclear@3 | 106 /** |
nuclear@3 | 107 * This function outputs floating point number from internal state. |
nuclear@3 | 108 * This function is implemented using multiplying by 1 / 2^32. |
nuclear@3 | 109 * floating point multiplication is faster than using union trick in |
nuclear@3 | 110 * my Intel CPU. |
nuclear@3 | 111 * @param random tinymt internal status |
nuclear@3 | 112 * @return floating point number r (0.0 <= r < 1.0) |
nuclear@3 | 113 */ |
nuclear@3 | 114 inline static float tinymt32_generate_float(tinymt32_t * random) { |
nuclear@3 | 115 tinymt32_next_state(random); |
nuclear@3 | 116 return tinymt32_temper(random) * TINYMT32_MUL; |
nuclear@3 | 117 } |
nuclear@3 | 118 #endif |
nuclear@3 | 119 |
nuclear@3 | 120 #define MIN_LOOP 8 |
nuclear@3 | 121 #define PRE_LOOP 8 |
nuclear@3 | 122 |
nuclear@3 | 123 /** |
nuclear@3 | 124 * This function certificate the period of 2^127-1. |
nuclear@3 | 125 * @param random tinymt state vector. |
nuclear@3 | 126 */ |
nuclear@3 | 127 static void period_certification(tinymt32_t * random) { |
nuclear@3 | 128 if ((random->status[0] & TINYMT32_MASK) == 0 && |
nuclear@3 | 129 random->status[1] == 0 && |
nuclear@3 | 130 random->status[2] == 0 && |
nuclear@3 | 131 random->status[3] == 0) { |
nuclear@3 | 132 random->status[0] = 'T'; |
nuclear@3 | 133 random->status[1] = 'I'; |
nuclear@3 | 134 random->status[2] = 'N'; |
nuclear@3 | 135 random->status[3] = 'Y'; |
nuclear@3 | 136 } |
nuclear@3 | 137 } |
nuclear@3 | 138 |
nuclear@3 | 139 /** |
nuclear@3 | 140 * This function initializes the internal state array with a 32-bit |
nuclear@3 | 141 * unsigned integer seed. |
nuclear@3 | 142 * @param random tinymt state vector. |
nuclear@3 | 143 * @param seed a 32-bit unsigned integer used as a seed. |
nuclear@3 | 144 */ |
nuclear@3 | 145 static void tinymt32_init(tinymt32_t * random, uint32_t seed) { |
nuclear@3 | 146 random->status[0] = seed; |
nuclear@3 | 147 random->status[1] = random->mat1; |
nuclear@3 | 148 random->status[2] = random->mat2; |
nuclear@3 | 149 random->status[3] = random->tmat; |
nuclear@3 | 150 for (int i = 1; i < MIN_LOOP; i++) { |
nuclear@3 | 151 random->status[i & 3] ^= i + 1812433253u |
nuclear@3 | 152 * (random->status[(i - 1) & 3] |
nuclear@3 | 153 ^ (random->status[(i - 1) & 3] >> 30)); |
nuclear@3 | 154 } |
nuclear@3 | 155 period_certification(random); |
nuclear@3 | 156 for (int i = 0; i < PRE_LOOP; i++) { |
nuclear@3 | 157 tinymt32_next_state(random); |
nuclear@3 | 158 } |
nuclear@3 | 159 } |