[Home] DMelt member access . Java source code: com.jstatcom.parser.CalcFunctions
/*
This file is part of the software framework JStatCom,
a library for building applications for data based analysis.
Copyright (C) 2000-2005 Markus Kraetzig
This library is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser 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 com.jstatcom.parser;
import java.util.HashMap;
import java.util.Map;
import java.util.Stack;
import com.jstatcom.util.UMatrix;
/**
* Enumeration of all functions that are used by CalcEngine. The
* defined functions objects override
* execute(int argNum, Stack argStack) to provide the respective
* functionality. All functions get their arguments from a stack and put the
* results back on the stack after successful computation.
*
* @author Markus Kraetzig
*/
public abstract class CalcFunctions {
/**
* The name of the function.
*/
private final String name;
/**
* The Map containing all functions with a string as key.
*/
private static final Map functionMap = new HashMap();
/**
* fracdiff(a, d), fractional differences of a.
*/
public static final CalcFunctions FRACDIFF = new CalcFunctions("FRACDIFF") {
public void execute(int argNum, Stack argStack) {
if (argNum != 2)
throw new IllegalArgumentException(
"Wrong number of arguments to fracdiff(a, d).");
/* Assemble the result as a double[] */
double[] dd = argStack.pop();
if (dd.length != 1)
throw new IllegalArgumentException(
"fracdiff(a, d) only takes scalar as 2nd argument.");
double[] aa = argStack.pop();
double[] result = UMatrix.fracdiff(aa, dd[0]);
argStack.push(result);
}
};
/**
* sin(a), computes sinus function for all elements of an array.
*/
public static final CalcFunctions SIN = new CalcFunctions("SIN") {
public void execute(int argNum, Stack argStack) {
if (argNum != 1)
throw new IllegalArgumentException(
"Wrong number of arguments to sin(a).");
/* Assemble the result as a double[] */
double[] aa = argStack.pop();
double[] result = new double[aa.length];
for (int i = 0; i < aa.length; i++)
result[i] = Math.sin(aa[i]);
argStack.push(result);
}
};
/**
* cos(a), computes cosinus function for all elements of an array.
*/
public static final CalcFunctions COS = new CalcFunctions("COS") {
public void execute(int argNum, Stack argStack) {
if (argNum != 1)
throw new IllegalArgumentException(
"Wrong number of arguments to cos(a).");
/* Assemble the result as a double[] */
double[] aa = argStack.pop();
double[] result = new double[aa.length];
for (int i = 0; i < aa.length; i++)
result[i] = Math.cos(aa[i]);
argStack.push(result);
}
};
/**
* tan(a), computes tangens function for all elements of an array.
*/
public static final CalcFunctions TAN = new CalcFunctions("TAN") {
public void execute(int argNum, Stack argStack) {
if (argNum != 1)
throw new IllegalArgumentException(
"Wrong number of arguments to tan(a).");
/* Assemble the result as a double[] */
double[] aa = argStack.pop();
double[] result = new double[aa.length];
for (int i = 0; i < aa.length; i++)
result[i] = Math.tan(aa[i]);
argStack.push(result);
}
};
/**
* sqrt(a), computes square root for all elements of an array.
*/
public static final CalcFunctions SQRT = new CalcFunctions("SQRT") {
public void execute(int argNum, Stack argStack) {
if (argNum != 1)
throw new IllegalArgumentException(
"Wrong number of arguments to sqrt(a).");
/* Assemble the result as a double[] */
double[] aa = argStack.pop();
double[] result = new double[aa.length];
for (int i = 0; i < aa.length; i++)
result[i] = Math.sqrt(aa[i]);
argStack.push(result);
}
};
/**
* log(a), computes natural logarithm for all elements of an array. Fails,
* if the array contains values smaller or equal to zero.
*/
public static final CalcFunctions LOG = new CalcFunctions("LOG") {
public void execute(int argNum, Stack argStack) {
if (argNum != 1)
throw new IllegalArgumentException(
"Wrong number of arguments to log(a).");
/* Assemble the result as a double[] */
double[] aa = argStack.pop();
double[] result = new double[aa.length];
for (int i = 0; i < aa.length; i++) {
if (aa[i] <= 0)
throw new IllegalArgumentException("Element at index "
+ (i + 1) + " <= 0 for log(a).");
result[i] = Math.log(aa[i]);
}
argStack.push(result);
}
};
/**
* lagn(a,b), lags the array by b elements and fills the resulting free
* slots with Double.NaN. Lagging means, that every element
* i is replaced by the element in i-b. The
* argument b can also be negative, which would result in a
* forward shift.
*/
public static final CalcFunctions LAGN = new CalcFunctions("LAGN") {
public void execute(int argNum, Stack argStack) {
if (argNum != 2)
throw new IllegalArgumentException(
"Wrong number of arguments to lagn(a,b).");
/* Assemble the result as a double[] */
double[] bb = argStack.pop();
double[] aa = argStack.pop();
if (bb.length != 1)
throw new IllegalArgumentException(
"lagn(a,b) only takes scalar as 2nd argument.");
int lag = new Double(bb[0]).intValue();
double[] result = new double[aa.length];
for (int i = 0; i < aa.length; i++) {
if (i - lag < 0 || i - lag > aa.length - 1)
result[i] = Double.NaN;
else
result[i] = aa[i - lag];
}
argStack.push(result);
}
};
/**
* rows(a), gets the rows of an array.
*/
public static final CalcFunctions ROWS = new CalcFunctions("ROWS") {
public void execute(int argNum, Stack argStack) {
if (argNum != 1)
throw new IllegalArgumentException(
"Wrong number of arguments to rows(a).");
/* Assemble the result as a double[] */
double[] aa = argStack.pop();
double[] result = new double[] { aa.length };
argStack.push(result);
}
};
/**
* ones(a), creates an array of ones with dimension (a x 1).
*/
public static final CalcFunctions ONES = new CalcFunctions("ONES") {
public void execute(int argNum, Stack argStack) {
if (argNum != 1)
throw new IllegalArgumentException(
"Wrong number of arguments to ones(a).");
/* Assemble the result as a double[] */
double[] aa = argStack.pop();
if (aa.length != 1 || aa[0] < 1)
throw new IllegalArgumentException(
"ones(a) takes only scalar >=1 as argument.");
int length = new Double(aa[0]).intValue();
double[] result = new double[length];
for (int i = 0; i < length; i++)
result[i] = 1;
argStack.push(result);
}
};
/**
* trend(a), creates an array of numbers incremented by 1 with dimension
* (a x 1), starting from 1.
*/
public static final CalcFunctions TREND = new CalcFunctions("TREND") {
public void execute(int argNum, Stack argStack) {
if (argNum != 1)
throw new IllegalArgumentException(
"Wrong number of arguments to trend(a).");
/* Assemble the result as a double[] */
double[] aa = argStack.pop();
if (aa.length != 1 || aa[0] < 1)
throw new IllegalArgumentException(
"trend(a) takes only scalar >=1 as argument.");
int length = new Double(aa[0]).intValue();
double[] result = new double[length];
for (int i = 0; i < length; i++)
result[i] = i + 1;
argStack.push(result);
}
};
/**
* rndn(a), creates an array of a random numbers between 0
* and 1.
*/
public static final CalcFunctions RNDN = new CalcFunctions("RNDN") {
public void execute(int argNum, Stack argStack) {
if (argNum != 1)
throw new IllegalArgumentException(
"Wrong number of arguments to rndn(a).");
/* Assemble the result as a double[] */
double[] aa = argStack.pop();
if (aa.length != 1 || aa[0] < 1)
throw new IllegalArgumentException(
"rndn(a) takes only scalar >=1 as argument.");
int length = new Double(aa[0]).intValue();
double[] result = new double[length];
for (int i = 0; i < length; i++)
result[i] = Math.random();
argStack.push(result);
}
};
/**
* sumc(a), computes the sum of all elements in an array.
*/
public static final CalcFunctions SUMC = new CalcFunctions("SUMC") {
public void execute(int argNum, Stack argStack) {
if (argNum != 1)
throw new IllegalArgumentException(
"Wrong number of arguments to sumc(a).");
/* Assemble the result as a double[] */
double[] aa = argStack.pop();
double[] result = new double[1];
for (int i = 0; i < aa.length; i++)
result[0] += aa[i];
argStack.push(result);
}
};
/**
* meanc(a), computes the mean of all elements in an array.
*/
public static final CalcFunctions MEANC = new CalcFunctions("MEANC") {
public void execute(int argNum, Stack argStack) {
if (argNum != 1)
throw new IllegalArgumentException(
"Wrong number of arguments to meanc(a).");
/* Assemble the result as a double[] */
double[] aa = argStack.pop();
double[] result = new double[1];
for (int i = 0; i < aa.length; i++)
result[0] += aa[i];
result[0] = result[0] / aa.length;
argStack.push(result);
}
};
/**
* stdc(a), computes the standard deviation of all elements in an array.
*/
public static final CalcFunctions STDC = new CalcFunctions("STDC") {
public void execute(int argNum, Stack argStack) {
if (argNum != 1)
throw new IllegalArgumentException(
"Wrong number of arguments to stdc(a).");
/* Assemble the result as a double[] */
double[] aa = argStack.pop();
double mean = 0;
for (int i = 0; i < aa.length; i++)
mean += aa[i];
mean = mean / aa.length;
double[] result = new double[1];
for (int i = 0; i < aa.length; i++)
result[0] += Math.pow((aa[i] - mean), 2);
result[0] = Math.sqrt(result[0] / aa.length);
argStack.push(result);
}
};
/**
* stand(a), creates a normalized version if the array by subtracting the
* mean and dividing by the standard deviation.
*/
public static final CalcFunctions STAND = new CalcFunctions("STAND") {
public void execute(int argNum, Stack argStack) {
if (argNum != 1)
throw new IllegalArgumentException(
"Wrong number of arguments to stand(a).");
/* Assemble the result as a double[] */
double[] aa = argStack.pop();
double mean = 0;
for (int i = 0; i < aa.length; i++)
mean += aa[i];
mean = mean / aa.length;
double std = 0;
for (int i = 0; i < aa.length; i++)
std += Math.pow((aa[i] - mean), 2);
std = Math.sqrt(std / aa.length);
double[] result = new double[aa.length];
for (int i = 0; i < aa.length; i++)
result[i] = (aa[i] - mean) / std;
argStack.push(result);
}
};
/**
* reverse(a), reverses the order of an array, starting from observation T
* to 1.
*/
public static final CalcFunctions REVERSE = new CalcFunctions("REVERSE") {
public void execute(int argNum, Stack argStack) {
if (argNum != 1)
throw new IllegalArgumentException(
"Wrong number of arguments to reverse(a).");
/* Assemble the result as a double[] */
double[] aa = argStack.pop();
double[] result = new double[aa.length];
for (int i = 0; i < aa.length; i++)
result[i] = aa[aa.length - 1 - i];
argStack.push(result);
}
};
/**
* min(a,b), returns an array with the minimum elements of a
* and b for each row.
*/
public static final CalcFunctions MIN = new CalcFunctions("MIN") {
public void execute(int argNum, Stack argStack) {
if (argNum != 2)
throw new IllegalArgumentException(
"Wrong number of arguments to min(a,b).");
/* Assemble the result as a double[] */
double[] bb = argStack.pop();
double[] aa = argStack.pop();
double[] result = new double[getLength(aa, bb)];
for (int i = 0; i < result.length; i++)
result[i] = Math.min(((aa.length == 1) ? aa[0] : aa[i]),
((bb.length == 1) ? bb[0] : bb[i]));
argStack.push(result);
}
};
/**
* max(a,b), returns an array with the maximum elements of a
* and b for each row.
*/
public static final CalcFunctions MAX = new CalcFunctions("MAX") {
public void execute(int argNum, Stack argStack) {
if (argNum != 2)
throw new IllegalArgumentException(
"Wrong number of arguments to max(a,b).");
/* Assemble the result as a double[] */
double[] bb = argStack.pop();
double[] aa = argStack.pop();
double[] result = new double[getLength(aa, bb)];
for (int i = 0; i < result.length; i++)
result[i] = Math.max(((aa.length == 1) ? aa[0] : aa[i]),
((bb.length == 1) ? bb[0] : bb[i]));
argStack.push(result);
}
};
/**
* Add a new EngineRunType by subclassing and overriding operate.
*/
protected CalcFunctions(String newName) {
this.name = newName.toLowerCase();
functionMap.put(name, this);
}
/**
* Executes a function specified with a name.
*
* @param functionName
* a case insensitive String with the name of the function to
* call
* @param argNum
* the number of arguments to the function
* @param argStack
* the current Stack to store the input as well as the result
* @throws IllegalArgumentException
* in case the function does not exist or the arguments are
* wrong
*/
public static void callFunctionForName(String functionName, int argNum,
Stack argStack) throws IllegalArgumentException {
if (functionName == null)
throw new IllegalArgumentException("Function name is null.");
Object key = functionName.toLowerCase();
if (!functionMap.containsKey(key))
throw new IllegalArgumentException("Function \"" + functionName
+ "\" is not defined.");
functionMap.get(key).execute(argNum, argStack);
}
/**
* Override prevention method to enforce a.equals(b) if and
* only if a==b.
*
* @param o
* object to compare with
* @return true if equal, false otherwise
*/
public final boolean equals(Object o) {
return super.equals(o);
}
/**
* This defines the operation that is actually carried out by the function.
* The method must be overridden if you define a new function. Input
* parameters as well as results are contained in the argStack.
*
* @param argNum
* the number of arguments to the function
* @param argStack
* the current Stack to store the input as well as the result
*/
public abstract void execute(int argNum, Stack argStack);
/**
* Computes the correct length when 2 array are combined.
*
* @param aa
* double array
* @param bb
* double array
* @return the length for the result array
* @throws ParseException
* if (aa.length != bb.length) && (aa.length != 1) && (bb.length !=
* 1)
*/
public static int getLength(double[] aa, double[] bb)
throws IllegalArgumentException {
if (aa.length == bb.length)
return aa.length;
if (aa.length == 1 && bb.length > 1)
return bb.length;
if (bb.length == 1 && aa.length > 1)
return aa.length;
throw new IllegalArgumentException("Array dimensions do not fit.");
}
/**
* Override prevention method invokes super method.
*
* @return hash code
*/
public final int hashCode() {
return super.hashCode();
}
/**
* Returns the name of the runtype, do not use for comparisons.
*/
public final String toString() {
return name;
}
}
Ads help maintain this website.