The com.singularsys.extensions.fastreal
packages offers fast evaluation routines for expressions involving double scalars.
These offer a 5-10 times speed improvement over the standard Jep evaluation and approaches the speed obtainable by native java code.
The classes are intended to be used in situations where the same expressions are repeatedly evaluated using different values of variables.
For expressions involving vectors and matrices see the fastmatrix package instead.

The com.singularsys.extensions.fastreal.RpEval
class is used to perform evaluation for scaler expressions using doubles. A two step process is used
first the expression is compiled into an `RpCommandList`

and this is later evaluated.
The name "RpEval" stems from
Reverse Polish notation
which is how the compiled expression is encoded.

Jep j = new Jep(); 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();

The evaluator maintains its only private list of variables values which are stored in an array. The array index of a variable can be found using

int ref = rpe.getVarRef("x");

or

Variable v = j.getVariable("x"); int ref2 = rpe.getVarRef(v);and the value of the variable can be set and read using

rpe.setVarValue(ref,0.1234); double val = rpe.getVarValue(ref);

// Parse and compile an expression RpEval rpe = new RpEval(jep); String s = "a x^2 + b y^2"; Node n = jep.parse(s); RpCommandList coms = rpe.compile(n); // Get the references to the variables int xRef = rpe.getVarRef("x"); int yRef = rpe.getVarRef("y"); int aRef = rpe.getVarRef("a"); int bRef = rpe.getVarRef("b"); // sets the two parameters a, b rpe.setVarValue(aRef, 2.5); rpe.setVarValue(bRef, -3.1); // loop over different values of x and y for(double x=-1.0;x<=1.0;x+=0.1) { rpe.setVarValue(xRef, x); for(double y=-1.0;y<1.0;y+=0.1) { rpe.setVarValue(yRef, y); // evaluate the expression with these variable values double res = rpe.evaluate(coms); System.out.printf("%4.1f ",res); } System.out.println(); }

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.

The `com.singularsys.extensions.fastreal.RpEvaluator`

allows the evaluator to be used
in normal jep code. To set up use

Jep jep = new Jep(new RpEvaluator(true));

And then continue to use the jep code as normal.
This is somewhat slower than using `rpe.evaluate()`

directly but is still faster than using the normal Jep evaluator.
Some speedup can be obtained by using `new RpEvaluator(false)`

which does not update the jep variables following evaluation.

A few cautionary notes:

- The same instance of RpEval is not thread safe, however the
`RpEval.duplicate()`

method can be used to allow the same command strings to be used in multiple threads. - It only works over doubles, expressions with complex numbers or strings will not work.
- The fastreal (RpEval) only works for expressions involving scalers.

A lot of things have been done to make it as fast as possible:

- Everything is final which maximise the possibility for in-lining.
- All object creation happens during compile.
- All calculations done using double values.
- Each operator/function is hand coded. To extend functionality you will have to modify the source.

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.

The table below indicates the evaluation speeds. Times are in milliseconds for a million evaluations.

Expression | Speed using Jep | Speed using rpe | Speed using Java |
---|---|---|---|

5 | 125 | 47 | |

x | 281 | 94 | |

1+x | 515 | 110 | |

x^2 | 594 | 109 | |

x*x | 468 | 109 | |

5*x | 484 | 110 | |

1+x+x^2 | 1375 | 172 | |

1+x+x^2+x^3 | 1671 | 250 | |

1+x+x^2+x^3+x^4 | 2234 | 328 | |

1+x+x^2+x^3+x^4+x^5 | 2860 | 406 | |

1+x(1+x(1+x(1+x(1+x)))) | 2375 | 359 | 62 |

cos(x) | 485 | 203 | 79 |

cos(x)^2+sin(x)^2 | 1750 | 406 | |

if(x>0.5,1,0) | 734 | 218 | |

y=x*x; z=y*y; w=z*z | 1829 | 313 |

This indicates a speed up of between 3 and 13 times as fast.

Both `RpEval`

and ` RpCommandList`

implements Serializable
so serialized versions of expressions can be stored or transmitted.

// set up and compile Jep jep = new Jep(); RpEval rpe = new RpEval(jep); String s = "1+2*x/4"; Node n = jep.parse(s); RpCommandList coms = rpe.compile(n); int xref = rpe.getVarRef("x"); // Serialize ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(baos); oos.writeObject(rpe); oos.writeObject(coms); oos.writeInt(xref); oos.close(); byte bytes[] = baos.toByteArray(); // Deserialize ByteArrayInputStream bais = new ByteArrayInputStream(bytes); ObjectInputStream ois = new ObjectInputStream(bais); RpEval rpe2 = (RpEval) ois.readObject(); RpCommandList coms2 = (RpCommandList) ois.readObject(); int xref2 = ois.readInt(); ois.close(); // Evaluate rpe2.setVarValue(xref2, 5.0); double res2 = rpe2.evaluate(coms2);

A Jep instance can also be serialised along with the rpe instance.
On deserialization the `ReEval.init(Jep jep)`

methods should be called.

- com.singularsys.extexamples.consoles.RpEvalConsole an interactive console application.
- com.singularsys.extexamples.diagnostics.ExtSpeedTest runs some speed test applications comparing speeds with a standard Jep evaluator.
- com.singularsys.extexamples.diagnostics.RpThreadSpeed Tests using evaluation in multiple threads.
- com.singularsys.extexamples.applets.ImplicitPlotter A plotting program for implicit curves/level sets. Uses the RpEval system to perform fast calculation over a 2D the domain.
- com.singularsys.exttests.RpTest some JUnit tests.