/*
* JELCompiledExpression.java
*
* Created on September 4, 2002, 6:15 AM
*/
package hep.aida.ref.function;
import gnu.jel.CompiledExpression;
import gnu.jel.DVMap;
import hep.aida.ref.jel.JELLibraryFactory;
import java.util.StringTokenizer;
/**
*
* @author serbo
*/
// Convenience wrapper around the JEL's CompiledExpression
public class JELCompiledExpression {
private String expression;
private String parsedExpression;
private int dim;
private int nPar;
private String[] parNames;
private CompiledExpression compExpression;
private ValueProvider pro;
private Object[] context;
private Resolver res;
public JELCompiledExpression(int dim, int nPar, String expr, String[] pNames) {
//System.out.println("JELCompiledExpression:: expr = "+expr+", nVar = "+dim+", nPar = "+nPar + ", pNames = "+pNames[0]+" "+pNames[1]+" "+pNames[2]);
this.dim = dim;
this.nPar = nPar;
expression = expr;
// Set parameter names
setParameterNames(pNames);
// Create a compiled expression
parse();
compile();
}
public void setParameterNames(String[] pNames) {
if (pNames == null) {
throw new IllegalArgumentException("Can not set parameter names to a null");
} else if (nPar != pNames.length) {
throw new IllegalArgumentException("Number of parameters ("+nPar+
") is different from number of supplied parameter names ("+pNames.length+")");
}
parNames = new String[pNames.length];
for (int i=0; i<pNames.length; i++) parNames[i] = pNames[i];
}
public void parse() {
parsedExpression = "";
StringTokenizer st = new StringTokenizer(expression, "[]");
while (st.hasMoreTokens()) {
String token = st.nextToken();
//System.out.println(token);
if (token.toLowerCase().endsWith("x")) {
parsedExpression += token.substring(0,token.length()-1) + "x" + st.nextToken();
//parsedExpression += token.substring(0,token.length()-1) + "___x" + st.nextToken() + "___";
//} else if (token.endsWith("p")) {
//parsedExpression += token.substring(0,token.length()-1) + "___p" + st.nextToken() + "___";
} else parsedExpression += token;
}
//System.out.println("NEW:::"+parsedExpression);
}
private void compile() {
pro = new ValueProvider(dim, nPar);
context = new Object[]{pro};
res = new Resolver();
compExpression = JELLibraryFactory.compile(res, pro.getClass(), parsedExpression, Double.TYPE);
}
public double evaluate(double[] var, double[] par) {
pro.setVar(var);
pro.setPar(par);
double num = 0;
try {
num = compExpression.evaluate_double(context);
} catch (Throwable t) {
throw new RuntimeException("Runtime JEL Evaluation Problems!", t);
}
return num;
}
public class Resolver extends DVMap {
public Resolver() {}
public String getTypeName(String name) {
//System.out.println("Resolver.getTypeName:: name = "+name);
// Loop over all possible variables first
for (int i=0; i<dim; i++) {
if (name.equals("x"+i)) return "Double";
}
// Then over all parameters
for (int i=0; i<nPar; i++) {
if (name.equals(parNames[i])) return "Double";
}
return null;
}
public Object translate(String name) {
//System.out.println("Resolver.translate:: name = "+name);
int n = -1;
int offset = 0;
// Loop over all possible variables first
for (int i=0; i<dim; i++) {
if (name.equals("x"+i)) return new Integer(i);
}
// Then over all parameters
for (int i=0; i<nPar; i++) {
if (name.equals(parNames[i])) return new Integer(i+dim);
}
return new Integer(n);
}
}
public class ValueProvider {
private double[] var;
private double[] par;
public ValueProvider(int dim, int nPar) {
var = new double[dim];
par = new double[nPar];
}
public void setVar(double[] v) { var = v; }
public void setPar(double[] p) { par = p; }
public double getDoubleProperty(int i) {
//System.out.println("ValueProvider.getDoubleProperty(int):: i = "+i);
if (i < dim) {
return var[i];
} else if (i >= dim) {
return par[i-dim];
} else if (i < 0 || i > dim+par.length) {
throw new IllegalArgumentException("Wrong argument number: "+i+", dimension = "+dim+
", N parameters = "+par.length);
}
return 0;
}
}
public int parseInt(String name) { return Integer.parseInt(name.substring(4, name.length()-3)); }
}