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 }