amiga_boottest

view src/rng.c @ 3:555b986cc420

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