1 #pragma once
2 
3 #include <cstdint>
4 #include "Common/Swap.h"
5 
6 // George Marsaglia-style random number generator.
7 class GMRng {
8 public:
GMRng()9 	GMRng() {
10 		m_w = 0x23E866ED;
11 		m_z = 0x80FD5AF2;
12 	}
Init(int seed)13 	void Init(int seed) {
14 		m_w = seed ^ (seed << 16);
15 		if (!m_w) m_w = 1337;
16 		m_z = ~seed;
17 		if (!m_z) m_z = 31337;
18 	}
R32()19 	uint32_t R32() {
20 		m_z = 36969 * (m_z & 65535) + (m_z >> 16);
21 		m_w = 18000 * (m_w & 65535) + (m_w >> 16);
22 		return (m_z << 16) + m_w;
23 	}
F()24 	float F() {
25 		return (float)R32() / (float)(0xFFFFFFFF);
26 	}
27 
28 	// public for easy save/load. Yes a bit ugly but better than moving DoState into native.
29 	uint32_t m_w;
30 	uint32_t m_z;
31 };
32 
33 
34 // Data must consist only of the index and the twister array. This matches the PSP
35 // MT context exactly.
36 class MersenneTwister {
37 public:
MersenneTwister(uint32_t seed)38 	MersenneTwister(uint32_t seed) : index_(0) {
39 		mt_[0] = seed;
40 		for (uint32_t i = 1; i < MT_SIZE; i++)
41 			mt_[i] = (1812433253UL * (mt_[i - 1] ^ (mt_[i - 1] >> 30)) + i);
42 	}
43 
R32()44 	uint32_t R32() {
45 		if (index_ == 0)
46 			gen();
47 		uint32_t y = mt_[index_];
48 		y ^=  y >> 11;
49 		y ^= (y <<  7) & 2636928640UL;
50 		y ^= (y << 15) & 4022730752UL;
51 		y ^=  y >> 18;
52 		index_ = (index_ + 1) % MT_SIZE;
53 		return y;
54 	}
55 
56 private:
57 	enum {
58 		MT_SIZE = 624,
59 	};
60 
61 	u32_le index_;
62 	u32_le mt_[MT_SIZE];
63 
gen()64 	void gen() {
65 		for(uint32_t i = 0; i < MT_SIZE; i++){
66 			uint32_t y = (mt_[i] & 0x80000000) + (mt_[(i + 1) % MT_SIZE] & 0x80000000);
67 			mt_[i] = mt_[(i + 397) % MT_SIZE] ^ (y >> 1);
68 			if (y % 2) mt_[i] ^= 2567483615UL;
69 		}
70 		return;
71 	}
72 };
73