Class RpEval

  • All Implemented Interfaces:
    JepComponent, ParserVisitor, java.io.Serializable

    public final class RpEval
    extends AbstractEval
    A fast evaluation algorithm for equations over Doubles, does not work with vectors or matrices. This is based around reverse polish notation and is optimised for speed at every opportunity.

    To use do

     Jep j = ...;
     Node node = ...; 
     RpEval rpe = new RpEval(j);
     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 corresponding jep value.

    The compile methods converts the expression represented by node into a string of commands. For example the expression "1+2*3" will be converted into the sequence of commands

     Constant no 1 (pushes constant onto stack)
     Constant no 2
     Constant no 3
     Multiply scalers (multiplies last two entries on stack)
     Add scalers (adds last two entries on stack)
     
    The evaluate method executes these methods sequentially using a stack and returns the last object on the stack.

    A few cautionary notes:

    • It only works over doubles expressions with complex numbers or strings will cause problems.
    • It only works for expressions involving scalers.
    • It is safe to use individual RpEval instances in separate threads, using the same instance in separate threads is like to cause exceptions. The RpCommandList objects created by compile are immutable and are safe to use across threads. The duplicate() method creates a copy of the RpEval object which can evaluate the same commandList in separate threads.

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

    • Everything is final which maximizes 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.

    This class and the RpCommandList can be serialised, allowing a expression to be stored or transmitted. The serialized form stores the constants, variables and custom functions used. It does not save the associated Jep instance. This allows a deserialized instance to be used with a deserialized RpCommandList. If a Jep instance is serialized in the same stream as the RpEval instance then the AbstractEval.init(Jep) should be called on deserialization.

    Author:
    Rich Morris Created on 14-Apr-2004
    See Also:
    Serialized Form
    • Constructor Detail

      • RpEval

        public RpEval​(Jep jep)
    • Method Detail

      • cleanUp

        public void cleanUp()
        Removes observers and other cleanup needed when evaluator no longer used.
      • getVariable

        public Variable getVariable​(int ref)
        Gets the Jep Variable for a give reference number
        Parameters:
        ref - reference number for the variable
        Returns:
        corresponding Jep variable, or null if no jep instance
      • getVarRef

        public int getVarRef​(Variable var)
                      throws JepException
        Gets the reference number for a given variable
        Parameters:
        var - Jep Variable
        Returns:
        reference number for the variable
        Throws:
        JepException - if there is a miss-match in sizes of the internal representation. This can be caused if the method is called using a lightweight instance with no
      • getVarRef

        public int getVarRef​(java.lang.String varName)
                      throws JepException
        Gets the reference number for a given variable
        Parameters:
        varName - name of variable
        Returns:
        reference number for the variable
        Throws:
        JepException - if no jep instance, can happen if using a lightweight instance
      • setVarValue

        public void setVarValue​(int ref,
                                double val)
        Sets the value of a variable
        Parameters:
        ref - reference number for the variable
        val - the value to set the variable
      • getVarValue

        public double getVarValue​(int ref)
        Gets the value of a variable
        Parameters:
        ref - reference number for the variable
      • updateJepVariables

        public void updateJepVariables()
        Copies all the values from the Rpe variable to the corresponding Jep variables.
      • updateFromJepVariables

        public void updateFromJepVariables()
                                    throws EvaluationException
        If the variables used by Jep has a valid value set the corresponding mrpe value
        Throws:
        EvaluationException - if the jep variable has different dimensions to the mrpe variable
        Since:
        Jep 4.0/Extensions 2.1
      • toString

        public java.lang.String toString()
        Overrides:
        toString in class java.lang.Object
      • toString

        public java.lang.String toString​(RpCommand com)
        Enhanced RpCommand to String conversion. Used when rpe instance is available, prints the values of the constants, variables and functions.
        Parameters:
        com - an RpCommand to convert
        Returns:
        string representation
      • duplicate

        public RpEval duplicate()
        Returns a copy of the RpEval object which is safe to use for evaluation in a new thread. RpEval rpe1 = new RpEval(jep); RpCommandList com = rpe1.compile(node); int varRef = rpe1.getVarRef(jep.getVar("x")); RpEval rpe2 = rpe1.duplicate(); rpe2.setVarValue(ref,0.5); double result = rpe2.evaluate(com); Since Jep 4.0, extension 2.1 just calls getLightWeightInstance() with a cast See AbstractEval.duplicateCustomFunctions(AbstractEval, Jep) for handling of custom functions.
        Returns:
        a new instance
      • getLightWeightInstance

        public JepComponent getLightWeightInstance()
        Creates a new instance which can be used in a separate thread without a jep instance. Variables can only refered to using the setVarValue(int, double) and getVarValue(int). RpEval rpe1 = new RpEval(jep); RpCommandList com = rpe1.compile(node); int varRef = rpe1.getVarRef(jep.getVar("x")); RpEval rpe2 = (RpEval) rpe1.getLightWeightInstance(); rpe2.setVarValue(ref,0.5); double result = rpe2.evaluate(com); See AbstractEval.duplicateCustomFunctions(AbstractEval, Jep) for handling of custom functions.
        Returns:
        a new instance
      • toString

        public java.lang.String toString​(RpCommandList coms1)