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
|