The org.lsmp.djep.rpe
and org.lsmp.djep.mrpe
packages offers fast evaluation routines for expressions involving scalars or matrices respectively.
These offer a 5-10 times speed improvement over the standard Jep evaluation and approach the speed obtainable by native java code.
To optimise the speed of evaluation, separate packages are provided for equations involving doubles, i.e. standard single valued functions and those involving vectors and matrices. The org.lsmp.djep.rpe package provides support for non vector equations.
To use do
JEP j = new XJep(); j.addStandardConstants(); j.addStandardFunctions(); j.addComplex(); j.setAllowUndeclared(true); j.setImplicitMul(true); j.setAllowAssignment(true); RpEval rpe = new RpEval(j); Node node = j.parse("cos(pi/3)^2"); RpCommandList list = rpe.compile(node); double val = rpe.evaluate(list); System.out.println(val); rpe.cleanUp();
Variable values in the evaluator are stored in a array. The array index of a variable can be found using
Variable v = j.getVar("x"); int ref = rpe.getVarRef(v);and the value of the variable set using
rpe.setVarValue(ref,0.1234);
Variable values can also be set using the standard Variable.setValue() or (slower) JEP.setVarVal(name,vlaue) methods. Setting the value of a jep variable will automatically update the corresponding rpe value but there will be a performance hit. Setting the value of the rpe variable does not change the value of the corresponding jep value.
The compile methods converts the expression represented by node into a string of commands. For example the expression "4+5*6" will be converted into the sequence of commands
Constant no 1 (4) (pushes constant onto stack) Constant no 2 (5) Constant no 3 (6) Multiply scalers (multiplies last two entries on stack) - (6*5), the result (30) is pushed onto the top of the stack Add scalers (adds last two entries on stack) - (30+4) the result (34) is pushed onto top of the stack
The evaluate method executes these methods sequentially using a stack and returns the last object on the stack.
A few cautionary notes: Its very unlikely to be thread safe. It only works over doubles, expressions with complex numbers or strings will cause problems. It only works for expressions involving scalers.
A lot of things have been done to make it as fast as possible:
Functions which take double arguments and return double results are supported. Other functions which return strings or complex numbers will raise exceptions when used.
Some functions have been optimised for speed these are: sin, cos, tan, sec, cosec, cot, asin, acos, atan, sinh, cosh, tanh, asinh, acosh, atanh, abs, exp, log, ln, sqrt, atan2, if these are hand coded in the routines for high performance.
Other jep functions which take double arguments and return double results are also supported. These can be used directly and no additional calls are required.
To improve performance four interfaces org.lsmp.djep.RealNullaryFunction (0 arguments) org.lsmp.djep.RealUnaryFunction (1 argument) org.lsmp.djep.RealBinaryFunction (2 arguments) org.lsmp.djep.RealNaryFunction (any number of arguments) have been created, a PostfixMathCommand which implements one of these interfaces will be faster to evaluate.
Expression | Speed using Jep | Speed using rpe | Speed using Java |
---|---|---|---|
5 | 156 | 47 | |
x | 297 | 78 | |
1+x | 781 | 94 | |
x^2 | 844 | 109 | |
x*x | 781 | 94 | |
5*x | 797 | 94 | |
cos(x) | 656 | 156 | 79 |
1+x+x^2 | 1828 | 172 | |
1+x+x^2+x^3 | 2844 | 281 | |
1+x+x^2+x^3+x^4 | 3891 | 312 | |
1+x+x^2+x^3+x^4+x^5 | 4891 | 375 | |
1+x(1+x(1+x(1+x(1+x)))) | 4766 | 391 | 62 |
if(x>0.5,1,0) | 1219 | 219 |