2026-10-09 12:34:15 -05:00 | | | //+------------------------------------------------------------------+
|
| | | //| Dbl.mqh |
|
| | | //| Copyright 2026, Niquel Mendoza. |
|
| | | //| https://www.mql5.com |
|
| | | //+------------------------------------------------------------------+
|
| | | #property copyright "Copyright 2026, Niquel Mendoza."
|
| | | #property link "https://www.mql5.com"
|
| | | #property strict
|
| | |
|
2026-10-09 12:56:38 -05:00 | | | #ifndef TSNSTD_SRC_STRING_CONVDEF_DBL_MQH
|
| | | #define TSNSTD_SRC_STRING_CONVDEF_DBL_MQH
|
2026-10-09 12:34:15 -05:00 | | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
| | | #include "Def.mqh"
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
| | | namespace TSN
|
| | | {
|
| | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
| | | //---
|
| | | // 5^q
|
| | | #define STRCONV_DBL_LOG2(q) ((((152170 + 65536) * (q)) >> 16) + 63)
|
| | |
|
| | | //---
|
| | | union __UDoubleToLong
|
| | | {
|
| | | double d;
|
| | | long l;
|
| | | ulong u;
|
| | | };
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
| | | class CDoubleParser
|
| | | {
|
| | | public:
|
| | | CDoubleParser(void) {}
|
| | | ~CDoubleParser(void) {}
|
| | |
|
| | | //---
|
| | | static void ComputeDbl(const int q, ulong w, ulong& mantissa, int& power2);
|
| | | };
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
| | | // la idea con esto es caualr la mejor aproximacion para w × 10^q
|
| | | // w = mantisa (numeros significativos)
|
| | | // q = exponente decimal
|
| | | //---
|
| | | #define MQLARTICLES_DBLPARSE_DBL_PRESICION (56)
|
| | | // real: ((P)<64)?(ulong)0xFFFFFFFFFFFFFFFF>>(P):(ulong)0xFFFFFFFFFFFFFFFF
|
| | | #define MQLARTICLES_DBLPARSE_PMASK(P) ((ulong)0xFFFFFFFFFFFFFFFF>>(P))
|
| | | #define MQLARTICLES_DBLPARSE_PMASK_DBL (MQLARTICLES_DBLPARSE_PMASK(MQLARTICLES_DBLPARSE_DBL_PRESICION))
|
| | |
|
| | | //---
|
| | | static void CDoubleParser::ComputeDbl(const int q, ulong w, ulong& mantissa, int& power2)
|
| | | {/*
|
| | | //---
|
| | | if(w == 0 || q < TSN_SMALLEST_POWER_OF_FIVE) // muy pequeño (0)
|
| | | {
|
| | | power2 = 0;
|
| | | mantissa = 0;
|
| | | return;
|
| | | }
|
| | | if(q > TSN_LARGEST_POWER_OF_FIVE) // muy grande (inf)
|
| | | {
|
| | | power2 = TSN_INFINITE_POWER;
|
| | | mantissa = 0;
|
| | | return;
|
| | | }
|
| | |
|
| | | //---
|
| | | const int lz = CBitTricks::CLZ(w);
|
| | | w <<= lz;
|
| | |
|
| | | //---
|
| | | ulong phi, plo;
|
| | |
|
| | | //--- algortimo de estimacino en si
|
| | | // valor - minimo posible (-(.))
|
| | | // valor - (-x)
|
| | | // valor + x
|
| | | // la idea es como aseguramnso que q el reusltado de esto no es nefativo
|
| | | // en teoria nucna lo sera pro que tenemos que q como minimo vale -342 + 342 = 0
|
| | | // como valor minimo
|
| | | const int index = int(q + (-TSN_SMALLEST_POWER_OF_FIVE)) << 1;
|
| | | // primera multiplicacion
|
| | | CNumberUtils::Mul64to128(w, g_tsn_power_of_five_128[index], phi, plo);
|
| | | if((phi & MQLARTICLES_DBLPARSE_PMASK_DBL) == MQLARTICLES_DBLPARSE_PMASK_DBL)
|
| | | {
|
| | | // mas presicion
|
| | | ulong shi = 0, slo = 0;
|
| | | CNumberUtils::Mul64to128(w, g_tsn_power_of_five_128[index + 1], phi, slo);
|
| | | plo += shi;
|
| | | if(shi > plo) // carry
|
| | | phi++;
|
| | | }
|
| | |
|
| | | //---
|
| | | const int upperbit = int(phi >> 63);
|
| | | // upperbit 1=0 por lo que shift >0
|
| | | const int shift = upperbit + (64 - TSN_MANTISSA_EXPLICIT_BITS - 3);
|
| | |
|
| | | //---
|
| | | mantissa = phi >> shift;
|
| | | power2 = STRCONV_DBL_LOG2(q) + upperbit - lz - TSN_MINIMUM_EXPONENT;
|
| | |
|
| | | //---
|
| | | if(power2 <= 0) // subnormal
|
| | | {
|
| | | const int s = -power2 + 1;
|
| | | if(s >= 64)
|
| | | {
|
| | | power2 = 0;
|
| | | mantissa = 0;
|
| | | return;
|
| | | }
|
| | |
|
| | | //---
|
| | | mantissa >>= s;
|
| | | mantissa += (mantissa & 1); // redondeo
|
| | | mantissa >>= 1;
|
| | | // si es true 1 si no 0
|
| | | power2 = (mantissa >= (1ULL << TSN_MANTISSA_EXPLICIT_BITS));
|
| | | return;
|
| | | }
|
| | |
|
| | | //---
|
| | | // if(plo <= 1 &&
|
| | | // q >= TSN_MIN_EXPONENT_ROUND_TO_EVEN &&
|
| | | // q <= TSN_MAX_EXPONENT_ROUND_TO_EVEN &&
|
| | | // (mantissa & 3) == 1 &&
|
| | | // (mantissa << shift) == phi)
|
| | | // {
|
| | | // mantissa &= (~1ULL); // forzar redondeo hacia abajo
|
| | | // }
|
| | |
|
| | | //--- redondeo final
|
| | | mantissa += (mantissa & 1);
|
| | | mantissa >>= 1;
|
| | |
|
| | | //--- correcion por carry
|
| | | if(mantissa >= (2ULL << TSN_MANTISSA_EXPLICIT_BITS))
|
| | | {
|
| | | mantissa = (1ULL << TSN_MANTISSA_EXPLICIT_BITS);
|
| | | power2++;
|
| | | }
|
| | |
|
| | | //--- limpieza de implicto
|
| | | mantissa &= (~(1ULL << TSN_MANTISSA_EXPLICIT_BITS));
|
| | |
|
| | | //--- clamp
|
| | | if(power2 >= TSN_INFINITE_POWER)
|
| | | {
|
| | | power2 = TSN_INFINITE_POWER;
|
| | | mantissa = 0;
|
| | | }*/
|
| | | }
|
| | | }
|
| | | //+------------------------------------------------------------------+
|
2026-10-09 12:56:38 -05:00 | | | #endif // TSNSTD_SRC_STRING_CONVDEF_DBL_MQH
|