//+------------------------------------------------------------------+ //| 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 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 __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 __forceinline void BigIBase::FillRandom() { TRandom::RandomUlongArr(m_v, m_v_s); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ template 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<> 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 */ //+------------------------------------------------------------------+