C++ Mathematical Expression Library (ExprTk) http://www.partow.net/programming/exprtk/index.html

This commit is contained in:
Arash Partow 2014-03-30 13:22:42 +11:00
parent 8a64a1faf6
commit 904f924005
2 changed files with 143 additions and 99 deletions

View File

@ -458,6 +458,36 @@ namespace exprtk
#undef exprtk_register_real_type_tag #undef exprtk_register_real_type_tag
#undef exprtk_register_int_type_tag #undef exprtk_register_int_type_tag
template <typename T>
struct epsilon_type
{
static inline T value()
{
const T epsilon = T(0.0000000001);
return epsilon;
}
};
template <>
struct epsilon_type <float>
{
static inline float value()
{
const float epsilon = float(0.000001f);
return epsilon;
}
};
template <>
struct epsilon_type <long double>
{
static inline long double value()
{
const long double epsilon = (long double)(0.000000000001);
return epsilon;
}
};
template <typename T> template <typename T>
inline bool is_true_impl(const T v) inline bool is_true_impl(const T v)
{ {
@ -479,13 +509,13 @@ namespace exprtk
template <typename T> template <typename T>
inline T equal_impl(const T v0, const T v1, real_type_tag) inline T equal_impl(const T v0, const T v1, real_type_tag)
{ {
static const T epsilon = T(0.0000000001); const T epsilon = epsilon_type<T>::value();
return (abs_impl(v0 - v1,real_type_tag()) <= (std::max(T(1),std::max(abs_impl(v0,real_type_tag()),abs_impl(v1,real_type_tag()))) * epsilon)) ? T(1) : T(0); return (abs_impl(v0 - v1,real_type_tag()) <= (std::max(T(1),std::max(abs_impl(v0,real_type_tag()),abs_impl(v1,real_type_tag()))) * epsilon)) ? T(1) : T(0);
} }
inline float equal_impl(const float v0, const float v1, real_type_tag) inline float equal_impl(const float v0, const float v1, real_type_tag)
{ {
static const float epsilon = float(0.000001f); const float epsilon = epsilon_type<float>::value();
return (abs_impl(v0 - v1,real_type_tag()) <= (std::max(1.0f,std::max(abs_impl(v0,real_type_tag()),abs_impl(v1,real_type_tag()))) * epsilon)) ? 1.0f : 0.0f; return (abs_impl(v0 - v1,real_type_tag()) <= (std::max(1.0f,std::max(abs_impl(v0,real_type_tag()),abs_impl(v1,real_type_tag()))) * epsilon)) ? 1.0f : 0.0f;
} }
@ -514,13 +544,13 @@ namespace exprtk
template <typename T> template <typename T>
inline T nequal_impl(const T v0, const T v1, real_type_tag) inline T nequal_impl(const T v0, const T v1, real_type_tag)
{ {
static const T epsilon = T(0.0000000001); const T epsilon = epsilon_type<T>::value();
return (abs_impl(v0 - v1,real_type_tag()) > (std::max(T(1),std::max(abs_impl(v0,real_type_tag()),abs_impl(v1,real_type_tag()))) * epsilon)) ? T(1) : T(0); return (abs_impl(v0 - v1,real_type_tag()) > (std::max(T(1),std::max(abs_impl(v0,real_type_tag()),abs_impl(v1,real_type_tag()))) * epsilon)) ? T(1) : T(0);
} }
inline float nequal_impl(const float v0, const float v1, real_type_tag) inline float nequal_impl(const float v0, const float v1, real_type_tag)
{ {
static const float epsilon = float(0.000001f); const float epsilon = epsilon_type<float>::value();
return (abs_impl(v0 - v1,real_type_tag()) > (std::max(1.0f,std::max(abs_impl(v0,real_type_tag()),abs_impl(v1,real_type_tag()))) * epsilon)) ? 1.0f : 0.0f; return (abs_impl(v0 - v1,real_type_tag()) > (std::max(1.0f,std::max(abs_impl(v0,real_type_tag()),abs_impl(v1,real_type_tag()))) * epsilon)) ? 1.0f : 0.0f;
} }
@ -3343,6 +3373,11 @@ namespace exprtk
return (0.0 != v); return (0.0 != v);
} }
inline bool is_true(const long double v)
{
return (0.0 != v);
}
inline bool is_true(const float v) inline bool is_true(const float v)
{ {
return (0.0f != v); return (0.0f != v);
@ -9547,7 +9582,7 @@ namespace exprtk
inline bool add_epsilon() inline bool add_epsilon()
{ {
static const T local_epsilon = std::numeric_limits<T>::epsilon(); static const T local_epsilon = details::numeric::details::epsilon_type<T>::value();
return add_constant("epsilon",local_epsilon); return add_constant("epsilon",local_epsilon);
} }

View File

@ -27,8 +27,8 @@
#include "exprtk.hpp" #include "exprtk.hpp"
typedef double numeric_type;
typedef std::pair<std::string,double> test_t; typedef std::pair<std::string,numeric_type> test_t;
static const test_t test_list[] = static const test_t test_list[] =
{ {
@ -1095,8 +1095,8 @@ inline bool test_expression(const std::string& expression_string, const T& expec
{ {
printf("test_expression() - Computation Error: Expression: [%s]\tExpected: %19.15f\tResult: %19.15f\n", printf("test_expression() - Computation Error: Expression: [%s]\tExpected: %19.15f\tResult: %19.15f\n",
expression_string.c_str(), expression_string.c_str(),
expected_result, (double)expected_result,
result); (double)result);
return false; return false;
} }
@ -1481,8 +1481,8 @@ inline bool run_test01()
{ {
printf("run_test01() - Computation Error: Expression: [%s]\tExpected: %19.15f\tResult: %19.15f\n", printf("run_test01() - Computation Error: Expression: [%s]\tExpected: %19.15f\tResult: %19.15f\n",
test.expr.c_str(), test.expr.c_str(),
test.result, (double)test.result,
result); (double)result);
loop_result = false; loop_result = false;
} }
} }
@ -1576,8 +1576,8 @@ inline bool run_test01()
{ {
printf("run_test01() - Computation Error: Expression: [%s]\tExpected: %19.15f\tResult: %19.15f\n", printf("run_test01() - Computation Error: Expression: [%s]\tExpected: %19.15f\tResult: %19.15f\n",
test.expr.c_str(), test.expr.c_str(),
test.result, (double)test.result,
result); (double)result);
loop_result = false; loop_result = false;
} }
} }
@ -1900,8 +1900,8 @@ inline bool run_test02()
{ {
printf("run_test02() - Computation Error: Expression: [%s]\tExpected: %19.15f\tResult: %19.15f\n", printf("run_test02() - Computation Error: Expression: [%s]\tExpected: %19.15f\tResult: %19.15f\n",
test.expr.c_str(), test.expr.c_str(),
test.result, (double)test.result,
result); (double)result);
return false; return false;
} }
} }
@ -2038,10 +2038,10 @@ inline bool run_test04()
{ {
printf("run_test04() - Computation Error: Expression: [%s]\tExpected: %19.15f\tResult: %19.15f x:%19.15f\ty:%19.15f\n", printf("run_test04() - Computation Error: Expression: [%s]\tExpected: %19.15f\tResult: %19.15f x:%19.15f\ty:%19.15f\n",
expression_string.c_str(), expression_string.c_str(),
result1, (double)result1,
result2, (double)result2,
x, (double)x,
y); (double)y);
return false; return false;
} }
@ -2103,10 +2103,10 @@ inline bool run_test05()
{ {
printf("run_test05() - Computation Error: Expression: [%s]\tExpected: %19.15f\tResult: %19.15f x:%19.15f\ty:%19.15f\tIndex:%d\n", printf("run_test05() - Computation Error: Expression: [%s]\tExpected: %19.15f\tResult: %19.15f x:%19.15f\ty:%19.15f\tIndex:%d\n",
expression_string.c_str(), expression_string.c_str(),
real_result, (double)real_result,
result, (double)result,
x, (double)x,
y, (double)y,
static_cast<unsigned int>(i)); static_cast<unsigned int>(i));
return false; return false;
} }
@ -2156,8 +2156,8 @@ inline bool run_test06()
if (not_equal(total_area1,T(pi) / T(2),T(0.000001))) if (not_equal(total_area1,T(pi) / T(2),T(0.000001)))
{ {
printf("run_test06() - Integration Error: Expected: %19.15f\tResult: %19.15f\n", printf("run_test06() - Integration Error: Expected: %19.15f\tResult: %19.15f\n",
pi / T(2), (double)(pi / T(2)),
total_area1); (double)total_area1);
return false; return false;
} }
@ -2205,9 +2205,9 @@ inline bool run_test07()
if (not_equal(deriv1_result1,deriv1_real_result,T(0.00001))) if (not_equal(deriv1_result1,deriv1_real_result,T(0.00001)))
{ {
printf("run_test07() - 1st Derivative Error: x: %19.15f\tExpected: %19.15f\tResult: %19.15f\n", printf("run_test07() - 1st Derivative Error: x: %19.15f\tExpected: %19.15f\tResult: %19.15f\n",
x, (double)x,
deriv1_real_result, (double)deriv1_real_result,
deriv1_result1); (double)deriv1_result1);
return false; return false;
} }
} }
@ -2226,9 +2226,9 @@ inline bool run_test07()
if (not_equal(deriv2_result1,deriv2_real_result,T(0.01))) if (not_equal(deriv2_result1,deriv2_real_result,T(0.01)))
{ {
printf("run_test07() - 2nd Derivative Error: x: %19.15f\tExpected: %19.15f\tResult: %19.15f\n", printf("run_test07() - 2nd Derivative Error: x: %19.15f\tExpected: %19.15f\tResult: %19.15f\n",
x, (double)x,
deriv2_real_result, (double)deriv2_real_result,
deriv2_result1); (double)deriv2_result1);
return false; return false;
} }
} }
@ -2247,9 +2247,9 @@ inline bool run_test07()
if (not_equal(deriv3_result1,deriv3_real_result,T(0.01))) if (not_equal(deriv3_result1,deriv3_real_result,T(0.01)))
{ {
printf("run_test07() - 3rd Derivative Error: x: %19.15f\tExpected: %19.15f\tResult: %19.15f\n", printf("run_test07() - 3rd Derivative Error: x: %19.15f\tExpected: %19.15f\tResult: %19.15f\n",
x, (double)x,
deriv3_real_result, (double)deriv3_real_result,
deriv3_result1); (double)deriv3_result1);
return false; return false;
} }
} }
@ -2528,8 +2528,8 @@ inline bool run_test09()
if (not_equal(result,expected,T(0.0000001))) if (not_equal(result,expected,T(0.0000001)))
{ {
printf("run_test09() - Error Expected: %19.15f\tResult: %19.15f\n", printf("run_test09() - Error Expected: %19.15f\tResult: %19.15f\n",
expected, (double)expected,
result); (double)result);
return false; return false;
} }
} }
@ -3515,8 +3515,8 @@ inline bool run_test15()
if (not_equal(base_result,result)) if (not_equal(base_result,result))
{ {
printf("run_test15() - Error in evaluation! (1) Base: %20.10f\tResult: %20.10f\tExpression: %s\n", printf("run_test15() - Error in evaluation! (1) Base: %20.10f\tResult: %20.10f\tExpression: %s\n",
base_result, (double)base_result,
result, (double)result,
expr_str_list[i].c_str()); expr_str_list[i].c_str());
failure = true; failure = true;
} }
@ -4466,8 +4466,8 @@ inline bool run_test19()
printf("run_test19() - Computation Error " printf("run_test19() - Computation Error "
"Expression: [%s]\tExpected: %12.8f\tResult: %12.8f\n", "Expression: [%s]\tExpected: %12.8f\tResult: %12.8f\n",
expression_str.c_str(), expression_str.c_str(),
std::sqrt(x), (double)std::sqrt(x),
result); (double)result);
failure = true; failure = true;
} }
} }
@ -4566,6 +4566,12 @@ inline bool run_test20()
return true; return true;
} }
template <typename T>
struct type_name { static inline std::string value() { return "unknown"; } };
template <> struct type_name<float> { static inline std::string value() { return "float"; } };
template <> struct type_name<double> { static inline std::string value() { return "double"; } };
template <> struct type_name<long double> { static inline std::string value() { return "long double"; } };
int main() int main()
{ {
#define perform_test(Type,Number) \ #define perform_test(Type,Number) \
@ -4574,36 +4580,39 @@ int main()
timer.start(); \ timer.start(); \
if (!run_test##Number<Type>()) \ if (!run_test##Number<Type>()) \
{ \ { \
printf("run_test"#Number" ("#Type") *** FAILED! ***\n"); \ printf("run_test"#Number" (%s) *** FAILED! ***\n", \
type_name<Type>::value().c_str()); \
} \ } \
else \ else \
{ \ { \
timer.stop(); \ timer.stop(); \
printf("run_test"#Number" ("#Type") - Result: SUCCESS Time: %8.4fsec\n",timer.time()); \ printf("run_test"#Number" (%s) - Result: SUCCESS Time: %8.4fsec\n", \
type_name<Type>::value().c_str(), \
timer.time()); \
} \ } \
} \ } \
perform_test(double,00) perform_test(numeric_type,00)
perform_test(double,01) perform_test(numeric_type,01)
perform_test(double,02) perform_test(numeric_type,02)
perform_test(double,03) perform_test(numeric_type,03)
perform_test(double,04) perform_test(numeric_type,04)
perform_test(double,05) perform_test(numeric_type,05)
perform_test(double,06) perform_test(numeric_type,06)
perform_test(double,07) perform_test(numeric_type,07)
perform_test(double,08) perform_test(numeric_type,08)
perform_test(double,09) perform_test(numeric_type,09)
perform_test(double,10) perform_test(numeric_type,10)
perform_test(double,11) perform_test(numeric_type,11)
perform_test(double,12) perform_test(numeric_type,12)
perform_test(double,13) perform_test(numeric_type,13)
perform_test(double,14) perform_test(numeric_type,14)
perform_test(double,15) perform_test(numeric_type,15)
perform_test(double,16) perform_test(numeric_type,16)
perform_test(double,17) perform_test(numeric_type,17)
perform_test(double,18) perform_test(numeric_type,18)
perform_test(double,19) perform_test(numeric_type,19)
perform_test(double,20) perform_test(numeric_type,20)
#undef perform_test #undef perform_test