BigNumberByLeo/Src/Base/Common.mqh

430 lines
13 KiB
MQL5

2026-09-09 20:01:29 -05:00
//+------------------------------------------------------------------+
//| 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);
2026-09-10 07:16:18 -05:00
BigIBase(const int vs_8, ulong& v[]);
//-- Se inicia desde un numero en especiifco y con un tamaño (Que tambien es la reserva)
2026-09-09 20:01:29 -05:00
BigIBase(const ulong number, const int vs);
//-- Se inicia con un valor de 0 pero la idea es reservar limbs inciiales\nada (32 defualt)
2026-09-10 07:16:18 -05:00
BigIBase(int initial_reserve);
2026-09-09 20:01:29 -05:00
BigIBase();
//--- Cmp
template <typename TNormAbs>
int CmpInt(const BigIBase &b) const;
2026-09-09 20:01:29 -05:00
public:
//--- raw
ulong m_v[];
int m_v_s;
2026-09-10 12:25:44 -05:00
//--- 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;
2026-09-09 20:01:29 -05:00
//--- Es par
__forceinline bool IsPar() const { return BIGNUMERBYLEO_UINTEGER_IZ_PAR; }
//--- es Zero
__forceinline bool IsZero() const { return BIGNUMERBYLEO_UINTEGER_IZ_ZERO; }
2026-09-10 09:23:17 -05:00
__forceinline bool IsNotZero() const { return BIGNUMERBYLEO_UINTEGER_IZ_NZERO; }
2026-09-09 20:01:29 -05:00
//--- 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;
2026-09-09 20:01:29 -05:00
//--- Swap
void Swap(BigIBase& other);
//--- Bits
ulong Ctz() const;
//---
__forceinline void RobarDe(BigIBase &other);
//---
template <typename TRandom>
__forceinline void FillRandom();
2026-09-11 14:45:51 -05:00
//---
void UShiftLeft(const ulong b);
2026-09-09 20:01:29 -05:00
//---- 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];
2026-09-10 07:16:18 -05:00
static const float EMPTY_ROBAR_CHECK[1];
2026-09-09 20:01:29 -05:00
};
//+------------------------------------------------------------------+
//| 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};
2026-09-10 07:16:18 -05:00
const float BigIBase::EMPTY_ROBAR_CHECK[1] = {0};
2026-09-09 20:01:29 -05:00
//+------------------------------------------------------------------+
2026-09-10 07:16:18 -05:00
//| Swap |
2026-09-09 20:01:29 -05:00
//+------------------------------------------------------------------+
// 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);
}
//+------------------------------------------------------------------+
2026-09-10 07:16:18 -05:00
BigIBase::BigIBase(const int vs_8, ulong& v[])
2026-09-09 20:01:29 -05:00
: m_v_s(vs_8)
{
// ahora m_v tiene el desipcrity de v y asi rotan
2026-09-10 09:23:17 -05:00
if(vs_8 == 0) // no hay tamaño
2026-09-10 07:16:18 -05:00
{
ArrayResize(m_v, 1);
m_v[0] = 0ULL;
}
else
{
ArraySwap(m_v, v);
}
2026-09-09 20:01:29 -05:00
}
//+------------------------------------------------------------------+
2026-09-10 07:16:18 -05:00
//| Valor |
2026-09-09 20:01:29 -05:00
//+------------------------------------------------------------------+
BigIBase::BigIBase(const ulong number, const int vs)
: m_v_s(vs)
{
2026-09-10 07:16:18 -05:00
ArrayResize(m_v, vs);
2026-09-09 20:01:29 -05:00
m_v[0] = (number);
}
2026-09-10 07:16:18 -05:00
//+------------------------------------------------------------------+
//| Default\Reserva |
2026-09-09 20:01:29 -05:00
//+------------------------------------------------------------------+
BigIBase::BigIBase()
2026-09-10 09:23:17 -05:00
: m_v_s(BIGNUMERBYLEO_INITIAL_SIZE_ZERO)
2026-09-09 20:01:29 -05:00
{
2026-09-10 07:16:18 -05:00
ArrayResize(m_v, BIGNUMERBYLEO_INITIAL_RESERVE, BIGNUMERBYLEO_INITIAL_RESERVE); // tamaño inicial de reserva
2026-09-09 20:01:29 -05:00
m_v[0] = 0ULL;
}
//+------------------------------------------------------------------+
2026-09-10 07:16:18 -05:00
BigIBase::BigIBase(int initial_reserve)
2026-09-10 09:23:17 -05:00
: m_v_s(BIGNUMERBYLEO_INITIAL_SIZE_ZERO)
2026-09-09 20:01:29 -05:00
{
ArrayResize(m_v, initial_reserve); // sion extra
m_v[0] = 0ULL;
}
2026-09-10 12:25:44 -05:00
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
// resta:
// v = this - v
// se asume que:
// vs = es positivo (magnitud)
2026-09-10 12:25:44 -05:00
void BigIBase::RestarConYResEn(ulong &v[], int& vs) const
{
//----
2026-09-11 14:45:51 -05:00
//BIGNUMERBYLEO_INT_NORMALIZE(vs)
2026-09-10 12:25:44 -05:00
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)
2026-09-11 14:45:51 -05:00
//BIGNUMERBYLEO_INT_SNEG(vs)
2026-09-10 12:25:44 -05:00
}
2026-09-09 20:01:29 -05:00
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
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
2026-09-09 20:01:29 -05:00
{
// 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--)
2026-09-09 20:01:29 -05:00
{
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)
2026-09-09 20:01:29 -05:00
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));
}
2026-09-11 14:45:51 -05:00
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
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
}
2026-09-09 20:01:29 -05:00
}
#endif // BIGNUMBERSBYLEO_SRC_BASE_COMMON_MQH
//+------------------------------------------------------------------+
2026-09-10 07:16:18 -05:00
/* 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
*/
//+------------------------------------------------------------------+