AlgLib_ver3.19/bitconvert.mqh
super.admin 9e263d779c convert
2025-05-30 14:39:48 +02:00

411 lines
14 KiB
MQL5

//+------------------------------------------------------------------+
//| bitconvert.mqh |
//| Copyright 2003-2022 Sergey Bochkanov (ALGLIB project) |
//| Copyright 2012-2023, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
//| Implementation of ALGLIB library in MetaQuotes Language 5 |
//| |
//| The features of the library include: |
//| - Linear algebra (direct algorithms, EVD, SVD) |
//| - Solving systems of linear and non-linear equations |
//| - Interpolation |
//| - Optimization |
//| - FFT (Fast Fourier Transform) |
//| - Numerical integration |
//| - Linear and nonlinear least-squares fitting |
//| - Ordinary differential equations |
//| - Computation of special functions |
//| - Descriptive statistics and hypothesis testing |
//| - Data analysis - classification, regression |
//| - Implementing linear algebra algorithms, interpolation, etc. |
//| in high-precision arithmetic (using MPFR) |
//| |
//| This file is free software; you can redistribute it and/or |
//| modify it under the terms of the GNU General Public License as |
//| published by the Free Software Foundation (www.fsf.org); either |
//| version 2 of the License, or (at your option) any later version. |
//| |
//| This program is distributed in the hope that it will be useful, |
//| but WITHOUT ANY WARRANTY; without even the implied warranty of |
//| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
//| GNU General Public License for more details. |
//+------------------------------------------------------------------+
#include "arrayresize.mqh"
//+------------------------------------------------------------------+
//| Converting numbers into an array of bits and vice versa |
//+------------------------------------------------------------------+
class BitConverter
{
public:
static void GetBytes(const int d,uchar &bytes[]);
static void GetBytes(const double d,uchar &bytes[]);
static int ToInt32(uchar &bytes[]);
static double ToDouble(uchar &bytes[]);
static bool IsLittleEndian(void);
};
//+------------------------------------------------------------------+
//| Converting integer to a byte array |
//+------------------------------------------------------------------+
void BitConverter::GetBytes(const int d,uchar &bytes[])
{
//--- create variables
int x;
int q;
int r;
int i;
int div;
//--- allocation
ArrayResize(bytes,4);
for(i=0; i<4; i++)
{
//--- check
if(d>=0)
bytes[i]=0;
else
bytes[i]=255;
}
//--- initialization
q=-1;
r=-1;
i=3;
div=256*256*256;
//--- check
if(d<0)
x=~d;
else
x=d;
//--- converting number
while(i!=-1)
{
//--- quotient
q=x/div;
//--- remainder of division
r=x%div;
//--- get byte
if(d>=0)
bytes[i]+=(uchar)q;
else
bytes[i]-=(uchar)q;
//--- the next iteration is reduced divisor
x=r;
div=div/256;
i--;
}
}
//+------------------------------------------------------------------+
//| Converting double to a byte array |
//+------------------------------------------------------------------+
void BitConverter::GetBytes(const double d,uchar &bytes[])
{
//--- module
double abs_d=MathAbs(d);
//--- number without its fractional
double floor_d=MathFloor(abs_d);
//--- fractional part
double fractional_d=abs_d-floor_d;
//--- variable will store the degree
int power;
//--- exponent shift
double exp_shift;
//--- create variables
int k;
int j;
uchar u;
double step;
double f;
//--- abs_d as bits
bool abs_d_to_bitArray[];
//--- d as bits in format IEEE 754
bool d_to_bitArray[];
//--- allocation
ArrayResizeAL(d_to_bitArray,64);
ArrayResizeAL(bytes,8);
//--- initialization
power=0;
//--- for integer part
while(1)
{
//--- if the number is less than or equal floor_d, we increase the degree
//--- if 2^power > floor_d, then maximal number < floor_d - it 2^(power-1)
if(floor_d>=MathPow(2,power))
power++;
else
break;
}
//--- get power-1
power--;
//--- if power=-1, then floor_d=0
//--- find a negative power for the fractional part
if(power==-1)
{
power=0;
while(1)
{
//--- the same principle as above
if(fractional_d<MathPow(2,power))
power--;
else
break;
}
}
//--- convert decimal to binary
j=0;
step=power;
while(abs_d!=0.0)
{
f=MathPow(2,step);
//--- check
if(f>abs_d)
{
//--- if abs_d < f - this bit is zero
ArrayResize(abs_d_to_bitArray,j+1);
abs_d_to_bitArray[j]=0;
j++;
step-=1;
}
else
{
//--- if abs_d >= f, then this bit is equal one
//--- reduction abs_d
abs_d-=f;
ArrayResize(abs_d_to_bitArray,j+1);
abs_d_to_bitArray[j]=1;
j++;
step-=1;
}
}
//--- according to IEEE 754,
//--- zero bit determines sign of the number, 0 -> '+', 1 -> '-'.
if(d>=0)
d_to_bitArray[0]=0;
else
d_to_bitArray[0]=1;
//--- offset input
exp_shift=1023+power;
//--- bits from the first and 11 are reserved for the shifted exponential
j=1;
for(int i=10; i>=0; i--)
{
if(MathPow(2,i)>exp_shift)
d_to_bitArray[j]=0;
else
{
d_to_bitArray[j]=1;
//--- reduction
exp_shift-=MathPow(2,i);
}
j++;
}
//--- Get the length of the array of the binary representation of abs_d
k=ArraySize(abs_d_to_bitArray);
j=1;
//--- Bits from 12 to 63 are filled with binary representation of abs_b
//--- the first element abs_d_to_bitArray is always 1
for(int i=12; i<64; i++)
{
if(j<k)
{
d_to_bitArray[i]=abs_d_to_bitArray[i-11];
j++;
}
else
d_to_bitArray[i]=0;
}
//--- reverse
ArrayReverse(d_to_bitArray);
//--- converting bit array to byte array
for(int i=0; i<8; i++)
{
u=0;
//--- get byte
for(int t=0; t<8; t++)
u+=(uchar)(d_to_bitArray[i*8+t]*MathPow(2,t));
//--- save byte
bytes[i]=u;
}
}
//+------------------------------------------------------------------+
//| Converting byte array to a integer |
//+------------------------------------------------------------------+
int BitConverter::ToInt32(uchar &bytes[])
{
//--- get size
int size=ArraySize(bytes);
//--- create variables
int d=0;
int mul=256*256*256;
//--- get number
for(int i=size-1; i>=0; i--)
{
d+=bytes[i]*mul;
mul=mul/256;
}
//--- return result
return(d);
}
//+------------------------------------------------------------------+
//| Converting byte array to a double |
//+------------------------------------------------------------------+
double BitConverter::ToDouble(uchar &bytes[])
{
//--- create variables
int s;
//--- exponent shift
int e=0;
//--- mantissa
double m=0;
//--- array of bits in IEEE 754
bool bits[];
ArrayResize(bits,64);
//--- get array of bits from array of bytes
for(int i=0; i<8; i++)
{
for(int j=7; j>=0; j--)
{
//--- if 2 in power >, bits[i*8+j]=0, else bits[i*8+j]=0
if(MathPow(2,j)>bytes[i])
bits[i*8+j]=0;
else
{
bits[i*8+j]=1;
//--- reduction
bytes[i]-=(uchar)MathPow(2,j);
}
}
}
//--- search bits with 1
bool allzero=true;
for(int i=0; i<64; i++)
if(bits[i]==1)
allzero=false;
//--- if all bits are 0, then number is 0
if(allzero==true)
return(0.0);
//--- reverse array
ArrayReverse(bits);
//--- s-the first bit, determines sign of the number
s=bits[0];
//--- calculation exponent shift
for(int i=10; i>=0; i--)
e+=(int)(bits[11-i]*MathPow(2,i));
//--- get mantissa
for(int i=0; i<52; i++)
m+=bits[12+i]*MathPow(2,-1-i);
//--- return result
return(MathPow(-1,s)*MathPow(2,e-1023)*(1+m));
}
//+------------------------------------------------------------------+
//| Byte ordering (forward, backward) |
//+------------------------------------------------------------------+
bool BitConverter::IsLittleEndian(void)
{
//--- forward
return(true);
}
//+------------------------------------------------------------------+
//| Get string from char array |
//+------------------------------------------------------------------+
string GetSelectionString(char &buf[],int startIndex,int lenght)
{
return(CharArrayToString(buf,startIndex,lenght));
}
//+------------------------------------------------------------------+
//| Get sign of number |
//+------------------------------------------------------------------+
double MathSign(const double x)
{
//--- if x>0
if(x>0)
return(1);
//--- if ?==0
if(x==0)
return(0);
//--- ?<0
return(-1);
}
//+------------------------------------------------------------------+
//| Structure stores a variable of type double |
//+------------------------------------------------------------------+
union UDoubleValue
{
double value;
long bits;
UDoubleValue(double dbl): value(dbl) { }
UDoubleValue(long bit_value): bits(bit_value) { }
};
//+------------------------------------------------------------------+
//| Work with infinity and NaN |
//+------------------------------------------------------------------+
class CInfOrNaN
{
public:
//--- checks
static bool IsPositiveInfinity(const double x);
static bool IsNegativeInfinity(const double x);
static bool IsInfinity(const double x);
static bool IsNaN(const double x);
//--- generation values
static double PositiveInfinity(void);
static double NegativeInfinity(void);
static double NaN(void);
};
//+------------------------------------------------------------------+
//| Check for +inf |
//+------------------------------------------------------------------+
bool CInfOrNaN::IsPositiveInfinity(const double x)
{
UDoubleValue val=x;
//--- check
return(val.bits==0x7FF0000000000000);
}
//+------------------------------------------------------------------+
//| Check for -inf |
//+------------------------------------------------------------------+
bool CInfOrNaN::IsNegativeInfinity(const double x)
{
UDoubleValue val=x;
//--- check
return(val.bits==0xFFF0000000000000);
}
//+------------------------------------------------------------------+
//| Check for +-inf |
//+------------------------------------------------------------------+
bool CInfOrNaN::IsInfinity(const double x)
{
return(MathClassify(x)==FP_INFINITE);
}
//+------------------------------------------------------------------+
//| Check for NaN |
//+------------------------------------------------------------------+
bool CInfOrNaN::IsNaN(const double x)
{
return(MathClassify(x)==FP_NAN);
}
//+------------------------------------------------------------------+
//| Return +inf |
//+------------------------------------------------------------------+
double CInfOrNaN::PositiveInfinity(void)
{
UDoubleValue val(0x7FF0000000000000);
return(val.value);
}
//+------------------------------------------------------------------+
//| Return -inf |
//+------------------------------------------------------------------+
double CInfOrNaN::NegativeInfinity(void)
{
UDoubleValue val(0xFFF0000000000000);
return(val.value);
}
//+------------------------------------------------------------------+
//| Return NaN |
//+------------------------------------------------------------------+
double CInfOrNaN::NaN(void)
{
UDoubleValue val(0x7FFFFFFFFFFFFFFF);
return(val.value);
}
//+------------------------------------------------------------------+