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