411 lines
14 KiB
MQL5
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);
|
|
}
|
|
//+------------------------------------------------------------------+
|