package de.congrace.exp4j;
/**
* This class is used to create custom operators for use in expressions<br/>
* The applyOperation(double[] values) will have to be implemented by users of this class. <br/>
* <b>Example</b><br/>
* <code><pre>{@code}
* CustomOperator greaterEq = new CustomOperator(">=", true, 4, 2) {
* double applyOperation(double[] values) {
* if (values[0] >= values[1]){
* return 1d;
* }else{
* return 0d;
* }
* }
* };
* Calculable calc = new ExpressionBuilder("1>=2").withOperation(greaterEq).build();
* assertTrue(0d == calc.calculate());
* </pre></code> When constructing {@link CustomOperator} special attention has to be given to the precedence of the
* operation. see http://en.wikipedia.org/wiki/Order_of_operations. The precendence values for the builtin operators are
* as follows: <br/>
* Addition and Subtraction (+,-) have precedence 1<br/>
* Division Multiplication, and Modulo (/,*,%) have precedence 3<br/>
* Exponentiation (^) has precendence 5 <br/>
* Unary minus and plus (+1,-1) have precedence 7
*
* @author frank asseg
*
*/
public abstract class CustomOperator {
final boolean leftAssociative;
final String symbol;
final int precedence;
final int operandCount;
/**
* Create a new {@link CustomOperator} for two operands
*
* @param symbol
* the symbol to be used in expressions to identify this operation
* @param leftAssociative
* true is the operation is left associative
* @param precedence
* the precedence of the operation
*/
protected CustomOperator(final String symbol, final boolean leftAssociative, final int precedence) {
super();
this.leftAssociative = leftAssociative;
this.symbol = symbol;
this.precedence = precedence;
this.operandCount = 2;
}
/**
* Create a new {@link CustomOperator}
*
* @param symbol
* the symbol to be used in expressions to identify this operation
* @param leftAssociative
* true is the operation is left associative
* @param precedence
* the precedence of the operation
* @param operandCount
* the number of operands of the operation. A value of 1 means the operation takes one operand. Any other
* value means the operation takes 2 arguments.
*/
protected CustomOperator(final String symbol, final boolean leftAssociative, final int precedence,
final int operandCount) {
super();
this.leftAssociative = leftAssociative;
this.symbol = symbol;
this.precedence = precedence;
this.operandCount = operandCount == 1 ? 1 : 2;
}
/**
* Create a left associative {@link CustomOperator} with precedence value of 1 that uses two operands
*
* @param symbol
* the {@link String} to use a symbol for this operation
*/
protected CustomOperator(final String symbol) {
super();
this.leftAssociative = true;
this.symbol = symbol;
this.precedence = 1;
this.operandCount = 2;
}
/**
* Create a left associative {@link CustomOperator} for two operands
*
* @param symbol
* the {@link String} to use a symbol for this operation
* @param precedence
* the precedence of the operation
*/
protected CustomOperator(final String symbol, final int precedence) {
super();
this.leftAssociative = true;
this.symbol = symbol;
this.precedence = precedence;
this.operandCount = 2;
}
/**
* Apply the custom operation on the two operands and return the result as an double An example implementation for a
* multiplication could look like this:
*
* <pre>
* <code>{@code}
* double applyOperation(double[] values) {
* return values[0]*values[1];
* }
* </pre>
*
* </code>
*
* @param values
* the operands for the operation. If the {@link CustomOperator} uses only one operand such as a
* factorial the operation has to be applied to the first element of the values array. If the
* {@link CustomOperator} uses two operands the operation has to be applied to the first two items in the
* values array, with special care given to the operator associativity. The operand to the left of the
* symbol is the first element in the array while the operand to the right is the second element of the
* array.
* @return the result of the operation
*/
protected abstract double applyOperation(double[] values);
}