package org.opensha2.function;
import static com.google.common.base.Preconditions.checkArgument;
import java.awt.geom.Point2D;
/**
* <b>Title:</b> DiscretizedFunc<p>
*
* <b>Description:</b> Abstract implementation of the DiscretizedFuncAPI.
* Performs standard simple or default functions so that subclasses don't have
* to keep reimplementing the same function bodies.<p>
*
* A Discretized Function is a collection of x and y values grouped together as
* the points that describe a function. A discretized form of a function is the
* only ways computers can represent functions. Instead of having y=x^2, you
* would have a sample of possible x and y values. <p>
*
* The basic functions this abstract class implements are:<br> <ul> <li>get, set
* Name() <li>get, set, Info() <li>get, set, Tolerance() <li>equals() - returns
* true if all three fields have the same values. </ul>
*
* See the interface documentation for further explanation of this framework<p>
*
* @author Steven W. Rock
* @version 1.0
*/
public abstract class AbstractDiscretizedFunc extends AbstractXY_DataSet
implements DiscretizedFunc {
/** Class name used for debbuging */
protected final static String C = "DiscretizedFunc";
/** if true print out debugging statements */
protected final static boolean D = false;
/**
* The tolerance allowed in specifying a x-value near a real x-value, so that
* the real x-value is used. Note that the tolerance must be smaller than 1/2
* the delta between data points for evenly discretized function, no
* restriction for arb discretized function, no standard delta.
*/
protected double tolerance = 0.0;
/** Returns the tolerance of this function. */
@Override
public double getTolerance() {
return tolerance;
}
/**
* Sets the tolerance of this function.
* @throws IllegalArgumentException if tolerance is less than zero
*/
@Override
public void setTolerance(double newTolerance) {
checkArgument(newTolerance >= 0, "Tolerance must be larger or equal to 0");
tolerance = newTolerance;
}
private boolean areBothNull(String first, String second) {
return first == null && second == null;
}
private boolean isOneNull(String first, String second) {
return first == null || second == null;
}
private boolean isSameWithNull(String first, String second) {
if (areBothNull(first, second)) {
return true;
}
if (isOneNull(first, second)) {
return false;
}
return first.equals(second);
}
/**
* Default equals for all Discretized Functions. Determines if two functions
* are the same by comparing that the name, info, and values are the same.
*/
@Override
public boolean equals(Object obj) {
// if (true)
// return true;
if (this == obj) {
return true;
}
if (!(obj instanceof DiscretizedFunc)) {
return false;
}
DiscretizedFunc function = (DiscretizedFunc) obj;
// now check names equal
if (!isSameWithNull(name(), function.name())) {
return false;
}
if ((name() == null && function.name() != null) ||
(name() != null && !name().equals(function.name()))) {
return false;
}
if (D) {
String S = C + ": equals(): ";
System.out.println(S + "This info = " + getInfo());
System.out.println(S + "New info = " + function.getInfo());
}
// now check info equal
if (!isSameWithNull(getInfo(), function.getInfo())) {
return false;
// if( !getInfo().equals(function.getInfo() ) ) return false;
}
// now check size
if (this.getNum() != function.getNum()) {
return false;
}
// now check that the points are equal
for (int i = 0; i < this.getNum(); i++) {
Point2D pt1 = this.get(i);
Point2D pt2 = function.get(i);
if (!pt1.equals(pt2)) {
return false;
}
}
return true;
}
// public Element toXMLMetadata(Element root) {
// return toXMLMetadata(root, AbstractDiscretizedFunc.XML_METADATA_NAME);
// }
//
// public Element toXMLMetadata(Element root, String elementName) {
// Element xml = root.addElement(elementName);
//
// xml.addAttribute("info", this.getInfo());
// xml.addAttribute("name", this.getName());
//
// xml.addAttribute("tolerance", this.getTolerance() + "");
// xml.addAttribute("xAxisName", this.getXAxisName());
// xml.addAttribute("yAxisName", this.getYAxisName());
// xml.addAttribute("num", this.getNum() + "");
// xml.addAttribute("minX", this.getMinX() + "");
// xml.addAttribute("maxX", this.getMaxX() + "");
// if (this instanceof EvenlyDiscretizedFunc) {
// xml.addAttribute("delta", ((EvenlyDiscretizedFunc)this).getDelta()+"");
// }
//
// Element points =
// xml.addElement(AbstractDiscretizedFunc.XML_METADATA_POINTS_NAME);
// for (int i=0; i<this.getNum(); i++) {
// Element point =
// points.addElement(AbstractDiscretizedFunc.XML_METADATA_POINT_NAME);
// point.addAttribute("x", this.getX(i) + "");
// point.addAttribute("y", this.getY(i) + "");
// }
//
// return root;
// }
//
// public static AbstractDiscretizedFunc fromXMLMetadata(Element funcElem) {
// String info = funcElem.attributeValue("info");
// String name = funcElem.attributeValue("name");
// String xAxisName = funcElem.attributeValue("xAxisName");
// String yAxisName = funcElem.attributeValue("yAxisName");
//
// AbstractDiscretizedFunc func;
// Attribute deltaAtt = funcElem.attribute("delta");
// if (deltaAtt == null) {
// func = new ArbitrarilyDiscretizedFunc();
// } else {
// int num = Integer.parseInt(funcElem.attributeValue("num"));
// double minX = Double.parseDouble(funcElem.attributeValue("minX"));
// double delta = Double.parseDouble(deltaAtt.getStringValue());
// func = new EvenlyDiscretizedFunc(minX, num, delta);
// }
//
// double tolerance =
// Double.parseDouble(funcElem.attributeValue("tolerance"));
//
// func.setInfo(info);
// func.setName(name);
// func.setXAxisName(xAxisName);
// func.setYAxisName(yAxisName);
// func.setTolerance(tolerance);
//
// Element points =
// funcElem.element(AbstractDiscretizedFunc.XML_METADATA_POINTS_NAME);
// Iterator<Element> it = points.elementIterator();
// while (it.hasNext()) {
// Element point = it.next();
// double x = Double.parseDouble(point.attributeValue("x"));
// double y = Double.parseDouble(point.attributeValue("y"));
// func.set(x, y);
// }
//
// return func;
// }
// public static void writeSimpleFuncFile(DiscretizedFunc func, String
// fileName) throws IOException {
// writeSimpleFuncFile(func, new File(fileName));
// }
//
// public static void writeSimpleFuncFile(DiscretizedFunc func, File
// outFile) throws IOException {
// FileWriter fr = new FileWriter(outFile);
// for (int i = 0; i < func.getNum(); ++i)
// fr.write(func.getX(i) + " " + func.getY(i) + "\n");
// fr.close();
// }
// public static ArbitrarilyDiscretizedFunc loadFuncFromSimpleFile(String
// fileName) throws FileNotFoundException, IOException {
// ArrayList<String> fileLines = FileUtils.loadFile(fileName);
// String dataLine;
// StringTokenizer st;
// ArbitrarilyDiscretizedFunc func = new ArbitrarilyDiscretizedFunc();
//
// for(int i=0;i<fileLines.size();++i) {
// dataLine=(String)fileLines.get(i);
// st=new StringTokenizer(dataLine);
// //using the currentIML and currentProb we interpolate the iml or prob
// //value entered by the user.
// double x = Double.parseDouble(st.nextToken());
// double y= Double.parseDouble(st.nextToken());
// func.set(x, y);
// }
// return func;
// }
//
// public static ArbitrarilyDiscretizedFunc
// loadFuncFromSimpleFile(InputStream is) throws FileNotFoundException,
// IOException {
// if (!(is instanceof BufferedInputStream))
// is = new BufferedInputStream(is);
// Scanner scanner = new Scanner(is);
//
// StringTokenizer st;
// ArbitrarilyDiscretizedFunc func = new ArbitrarilyDiscretizedFunc();
//
// try {
// while (scanner.hasNextLine()){
// st=new StringTokenizer(scanner.nextLine());
// //using the currentIML and currentProb we interpolate the iml or prob
// //value entered by the user.
// double x = Double.parseDouble(st.nextToken());
// double y = Double.parseDouble(st.nextToken());
// func.set(x, y);
// }
// }
// finally{
// scanner.close();
// }
// return func;
// }
public double calcSumOfY_Vals() {
double sum = 0;
for (int i = 0; i < getNum(); i++) {
sum += getY(i);
}
return sum;
}
@Override
public void scale(double val) {
for (int i = 0; i < getNum(); i++) {
this.set(i, val * getY(i));
}
}
}