TSNStd/Src/String/ConvDef/Dbl.mqh
Nique_372 1dc77364ec
2026-10-09 12:56:38 -05:00

169 lines
4.9 KiB
MQL5

//+------------------------------------------------------------------+
//| Dbl.mqh |
//| Copyright 2026, Niquel Mendoza. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2026, Niquel Mendoza."
#property link "https://www.mql5.com"
#property strict
#ifndef TSNSTD_SRC_STRING_CONVDEF_DBL_MQH
#define TSNSTD_SRC_STRING_CONVDEF_DBL_MQH
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
#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;
}*/
}
}
//+------------------------------------------------------------------+
#endif // TSNSTD_SRC_STRING_CONVDEF_DBL_MQH