430 lines
13 KiB
MQL5
430 lines
13 KiB
MQL5
//+------------------------------------------------------------------+
|
|
//| Common.mqh |
|
|
//| Copyright 2026, Niquel Mendoza. |
|
|
//| https://www.mql5.com |
|
|
//+------------------------------------------------------------------+
|
|
#property copyright "Copyright 2026, Niquel Mendoza."
|
|
#property link "https://www.mql5.com"
|
|
#property strict
|
|
|
|
#ifndef BIGNUMBERSBYLEO_SRC_BASE_COMMON_MQH
|
|
#define BIGNUMBERSBYLEO_SRC_BASE_COMMON_MQH
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
#include "..\\Utils\\Main.mqh"
|
|
#include "Def.mqh"
|
|
#include "..\\Utils\\DER.mqh"
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
namespace TSN
|
|
{
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
struct BigIBase
|
|
{
|
|
protected:
|
|
//--- Swap version con e tambien actuliza el vs8 del v..
|
|
BigIBase(ulong& v[], const int vs_8);
|
|
BigIBase(const int vs_8, ulong& v[]);
|
|
|
|
//-- Se inicia desde un numero en especiifco y con un tamaño (Que tambien es la reserva)
|
|
BigIBase(const ulong number, const int vs);
|
|
|
|
//-- Se inicia con un valor de 0 pero la idea es reservar limbs inciiales\nada (32 defualt)
|
|
BigIBase(int initial_reserve);
|
|
BigIBase();
|
|
|
|
//--- Cmp
|
|
template <typename TNormAbs>
|
|
int CmpInt(const BigIBase &b) const;
|
|
|
|
public:
|
|
//--- raw
|
|
ulong m_v[];
|
|
int m_v_s;
|
|
|
|
//--- Resta:
|
|
// v = this - v
|
|
// se asume que v es menor que this siempre
|
|
// ahora v es menor que this siempre (o tiene que serlo ya se garantiza)
|
|
void RestarConYResEn(ulong &v[], int& vs) const;
|
|
|
|
|
|
//--- Es par
|
|
__forceinline bool IsPar() const { return BIGNUMERBYLEO_UINTEGER_IZ_PAR; }
|
|
|
|
//--- es Zero
|
|
__forceinline bool IsZero() const { return BIGNUMERBYLEO_UINTEGER_IZ_ZERO; }
|
|
__forceinline bool IsNotZero() const { return BIGNUMERBYLEO_UINTEGER_IZ_NZERO; }
|
|
|
|
//--- acceso a limbs (sin chekeo raw maxima velociad)
|
|
__forceinline ulong operator[](const int limb_idx) const { return m_v[limb_idx]; }
|
|
|
|
//---
|
|
void SetBit(const ulong bit_pos, bool v);
|
|
__forceinline bool GetBit(const ulong bit_pos) const;
|
|
|
|
|
|
|
|
|
|
//--- Swap
|
|
void Swap(BigIBase& other);
|
|
|
|
//--- Bits
|
|
ulong Ctz() const;
|
|
|
|
//---
|
|
__forceinline void RobarDe(BigIBase &other);
|
|
|
|
//---
|
|
template <typename TRandom>
|
|
__forceinline void FillRandom();
|
|
|
|
|
|
//---
|
|
void UShiftLeft(const ulong b);
|
|
|
|
//---- Static utils
|
|
// CTZ (maximo comun para ambos a y b)
|
|
static ulong CTZ_Commons(const BigIBase& a, const BigIBase& b);
|
|
|
|
//-- EMPTY bufffers
|
|
// Dado que requiero sobrecargar el constructo hay un tema si hago (int) y (long) dara errores
|
|
// y habra ambiguedad parte aevecs necsito el mismo tipo (initial reserve y number)
|
|
// asi qeu para egerera sobrecargar el parmtor #1 aveces pedira un buffer (arrray)
|
|
// vacio.... o cualquier cosa... entonces par eso esta esto..
|
|
static const int EMPTY_INITIAL_RESERVE[1];
|
|
static const double EMPTY_NUMBER_EXACT[1];
|
|
static const ENUM_TIMEFRAMES EMPTY_SWAP[1];
|
|
static const float EMPTY_ROBAR_CHECK[1];
|
|
};
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Variables estaticas |
|
|
//+------------------------------------------------------------------+
|
|
const int BigIBase::EMPTY_INITIAL_RESERVE[1] = {0};
|
|
const double BigIBase::EMPTY_NUMBER_EXACT[1] = {0.0};
|
|
const ENUM_TIMEFRAMES BigIBase::EMPTY_SWAP[1] = {0};
|
|
const float BigIBase::EMPTY_ROBAR_CHECK[1] = {0};
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Swap |
|
|
//+------------------------------------------------------------------+
|
|
// Nota v ya muere ahi noramlte esto lo usarimos en operator
|
|
// pro que ahora v tiene size=0 nada
|
|
BigIBase::BigIBase(ulong &v[], const int vs_8)
|
|
: m_v_s(vs_8)
|
|
{
|
|
// ahora m_v tiene el desipcrity de v y asi rotan
|
|
ArraySwap(m_v, v);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
BigIBase::BigIBase(const int vs_8, ulong& v[])
|
|
: m_v_s(vs_8)
|
|
{
|
|
// ahora m_v tiene el desipcrity de v y asi rotan
|
|
if(vs_8 == 0) // no hay tamaño
|
|
{
|
|
ArrayResize(m_v, 1);
|
|
m_v[0] = 0ULL;
|
|
}
|
|
else
|
|
{
|
|
ArraySwap(m_v, v);
|
|
}
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Valor |
|
|
//+------------------------------------------------------------------+
|
|
BigIBase::BigIBase(const ulong number, const int vs)
|
|
: m_v_s(vs)
|
|
{
|
|
ArrayResize(m_v, vs);
|
|
m_v[0] = (number);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Default\Reserva |
|
|
//+------------------------------------------------------------------+
|
|
BigIBase::BigIBase()
|
|
: m_v_s(BIGNUMERBYLEO_INITIAL_SIZE_ZERO)
|
|
{
|
|
ArrayResize(m_v, BIGNUMERBYLEO_INITIAL_RESERVE, BIGNUMERBYLEO_INITIAL_RESERVE); // tamaño inicial de reserva
|
|
m_v[0] = 0ULL;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
BigIBase::BigIBase(int initial_reserve)
|
|
: m_v_s(BIGNUMERBYLEO_INITIAL_SIZE_ZERO)
|
|
{
|
|
ArrayResize(m_v, initial_reserve); // sion extra
|
|
m_v[0] = 0ULL;
|
|
}
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
// resta:
|
|
// v = this - v
|
|
// se asume que:
|
|
// vs = es positivo (magnitud)
|
|
void BigIBase::RestarConYResEn(ulong &v[], int& vs) const
|
|
{
|
|
//----
|
|
//BIGNUMERBYLEO_INT_NORMALIZE(vs)
|
|
ulong borrow = 0;
|
|
int i = 0;
|
|
|
|
//---
|
|
const int lkc = vs;
|
|
vs = m_v_s;
|
|
if(vs > ArraySize(v))
|
|
ArrayResize(v, vs);
|
|
|
|
//---
|
|
// Chekea ambos daod qeu b en caso pueda tener mas bytes esos ya no se procesan
|
|
for(; i < lkc; i++)
|
|
{
|
|
const ulong res_bor = m_v[i] - borrow; // paso 0 (a-resto)
|
|
const ulong res_f = res_bor - v[i]; // paso 1 (r-b)
|
|
borrow = (m_v[i] < borrow) | // en caso sea menor (tipo m_v es 0 y borro viene cno 1
|
|
// en ese caso tendremismo qeu prestarmos 1..
|
|
// Igual aqui si el left menor al right tendra uqe prestartse
|
|
(res_bor < v[i]);
|
|
//Print(res_f);
|
|
v[i] = res_f;
|
|
}
|
|
// sobra
|
|
for(; i < m_v_s; i++)
|
|
{
|
|
const ulong r = m_v[i] - borrow;
|
|
borrow = (m_v[i] < borrow); // si es menor enonces hubo uover
|
|
v[i] = r;
|
|
}
|
|
|
|
//---
|
|
BIGNUMBERSBYLEO_CLEAN_HIGH_ZEROS(v, vs)
|
|
//BIGNUMERBYLEO_INT_SNEG(vs)
|
|
}
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
static ulong BigIBase::CTZ_Commons(const BigIBase &a, const BigIBase &b)
|
|
{
|
|
//---
|
|
int k = 0;
|
|
ulong num = 0;
|
|
const int s = a.m_v_s > b.m_v_s ? b.m_v_s : a.m_v_s; // min
|
|
|
|
//--- saltamos los 0
|
|
ulong v = a.m_v[k] | b.m_v[k];
|
|
while(true)
|
|
{
|
|
if(v) // alguno de ambos no es 0
|
|
break;
|
|
|
|
//--- sigue 0
|
|
num += 64;
|
|
|
|
//---
|
|
// Aun nada pero todo 0
|
|
// pero por lo visto almenos uno de los dos numeros es es 0
|
|
if(++k >= s)
|
|
return ULONG_MAX; // maximo posible ()
|
|
|
|
//--- segimos
|
|
v = a.m_v[k] | b.m_v[k];
|
|
}
|
|
|
|
//--- limb con valor..
|
|
const ulong flag = TSNTABLES_BIT_DEJAR_SOLO_MINUS_SIG_BYTE(v);
|
|
return num + TSNTABLES_CTZ_64_GET_BIT(flag);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Ctz |
|
|
//+------------------------------------------------------------------+
|
|
ulong BigIBase::Ctz() const
|
|
{
|
|
//---
|
|
int k = 0;
|
|
ulong num = 0;
|
|
|
|
//--- saltamos los 0
|
|
ulong v = m_v[k];
|
|
while(true)
|
|
{
|
|
//---
|
|
if(v)
|
|
break;
|
|
|
|
//--- sigue 0
|
|
num += 64;
|
|
|
|
//---
|
|
// Aun nada pero todo 0
|
|
if(++k >= m_v_s)
|
|
return ULONG_MAX; // maximo posible
|
|
|
|
//---
|
|
v = m_v[k];
|
|
}
|
|
|
|
//--- limb con valor..
|
|
const ulong flag = TSNTABLES_BIT_DEJAR_SOLO_MINUS_SIG_BYTE(v);
|
|
return num + TSNTABLES_CTZ_64_GET_BIT(flag);
|
|
}
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
template <typename TRandom>
|
|
__forceinline void BigIBase::FillRandom()
|
|
{
|
|
TRandom::RandomUlongArr(m_v, m_v_s);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
template <typename TNormAbs>
|
|
int BigIBase::CmpInt(const BigIBase &b) const
|
|
{
|
|
// iniciales
|
|
if(m_v_s > b.m_v_s)
|
|
return BIGINTEGER_CMP_MAYOR;
|
|
if(m_v_s < b.m_v_s)
|
|
return BIGINTEGER_CMP_MENOR;
|
|
// equal en size
|
|
int i = TNormAbs::AbsS(m_v_s) - 1;
|
|
for(; i >= 0; i--)
|
|
{
|
|
if(m_v[i] != b.m_v[i]) // no coindice
|
|
return m_v[i] > b.m_v[i] ? BIGINTEGER_CMP_MAYOR : BIGINTEGER_CMP_MENOR;
|
|
}
|
|
return BIGINTEGER_CMP_EQ; // iguales
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
void BigIBase::Swap(BigIBase &other)
|
|
{
|
|
BIGNUMERBYLEO_SWAP(m_v_s, other.m_v_s, int)
|
|
ArraySwap(m_v, other.m_v);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
__forceinline void BigIBase::RobarDe(BigIBase &other)
|
|
{
|
|
m_v_s = other.m_v_s;
|
|
ArraySwap(m_v, other.m_v);
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
__forceinline bool BigIBase::GetBit(const ulong bit_pos) const
|
|
{
|
|
return bool(m_v[bit_pos >> 6] & (1ULL << (bit_pos & 63)));
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
void BigIBase::SetBit(const ulong bit_pos, bool v)
|
|
{
|
|
m_v[bit_pos >> 6] &= (ulong(v) << (bit_pos & 63));
|
|
}
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
void BigIBase::UShiftLeft(const ulong b)
|
|
{
|
|
//--- chekeamos 0 dado que 0<<x con x grande peude hacer crecer el tamaño artificilaemtne de mvs
|
|
if(BIGNUMERBYLEO_UINTEGER_IZ_ZERO)
|
|
return;
|
|
|
|
//---
|
|
const int els = int(b >> 6); // b / 64
|
|
const int els_sob = int(b & 63); // % 64
|
|
|
|
//---
|
|
if(els_sob == 0) // exacto
|
|
{
|
|
//---
|
|
m_v_s += els;
|
|
if(m_v_s < ArraySize(m_v))
|
|
ArrayResize(m_v, m_v_s);
|
|
|
|
//---
|
|
int i = m_v_s - 1;
|
|
for(; i >= els; i--)
|
|
m_v[i] = m_v[i - els];
|
|
|
|
//---
|
|
for(; i >= 0; i--)
|
|
m_v[i] = 0ULL;
|
|
|
|
//---
|
|
return;
|
|
}
|
|
|
|
//---
|
|
int r = m_v_s - 1; // read pointer
|
|
const int srh = (64 - els_sob); // shr
|
|
ulong hi = m_v[r]; // valor de lectura actual hi
|
|
const ulong overflow = hi >> srh; // si los altos habia valor randeo del dhift en adelante
|
|
|
|
//---
|
|
m_v_s += els;
|
|
int w = m_v_s - 1; // escritura en els-1 (depende de que tantos salots elsb haya)
|
|
if(overflow)
|
|
{
|
|
if(++m_v_s > ArraySize(m_v)) // si la reserva actual es menor al vactual
|
|
ArrayResize(m_v, m_v_s);
|
|
m_v[m_v_s - 1] = overflow;
|
|
}
|
|
else
|
|
{
|
|
// no hay ovw enotnces nada
|
|
if(m_v_s > ArraySize(m_v)) // si la reserva actual es menor al vactual
|
|
ArrayResize(m_v, m_v_s);
|
|
}
|
|
|
|
//--- iter
|
|
while(r > 0)
|
|
{
|
|
const ulong prev = m_v[--r]; // valor previo
|
|
m_v[w--] = (hi << els_sob) | (prev >> srh); // (valor alto dezplaado) | (valor bajo overflow siguiente)
|
|
hi = prev; // ahora el alto es nuestro prev (Curr)
|
|
}
|
|
m_v[w] = hi << els_sob; // terminos con el valor 0 o ultimo
|
|
}
|
|
|
|
}
|
|
|
|
#endif // BIGNUMBERSBYLEO_SRC_BASE_COMMON_MQH
|
|
//+------------------------------------------------------------------+
|
|
/* Notas
|
|
- FromBytes: Si se pasa un buffer vacio o con tamaño de 1 y valor 0, se interpreta como 0
|
|
- Se asume que:
|
|
1. El buffer siempre tendra al menos un elemento y con valor 0
|
|
|
|
*/
|
|
//+------------------------------------------------------------------+
|