Skip to content

Commit

Permalink
Fixed the test app.
Browse files Browse the repository at this point in the history
  • Loading branch information
kobalicek committed Dec 12, 2015
1 parent eb9de20 commit 2737a74
Show file tree
Hide file tree
Showing 2 changed files with 165 additions and 118 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ MathPresso is a C++ library designed to parse mathematical expressions and compi

This is an updated version of MathPresso that works with a new AsmJit library and uses double-precision floating points. It has many bugs fixed compared to the last version on google-code and contains improvements that can make execution of certain built-in functions faster if the host CPU supports SSE4.1 (rounding, modulo).

This version of MathPresso is currently not completely up-to-date with its forks called DoublePresso. Pull request that add functionality contained there and fixes bugs are welcome.
This version of MathPresso is currently not completely up-to-date with its forks called DoublePresso. Pull request that add functionality contained there and bugs fixes are welcome.

This is also a transitional version that is available to users that want to use MathPresso and cannot wait for the new MPSL engine, which is a work in progress.

Expand Down
281 changes: 164 additions & 117 deletions src/test/mptest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,133 +29,180 @@ struct TestExpression {
# undef max
#endif // max

namespace environment {
const double E = 2.7182818284590452354;
const double PI = 3.14159265358979323846;
#if defined(__GNUC__) || defined(__clang__)
inline void set_x87_mode(unsigned short mode) {
__asm__ __volatile__ ("fldcw %0" :: "m" (*&mode));
}
#endif

// The reason for TextApp is that we want to replace all functions the
// expression can use.
struct TestApp {
TestApp(int argc, char* argv[])
: argc(argc),
argv(argv),
E(2.7182818284590452354),
PI(3.14159265358979323846),
x(5.1),
y(6.7),
z(9.9) {
}

inline double avg(double x, double y) { return (x + y) * 0.5; }
inline double min(double x, double y) { return x < y ? x : y; }
inline double max(double x, double y) { return x > y ? x : y; }
int run() {
bool failed = false;

// Set the FPU precision to `double` if running 32-bit. Required
// to be able to compare the result of C++ code with JIT code.
#if defined(__GNUC__) || defined(__clang__)
if (sizeof(void*) == 4)
set_x87_mode(0x027FU);
#endif

mathpresso::Context ctx;
mathpresso::Expression e0;
mathpresso::Expression e1;

ctx.addEnvironment(mathpresso::kMPEnvironmentAll);
ctx.addVariable("x", 0 * sizeof(double));
ctx.addVariable("y", 1 * sizeof(double));
ctx.addVariable("z", 2 * sizeof(double));

double variables[] = { x, y, z };

TestExpression tests[] = {
TEST_EXPRESSION( x+y ),
TEST_EXPRESSION( x-y ),
TEST_EXPRESSION( x*y ),
TEST_EXPRESSION( x/y ),
TEST_EXPRESSION( -(x+y) ),
TEST_EXPRESSION( -(x-y) ),
TEST_EXPRESSION( x*z + y*z),
TEST_EXPRESSION( x*z - y*z),
TEST_EXPRESSION( x*z*y*z),
TEST_EXPRESSION( x*z/y*z),
TEST_EXPRESSION( x == y ),
TEST_EXPRESSION( x != y ),
TEST_EXPRESSION( x < y ),
TEST_EXPRESSION( x <= y ),
TEST_EXPRESSION( x > y ),
TEST_EXPRESSION( x >= y ),
TEST_EXPRESSION( x + y == y - z ),
TEST_EXPRESSION( x > y == y < z ),
TEST_EXPRESSION( -x ),
TEST_EXPRESSION( -1 + x ),
TEST_EXPRESSION( -(-(-1)) ),
TEST_EXPRESSION( -(-(-x)) ),
TEST_EXPRESSION( (x+y)*x ),
TEST_EXPRESSION( (x+y)*y ),
TEST_EXPRESSION( (x+y)*(1.19+z) ),
TEST_EXPRESSION( ((x+(x+2.13))*y) ),
TEST_EXPRESSION( (x+y+z*2+(x*z+z*1.5)) ),
TEST_EXPRESSION( (((((((x-0.28)+y)+x)+x)*x)/1.12)*y) ),
TEST_EXPRESSION( ((((x*((((y-1.50)+1.82)-x)/PI))/x)*x)+z) ),
TEST_EXPRESSION( (((((((((x+1.35)+PI)/PI)-y)+z)-z)+y)/x)+0.81) ),
TEST_EXPRESSION( round(x) ),
TEST_EXPRESSION( round(-x) ),
TEST_EXPRESSION( floor(x) ),
TEST_EXPRESSION( floor(-x) ),
TEST_EXPRESSION( ceil(x) ),
TEST_EXPRESSION( ceil(-x) ),
TEST_EXPRESSION( abs(-x) ),
TEST_EXPRESSION( sqrt(x) ),
TEST_EXPRESSION( recip(x) ),
TEST_EXPRESSION( exp(x) ),
TEST_EXPRESSION( log(x) ),
TEST_EXPRESSION( log10(x) ),
TEST_EXPRESSION( sin(x) ),
TEST_EXPRESSION( cos(x) ),
TEST_EXPRESSION( tan(x) ),
TEST_EXPRESSION( sin(x) * cos(y) * tan(z) ),
TEST_EXPRESSION( avg(x, y) ),
TEST_EXPRESSION( min(x, y) ),
TEST_EXPRESSION( max(x, y) ),
TEST_EXPRESSION( pow(x, y) )
};

for (int i = 0; i < TABLE_SIZE(tests); i++) {
const char* exp = tests[i].expression;
bool expOk = true;

int err;
if ((err = e0.create(ctx, exp, mathpresso::kMPOptionDisableJIT))) {
printf("[Failure]: \"%s\" (eval)\n", exp);
printf(" ERROR %d (jit disabled).\n", err);
continue;
}

if ((err = e1.create(ctx, exp, mathpresso::kMPOptionNone))) {
printf("[Failure]: \"%s\" (jit)\n", exp);
printf(" ERROR %d (jit enabled).\n", err);
continue;
}

double expected = tests[i].expected;
double res0 = e0.evaluate(variables);
double res1 = e1.evaluate(variables);

if (res0 != expected) {
printf("[Failure]: \"%s\" (eval)\n", exp);
printf(" result(%f) != expected(%f)\n", res0, expected);
expOk = false;
}

if (res1 != expected) {
printf("[Failure]: \"%s\" (jit)\n", exp);
printf(" result(%f) != expected(%f)\n", res1, expected);
expOk = false;
}

if (expOk) {
printf("[Success]: \"%s\" -> %f\n", exp, expected);
}
else {
failed = true;
}
}

inline double recip(double x) { return 1.0 / x; }
}
return failed ? 1 : 0;
}

int main(int argc, char* argv[]) {
using namespace environment;
// --------------------------------------------------------------------------
// [Members]
// --------------------------------------------------------------------------

int argc;
char** argv;

bool failed = false;
// --------------------------------------------------------------------------
// [Constants]
// --------------------------------------------------------------------------

volatile double E;
volatile double PI;

// --------------------------------------------------------------------------
// [Variables]
// --------------------------------------------------------------------------

// Made volatile so the compiler doesn't optimize evaluation of the
// expression into 80-bit FPU registers. Otherwise we will have some
// failures.
volatile double x = 5.1;
volatile double y = 6.7;
volatile double z = 9.9;

mathpresso::Context ctx;
mathpresso::Expression e0;
mathpresso::Expression e1;

ctx.addEnvironment(mathpresso::kMPEnvironmentAll);
ctx.addVariable("x", 0 * sizeof(double));
ctx.addVariable("y", 1 * sizeof(double));
ctx.addVariable("z", 2 * sizeof(double));

double variables[] = { x, y, z };

TestExpression tests[] = {
TEST_EXPRESSION( x+y ),
TEST_EXPRESSION( x-y ),
TEST_EXPRESSION( x*y ),
TEST_EXPRESSION( x/y ),
TEST_EXPRESSION( -(x+y) ),
TEST_EXPRESSION( -(x-y) ),
TEST_EXPRESSION( x*z + y*z),
TEST_EXPRESSION( x*z - y*z),
TEST_EXPRESSION( x*z*y*z),
TEST_EXPRESSION( x*z/y*z),
TEST_EXPRESSION( x == y ),
TEST_EXPRESSION( x != y ),
TEST_EXPRESSION( x < y ),
TEST_EXPRESSION( x <= y ),
TEST_EXPRESSION( x > y ),
TEST_EXPRESSION( x >= y ),
TEST_EXPRESSION( x + y == y - z ),
TEST_EXPRESSION( x > y == y < z ),
TEST_EXPRESSION( -x ),
TEST_EXPRESSION( -1 + x ),
TEST_EXPRESSION( -(-(-1)) ),
TEST_EXPRESSION( -(-(-x)) ),
TEST_EXPRESSION( (x+y)*x ),
TEST_EXPRESSION( (x+y)*y ),
TEST_EXPRESSION( (x+y)*(1.19+z) ),
TEST_EXPRESSION( ((x+(x+2.13))*y) ),
TEST_EXPRESSION( (x+y+z*2+(x*z+z*1.5)) ),
TEST_EXPRESSION( (((((((x-0.28)+y)+x)+x)*x)/1.12)*y) ),
TEST_EXPRESSION( ((((x*((((y-1.50)+1.82)-x)/PI))/x)*x)+z) ),
TEST_EXPRESSION( (((((((((x+1.35)+PI)/PI)-y)+z)-z)+y)/x)+0.81) ),
TEST_EXPRESSION( round(x) ),
TEST_EXPRESSION( round(-x) ),
TEST_EXPRESSION( floor(x) ),
TEST_EXPRESSION( floor(-x) ),
TEST_EXPRESSION( ceil(x) ),
TEST_EXPRESSION( ceil(-x) ),
TEST_EXPRESSION( abs(-x) ),
TEST_EXPRESSION( sqrt(x) ),
TEST_EXPRESSION( recip(x) ),
TEST_EXPRESSION( exp(x) ),
TEST_EXPRESSION( log(x) ),
TEST_EXPRESSION( log10(x) ),
TEST_EXPRESSION( sin(x) ),
TEST_EXPRESSION( cos(x) ),
TEST_EXPRESSION( tan(x) ),
TEST_EXPRESSION( sin(x) * cos(y) * tan(z) ),
TEST_EXPRESSION( avg(x, y) ),
TEST_EXPRESSION( min(x, y) ),
TEST_EXPRESSION( max(x, y) ),
TEST_EXPRESSION( pow(x, y) )
};

for (int i = 0; i < TABLE_SIZE(tests); i++) {
const char* exp = tests[i].expression;
bool expOk = true;

int err;
if ((err = e0.create(ctx, exp, mathpresso::kMPOptionDisableJIT))) {
printf("[Failure]: \"%s\" (eval)\n", exp);
printf(" ERROR %d (jit disabled).\n", err);
continue;
}
volatile double x;
volatile double y;
volatile double z;

if ((err = e1.create(ctx, exp, mathpresso::kMPOptionNone))) {
printf("[Failure]: \"%s\" (jit)\n", exp);
printf(" ERROR %d (jit enabled).\n", err);
continue;
}

double expected = tests[i].expected;
double res0 = e0.evaluate(variables);
double res1 = e1.evaluate(variables);

if (res0 != expected) {
printf("[Failure]: \"%s\" (eval)\n", exp);
printf(" result(%f) != expected(%f)\n", res0, expected);
expOk = false;
}
// --------------------------------------------------------------------------
// [Functions]
// --------------------------------------------------------------------------

if (res1 != expected) {
printf("[Failure]: \"%s\" (jit)\n", exp);
printf(" result(%f) != expected(%f)\n", res1, expected);
expOk = false;
}
inline double abs(double x) { return x < 0.0 ? -x : x; }
inline double recip(double x) { return 1.0 / x; }

if (expOk) {
printf("[Success]: \"%s\" -> %f\n", exp, expected);
}
else {
failed = true;
}
}
inline double avg(double x, double y) { return (x + y) * 0.5; }
inline double min(double x, double y) { return x < y ? x : y; }
inline double max(double x, double y) { return x > y ? x : y; }
};

return failed ? 1 : 0;
int main(int argc, char* argv[]) {
return TestApp(argc, argv).run();
}

0 comments on commit 2737a74

Please sign in to comment.