//
// FormulaUtil.java
//
/*
VisAD system for interactive analysis and visualization of numerical
data. Copyright (C) 1996 - 2017 Bill Hibbard, Curtis Rueden, Tom
Rink, Dave Glowacki, Steve Emmerson, Tom Whittaker, Don Murray, and
Tommy Jasmin.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
MA 02111-1307, USA
*/
package visad.formula;
import java.lang.reflect.*;
import java.rmi.RemoteException;
import java.util.*;
import visad.*;
/** Contains a variety of useful methods related to the
visad.formula package. */
public class FormulaUtil {
/** create a FormulaManager object with many commonly desired features */
public static FormulaManager createStandardManager() {
String[] binOps = {".", "^", "*", "/", "%", "+", "-"};
int[] binPrec = {200, 400, 600, 600, 600, 800, 800};
String[] binMethods = {
"visad.formula.FormulaUtil.dot(visad.TupleIface, visad.Real)",
"visad.Data.pow(visad.Data)",
"visad.Data.multiply(visad.Data)",
"visad.Data.divide(visad.Data)",
"visad.Data.remainder(visad.Data)",
"visad.Data.add(visad.Data)",
"visad.Data.subtract(visad.Data)"
};
String[] unaryOps = {"-"};
int[] unaryPrec = {500};
String[] unaryMethods = {"visad.Data.negate()"};
String[] functions = {
"abs", "acos", "acosDegrees", "asin", "asinDegrees", "atan", "atan2",
"atanDegrees", "atan2Degrees", "ceil", "combine", "cos", "cosDegrees",
"derive", "domainMultiply", "domainFactor", "exp", "extract", "floor",
"getSample", "linkx", "log", "max", "min", "negate", "rint", "round",
"sin", "sinDegrees", "sqrt", "tan", "tanDegrees"
};
String[] funcMethods = {
"visad.Data.abs()",
"visad.Data.acos()",
"visad.Data.acosDegrees()",
"visad.Data.asin()",
"visad.Data.asinDegrees()",
"visad.Data.atan()",
"visad.Data.atan2(visad.Data)",
"visad.Data.atanDegrees()",
"visad.Data.atan2Degrees(visad.Data)",
"visad.Data.ceil()",
"visad.FieldImpl.combine(visad.Field[])",
"visad.Data.cos()",
"visad.Data.cosDegrees()",
"visad.formula.FormulaUtil.derive(visad.Function, " +
"visad.formula.VRealType)",
"visad.FieldImpl.domainMultiply()",
"visad.formula.FormulaUtil.factor(" +
"visad.FieldImpl, visad.formula.VRealType)",
"visad.Data.exp()",
"visad.formula.FormulaUtil.extract(visad.Field, visad.Real)",
"visad.Data.floor()",
"visad.formula.FormulaUtil.brackets(visad.Field, visad.Real)",
"visad.formula.FormulaUtil.link(visad.formula.VMethod, " +
"java.lang.Object[])",
"visad.Data.log()",
"visad.Data.max(visad.Data)",
"visad.Data.min(visad.Data)",
"visad.Data.negate()",
"visad.Data.rint()",
"visad.Data.round()",
"visad.Data.sin()",
"visad.Data.sinDegrees()",
"visad.Data.sqrt()",
"visad.Data.tan()",
"visad.Data.tanDegrees()"
};
int implicitPrec = 200;
String[] implicitMethods = {
"visad.formula.FormulaUtil.implicit(visad.Function, visad.Real)",
"visad.Function.evaluate(visad.RealTuple)"
};
String preParseMethod = "visad.formula.FormulaUtil.preParse(" +
"java.lang.String, visad.formula.FormulaManager)";
FormulaManager f;
try {
f = new FormulaManager(binOps, binPrec, binMethods,
unaryOps, unaryPrec, unaryMethods, functions, funcMethods,
implicitPrec, implicitMethods, preParseMethod);
}
catch (FormulaException exc) {
if (FormulaVar.DEBUG) exc.printStackTrace();
return null;
}
return f;
}
/** evaluate the dot operator */
public static Data dot(TupleIface t, Real r) {
Data d = null;
try {
d = t.getComponent((int) r.getValue());
}
catch (VisADException exc) {
if (FormulaVar.DEBUG) exc.printStackTrace();
}
catch (RemoteException exc) {
if (FormulaVar.DEBUG) exc.printStackTrace();
}
return d;
}
/** evaluate the derive function */
public static Data derive(Function f, VRealType rt) {
Data val = null;
try {
val = f.derivative(rt.getRealType(), Data.NO_ERRORS);
}
catch (VisADException exc) {
if (FormulaVar.DEBUG) exc.printStackTrace();
}
catch (RemoteException exc) {
if (FormulaVar.DEBUG) exc.printStackTrace();
}
return val;
}
/** evaluate the domainFactor function */
public static visad.Field factor(FieldImpl f, VRealType rt) {
visad.Field val = null;
try {
val = f.domainFactor(rt.getRealType());
}
catch (VisADException exc) {
if (FormulaVar.DEBUG) exc.printStackTrace();
}
catch (RemoteException exc) {
if (FormulaVar.DEBUG) exc.printStackTrace();
}
return val;
}
/** evaluate the extract function */
public static Data extract(visad.Field f, Real r) {
Data d = null;
try {
d = f.extract((int) r.getValue());
}
catch (VisADException exc) {
if (FormulaVar.DEBUG) exc.printStackTrace();
}
catch (RemoteException exc) {
if (FormulaVar.DEBUG) exc.printStackTrace();
}
return d;
}
/** evaluate the link function */
public static Data link(VMethod m, Object[] o) throws VisADException {
Data ans = null;
if (o != null) {
for (int i=0; i0; i++) {
// check for correct syntax
if (i >= len) return s;
char c = l.charAt(i);
if (c == '(') paren++;
if (c == ')') paren--;
}
int e1 = i-1;
// check for correct syntax
if (i > len - 3 || !l.substring(i, i+3).equals("/d(")) return s;
i += 3;
int s2 = i;
for (int paren=1; paren>0; i++) {
// check for correct syntax
if (i >= len) return s;
char c = l.charAt(i);
if (c == '(') paren++;
if (c == ')') paren--;
}
int e2 = i-1;
ns = ns + "derive(" + s.substring(s1, e1) +
"," + s.substring(s2, e2) + ")";
i--;
}
else if (!letter && i < len - 4 && l.substring(i, i+5).equals("link(")) {
// evaluate link(code) notation and replace with link variable
i += 5;
int s1 = i;
try {
while (l.charAt(i) != '(') i++;
}
catch (ArrayIndexOutOfBoundsException exc) {
// incorrect syntax
return s;
}
i++;
int e1 = i-1;
int s2 = i;
for (int paren=2; paren>1; i++) {
// check for correct syntax
if (i >= len) return s;
char c = l.charAt(i);
if (c == '(') paren++;
if (c == ')') paren--;
}
int e2 = i-1;
// check for correct syntax
if (i >= len || l.charAt(i) != ')') return s;
String prestr = s.substring(s1, e1) + "(";
String str = prestr;
// parse method's arguments; determine if they are Data or RealType
String sub = s.substring(s2, e2);
StringTokenizer st = new StringTokenizer(sub, ",", false);
boolean first = true;
Vector v = new Vector();
while (st.hasMoreTokens()) {
String token = st.nextToken();
if (first) first = false;
else str = str + ",";
RealType rt = RealType.getRealTypeByName(token);
String sv = (rt == null ? "visad.Data" : "visad.RealType");
v.add(sv);
str = str + sv;
}
str = str + ")";
// obtain Method object
Method[] meths = FormulaUtil.stringsToMethods(new String[] {str});
if (meths[0] == null) {
// attempt to identify any matching methods by compressing
// some or all of the arguments into array form
int vlen = v.size();
Vector vstrs = new Vector();
for (int iv=0; iv= 0) meths[0] = meths[found];
else {
// could not find a matching method
return s;
}
}
// store method object in a link variable
String link = "link" + (++linkNum);
try {
fm.setThing(link, new VMethod(meths[0]));
}
// catch any errors setting the link variable
catch (FormulaException exc) {
return s;
}
catch (VisADException exc) {
return s;
}
catch (RemoteException exc) {
return s;
}
ns = ns + "linkx(" + link + "," + s.substring(s2, e2) + ")";
}
else if (!letter) {
int j = i;
char c = l.charAt(j++);
while (j < len && ((c >= 'a' && c <= 'z') || (c >= '0' && c <= '9'))) {
c = l.charAt(j++);
}
// check for end-of-string
if (j == len) return ns + s.substring(i, len);
if (c == '[') {
// convert x[y] notation to standard getSample(x, y) notation
int k = j;
for (int paren=1; paren>0; k++) {
// check for correct syntax
if (k >= len) return s;
c = l.charAt(k);
if (c == '[') paren++;
if (c == ']') paren--;
}
ns = ns + "getSample(" + s.substring(i, j-1) +
"," + s.substring(j, k-1) + ")";
i = k-1;
}
else ns = ns + s.charAt(i);
}
else {
// append character to new string
ns = ns + s.charAt(i);
}
char c = (i < len) ? l.charAt(i) : '\0';
letter = (c >= 'a' && c <= 'z');
}
return ns;
}
// useful methods for advanced reflection:
/** convert an array of strings of the form
"package.Class.method(Class, Class, ...)"
to an array of Method objects */
public static Method[] stringsToMethods(String[] strings) {
int len = strings.length;
Method[] methods = new Method[len];
for (int j=0; j 0) {
if (a < 0) {
args = new Object[num];
System.arraycopy(o, 0, args, 0, num);
}
else {
// compress some of the arguments into array form
args = new Object[len];
if (a > 0) System.arraycopy(o, 0, args, 0, a);
Object array = Array.newInstance(c[a].getComponentType(), num-len+1);
System.arraycopy(o, a, array, 0, num-len+1);
args[a] = array;
if (a < len-1) System.arraycopy(o, num-len+a+1, args, a+1, len-a-1);
}
}
else args = null;
}
else {
// object method
if (num > 0) obj = o[0];
else {
// invalid object method
return null;
}
if (num > 1) {
if (a < 0) {
args = new Object[num-1];
System.arraycopy(o, 1, args, 0, num-1);
}
else {
// compress some of the arguments into array form
args = new Object[len];
if (a > 0) System.arraycopy(o, 1, args, 0, a);
Object array = Array.newInstance(c[a].getComponentType(), num-len);
System.arraycopy(o, a+1, array, 0, num-len);
args[a+1] = array;
if (a < len-1) System.arraycopy(o, num-len+a+1, args, a+1, len-a-1);
}
}
else args = null;
}
return m.invoke(obj, args);
}
}
Ads help maintain this website.