You implement the
These abstract classes provide additional functionality to provide a description, data type information, and a function call template for the Calculation editor to use. All functions must have a name. Except for functions used as operators, the name must start with a letter and continue with only letters, digits, and underscores. A function whose name contains punctuation or spaces cannot be called. Functions can have the same name as a parameter—a function name is distinguished as being followed by open parentheses in the text of a Calculation expression. These classes and all other classes described in this section
are described in the Isight
API javadocs. You can find the classes in the Any class that implements a function must be coded so that it can
be reentered, since the same function object can be used simultaneously
from multiple instances of the Calculation engine on different threads.
Therefore, all working storage must be held in local variables of the
If a function will be implemented using an existing Java class, an
instance of that class should be created in the Extending AbstractDoubleFunctionTo implement a function that takes only real numbers as arguments
and returns a real number as the result, extend class
import com.engineous.sdk.calc.*;
class Sind extends AbstractDoubleFunction {
public Sind() { super("sind", 1); }
public double eval(double[] arg) throws CalcException {
return Math.sin(arg[0] * Math.PI / 180.0);
}
}
The call to the super-class constructor is required. The first argument
is the name of the function as used in the Calculation engine. The second
argument is the number of arguments the function expects. Zero or a positive
number means that exactly that number of arguments is required. A negative
number indicates that the function takes a variable number of arguments
and the absolute value is the minimum number of arguments. That is, If the function requires only certain patterns of arguments (e.g.,
1 or 2 arguments but never more than 2), override the method The A function can be defined as an anonymous inner class as follows:
Function argument = new AbstractDoubleFunction("argument", 2) {
public double eval(double[] arg) {
double re = arg[0];
double im = arg[1];
return Math.sqrt(re * re + im * im);
}};
The following is a simple example of a function that accepts a variable number of arguments. It calculates the product of all its arguments:
Function prod = new AbstractDoubleFunction("product", -1) {
public double eval(double[] arg) {
double result = arg[0];
for (int i = 1; i < arg.length; i++) {
result *= arg[i];
}
return result;
}};
Extending AbstractScalar FunctionInstead of directly passing the arguments to the function, the You can use methods of the
The following is an example of the
public void eval(ScalarEnv env) throws CalcException {
StringBuilder buf = new StringBuilder();
for (int i = 0; i < env.getNargs(); i++) {
buf.append(env.getAsString(i));
}
env.setResult(buf.toString());
}
It is not necessary to do an explicit check of the argument number or
type if there is only one reasonable number or type; you can retrieve
the arguments you expect to be there using the data type you expect.
If the actual arguments are wrong, the The constructor for a class derived from
import com.engineous.sdk.calc.*;
import com.engineous.sdk.vars.EsiTypes;
public class Concat extends AbstractScalarFunction {
public Concat() {
super("concat", -2);
argType = EsiTypes.STRING;
resultType = EsiTypes.STRING;
description = "Concatenate two or more strings into one
string.";
}
public void eval(ScalarEnv env) throws CalcException {
StringBuilder buf = new StringBuilder();
for (int i = 0; i < env.getNargs(); i++) {
buf.append(env.getAsString(i));
}
env.setResult(buf.toString());
}
}
See the JavaDocs for To view an example of a function that takes one string argument and
two integer arguments, see the inner class Extending AbstractFunctionThe abstract class An argument to your function is evaluated each time g The Calculation example has two functions that use The method The following is part of the code for the
public class Mean extends AbstractFunction implements
ScalarFunction {
public Mean() {
super("mean", -1); // note 1 or more argument allowed
resultType = EsiTypes.REAL; // result MUST be real
// Note that argument types are not given - anything will
// be converted to a Real before processing (if possible)
}
// override from AbstractFunction to give different arg.
structures
public int int getArgStructure(int argNo, int nArgs) {
if (nArgs == 1) {
// one argument MUST be an array
return Variable.STRUCT_ARRAY;
} else {
// otherwise use default (which is Scalar or Array)
return super.getArgStructure(argNo, nArgs);
}
}
public Variable eval(FunctionEnv env) {
if (env.getNargs() == 1) {
return evalMean(VariableUtil.getArrayAsReal1d(
(ArrayVariable)env.getArgument(0));
}
else {
return env.evalScalar(this);
}
}
// implement ScalarFunction interface
// pack all arguments into a double array and then calculate
result.
public void eval(ScalarEnv senv) {
double[] args = new double[senv.getNargs()];
for (int i = 0; i < senv.getNargs(); i++) {
args[i] = senv.getAsReal(i);
}
senv.setResult(evalMean(args));
}
// Actual implementation of mean
private double evalMean(double[] args) {
double sum = 0.0;
for (int i = 0; i < args.length; i++) {
sum += args[i];
}
return sum / args.length;
}
}
Implementing Function DirectlyOn occasion, you may need to implement the Implementing the CalculationPlugin InterfaceTo allow a Calculation plug-in to define multiple functions or operators,
the implementation class of the plug-in must implement the
import com.engineous.sdk.calc.*;
import java.util.*;
public class StringFunc implements CalculationPlugin {
public Collection<Function> getFunctions() {
ArrayList<Function> func = new ArrayList<Function>();
func.add(new MyFunc1());
func.add(new MyFunc2());
return func;
}
public Collection<Operator> getOperators() {
ArrayList<Operator> op = new ArrayList<Operator>();
op.add(new Operator(Operator.OpType.INFIX,
Operator.OpAssoc.LEFT, 10, "&", new MyFunc3(), null);
return op;
}
}
That is, you build a collection of function objects and return it from
Operators are always built with the constructor for the class operator—never sub-class this class. An operator is a description of what symbol is used for the operator and where it can be used. Note:
See the JavaDocs for the operator class for the arguments
to the operator constructor and the enum values that can be passed to
some of the arguments.
Each operator object has a function object that implements the operator. The number of arguments must match how the operator is used—one argument for a unary prefix operator, two arguments for a binary infix operator. The function name does not matter—it can be the operator symbol, or it can be a proper function name that can be called as a function. The symbol for an operator can be any Unicode character string as long as it starts with a character that is not a letter or digit and it is not one of the reserved characters: comma, semicolon, parentheses, and square brackets. While the enum class The example file in | |||||||