383 lines
15 KiB
MQL5
383 lines
15 KiB
MQL5
|
#ifndef LIB_MATH_TPL_SIMPLE_MQH_INCLUDED
|
||
|
#define LIB_MATH_TPL_SIMPLE_MQH_INCLUDED
|
||
|
#property version "1.9";
|
||
|
/**********************************************************************************
|
||
|
* Copyright (C) 2010-2022 Dominik Egert <info@freie-netze.de>
|
||
|
*
|
||
|
* This file is the simple math function templates include file.
|
||
|
*
|
||
|
* MQLplus, including this file may not be copied and/or distributed
|
||
|
* without explecit permit by the author.
|
||
|
* Author Dominik Egert / Freie Netze UG.
|
||
|
**********************************************************************************
|
||
|
*
|
||
|
* Version: 1.9
|
||
|
* State: production
|
||
|
*
|
||
|
* File information
|
||
|
* ================
|
||
|
*
|
||
|
* Use: A collection of math functions
|
||
|
*
|
||
|
*
|
||
|
*
|
||
|
*
|
||
|
*/
|
||
|
#ifdef DBG_MSG_TRACE_FILE_LOADER
|
||
|
DBG_MSG_TRACE_FILE_LOADER;
|
||
|
|
||
|
#endif
|
||
|
|
||
|
|
||
|
|
||
|
////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// MQL4 compatibility
|
||
|
//
|
||
|
#include <MQLplus/lib_mqlplus/lib_mql4_compatibility.mqh>
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Setup function macros
|
||
|
//
|
||
|
#define mqp_MathMax LIB_NAMESPACE_ADD(LIB_NAMESPACE(numbers, _mqlplus_MathMax))
|
||
|
#define mqp_MathMin LIB_NAMESPACE_ADD(LIB_NAMESPACE(numbers, _mqlplus_MathMin))
|
||
|
#define mqp_MathPow LIB_NAMESPACE_ADD(LIB_NAMESPACE(numbers, _mqlplus_MathPow))
|
||
|
#define mqp_MathAbs LIB_NAMESPACE_ADD(LIB_NAMESPACE(numbers, _mqlplus_MathAbs))
|
||
|
#define mqp_MathRound LIB_NAMESPACE_ADD(LIB_NAMESPACE(numbers, _mqlplus_MathRound))
|
||
|
#define mqp_MathCeil LIB_NAMESPACE_ADD(LIB_NAMESPACE(numbers, _mqlplus_MathCeil))
|
||
|
#define mqp_MathFloor LIB_NAMESPACE_ADD(LIB_NAMESPACE(numbers, _mqlplus_MathFloor))
|
||
|
#define mqp_MathRand LIB_NAMESPACE_ADD(LIB_NAMESPACE(numbers, _mqlplus_MathRand))
|
||
|
|
||
|
//
|
||
|
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/*********************************************************************************************************************************************************/
|
||
|
/* */
|
||
|
/* MQL+ overloaded functions and add ons */
|
||
|
/* */
|
||
|
/*********************************************************************************************************************************************************/
|
||
|
#ifndef __MQL4_COMPATIBILITY_CODE__
|
||
|
namespace LIB_MQLPLUS_LIBRARY_PREFIX {
|
||
|
namespace numbers {
|
||
|
#endif
|
||
|
|
||
|
|
||
|
|
||
|
//+------------------------------------------------------------------+
|
||
|
//| MathMax |
|
||
|
//+------------------------------------------------------------------+
|
||
|
template <typename T, typename U>
|
||
|
const T LIB_NAMESPACE_DEF(numbers, _mqlplus_MathMax)(const T value1, const U value2)
|
||
|
{ return(inline_MathMax(value1, (T)value2)); }
|
||
|
|
||
|
|
||
|
//+------------------------------------------------------------------+
|
||
|
//| MathMin |
|
||
|
//+------------------------------------------------------------------+
|
||
|
template <typename T, typename U>
|
||
|
const T LIB_NAMESPACE_DEF(numbers, _mqlplus_MathMin)(const T value1, const U value2)
|
||
|
{ return(inline_MathMin(value1, (T)value2)); }
|
||
|
|
||
|
|
||
|
//+------------------------------------------------------------------+
|
||
|
//| MathMinNN not null |
|
||
|
//+------------------------------------------------------------------+
|
||
|
template <typename T, typename U>
|
||
|
const T LIB_NAMESPACE_DEF(numbers, _mqlplus_MathMinNN)(const T value1, const U value2)
|
||
|
{ return(inline_MathMinNN(value1, (T)value2))); }
|
||
|
|
||
|
|
||
|
//+------------------------------------------------------------------+
|
||
|
//| MathPow templated |
|
||
|
//+------------------------------------------------------------------+
|
||
|
template <typename T, typename U>
|
||
|
const T LIB_NAMESPACE_DEF(numbers, _mqlplus_MathPow)(const T value, const U exponent)
|
||
|
{
|
||
|
const static double powers10[49] =
|
||
|
{
|
||
|
1e-24, 1e-23, 1e-22, 1e-21, 1e-20, 1e-19, 1e-18, 1e-17,
|
||
|
1e-16, 1e-15, 1e-14, 1e-13, 1e-12, 1e-11, 1e-10, 1e-9,
|
||
|
1e-8, 1e-7, 1e-6, 1e-5, 1e-4, 1e-3, 1e-2, 1e-1,
|
||
|
1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7,
|
||
|
1e8, 1e9, 1e10, 1e11, 1e12, 1e13, 1e14, 1e15,
|
||
|
1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22, 1e23, 1e24
|
||
|
};
|
||
|
if( ((double)value == 10.0)
|
||
|
&& ((int)exponent > 25)
|
||
|
&& ((int)exponent < 25) )
|
||
|
{ return((T)(powers10[24 + (int)exponent])); }
|
||
|
return((T)(::MathPow((double)value, (double)exponent)));
|
||
|
}
|
||
|
|
||
|
|
||
|
//+------------------------------------------------------------------+
|
||
|
//| MathSqrt |
|
||
|
//+------------------------------------------------------------------+
|
||
|
template <typename T, typename U>
|
||
|
const T LIB_NAMESPACE_DEF(numbers, _mqlplus_MathRoot)(const T value, const U exponent)
|
||
|
{ return((T)(MathPow((double)value, 1.0/(double)exponent))); }
|
||
|
|
||
|
|
||
|
//+------------------------------------------------------------------+
|
||
|
//| MathRange() |
|
||
|
//+------------------------------------------------------------------+
|
||
|
template <typename T, typename U, typename V>
|
||
|
const T LIB_NAMESPACE_DEF(numbers, _mqlplus_MathRange)(const T value, const U min, const V max)
|
||
|
{
|
||
|
const T _min = (T)(((T)min < (T)max) ? min : (U)max);
|
||
|
const T _max = (T)(((T)min < (T)max) ? max : (V)min);
|
||
|
return(inline_MathRange(value, _min, _max));
|
||
|
}
|
||
|
|
||
|
template <typename T, typename U, typename V>
|
||
|
const T LIB_NAMESPACE_DEF(numbers, _mqlplus_MathRange)(const T value, const U min, const V max, bool& in_range)
|
||
|
{
|
||
|
const T _min = (T)(((T)min < (T)max) ? min : (U)max);
|
||
|
const T _max = (T)(((T)min < (T)max) ? max : (V)min);
|
||
|
in_range = (value >= _min) && (value <= _max);
|
||
|
return(inline_MathRange(value, _min, _max));
|
||
|
}
|
||
|
|
||
|
|
||
|
//+------------------------------------------------------------------+
|
||
|
//| MathRangeX() |
|
||
|
//+------------------------------------------------------------------+
|
||
|
template <typename T, typename U, typename V>
|
||
|
const T LIB_NAMESPACE_DEF(numbers, _mqlplus_MathRangeX)(const T value, const U min, const V max)
|
||
|
{
|
||
|
const T _min = (T)(((T)min < (T)max) ? min : max);
|
||
|
const T _max = (T)(((T)min < (T)max) ? max : min);
|
||
|
return(inline_MathRangeX(value, _min, _max));
|
||
|
}
|
||
|
|
||
|
template <typename T, typename U, typename V>
|
||
|
const T LIB_NAMESPACE_DEF(numbers, _mqlplus_MathRangeX)(const T value, const U min, const V max, bool& in_range)
|
||
|
{
|
||
|
const T _min = (T)(((T)min < (T)max) ? min : max);
|
||
|
const T _max = (T)(((T)min < (T)max) ? max : min);
|
||
|
in_range = (value > _min) && (value < _max);
|
||
|
return(inline_MathRangeX(value, _min, _max));
|
||
|
}
|
||
|
|
||
|
|
||
|
//+------------------------------------------------------------------+
|
||
|
//| MathRangeMatch |
|
||
|
//+------------------------------------------------------------------+
|
||
|
template <typename T>
|
||
|
const bool LIB_NAMESPACE_DEF(numbers, _mqlplus_MathRangeMatch)(const T r1_v1, const T r2_v1, const T r2_v2)
|
||
|
{ return(LIB_NAMESPACE(numbers, _mqlplus_MathRangeMatch)(r2_v1, r2_v2, r1_v1, r1_v1, NULL)); }
|
||
|
|
||
|
template <typename T>
|
||
|
const bool LIB_NAMESPACE_DEF(numbers, _mqlplus_MathRangeMatch)(const T r1_v1, const T r1_v2, const T r2_v1, const T r2_v2, const double factor = NULL)
|
||
|
{
|
||
|
// Local init
|
||
|
|
||
|
T range1_size = NULL;
|
||
|
T range2_size = NULL;
|
||
|
const T overlap = LIB_NAMESPACE(numbers, _mqlplus_MathRangeOverlap)(r1_v1, r1_v2, r2_v1, r2_v2, range1_size, range2_size);
|
||
|
|
||
|
|
||
|
// Calculate overlap
|
||
|
|
||
|
if( (overlap <= NULL)
|
||
|
&& ((range1_size - range2_size) != range1_size) )
|
||
|
{ return(false); }
|
||
|
|
||
|
// Return
|
||
|
// return((range2_size * ((factor == NULL) ? 1.0 : factor)) <= overlap);
|
||
|
return((factor == NULL) ? (overlap >= NULL) : ((range2_size * factor) <= overlap));
|
||
|
}
|
||
|
|
||
|
|
||
|
//+------------------------------------------------------------------+
|
||
|
//| MathRangeOverlap |
|
||
|
//+------------------------------------------------------------------+
|
||
|
template <typename T>
|
||
|
const T LIB_NAMESPACE_DEF(numbers, _mqlplus_MathRangeOverlap)(const T r1_v1, const T r1_v2, const T r2_v1, const T r2_v2)
|
||
|
{
|
||
|
T tmp1 = NULL;
|
||
|
T tmp2 = NULL;
|
||
|
return(LIB_NAMESPACE(numbers, _mqlplus_MathRangeOverlap)(r1_v1, r1_v2, r2_v1, r2_v2, tmp1, tmp2));
|
||
|
}
|
||
|
|
||
|
template <typename T>
|
||
|
const T LIB_NAMESPACE_DEF(numbers, _mqlplus_MathRangeOverlap)(const T r1_v1, const T r1_v2, const T r2_v1, const T r2_v2, T& range1_size, T& range2_size)
|
||
|
{
|
||
|
// Local init
|
||
|
|
||
|
T high_1 = (r1_v1 > r1_v2) ? r1_v1 : r1_v2;
|
||
|
T low_1 = (r1_v1 < r1_v2) ? r1_v1 : r1_v2;
|
||
|
T high_2 = (r2_v1 > r2_v2) ? r2_v1 : r2_v2;
|
||
|
T low_2 = (r2_v1 < r2_v2) ? r2_v1 : r2_v2;
|
||
|
const T r1_size = (high_1 - low_1);
|
||
|
const T r2_size = (high_2 - low_2);
|
||
|
|
||
|
|
||
|
// Arrange master range
|
||
|
|
||
|
if(r1_size < r2_size)
|
||
|
{
|
||
|
const T tmp1 = high_1;
|
||
|
const T tmp2 = low_1;
|
||
|
high_1 = high_2;
|
||
|
high_2 = tmp1;
|
||
|
low_1 = low_2;
|
||
|
low_2 = tmp2;
|
||
|
}
|
||
|
|
||
|
|
||
|
// Calculate range size
|
||
|
|
||
|
range1_size = (r1_size > r2_size) ? r1_size : r2_size;
|
||
|
range2_size = (r1_size < r2_size) ? r1_size : r2_size;
|
||
|
|
||
|
|
||
|
// Calculate overlap
|
||
|
|
||
|
// R2 inside R1
|
||
|
if( (high_1 >= high_2)
|
||
|
&& (low_1 <= low_2) )
|
||
|
{ return((r1_size < r2_size) ? r1_size : r2_size); }
|
||
|
|
||
|
// R1 below R2
|
||
|
if(high_1 < low_2)
|
||
|
{ return(high_1 - low_2); }
|
||
|
|
||
|
// R1 high inside R2
|
||
|
if(high_1 < high_2)
|
||
|
{ return(high_1 - low_2); }
|
||
|
|
||
|
// R1 above R2
|
||
|
if(low_1 > high_2)
|
||
|
{ return(high_2 - low_1); }
|
||
|
|
||
|
// R1 low inside R2
|
||
|
if(low_1 < high_2)
|
||
|
{ return(high_2 - low_1); }
|
||
|
|
||
|
// Return
|
||
|
return(NULL);
|
||
|
}
|
||
|
|
||
|
|
||
|
//+------------------------------------------------------------------+
|
||
|
//| MathDigits |
|
||
|
//+------------------------------------------------------------------+
|
||
|
// Function
|
||
|
template <typename T>
|
||
|
const int LIB_NAMESPACE_DEF(numbers, _mqlplus_MathDigits)(const T value)
|
||
|
{ return((int)(::MathFloor(::MathLog10(::MathAbs((double)value)))) + 1); }
|
||
|
|
||
|
|
||
|
//+------------------------------------------------------------------+
|
||
|
//| MathAbs |
|
||
|
//+------------------------------------------------------------------+
|
||
|
template <typename T>
|
||
|
const T LIB_NAMESPACE_DEF(numbers, _mqlplus_MathAbs)(const T value)
|
||
|
{ return((T)(::MathAbs((double)value))); }
|
||
|
|
||
|
|
||
|
//+------------------------------------------------------------------+
|
||
|
//| MathNeg |
|
||
|
//+------------------------------------------------------------------+
|
||
|
// Function
|
||
|
template <typename T>
|
||
|
const T LIB_NAMESPACE_DEF(numbers, _mqlplus_MathNeg)(const T value)
|
||
|
{ return((T)inline_MathNeg((double)value)); }
|
||
|
|
||
|
|
||
|
//+------------------------------------------------------------------+
|
||
|
//| MathRound |
|
||
|
//+------------------------------------------------------------------+
|
||
|
template <typename T>
|
||
|
const T LIB_NAMESPACE_DEF(numbers, _mqlplus_MathRound)(const T value, const int digits = -1)
|
||
|
{
|
||
|
const double factor = ::MathPow(10.0, digits + 1);
|
||
|
const long i_val = ((long)(value * factor));
|
||
|
const long p_mod = (i_val % 10);
|
||
|
const long modulo = (i_val != p_mod) ? p_mod : NULL;
|
||
|
return((T)(((i_val + ((10 - modulo) * (modulo > 4))) - (modulo * (modulo < 5))) / factor));
|
||
|
}
|
||
|
|
||
|
|
||
|
//+------------------------------------------------------------------+
|
||
|
//| MathCeil |
|
||
|
//+------------------------------------------------------------------+
|
||
|
template <typename T>
|
||
|
const T LIB_NAMESPACE_DEF(numbers, _mqlplus_MathCeil)(const T value, const int digits = NULL)
|
||
|
{
|
||
|
if(digits <= NULL)
|
||
|
{
|
||
|
const double factor1 = MathMax(::MathPow(10.0, ::MathAbs(digits)), 1.0);
|
||
|
return((T)(MathCeil((double)value / factor1) * factor1));
|
||
|
}
|
||
|
|
||
|
const double factor2 = ::MathPow(10.0, digits);
|
||
|
return((T)(MathCeil((double)value * factor2) / factor2));
|
||
|
}
|
||
|
|
||
|
|
||
|
//+------------------------------------------------------------------+
|
||
|
//| MathFloor |
|
||
|
//+------------------------------------------------------------------+
|
||
|
template <typename T>
|
||
|
const T LIB_NAMESPACE_DEF(numbers, _mqlplus_MathFloor)(const T value, const int digits = NULL)
|
||
|
{
|
||
|
if(digits <= NULL)
|
||
|
{
|
||
|
const double factor1 = MathMax(::MathPow(10.0, ::MathAbs(digits)), 1.0);
|
||
|
return((T)(MathFloor((double)value / factor1) * factor1));
|
||
|
}
|
||
|
|
||
|
const double factor2 = ::MathPow(10.0, digits);
|
||
|
return((T)(MathFloor((double)value * factor2) / factor2));
|
||
|
}
|
||
|
|
||
|
|
||
|
//+------------------------------------------------------------------+
|
||
|
//| Random value in the range [min, max] |
|
||
|
//| Generates random numbers with a uniform distribution (bias-free).|
|
||
|
//| Maximum granularity of generator is 32768 values. |
|
||
|
//+------------------------------------------------------------------+
|
||
|
template <typename T>
|
||
|
T LIB_NAMESPACE_DEF(numbers, _mqlplus_MathRand)(const T min, const T max)
|
||
|
{ return((T)(mqp_MathRandN() * (double)(max - min)) + min); }
|
||
|
|
||
|
|
||
|
//+------------------------------------------------------------------+
|
||
|
//| Can given value be evaluated to be zero |
|
||
|
//+------------------------------------------------------------------+
|
||
|
template <typename T>
|
||
|
const bool LIB_NAMESPACE_DEF(numbers, _mqlplus_MathZero)(const T value)
|
||
|
{
|
||
|
return( (value == (T)0x0000000000000000) // NULL
|
||
|
|| (value == (T)EMPTY_VALUE) // EMPTY_VALUE
|
||
|
#ifdef LIB_MQLPLUS_EMPTY_VALUE
|
||
|
|| (value == (T)LIB_MQLPLUS_EMPTY_VALUE) // INDICATOR DISPLAY EMPTY_VALUE
|
||
|
|
||
|
#endif
|
||
|
);
|
||
|
}
|
||
|
|
||
|
|
||
|
#ifndef __MQL4_COMPATIBILITY_CODE__
|
||
|
}; // END Namespace numbers
|
||
|
}; // END Namespace LIB_MQLPLUS_LIBRARY_PREFIX
|
||
|
#endif
|
||
|
|
||
|
|
||
|
|
||
|
//
|
||
|
// END Simple math functions */
|
||
|
//*********************************************************************************************************************************************************/
|
||
|
#endif // LIB_MATH_TPL_SIMPLE_MQH_INCLUDED
|