//******************************************************************************
//
// File: Interpolation.java
// Package: edu.rit.numeric
// Unit: Class edu.rit.numeric.Interpolation
//
// This Java source file is copyright (C) 2011 by Alan Kaminsky. All rights
// reserved. For further information, contact the author, Alan Kaminsky, at
// ark@cs.rit.edu.
//
// This Java source file is part of the Parallel Java Library ("PJ"). PJ is free
// software; you can redistribute it and/or modify it under the terms of the GNU
// General Public License as published by the Free Software Foundation; either
// version 3 of the License, or (at your option) any later version.
//
// PJ 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 General Public License for more details.
//
// A copy of the GNU General Public License is provided in the file gpl.txt. You
// may also obtain a copy of the GNU General Public License on the World Wide
// Web at http://www.gnu.org/licenses/gpl.html.
//
//******************************************************************************
package edu.rit.numeric;
import edu.rit.util.Sorting;
/**
* Class Interpolation provides an object for interpolating in an {@linkplain
* XYSeries} of real values (type double). Linear interpolation is
* used. The X-Y series must have at least two elements; the X values must be
* distinct; but the X values need not be in any particular order. When doing
* interpolations, the (X,Y) pairs are arranged in ascending order of X values.
*
* Class Interpolation implements interface {@linkplain Function}. An instance
* of class Interpolation can be used as a function object.
*
* @author Alan Kaminsky
* @version 18-Aug-2011
*/
public class Interpolation
implements Function
{
// Hidden data members.
// X and Y values in which to interpolate. X values in ascending order.
private double[] xData;
private double[] yData;
// Number of data values, minus 2.
private int NM2;
// Index of the lower (x,y) pair of the interval in which the last
// interpolation occurred.
private int myIndex;
// Last interpolation interval was (x1,y1) .. (x2,y2).
private double x1;
private double y1;
private double x2;
private double y2;
// Exported constructors.
/**
* Construct a new interpolation object that will interpolate between values
* in the given X-Y series. The X-Y series must have at least two elements;
* the X values must be distinct; but the X values need not be in any
* particular order.
*
* Note: A copy of the given series' elements is made. Changing
* theSeries will not affect this interpolation object.
*
* @param theSeries X-Y series.
*
* @exception NullPointerException
* (unchecked exception) Thrown if theSeries is null.
* @exception IllegalArgumentException
* (unchecked exception) Thrown if theSeries has fewer than two
* elements. Thrown if the X values in theSeries are not
* distinct.
*/
public Interpolation
(XYSeries theSeries)
{
int N = theSeries.length();
if (N < 2)
{
throw new IllegalArgumentException
("Interpolation(): theSeries length < 2");
}
xData = new double [N];
yData = new double [N];
for (int i = 0; i < N; ++ i)
{
xData[i] = theSeries.x(i);
yData[i] = theSeries.y(i);
}
Sorting.sort (xData, new Sorting.Double()
{
public void swap (double[] x, int a, int b)
{
double tmp;
tmp = xData[a];
xData[a] = xData[b];
xData[b] = tmp;
tmp = yData[a];
yData[a] = yData[b];
yData[b] = tmp;
}
});
NM2 = N - 2;
for (int i = 0; i <= NM2; ++ i)
{
if (xData[i] == xData[i+1])
{
throw new IllegalArgumentException
("Interpolation(): Duplicate X value: "+xData[i]);
}
}
myIndex = 0;
x1 = xData[0];
y1 = yData[0];
x2 = xData[1];
y2 = yData[1];
}
// Exported operations.
/**
* Using linear interpolation, compute the Y value for the given X value.
* If x is less than the smallest X value in the underlying X-Y
* series, the Y value is computed by extrapolating the first interval. If
* x is greater than the largest X value in the underlying X-Y
* series, the Y value is computed by extrapolating the last interval.
*
* @param x X value.
*
* @return Interpolated or extrapolated Y value.
*/
public double f
(double x)
{
// Scan forward if necessary to find the correct interval for x.
while (myIndex < NM2 && x >= x2)
{
++ myIndex;
x1 = x2;
y1 = y2;
x2 = xData[myIndex + 1];
y2 = yData[myIndex + 1];
}
// Scan backward if necessary to find the correct interval for x.
while (myIndex > 0 && x < x1)
{
-- myIndex;
x2 = x1;
y2 = y1;
x1 = xData[myIndex];
y1 = yData[myIndex];
}
// Interpolate on x.
double dx = (x - x1)/(x2 - x1);
return (1.0 - dx)*y1 + dx*y2;
}
}
Ads help maintain this website.