summaryrefslogtreecommitdiff
path: root/Runtime/Math/Random/rand.h
blob: 1971ab44a19f83a0a1773081bdd64470922fe5b5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#ifndef RAND_H
#define RAND_H

/*
Some random generator timings:
MacBook Pro w/ Core 2 Duo 2.4GHz. Times are for gcc 4.0.1 (OS X 10.6.2) / VS2008 SP1 (Win XP SP3),
in milliseconds for this loop (4915200 calls):

 for (int j = 0; j < 100; ++j)
   for (int i = 0; i < 128*128*3; ++i)
     data[i] = (rnd.get() & 0x3) << 6;

                  gcc   vs2008    Size
C's rand():       57.0  109.3 ms     1
Mersenne Twister: 56.0   37.4 ms  2500
Unity 2.x LCG:    11.1    9.2 ms     4
Xorshift 128:     15.0   17.8 ms    16
Xorshift 32:      20.6   10.7 ms     4
WELL 512:         43.6   55.1 ms    68 
*/


// Xorshift 128 implementation
// Xorshift paper: http://www.jstatsoft.org/v08/i14/paper
// Wikipedia: http://en.wikipedia.org/wiki/Xorshift
class Rand {
public:
	
	Rand (UInt32 seed = 0)
	{
		SetSeed (seed);
	}
	
	UInt32 Get ()
	{
		UInt32 t;
		t = x ^ (x << 11);
		x = y; y = z; z = w;
		return w = (w ^ (w >> 19)) ^ (t ^ (t >> 8));
	}

	inline static float GetFloatFromInt (UInt32 value)
	{
		// take 23 bits of integer, and divide by 2^23-1
		return float(value & 0x007FFFFF) * (1.0f / 8388607.0f);
	}

	inline static UInt8 GetByteFromInt (UInt32 value)
	{
		// take the most significant byte from the 23-bit value
		return UInt8(value >> (23 - 8));
	}
	
	// random number between 0.0 and 1.0
	float GetFloat ()
	{
		return GetFloatFromInt (Get ());
	}

	// random number between -1.0 and 1.0
	float GetSignedFloat ()
	{
	    return GetFloat() * 2.0f - 1.0f;
	}

	void SetSeed (UInt32 seed)
	{
		x = seed;
		y = x * 1812433253U + 1;
		z = y * 1812433253U + 1;
		w = z * 1812433253U + 1;
	}
	
	UInt32 GetSeed () const { return x; }
	
private:
	UInt32 x, y, z, w;
};


#endif