PNRGByLeo/Src/Imp/MT64/MT64.mqh

158 lines
4.5 KiB
MQL5
Raw Permalink Normal View History

2026-08-31 21:47:56 -05:00
//+------------------------------------------------------------------+
//| 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
2026-09-01 08:23:33 -05:00
//---
#define UM 0xFFFFFFFF80000000
#define LM 0x7FFFFFFF
#define NN 312
#define MM 156
2026-08-31 21:47:56 -05:00
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
class CMersenneTwister64
{
protected:
//---
2026-09-01 08:23:33 -05:00
ulong m_MT[NN];
2026-08-31 21:47:56 -05:00
int m_index;
//---
void Twist();
2026-08-31 21:48:47 -05:00
//---
2026-09-01 08:23:33 -05:00
uint m_uinteger;
2026-08-31 21:48:47 -05:00
2026-08-31 21:47:56 -05:00
public:
CMersenneTwister64();
~CMersenneTwister64() {}
//---
void Seed(ulong seed);
2026-09-01 09:13:18 -05:00
//---
ulong nextUInt64();
uint nextUInt32();
2026-08-31 21:47:56 -05:00
};
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
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)
{
2026-09-01 08:23:33 -05:00
m_uinteger = 0U;
m_index = NN;
2026-08-31 21:47:56 -05:00
m_MT[0] = seed;
2026-09-01 08:23:33 -05:00
for(int i = 1; i < NN; i++)
2026-08-31 21:47:56 -05:00
{
2026-09-01 08:23:33 -05:00
m_MT[i] = (6364136223846793005ULL * (m_MT[i - 1] ^ (m_MT[i - 1] >> 62)) + i);
2026-08-31 21:47:56 -05:00
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
ulong CMersenneTwister64::nextUInt64()
{
2026-09-01 08:23:33 -05:00
if(m_index >= NN)
2026-08-31 21:47:56 -05:00
{
Twist();
}
//---
ulong y = m_MT[m_index];
2026-09-01 08:23:33 -05:00
y ^= (y >> 29) & 0x5555555555555555;
y ^= (y << 17) & 0x71D67FFFEDA60000;
y ^= (y << 37) & 0xFFF7EEE000000000;
y ^= (y >> 43);
2026-08-31 21:47:56 -05:00
//---
m_index++;
return y;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CMersenneTwister64::Twist()
{
2026-09-01 08:23:33 -05:00
//---
const ulong mag01[2] = {0ULL, 0xB5026F5AA96619E9};
//---
ulong x;
int i;
for(i = 0; i < NN - MM; i++)
2026-08-31 21:47:56 -05:00
{
2026-09-01 08:23:33 -05:00
x = (m_MT[i] & UM) | (m_MT[i + 1] & LM);
m_MT[i] = m_MT[i + MM] ^ (x >> 1) ^ mag01[(x & 1)];
2026-08-31 21:47:56 -05:00
}
2026-09-01 08:23:33 -05:00
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)];
//---
2026-08-31 21:47:56 -05:00
m_index = 0;
}
2026-08-31 21:48:47 -05:00
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
uint CMersenneTwister64::nextUInt32(void)
{
2026-09-01 08:23:33 -05:00
if(m_uinteger) // en caso no haya un valor previo
2026-08-31 21:48:47 -05:00
{
2026-09-01 08:23:33 -05:00
const uint t = m_uinteger; // temporal
m_uinteger = 0; // reset
2026-08-31 21:48:47 -05:00
return t; // retornamos
}
const ulong next = nextUInt64();
2026-09-01 08:23:33 -05:00
m_uinteger = (uint)(next >> 32);
return (uint)(next);
2026-08-31 21:48:47 -05:00
}
2026-09-01 08:23:33 -05:00
//----
#undef UM
#undef LM
#undef NN
#undef MM
2026-08-31 21:47:56 -05:00
}
#endif // PRNGBYLEO_SRC_IMP_MT64_MT64_MQH