DragonNest/Common/Utility/MtRandom.cpp
2024-12-20 16:56:44 +08:00

105 lines
No EOL
4.5 KiB
C++
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "stdafx.h"
#include "MtRandom.h"
#include <time.h>
// 생성자, 파괴자 등이 있는 클래스는 TLS에 할당되지 못하며,
// 전역 구조체의 변수는 모두 0 으로 초기화되는데 그것에 대한 처리도 해주어야 된다.
#ifdef _DEBUG
#define new new(_NORMAL_BLOCK,__FILE__,__LINE__)
#endif
void CMtRandom::srand(unsigned long seed)
{
m_seed = seed;
int j;
m_state[0]= seed & 0xffffffffUL;
for (j=1; j<N; j++) {
m_state[j] = (1812433253UL * (m_state[j-1] ^ (m_state[j-1] >> 30)) + j);
m_state[j] &= 0xffffffffUL;
}
m_left = 1;
m_initf = 1;
}
#define MT_MIXBITS(u,v) ( ((u) & UMASK) | ((v) & LMASK) )
#define MT_TWIST(u,v) ((MT_MIXBITS(u,v) >> 1) ^ ((v)&1UL ? MATRIX_A : 0UL))
void CMtRandom::next_state(void)
{
unsigned long *p=m_state;
int j;
if (m_initf==0) srand((unsigned long)time(0));
m_left = N;
m_next = m_state;
for (j=N-M+1; --j; p++)
*p = p[M] ^ MT_TWIST(p[0], p[1]);
for (j=M; --j; p++)
*p = p[M-N] ^ MT_TWIST(p[0], p[1]);
*p = p[M-N] ^ MT_TWIST(p[0], m_state[0]);
}
float CMtRandom::genrand_real2(void)
{
return (float)rand() * (1.f/4294967296.f);
/* divided by 2^32 */
}
int CMtRandom::rand(void)
{
if( m_initf == 0 ) m_left = 1;
int y;
if (--m_left == 0) next_state();
y = *m_next++;
/* Tempering */
y ^= (y >> 11);
y ^= (y << 7) & 0x9d2c5680UL;
y ^= (y << 15) & 0xefc60000UL;
y ^= (y >> 18);
if( y < 0 ) y = -y;
return y;
}
int CMtRandom::rand(unsigned long range)
{
// Find which bits are used in n
// Optimized by Magnus Jonsson (magnus@smartelectronix.com)
unsigned int used = range;
used |= used >> 1;
used |= used >> 2;
used |= used >> 4;
used |= used >> 8;
used |= used >> 16;
// Draw numbers until one is found in [0, range-1]
int n;
do {
n = (unsigned int)rand() & used; // toss unused bits to shorten search
}
while( n >= (int)range );
return n;
/*return rand() % range;*/
}
// float CMtRandom::rand(float smallVal, float largeVal)
// {
// float interval = genrand_real2();
// return smallVal * interval + largeVal * (1-interval);
// }
int CMtRandom::rand(int smallVal, int largeVal)
{
return rand(largeVal-smallVal+1) + smallVal;
}
float CMtRandom::rand_float(float smallVal, float largeVal)
{
return (smallVal + float(rand()) / (2147483648.f/(largeVal - smallVal)));
}