Files
ppsspp/Common/Data/Random/Rng.h

73 lines
1.5 KiB
C
Raw Permalink Normal View History

#pragma once
2012-03-24 23:39:19 +01:00
#include <cstdint>
#include "Common/Swap.h"
2012-03-24 23:39:19 +01:00
// George Marsaglia-style random number generator.
class GMRng {
2012-10-31 13:55:17 +01:00
public:
GMRng() {
m_w = 0x23E866ED;
m_z = 0x80FD5AF2;
}
void Init(int seed) {
m_w = seed ^ (seed << 16);
if (!m_w) m_w = 1337;
m_z = ~seed;
if (!m_z) m_z = 31337;
}
uint32_t R32() {
2012-10-31 13:55:17 +01:00
m_z = 36969 * (m_z & 65535) + (m_z >> 16);
m_w = 18000 * (m_w & 65535) + (m_w >> 16);
return (m_z << 16) + m_w;
}
float F() {
return (float)R32() / (float)(0xFFFFFFFF);
}
2012-03-24 23:39:19 +01:00
// public for easy save/load. Yes a bit ugly but better than moving DoState into native.
uint32_t m_w;
uint32_t m_z;
2012-03-24 23:39:19 +01:00
};
// Data must consist only of the index and the twister array. This matches the PSP
// MT context exactly.
class MersenneTwister {
public:
MersenneTwister(uint32_t seed) : index_(0) {
mt_[0] = seed;
for (uint32_t i = 1; i < MT_SIZE; i++)
2013-05-22 11:04:14 +02:00
mt_[i] = (1812433253UL * (mt_[i - 1] ^ (mt_[i - 1] >> 30)) + i);
}
uint32_t R32() {
if (index_ == 0)
gen();
uint32_t y = mt_[index_];
y ^= y >> 11;
2013-05-22 11:04:14 +02:00
y ^= (y << 7) & 2636928640UL;
y ^= (y << 15) & 4022730752UL;
y ^= y >> 18;
index_ = (index_ + 1) % MT_SIZE;
return y;
}
private:
enum {
MT_SIZE = 624,
};
u32_le index_;
u32_le mt_[MT_SIZE];
void gen() {
for(uint32_t i = 0; i < MT_SIZE; i++){
uint32_t y = (mt_[i] & 0x80000000) + (mt_[(i + 1) % MT_SIZE] & 0x80000000);
mt_[i] = mt_[(i + 397) % MT_SIZE] ^ (y >> 1);
2013-05-22 11:04:14 +02:00
if (y % 2) mt_[i] ^= 2567483615UL;
}
return;
}
};