From 94fe42391cb9465c9717ad4f337d053bd7c8afeb Mon Sep 17 00:00:00 2001 From: chendotjs Date: Wed, 15 Mar 2017 18:25:37 +0800 Subject: [PATCH] add fac and infs/combinatoric test --- test.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ tinyexpr.c | 21 +++++++++++++++++++ 2 files changed, 81 insertions(+) diff --git a/test.c b/test.c index b86a83f..82611eb 100644 --- a/test.c +++ b/test.c @@ -213,6 +213,7 @@ void test_nans() { "1%0", "1%(1%0)", "(1%0)%1", + "fac(-1)", }; int i; @@ -234,6 +235,34 @@ void test_nans() { } +void test_infs() { + + const char *infs[] = { + "1/0", + "log(0)", + "pow(2,10000000)", + "fac(300)", + }; + + int i; + for (i = 0; i < sizeof(infs) / sizeof(const char *); ++i) { + const char *expr = infs[i]; + + int err; + const double r = te_interp(expr, &err); + lequal(err, 0); + lok(r == r + 1); + + te_expr *n = te_compile(expr, 0, 0, &err); + lok(n); + lequal(err, 0); + const double c = te_eval(n); + lok(c == c + 1); + te_free(n); + } +} + + void test_variables() { double x, y, test; @@ -587,17 +616,48 @@ void test_pow() { } +void test_combinatorics() { + test_case cases[] = { + {"fac(0) ", 1}, + {"fac(0.2) ", 1}, + {"fac(1) ", 1}, + {"fac(2) ", 2}, + {"fac(3) ", 6}, + {"fac(4.8) ", 24}, + {"fac(10) ", 3628800}, + }; + + + int i; + for (i = 0; i < sizeof(cases) / sizeof(test_case); ++i) { + const char *expr = cases[i].expr; + const double answer = cases[i].answer; + + int err; + const double ev = te_interp(expr, &err); + lok(!err); + lfequal(ev, answer); + + if (err) { + printf("FAILED: %s (%d)\n", expr, err); + } + } +} + + int main(int argc, char *argv[]) { lrun("Results", test_results); lrun("Syntax", test_syntax); lrun("NaNs", test_nans); + lrun("INFs", test_infs); lrun("Variables", test_variables); lrun("Functions", test_functions); lrun("Dynamic", test_dynamic); lrun("Closure", test_closure); lrun("Optimize", test_optimize); lrun("Pow", test_pow); + lrun("Combinatorics", test_combinatorics); lresults(); return lfails != 0; diff --git a/tinyexpr.c b/tinyexpr.c index e6b61dc..f2a6175 100755 --- a/tinyexpr.c +++ b/tinyexpr.c @@ -39,11 +39,17 @@ For log = natural log uncomment the next line. */ #include #include #include +#include #ifndef NAN #define NAN (0.0/0.0) #endif +#ifndef INFINITY +#define INFINITY (1.0/0.0) +#endif + + typedef double (*te_fun2)(double, double); enum { @@ -113,6 +119,20 @@ void te_free(te_expr *n) { static double pi() {return 3.14159265358979323846;} static double e() {return 2.71828182845904523536;} +static double fac(double a) {/* simplest version of fac */ + if (a < 0.0) + return NAN; + if (a > UINT_MAX) + return INFINITY; + unsigned int ua = (unsigned int)(a); + unsigned long int result = 1, i = 1; + for (i = 1; i <= ua; i++) { + if (ua > ULONG_MAX / result) + return INFINITY; + result *= i; + } + return (double)result; +} static const te_variable functions[] = { /* must be in alphabetical order */ @@ -126,6 +146,7 @@ static const te_variable functions[] = { {"cosh", cosh, TE_FUNCTION1 | TE_FLAG_PURE, 0}, {"e", e, TE_FUNCTION0 | TE_FLAG_PURE, 0}, {"exp", exp, TE_FUNCTION1 | TE_FLAG_PURE, 0}, + {"fac", fac, TE_FUNCTION1 | TE_FLAG_PURE, 0}, {"floor", floor, TE_FUNCTION1 | TE_FLAG_PURE, 0}, {"ln", log, TE_FUNCTION1 | TE_FLAG_PURE, 0}, #ifdef TE_NAT_LOG