From 5d86274da2013756ac551a92fe425f91729a578e Mon Sep 17 00:00:00 2001 From: Samuel Pfrommer Date: Sun, 22 Mar 2015 16:42:47 -0400 Subject: [PATCH] Finished implement all cmath functions --- include/chaiscript/extras/math.hpp | 579 ++++++++++++++++++++++++++++- tests/math.cpp | 65 +++- 2 files changed, 628 insertions(+), 16 deletions(-) diff --git a/include/chaiscript/extras/math.hpp b/include/chaiscript/extras/math.hpp index 5e3fb8d..b5faba1 100644 --- a/include/chaiscript/extras/math.hpp +++ b/include/chaiscript/extras/math.hpp @@ -1,20 +1,13 @@ #include #include -#include +#include "../dispatchkit/dispatchkit.hpp" +#include "../chaiscript.hpp" namespace chaiscript { namespace extras { namespace math { - template - ModulePtr floor(ModulePtr m = std::make_shared()) - { - // using the overloads provided by C++11 - // http://www.cplusplus.com/reference/cmath/floor/ - m->add(chaiscript::fun(static_cast(&std::floor)), "floor"); - return m; - } - + // TRIG FUNCTIONS template ModulePtr cos(ModulePtr m = std::make_shared()) { @@ -64,6 +57,7 @@ namespace chaiscript { return m; } + // HYPERBOLIC FUNCTIONS template ModulePtr cosh(ModulePtr m = std::make_shared()) { @@ -106,6 +100,105 @@ namespace chaiscript { return m; } + // EXPONENTIAL AND LOGARITHMIC FUNCTIONS + template + ModulePtr exp(ModulePtr m = std::make_shared()) + { + m->add(chaiscript::fun(static_cast(&std::exp)), "exp"); + return m; + } + + template + ModulePtr frexp(ModulePtr m = std::make_shared()) + { + m->add(chaiscript::fun(static_cast(&std::frexp)), "frexp"); + return m; + } + + template + ModulePtr ldexp(ModulePtr m = std::make_shared()) + { + m->add(chaiscript::fun(static_cast(&std::ldexp)), "ldexp"); + return m; + } + + template + ModulePtr log(ModulePtr m = std::make_shared()) + { + m->add(chaiscript::fun(static_cast(&std::log)), "log"); + return m; + } + + template + ModulePtr log10(ModulePtr m = std::make_shared()) + { + m->add(chaiscript::fun(static_cast(&std::log10)), "log10"); + return m; + } + + template + ModulePtr modf(ModulePtr m = std::make_shared()) + { + m->add(chaiscript::fun(static_cast(&std::modf)), "modf"); + return m; + } + template + ModulePtr exp2(ModulePtr m = std::make_shared()) + { + m->add(chaiscript::fun(static_cast(&std::exp2)), "exp2"); + return m; + } + + template + ModulePtr expm1(ModulePtr m = std::make_shared()) + { + m->add(chaiscript::fun(static_cast(&std::expm1)), "expm1"); + return m; + } + + template + ModulePtr ilogb(ModulePtr m = std::make_shared()) + { + m->add(chaiscript::fun(static_cast(&std::ilogb)), "ilogb"); + return m; + } + + template + ModulePtr log1p(ModulePtr m = std::make_shared()) + { + m->add(chaiscript::fun(static_cast(&std::log1p)), "log1p"); + return m; + } + + template + ModulePtr log2(ModulePtr m = std::make_shared()) + { + m->add(chaiscript::fun(static_cast(&std::log2)), "log2"); + return m; + } + + template + ModulePtr logb(ModulePtr m = std::make_shared()) + { + m->add(chaiscript::fun(static_cast(&std::logb)), "logb"); + return m; + } + + template + ModulePtr scalbn(ModulePtr m = std::make_shared()) + { + m->add(chaiscript::fun(static_cast(&std::scalbn)), "scalbn"); + return m; + } + + template + ModulePtr scalbln(ModulePtr m = std::make_shared()) + { + m->add(chaiscript::fun(static_cast(&std::scalbln)), "scalbln"); + return m; + } + + // POWER FUNCTIONS template ModulePtr pow(ModulePtr m = std::make_shared()) { @@ -134,6 +227,7 @@ namespace chaiscript { return m; } + // ERROR AND GAMMA FUNCTIONS template ModulePtr erf(ModulePtr m = std::make_shared()) { @@ -162,12 +256,263 @@ namespace chaiscript { return m; } - ModulePtr bootstrap(ModulePtr m = std::make_shared()) + // ROUNDING AND REMAINDER FUNCTIONS + template + ModulePtr ceil(ModulePtr m = std::make_shared()) { - floor(m); - floor(m); - floor(m); + m->add(chaiscript::fun(static_cast(&std::ceil)), "ceil"); + return m; + } + + template + ModulePtr floor(ModulePtr m = std::make_shared()) + { + m->add(chaiscript::fun(static_cast(&std::floor)), "floor"); + return m; + } + + template + ModulePtr fmod(ModulePtr m = std::make_shared()) + { + m->add(chaiscript::fun(static_cast(&std::fmod)), "fmod"); + return m; + } + + template + ModulePtr trunc(ModulePtr m = std::make_shared()) + { + m->add(chaiscript::fun(static_cast(&std::trunc)), "trunc"); + return m; + } + + template + ModulePtr round(ModulePtr m = std::make_shared()) + { + m->add(chaiscript::fun(static_cast(&std::round)), "round"); + return m; + } + + template + ModulePtr lround(ModulePtr m = std::make_shared()) + { + m->add(chaiscript::fun(static_cast(&std::lround)), "lround"); + return m; + } + + // long long ints do not work + /*template + ModulePtr llround(ModulePtr m = std::make_shared()) + { + m->add(chaiscript::fun(static_cast(&std::llround)), "llround"); + return m; + }*/ + + template + ModulePtr rint(ModulePtr m = std::make_shared()) + { + m->add(chaiscript::fun(static_cast(&std::rint)), "rint"); + return m; + } + + template + ModulePtr lrint(ModulePtr m = std::make_shared()) + { + m->add(chaiscript::fun(static_cast(&std::lrint)), "lrint"); + return m; + } + + // long long ints do not work + /*template + ModulePtr llrint(ModulePtr m = std::make_shared()) + { + m->add(chaiscript::fun(static_cast(&std::llrint)), "llrint"); + return m; + }*/ + + template + ModulePtr nearbyint(ModulePtr m = std::make_shared()) + { + m->add(chaiscript::fun(static_cast(&std::nearbyint)), "nearbyint"); + return m; + } + + template + ModulePtr remainder(ModulePtr m = std::make_shared()) + { + m->add(chaiscript::fun(static_cast(&std::remainder)), "remainder"); + return m; + } + + template + ModulePtr remquo(ModulePtr m = std::make_shared()) + { + m->add(chaiscript::fun(static_cast(&std::remquo)), "remquo"); + return m; + } + + // FLOATING-POINT MANIPULATION FUNCTIONS + template + ModulePtr copysign(ModulePtr m = std::make_shared()) + { + m->add(chaiscript::fun(static_cast(&std::copysign)), "copysign"); + return m; + } + + template + ModulePtr nan(ModulePtr m = std::make_shared()) + { + m->add(chaiscript::fun(static_cast(&std::nan)), "nan"); + return m; + } + + template + ModulePtr nextafter(ModulePtr m = std::make_shared()) + { + m->add(chaiscript::fun(static_cast(&std::nextafter)), "nextafter"); + return m; + } + + template + ModulePtr nexttoward(ModulePtr m = std::make_shared()) + { + m->add(chaiscript::fun(static_cast(&std::nexttoward)), "nexttoward"); + return m; + } + + // MINIMUM, MAXIMUM, DIFFERENCE FUNCTIONS + template + ModulePtr fdim(ModulePtr m = std::make_shared()) + { + m->add(chaiscript::fun(static_cast(&std::fdim)), "fdim"); + return m; + } + + template + ModulePtr fmax(ModulePtr m = std::make_shared()) + { + m->add(chaiscript::fun(static_cast(&std::fmax)), "fmax"); + return m; + } + + template + ModulePtr fmin(ModulePtr m = std::make_shared()) + { + m->add(chaiscript::fun(static_cast(&std::fmin)), "fmin"); + return m; + } + + // OTHER FUNCTIONS + template + ModulePtr fabs(ModulePtr m = std::make_shared()) + { + m->add(chaiscript::fun(static_cast(&std::fabs)), "fabs"); + return m; + } + + template + ModulePtr abs(ModulePtr m = std::make_shared()) + { + m->add(chaiscript::fun(static_cast(&std::abs)), "abs"); + return m; + } + + template + ModulePtr fma(ModulePtr m = std::make_shared()) + { + m->add(chaiscript::fun(static_cast(&std::fma)), "fma"); + return m; + } + + // CLASSIFICATION FUNCTIONS + template + ModulePtr fpclassify(ModulePtr m = std::make_shared()) + { + m->add(chaiscript::fun(static_cast(&std::fpclassify)), "fpclassify"); + return m; + } + + template + ModulePtr isfinite(ModulePtr m = std::make_shared()) + { + m->add(chaiscript::fun(static_cast(&std::isfinite)), "isfinite"); + return m; + } + + template + ModulePtr isinf(ModulePtr m = std::make_shared()) + { + m->add(chaiscript::fun(static_cast(&std::isinf)), "isinf"); + return m; + } + + template + ModulePtr isnan(ModulePtr m = std::make_shared()) + { + m->add(chaiscript::fun(static_cast(&std::isnan)), "isnan"); + return m; + } + + template + ModulePtr isnormal(ModulePtr m = std::make_shared()) + { + m->add(chaiscript::fun(static_cast(&std::isnormal)), "isnormal"); + return m; + } + + template + ModulePtr signbit(ModulePtr m = std::make_shared()) + { + m->add(chaiscript::fun(static_cast(&std::signbit)), "signbit"); + return m; + } + + + // COMPARISON FUNCTIONS + template + ModulePtr isgreater(ModulePtr m = std::make_shared()) + { + m->add(chaiscript::fun(static_cast(&std::isgreater)), "isgreater"); + return m; + } + template + ModulePtr isgreaterequal(ModulePtr m = std::make_shared()) + { + m->add(chaiscript::fun(static_cast(&std::isgreaterequal)), "isgreaterequal"); + return m; + } + + template + ModulePtr isless(ModulePtr m = std::make_shared()) + { + m->add(chaiscript::fun(static_cast(&std::isless)), "isless"); + return m; + } + + template + ModulePtr islessequal(ModulePtr m = std::make_shared()) + { + m->add(chaiscript::fun(static_cast(&std::islessequal)), "islessequal"); + return m; + } + + template + ModulePtr islessgreater(ModulePtr m = std::make_shared()) + { + m->add(chaiscript::fun(static_cast(&std::islessgreater)), "islessgreater"); + return m; + } + + template + ModulePtr isunordered(ModulePtr m = std::make_shared()) + { + m->add(chaiscript::fun(static_cast(&std::isunordered)), "isunordered"); + return m; + } + + ModulePtr bootstrap(ModulePtr m = std::make_shared()) + { + // TRIG FUNCTIONS cos(m); cos(m); cos(m); @@ -196,6 +541,7 @@ namespace chaiscript { atan2(m); atan2(m); + // HYPERBOLIC FUNCTIONS cosh(m); cosh(m); cosh(m); @@ -220,6 +566,64 @@ namespace chaiscript { atanh(m); atanh(m); + // EXPONENTIAL AND LOGARITHMIC FUNCTIONS + exp(m); + exp(m); + exp(m); + + frexp(m); + frexp(m); + frexp(m); + + ldexp(m); + ldexp(m); + ldexp(m); + + log(m); + log(m); + log(m); + + log10(m); + log10(m); + log10(m); + + modf(m); + modf(m); + modf(m); + + exp2(m); + exp2(m); + exp2(m); + + expm1(m); + expm1(m); + expm1(m); + + ilogb(m); + ilogb(m); + ilogb(m); + + log1p(m); + log1p(m); + log1p(m); + + log2(m); + log2(m); + log2(m); + + logb(m); + logb(m); + logb(m); + + scalbn(m); + scalbn(m); + scalbn(m); + + scalbln(m); + scalbln(m); + scalbln(m); + + // POWER FUNCTIONS pow(m); pow(m); pow(m); @@ -236,6 +640,7 @@ namespace chaiscript { hypot(m); hypot(m); + // ERROR AND GAMMA FUNCTIONS erf(m); erf(m); erf(m); @@ -252,6 +657,152 @@ namespace chaiscript { lgamma(m); lgamma(m); + // ROUNDING AND REMAINDER FUNCTIONS + ceil(m); + ceil(m); + ceil(m); + + floor(m); + floor(m); + floor(m); + + fmod(m); + fmod(m); + fmod(m); + + trunc(m); + trunc(m); + trunc(m); + + round(m); + round(m); + round(m); + + lround(m); + lround(m); + lround(m); + + // long long ints do not work + /*llround(m); + llround(m); + llround(m);*/ + + rint(m); + rint(m); + rint(m); + + lrint(m); + lrint(m); + lrint(m); + + // long long ints do not work + /*llrint(m); + llrint(m); + llrint(m);*/ + + nearbyint(m); + nearbyint(m); + nearbyint(m); + + remainder(m); + remainder(m); + remainder(m); + + remquo(m); + remquo(m); + remquo(m); + + // FLOATING-POINT MANIPULATION FUNCTIONS + copysign(m); + copysign(m); + copysign(m); + + nan(m); + + nextafter(m); + nextafter(m); + nextafter(m); + + nexttoward(m); + nexttoward(m); + nexttoward(m); + + // MINIMUM, MAXIMUM, DIFFERENCE FUNCTIONS + fdim(m); + fdim(m); + fdim(m); + + fmax(m); + fmax(m); + fmax(m); + + fmin(m); + fmin(m); + fmin(m); + + // OTHER FUNCTIONS + fabs(m); + fabs(m); + fabs(m); + + abs(m); + abs(m); + abs(m); + + fma(m); + fma(m); + fma(m); + + // CLASSIFICATION FUNCTIONS + fpclassify(m); + fpclassify(m); + fpclassify(m); + + isfinite(m); + isfinite(m); + isfinite(m); + + isinf(m); + isinf(m); + isinf(m); + + isnan(m); + isnan(m); + isnan(m); + + isnormal(m); + isnormal(m); + isnormal(m); + + signbit(m); + signbit(m); + signbit(m); + + // COMPARISON FUNCTIONS + isgreater(m); + isgreater(m); + isgreater(m); + + isgreaterequal(m); + isgreaterequal(m); + isgreaterequal(m); + + isless(m); + isless(m); + isless(m); + + islessequal(m); + islessequal(m); + islessequal(m); + + islessgreater(m); + islessgreater(m); + islessgreater(m); + + isunordered(m); + isunordered(m); + isunordered(m); + return m; } } diff --git a/tests/math.cpp b/tests/math.cpp index 8d2a0cf..bdf43ce 100644 --- a/tests/math.cpp +++ b/tests/math.cpp @@ -5,6 +5,8 @@ #include #include "../include/chaiscript/extras/math.hpp" +#include + TEST_CASE( "Math functions work", "[math]" ) { auto stdlib = chaiscript::Std_Lib::library(); auto mathlib = chaiscript::extras::math::bootstrap(); @@ -12,8 +14,7 @@ TEST_CASE( "Math functions work", "[math]" ) { chaiscript::ChaiScript chai(stdlib); chai.add(mathlib); - CHECK(chai.eval("floor(2.2)") == floor(2.2)); - + // TRIG FUNCTIONS CHECK(chai.eval("cos(0.5)") == cos(0.5)); CHECK(chai.eval("sin(0.5)") == sin(0.5)); CHECK(chai.eval("tan(0.5)") == tan(0.5)); @@ -23,6 +24,7 @@ TEST_CASE( "Math functions work", "[math]" ) { CHECK(chai.eval("atan(0.5)") == atan(0.5)); CHECK(chai.eval("atan2(0.5, 0.5)") == atan2(0.5, 0.5)); + // HYPERBOLIC FUNCTIONS CHECK(chai.eval("cosh(0.5)") == cosh(0.5)); CHECK(chai.eval("sinh(0.5)") == sinh(0.5)); CHECK(chai.eval("tanh(0.5)") == tanh(0.5)); @@ -31,15 +33,74 @@ TEST_CASE( "Math functions work", "[math]" ) { CHECK(chai.eval("asinh(0.5)") == asinh(0.5)); CHECK(chai.eval("atanh(0.5)") == atanh(0.5)); + // EXPONENTIAL AND LOGARITHMIC FUNCTIONS + CHECK(chai.eval("exp(0.5)") == exp(0.5)); + int exp = 0; CHECK(chai.eval("var exp = 2\nfrexp(0.5, exp)") == frexp(0.5, &exp)); + CHECK(chai.eval("ldexp(0.5, 2)") == ldexp(0.5, 2)); + CHECK(chai.eval("log(0.5)") == log(0.5)); + CHECK(chai.eval("log10(0.5)") == log10(0.5)); + double ipart = 0.5; CHECK(chai.eval("var ipart = 0.5\nmodf(0.5, ipart)") == modf(0.5, &ipart)); + CHECK(chai.eval("exp2(0.5)") == exp2(0.5)); + CHECK(chai.eval("expm1(0.5)") == expm1(0.5)); + CHECK(chai.eval("ilogb(0.5)") == ilogb(0.5)); + CHECK(chai.eval("log1p(0.5)") == log1p(0.5)); + CHECK(chai.eval("log2(0.5)") == log2(0.5)); + CHECK(chai.eval("logb(0.5)") == ilogb(0.5)); + CHECK(chai.eval("scalbn(0.5, 2)") == scalbn(0.5, 2)); + CHECK(chai.eval("scalbln(0.5, 2l)") == scalbln(0.5, 2)); + + // POWER FUNCTIONS CHECK(chai.eval("pow(0.5, 3.0)") == pow(0.5, 3.0)); CHECK(chai.eval("sqrt(0.5)") == sqrt(0.5)); CHECK(chai.eval("cbrt(0.5)") == cbrt(0.5)); CHECK(chai.eval("hypot(0.5, 0.5)") == hypot(0.5, 0.5)); + // ERROR AND GAMMA FUNCTIONS CHECK(chai.eval("erf(0.5)") == erf(0.5)); CHECK(chai.eval("erfc(0.5)") == erfc(0.5)); CHECK(chai.eval("tgamma(0.5)") == tgamma(0.5)); CHECK(chai.eval("lgamma(0.5)") == lgamma(0.5)); + + // ROUNDING AND REMAINDER FUNCTIONS + CHECK(chai.eval("ceil(0.5)") == ceil(0.5)); + CHECK(chai.eval("floor(0.5)") == floor(0.5)); + CHECK(chai.eval("fmod(0.5, 0.5)") == fmod(0.5, 0.5)); + CHECK(chai.eval("trunc(0.5)") == trunc(0.5)); + CHECK(chai.eval("round(0.5)") == round(0.5)); + CHECK(chai.eval("lround(0.5)") == lround(0.5)); + // CHECK(chai.eval("llround(0.5)") == llround(0.5)); // long longs do not work + CHECK(chai.eval("rint(0.5)") == rint(0.5)); + CHECK(chai.eval("lrint(0.5)") == lrint(0.5)); + // CHECK(chai.eval("llrint(0.5)") == llrint(0.5)); + CHECK(chai.eval("nearbyint(0.5)") == nearbyint(0.5)); + CHECK(chai.eval("remainder(6.0, 2.5)") == remainder(6.0, 2.5)); + int quot = 0; CHECK(chai.eval("var quot = 0\nremquo(6.0, 2.5, quot)") == remquo(6.0, 2.5, ")); + + // MINIMUM, MAXIMUM, DIFFERENCE FUNCTIONS + CHECK(chai.eval("fdim(6.0, 2.5)") == fdim(6.0, 2.5)); + CHECK(chai.eval("fmax(6.0, 2.5)") == fmax(6.0, 2.5)); + CHECK(chai.eval("fmin(6.0, 2.5)") == fmin(6.0, 2.5)); + + // OTHER FUNCTIONS + CHECK(chai.eval("fabs(-0.5)") == fabs(-0.5)); + CHECK(chai.eval("abs(-0.5)") == std::abs(-0.5)); + CHECK(chai.eval("fma(0.5, 0.5, 0.5)") == fma(0.5, 0.5, 0.5)); + + // CLASSIFICATION FUNCTIONS + CHECK(chai.eval("fpclassify(0.5)") == std::fpclassify(0.5)); + CHECK(chai.eval("isfinite(0.5)") == std::isfinite(0.5)); + CHECK(chai.eval("isinf(0.5)") == std::isinf(0.5)); + CHECK(chai.eval("isnan(0.5)") == std::isnan(0.5)); + CHECK(chai.eval("isnormal(0.5)") == std::isnormal(0.5)); + CHECK(chai.eval("signbit(0.5)") == std::signbit(0.5)); + + // COMPARISON FUNCTIONS + CHECK(chai.eval("isgreater(1.0, 0.5)") == std::isgreater(1.0, 0.5)); + CHECK(chai.eval("isgreaterequal(1.0, 0.5)") == std::isgreaterequal(1.0, 0.5)); + CHECK(chai.eval("isless(1.0, 0.5)") == std::isless(1.0, 0.5)); + CHECK(chai.eval("islessequal(1.0, 0.5)") == std::islessequal(1.0, 0.5)); + CHECK(chai.eval("islessgreater(1.0, 0.5)") == std::islessgreater(1.0, 0.5)); + CHECK(chai.eval("isunordered(1.0, 0.5)") == std::isunordered(1.0, 0.5)); }