169 lines
4.9 KiB
MQL5
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
|