/*
* JGrass - Free Open Source Java GIS http://www.jgrass.org
* (C) HydroloGIS - www.hydrologis.com
*
* 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 Foundation, Inc., 59
* Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package org.jgrasstools.gears.utils.math.interpolation;
import java.util.List;
import org.jgrasstools.gears.libs.modules.JGTConstants;
/**
* A least square regression interpolator.
*
* <p>
* This was done basing on the Java Number Cruncher Book by Ronald Mak
* (see http://www.apropos-logic.com/books.html).
* </p>
*
* @author Andrea Antonello (www.hydrologis.com)
*/
public class LeastSquaresInterpolator implements Interpolator {
private int n;
private double[][] data;
/** line coefficient a0 */
private double a0;
/** line coefficient a1 */
private double a1;
private double sumX;
private double sumY;
private double sumXX;
private double sumXY;
private boolean coefsValid;
/**
* Constructor.
*
* @param xList the list of X samples.
* @param yList the list of Y = f(X) samples.
*/
public LeastSquaresInterpolator( List<Double> xList, List<Double> yList ) {
data = new double[xList.size()][xList.size()];
for( int i = 0; i < xList.size(); i++ ) {
data[i][0] = xList.get(i);
data[i][1] = yList.get(i);
}
for( int i = 0; i < data.length; ++i ) {
addPoint(data[i]);
}
}
private void addPoint( double[] dataPoint ) {
if (n >= data.length)
return;
sumX += dataPoint[0];
sumY += dataPoint[1];
sumXX += dataPoint[0] * dataPoint[0];
sumXY += dataPoint[0] * dataPoint[1];
++n;
coefsValid = false;
}
public double getInterpolated( double x ) {
if (n < 2)
return JGTConstants.doubleNovalue;
validateCoefficients();
return a0 + a1 * x;
}
/**
* Validate the coefficients.
*/
private void validateCoefficients() {
if (coefsValid)
return;
if (n >= 2) {
double xBar = (double) sumX / n;
double yBar = (double) sumY / n;
a1 = (double) ((n * sumXY - sumX * sumY) / (n * sumXX - sumX * sumX));
a0 = (double) (yBar - a1 * xBar);
} else {
a0 = a1 = Double.NaN;
}
coefsValid = true;
}
/**
* Return the coefficient a0.
* @return the value of a0
*/
public double getA0() {
validateCoefficients();
return a0;
}
/**
* Return the coefficient a1.
* @return the value of a1
*/
public double getA1() {
validateCoefficients();
return a1;
}
/**
* Return the sum of the x values.
* @return the sum
*/
public double getSumX() {
return sumX;
}
/**
* Return the sum of the y values.
* @return the sum
*/
public double getSumY() {
return sumY;
}
/**
* Return the sum of the x*x values.
* @return the sum
*/
public double getSumXX() {
return sumXX;
}
/**
* Return the sum of the x*y values.
* @return the sum
*/
public double getSumXY() {
return sumXY;
}
}