#ifndef LIB_MATH_TPL_SIMPLE_MQH_INCLUDED #define LIB_MATH_TPL_SIMPLE_MQH_INCLUDED #property version "1.9"; /********************************************************************************** * Copyright (C) 2010-2022 Dominik Egert * * 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 ///////////////////////////////////////////////////////////////////////////////////////////////////// // // 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 const T LIB_NAMESPACE_DEF(numbers, _mqlplus_MathMax)(const T value1, const U value2) { return(inline_MathMax(value1, (T)value2)); } //+------------------------------------------------------------------+ //| MathMin | //+------------------------------------------------------------------+ template const T LIB_NAMESPACE_DEF(numbers, _mqlplus_MathMin)(const T value1, const U value2) { return(inline_MathMin(value1, (T)value2)); } //+------------------------------------------------------------------+ //| MathMinNN not null | //+------------------------------------------------------------------+ template const T LIB_NAMESPACE_DEF(numbers, _mqlplus_MathMinNN)(const T value1, const U value2) { return(inline_MathMinNN(value1, (T)value2))); } //+------------------------------------------------------------------+ //| MathPow templated | //+------------------------------------------------------------------+ template 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 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 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 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 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 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 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 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 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 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 const int LIB_NAMESPACE_DEF(numbers, _mqlplus_MathDigits)(const T value) { return((int)(::MathFloor(::MathLog10(::MathAbs((double)value)))) + 1); } //+------------------------------------------------------------------+ //| MathAbs | //+------------------------------------------------------------------+ template const T LIB_NAMESPACE_DEF(numbers, _mqlplus_MathAbs)(const T value) { return((T)(::MathAbs((double)value))); } //+------------------------------------------------------------------+ //| MathNeg | //+------------------------------------------------------------------+ // Function template const T LIB_NAMESPACE_DEF(numbers, _mqlplus_MathNeg)(const T value) { return((T)inline_MathNeg((double)value)); } //+------------------------------------------------------------------+ //| MathRound | //+------------------------------------------------------------------+ template 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 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 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 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 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