1 /**************************************************************************
3 * Copyright 2013-2014 RAD Game Tools and Valve Software
4 * Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 **************************************************************************/
30 #include "vogl_core.h"
31 #include "vogl_threading.h"
33 #define VOGL_SHR3 (jsr ^= (jsr << 17), jsr ^= (jsr >> 13), jsr ^= (jsr << 5))
34 #define VOGL_CONG (jcong = 69069 * jcong + 1234567)
45 void seed(uint32 i, uint32 j, uint32 k);
65 void seed(uint32 seed[cStateSize]);
66 void seed(uint32 seed);
67 void seed(uint32 seed1, uint32 seed2, uint32 seed3);
68 void seed(uint32 seed1, uint32 seed2, uint32 seed3, uint seed4);
73 uint32 m_state[cStateSize];
85 void seed(uint32 seed);
96 // Originally from Numerical Recipes in C
97 // Interesting because the seed is just a 64-bit counter.
106 void seed(uint64_t s)
111 inline uint64_t get_seed() const
116 inline uint32 next32()
118 uint32 l = static_cast<uint32>(m_ctr);
119 uint32 h = static_cast<uint32>(m_ctr >> 32U);
120 psdes_hash_64(&h, &l);
125 inline uint64_t next64()
127 uint32 l = static_cast<uint32>(m_ctr);
128 uint32 h = static_cast<uint32>(m_ctr >> 32U);
129 psdes_hash_64(&h, &l);
131 return static_cast<uint64_t>(l) | (static_cast<uint64_t>(h) << 32U);
135 void psdes_hash_64(uint *pword0, uint *pword1)
137 const uint NITER = 4;
138 uint i, iswap, ia, iah, ial, ib, ic;
139 static const uint c1[NITER] = { 0xbaa96887, 0x1e17d32c, 0x03bcdc3c, 0x0f33d1b2 };
140 static const uint c2[NITER] = { 0x4b0f3b58, 0xe874f0c3, 0x6955c5a6, 0x55a7ca46 };
141 for (i = 0; i < NITER; i++)
147 ib = ial * ial + ~(iah * iah);
148 ic = (ib >> 16) | ((ib & 0xffff) << 16);
149 *pword1 = (*pword0) ^ ((ic ^ c2[i]) + ial * iah);
165 void seed(uint32 i1, uint32 i2, uint32 i3);
166 void seed(uint32 i1, uint32 i2, uint32 i3, uint32 i4);
167 void seed(const md5_hash &h);
168 void seed_from_urandom();
172 return static_cast<uint8>(urand32());
176 return static_cast<uint16>(urand32());
181 // "Fast" variant uses no multiplies.
182 uint32 fast_urand32();
186 // Returns random double between [0, 1)
187 double drand(double l, double h);
189 float frand(float l, float h);
191 // Returns random signed int between [l, h)
192 int irand(int l, int h);
194 // Returns random signed int between [l, h]
195 int irand_inclusive(int l, int h);
197 // Returns random unsigned int between [l, h)
198 uint urand(uint l, uint h);
200 // Returns random unsigned int between [l, h]
201 uint urand_inclusive(uint l, uint h);
203 // Returns random 64-bit unsigned int between [l, h)
204 uint64_t urand64(uint64_t l, uint64_t h);
206 // Returns random 64-bit unsigned int between [l, h]
207 uint64_t urand64_inclusive(uint64_t l, uint64_t h);
209 double gaussian(double mean, double stddev);
218 class thread_safe_random
221 thread_safe_random();
222 thread_safe_random(uint32 i);
226 void seed(uint32 i1, uint32 i2, uint32 i3);
227 void seed(uint32 i1, uint32 i2, uint32 i3, uint32 i4);
228 void seed(const md5_hash &h);
229 void seed_from_urandom();
236 // "Fast" variant uses no multiplies.
237 uint32 fast_urand32();
241 // Returns random double between [0, 1)
242 double drand(double l, double h);
244 float frand(float l, float h);
246 // Returns random signed int between [l, h)
247 int irand(int l, int h);
249 // Returns random signed int between [l, h]
250 int irand_inclusive(int l, int h);
252 // Returns random unsigned int between [l, h)
253 uint urand(uint l, uint h);
255 // Returns random unsigned int between [l, h]
256 uint urand_inclusive(uint l, uint h);
258 // Returns random 64-bit unsigned int between [l, h)
259 uint64_t urand64(uint64_t l, uint64_t h);
261 // Returns random 64-bit unsigned int between [l, h]
262 uint64_t urand64_inclusive(uint64_t l, uint64_t h);
264 double gaussian(double mean, double stddev);
271 // Simpler, minimal state PRNG - combines SHR3 and CONG.
272 // This thing fails many tests (Gorilla, Collision, Birthday).
277 : jsr(0xABCD917A), jcong(0x17F3DEAD)
280 inline fast_random(const fast_random &other)
281 : jsr(other.jsr), jcong(other.jcong)
284 inline fast_random(uint32 i)
288 inline fast_random &operator=(const fast_random &other)
295 inline void seed(uint32 i);
296 inline void set_default_seed()
302 inline uint32 urand32();
303 inline uint64_t urand64();
304 inline uint32 get_bit();
306 int irand(int l, int h);
307 uint urand(uint l, uint h);
309 double drand(double l, double h);
311 float frand(float l, float h);
320 inline void fast_random::seed(uint32 i)
324 jcong = (~i) ^ 0xDEADBEEF;
327 inline uint32 fast_random::urand32()
329 return VOGL_SHR3 ^ VOGL_CONG;
332 inline uint32 fast_random::get_bit()
334 uint32 k = urand32();
335 return ((k >> 31U) ^ (k >> 29U)) & 1;
338 inline uint64_t fast_random::urand64()
340 uint64_t result = urand32();
346 inline void memset_random(fast_random &context, void *pDst, uint n)
350 *reinterpret_cast<uint32 *>(pDst) = context.urand32();
351 pDst = reinterpret_cast<uint32 *>(pDst) + 1;
357 *reinterpret_cast<uint8 *>(pDst) = static_cast<uint8>(context.urand32());
358 pDst = reinterpret_cast<uint8 *>(pDst) + 1;
363 // non-thread safe global instances, for simplicity in single threaded tools/experiments
364 extern random g_random;
365 extern fast_random g_fast_random;
366 extern thread_safe_random g_thread_safe_random;