Oolite 1.91.0.7604-240417-a536cbe
Loading...
Searching...
No Matches
legacy_random.c
Go to the documentation of this file.
1/*
2
3legacy_random.c
4
5
6Oolite
7Copyright (C) 2004-2008 Giles C Williams and contributors
8
9This program is free software; you can redistribute it and/or
10modify it under the terms of the GNU General Public License
11as published by the Free Software Foundation; either version 2
12of the License, or (at your option) any later version.
13
14This program is distributed in the hope that it will be useful,
15but WITHOUT ANY WARRANTY; without even the implied warranty of
16MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17GNU General Public License for more details.
18
19You should have received a copy of the GNU General Public License
20along with this program; if not, write to the Free Software
21Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
22MA 02110-1301, USA.
23
24*/
25
26#include <stdio.h>
27#include <math.h>
28#include <stdint.h>
29#include <stdbool.h>
30#include <assert.h>
31#include "legacy_random.h"
32
33
35
36
38
39
40// TODO: Why is this based on a static? Should change to OOMungeCheckSum(&checkSum, value);
41static int32_t checksum;
43{
44 checksum = 0;
45}
46
47
48int16_t munge_checksum(long long value_)
49{
50 uint32_t value = (uint32_t)value_;
51 int32_t mult1 = (value & 15) + 8;
52 checksum += value;
53 checksum *= mult1;
54 checksum += mult1;
55 checksum &= 0xffff;
56 return checksum;
57}
58
59
60// cunning price rounding routine:
61//
62double cunningFee(double value, double precision)
63{
64 double fee = value;
65 double superfee = 100000.0;
66 double max = 1 + precision;
67 double min = 1 - precision;
68 unsigned long long rounded_fee = superfee * floor(0.5 + fee / superfee);
69 if (rounded_fee == 0) rounded_fee = 1;
70 double ratio = fee / (double)rounded_fee;
71
72 while ((ratio < min || ratio > max) && superfee > 1)
73 {
74 rounded_fee = superfee * floor(0.5 + fee / superfee);
75 if (rounded_fee == 0) rounded_fee = 1;
76 ratio = fee / (double)rounded_fee;
77 superfee /= 10.0;
78 }
79
80 if (ratio > min && ratio < max)
81 fee = rounded_fee;
82
83 return fee;
84}
85
86
87// an implementation of RANROT
88// pseudo random number generator
89//
91
92
93unsigned Ranrot(void)
94{
95 sRANROT.high = (sRANROT.high << 16) + (sRANROT.high >> 16);
98 return sRANROT.high & 0x7FFFFFFF;
99}
100
101
102unsigned RanrotWithSeed(RANROTSeed *ioSeed)
103{
104 assert(ioSeed != NULL);
105
106 ioSeed->high = (ioSeed->high << 16) + (ioSeed->high >> 16);
107 ioSeed->high += ioSeed->low;
108 ioSeed->low += ioSeed->high;
109 return ioSeed->high & 0x7FFFFFFF;
110}
111
112
114{
115 RANROTSeed result =
116 {
117 .low = seed,
118 .high = ~seed
119 };
120
121 // Mix it up a bit.
122 RanrotWithSeed(&result);
123 RanrotWithSeed(&result);
124 RanrotWithSeed(&result);
125
126 return result;
127}
128
129
131{
132 return MakeRanrotSeed(seed.a * 0x1000000 + seed.b * 0x10000 + seed.c * 0x100 + seed.d);
133}
134
135
137{
138 // Same pattern as seed_for_planet_description().
139 RNG_Seed s =
140 {
141 .a = seed.c,
142 .b = seed.d,
143 .c = seed.e,
144 .d = seed.f
145 };
146 return RanrotSeedFromRNGSeed(s);
147}
148
149
150void ranrot_srand(uint32_t seed)
151{
152 sRANROT = MakeRanrotSeed(seed);
153}
154
155
156float randf (void)
157{
158 return (Ranrot() & 0xffff) * (1.0f / 65536.0f);
159}
160
161
163{
164 return (RanrotWithSeed(ioSeed) & 0xffff) * (1.0f / 65536.0f);
165}
166
167
168float bellf (int n)
169{
170 int i = n;
171 float total = 0;
172
173 if (EXPECT_NOT(i <= 0))
174 {
175 printf("***** ERROR - attempt to generate bellf(%d)\n", n);
176 return 0.0f; // catch possible div-by-zero problem
177 }
178
179 while (i-- > 0)
180 total += (Ranrot() & 1023);
181 return total / (1024.0f * n);
182}
183
184
186{
187 return sRANROT;
188}
189
190
192{
193 sRANROT = seed;
194}
195
196
198{
199 rnd_seed.a = s_seed.c;
200 rnd_seed.b = s_seed.d;
201 rnd_seed.c = s_seed.e;
202 rnd_seed.d = s_seed.f;
203}
204
205
211
212
214{
215 return rnd_seed;
216}
217
218
220{
221 rnd_seed = a_seed;
222}
223
224
226{
227 int a,x;
228
229 x = (rnd_seed.a * 2) & 0xFF;
230 a = x + rnd_seed.c;
231 if (rnd_seed.a > 127)
232 a++;
233 rnd_seed.a = a & 0xFF;
234 rnd_seed.c = x;
235
236 a = a / 256; /* a = any carry left from above */
237 x = rnd_seed.b;
238 a = (a + x + rnd_seed.d) & 0xFF;
239 rnd_seed.b = a;
240 rnd_seed.d = x;
241 return a;
242}
243
244
245static bool sReallyRandomInited = false;
247
248
249uint32_t OOReallyRandom(void)
250{
251 assert(sReallyRandomInited);
253}
254
255
256void OOInitReallyRandom(uint64_t seed)
257{
258 assert(!sReallyRandomInited);
259 seed ^= 0xA471D52AEF3B6322ULL;
260 sReallyRandomSeed.high = (seed >> 32) & 0xFFFFFFFF;
261 sReallyRandomSeed.low = seed & 0xFFFFFFFF;
262 sReallyRandomInited = true;
264}
265
266
268{
269 assert(sReallyRandomInited);
271 OOReallyRandom(); // Don't go reusing it.
272}
273
274
276{
277 uint32_t val = OOReallyRandom();
278 rnd_seed.a = (val >> 24) & 0xFF;
279 rnd_seed.b = (val >> 16) & 0xFF;
280 rnd_seed.c = (val >> 8) & 0xFF;
281 rnd_seed.d = val & 0xFF;
282}
283
284
290
291
293{
294 return (OORandomState)
295 {
296 .ranrot = sRANROT,
297 .rnd = rnd_seed
298 };
299}
300
301
303{
304 sRANROT = state.ranrot;
305 rnd_seed = state.rnd;
306}
307
308
310{
311 seed_ptr->a = gen_rnd_number();
312 seed_ptr->b = gen_rnd_number();
313 seed_ptr->c = gen_rnd_number();
314 seed_ptr->d = gen_rnd_number();
315 seed_ptr->e = gen_rnd_number();
316 seed_ptr->f = gen_rnd_number();
317}
318
319
320void rotate_seed (Random_Seed *seed_ptr)
321{
322 uint_fast16_t x;
323 uint_fast16_t y;
324
325 /* Note: this is equivalent to adding three (little-endian) 16-bit values
326 together, rotating the three numbers and replacing one of them with
327 the sum. The byte-oriented approach is presumably because it was
328 reverse-engineered from eight-bit machine code. Switching to a plain
329 sixteen-bit representation is more trouble than it's worth since so
330 much code uses byte values from the seed struct directly.
331 */
332 x = seed_ptr->a + seed_ptr->c + seed_ptr->e;
333 y = seed_ptr->b + seed_ptr->d + seed_ptr->f;
334
335 seed_ptr->a = seed_ptr->c;
336 seed_ptr->b = seed_ptr->d;
337
338 seed_ptr->c = seed_ptr->e;
339 seed_ptr->d = seed_ptr->f;
340
341 seed_ptr->e = x;
342 seed_ptr->f = y + (x >> 8);
343}
#define EXPECT_NOT(x)
float y
float x
RANROTSeed RanrotSeedFromRandomSeed(Random_Seed seed)
const Random_Seed kNilRandomSeed
float randf(void)
void clear_checksum()
void make_pseudo_random_seed(Random_Seed *seed_ptr)
static bool sReallyRandomInited
RANROTSeed RANROTGetFullSeed(void)
void seed_RNG_only_for_planet_description(Random_Seed s_seed)
void ranrot_srand(uint32_t seed)
void OOSetReallyRandomRANROTSeed(void)
void setRandomSeed(RNG_Seed a_seed)
int16_t munge_checksum(long long value_)
uint32_t OOReallyRandom(void)
float randfWithSeed(RANROTSeed *ioSeed)
float bellf(int n)
RNG_Seed currentRandomSeed(void)
void OOInitReallyRandom(uint64_t seed)
static RANROTSeed sRANROT
void OORestoreRandomState(OORandomState state)
static RANROTSeed sReallyRandomSeed
OORandomState OOSaveRandomState(void)
void RANROTSetFullSeed(RANROTSeed seed)
RANROTSeed RanrotSeedFromRNGSeed(RNG_Seed seed)
static int32_t checksum
void OOSetReallyRandomRndSeed(void)
unsigned RanrotWithSeed(RANROTSeed *ioSeed)
int gen_rnd_number(void)
double cunningFee(double value, double precision)
static RNG_Seed rnd_seed
void seed_for_planet_description(Random_Seed s_seed)
RANROTSeed MakeRanrotSeed(uint32_t seed)
void OOSetReallyRandomRANROTAndRndSeeds(void)
unsigned Ranrot(void)
void rotate_seed(Random_Seed *seed_ptr)
RANROTSeed ranrot
uint32_t low
uint32_t high
int32_t c
int32_t d
int32_t a
int32_t b