PNRGByLeo/Src/Imp/MT64/MT64.mqh
2026-09-01 09:13:18 -05:00

158 lines
4.5 KiB
MQL5

//+------------------------------------------------------------------+
//| MT64.mqh |
//| Copyright 2026, Niquel Mendoza |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2026, Niquel Mendoza"
#property link "https://www.mql5.com"
#property strict
#ifndef PRNGBYLEO_SRC_IMP_MT64_MT64_MQH
#define PRNGBYLEO_SRC_IMP_MT64_MT64_MQH
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
namespace TSN
{
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
// referencias:
// https://www.mql5.com/en/articles/14413
//---
#define UM 0xFFFFFFFF80000000
#define LM 0x7FFFFFFF
#define NN 312
#define MM 156
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
class CMersenneTwister64
{
protected:
//---
ulong m_MT[NN];
int m_index;
//---
void Twist();
//---
uint m_uinteger;
public:
CMersenneTwister64();
~CMersenneTwister64() {}
//---
void Seed(ulong seed);
//---
ulong nextUInt64();
uint nextUInt32();
};
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
CMersenneTwister64::CMersenneTwister64()
{
ulong v = (ulong)TerminalInfoInteger(TERMINAL_PING_LAST) ^ (ulong)TerminalInfoInteger(TERMINAL_MEMORY_USED);
v ^= (ulong)GetTickCount64();
v ^= (ulong)TerminalInfoDouble(TERMINAL_RETRANSMISSION) * 100000ULL;
v ^= (ulong)MQLInfoInteger(MQL_GLOBAL_COUNTER);
Seed(v);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CMersenneTwister64::Seed(ulong seed)
{
m_uinteger = 0U;
m_index = NN;
m_MT[0] = seed;
for(int i = 1; i < NN; i++)
{
m_MT[i] = (6364136223846793005ULL * (m_MT[i - 1] ^ (m_MT[i - 1] >> 62)) + i);
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
ulong CMersenneTwister64::nextUInt64()
{
if(m_index >= NN)
{
Twist();
}
//---
ulong y = m_MT[m_index];
y ^= (y >> 29) & 0x5555555555555555;
y ^= (y << 17) & 0x71D67FFFEDA60000;
y ^= (y << 37) & 0xFFF7EEE000000000;
y ^= (y >> 43);
//---
m_index++;
return y;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CMersenneTwister64::Twist()
{
//---
const ulong mag01[2] = {0ULL, 0xB5026F5AA96619E9};
//---
ulong x;
int i;
for(i = 0; i < NN - MM; i++)
{
x = (m_MT[i] & UM) | (m_MT[i + 1] & LM);
m_MT[i] = m_MT[i + MM] ^ (x >> 1) ^ mag01[(x & 1)];
}
for(; i < NN - 1; i++)
{
x = (m_MT[i] & UM) | (m_MT[i + 1] & LM);
m_MT[i] = m_MT[i + (MM - NN)] ^ (x >> 1) ^ mag01[(x & 1)];
}
x = (m_MT[311] & UM) | (m_MT[0] & LM);
m_MT[311] = m_MT[155] ^ (x >> 1) ^ mag01[(x & 1)];
//---
m_index = 0;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
uint CMersenneTwister64::nextUInt32(void)
{
if(m_uinteger) // en caso no haya un valor previo
{
const uint t = m_uinteger; // temporal
m_uinteger = 0; // reset
return t; // retornamos
}
const ulong next = nextUInt64();
m_uinteger = (uint)(next >> 32);
return (uint)(next);
}
//----
#undef UM
#undef LM
#undef NN
#undef MM
}
#endif // PRNGBYLEO_SRC_IMP_MT64_MT64_MQH