Cleanup.
* Formatting (braces, indent, conditionals, array declaration, ...). * Reduce variable's scope. * Temporary variable to avoid multiple accesses to the same array element. * Use "final" keyword.
This commit is contained in:
parent
ed565027c7
commit
e3700ef350
|
@ -37,30 +37,18 @@ import org.apache.commons.math3.util.Precision;
|
|||
* This implementation is based on the Akima implementation in the CubicSpline
|
||||
* class in the Math.NET Numerics library. The method referenced is
|
||||
* CubicSpline.InterpolateAkimaSorted
|
||||
* <p>
|
||||
* The {@link #interpolate(double[], double[])} method returns a
|
||||
* {@link PolynomialSplineFunction} consisting of n cubic polynomials, defined
|
||||
* over the subintervals determined by the x values, x[0] < x[i] ... < x[n]. The
|
||||
* Akima algorithm requires that n >= 5.
|
||||
* </p>
|
||||
* <p>
|
||||
* The {@link #interpolate(double[], double[]) interpolate} method returns a
|
||||
* {@link PolynomialSplineFunction} consisting of n cubic polynomials, defined
|
||||
* over the subintervals determined by the x values, {@code x[0] < x[i] ... < x[n]}.
|
||||
* The Akima algorithm requires that {@code n >= 5}.
|
||||
* </p>
|
||||
*/
|
||||
|
||||
public class AkimaSplineInterpolator
|
||||
implements UnivariateInterpolator {
|
||||
|
||||
|
||||
/**
|
||||
* The minimum number of points that are needed to compute the function
|
||||
*/
|
||||
public static final int MINIMUM_NUMBER_POINTS = 5;
|
||||
|
||||
/**
|
||||
* Default constructor. Builds an AkimaSplineInterpolator object
|
||||
*/
|
||||
public AkimaSplineInterpolator() {
|
||||
|
||||
}
|
||||
/** The minimum number of points that are needed to compute the function. */
|
||||
private static final int MINIMUM_NUMBER_POINTS = 5;
|
||||
|
||||
/**
|
||||
* Computes an interpolating function for the data set.
|
||||
|
@ -68,17 +56,20 @@ public class AkimaSplineInterpolator
|
|||
* @param xvals the arguments for the interpolation points
|
||||
* @param yvals the values for the interpolation points
|
||||
* @return a function which interpolates the data set
|
||||
* @throws DimensionMismatchException if {@code x} and {@code y} have
|
||||
* @throws DimensionMismatchException if {@code xvals} and {@code yvals} have
|
||||
* different sizes.
|
||||
* @throws NonMonotonicSequenceException if {@code x} is not sorted in
|
||||
* @throws NonMonotonicSequenceException if {@code xvals} is not sorted in
|
||||
* strict increasing order.
|
||||
* @throws NumberIsTooSmallException if the size of {@code x} is smaller
|
||||
* @throws NumberIsTooSmallException if the size of {@code xvals} is smaller
|
||||
* than 5.
|
||||
*/
|
||||
public PolynomialSplineFunction interpolate(double[] xvals, double[] yvals)
|
||||
throws DimensionMismatchException, NumberIsTooSmallException,
|
||||
NonMonotonicSequenceException {
|
||||
if (xvals == null || yvals == null) {
|
||||
public PolynomialSplineFunction interpolate(double[] xvals,
|
||||
double[] yvals)
|
||||
throws DimensionMismatchException,
|
||||
NumberIsTooSmallException,
|
||||
NonMonotonicSequenceException {
|
||||
if (xvals == null ||
|
||||
yvals == null) {
|
||||
throw new NullArgumentException();
|
||||
}
|
||||
|
||||
|
@ -87,8 +78,7 @@ public class AkimaSplineInterpolator
|
|||
}
|
||||
|
||||
if (xvals.length < MINIMUM_NUMBER_POINTS) {
|
||||
throw new NumberIsTooSmallException(
|
||||
LocalizedFormats.NUMBER_OF_POINTS,
|
||||
throw new NumberIsTooSmallException(LocalizedFormats.NUMBER_OF_POINTS,
|
||||
xvals.length,
|
||||
MINIMUM_NUMBER_POINTS, true);
|
||||
}
|
||||
|
@ -97,47 +87,44 @@ public class AkimaSplineInterpolator
|
|||
|
||||
final int numberOfDiffAndWeightElements = xvals.length - 1;
|
||||
|
||||
double differences[] = new double[numberOfDiffAndWeightElements];
|
||||
double weights[] = new double[numberOfDiffAndWeightElements];
|
||||
final double[] differences = new double[numberOfDiffAndWeightElements];
|
||||
final double[] weights = new double[numberOfDiffAndWeightElements];
|
||||
|
||||
for (int i = 0; i < differences.length; i++) {
|
||||
differences[i] = (yvals[i + 1] - yvals[i]) /
|
||||
(xvals[i + 1] - xvals[i]);
|
||||
differences[i] = (yvals[i + 1] - yvals[i]) / (xvals[i + 1] - xvals[i]);
|
||||
}
|
||||
|
||||
for (int i = 1; i < weights.length; i++) {
|
||||
weights[i] = FastMath.abs(differences[i] - differences[i - 1]);
|
||||
}
|
||||
|
||||
/* Prepare Hermite interpolation scheme */
|
||||
|
||||
double firstDerivatives[] = new double[xvals.length];
|
||||
// Prepare Hermite interpolation scheme.
|
||||
final double[] firstDerivatives = new double[xvals.length];
|
||||
|
||||
for (int i = 2; i < firstDerivatives.length - 2; i++) {
|
||||
if (Precision.equals(weights[i - 1], 0.0) &&
|
||||
Precision.equals(weights[i + 1], 0.0)) {
|
||||
firstDerivatives[i] = (((xvals[i + 1] - xvals[i]) * differences[i - 1]) + ((xvals[i] - xvals[i - 1]) * differences[i])) /
|
||||
(xvals[i + 1] - xvals[i - 1]);
|
||||
final double wP = weights[i + 1];
|
||||
final double wM = weights[i - 1];
|
||||
if (Precision.equals(wP, 0.0) &&
|
||||
Precision.equals(wM, 0.0)) {
|
||||
final double xv = xvals[i];
|
||||
final double xvP = xvals[i + 1];
|
||||
final double xvM = xvals[i - 1];
|
||||
firstDerivatives[i] = (((xvP - xv) * differences[i - 1]) + ((xv - xvM) * differences[i])) / (xvP - xvM);
|
||||
} else {
|
||||
firstDerivatives[i] = ((weights[i + 1] * differences[i - 1]) + (weights[i - 1] * differences[i])) /
|
||||
(weights[i + 1] + weights[i - 1]);
|
||||
firstDerivatives[i] = ((wP * differences[i - 1]) + (wM * differences[i])) / (wP + wM);
|
||||
}
|
||||
}
|
||||
|
||||
firstDerivatives[0] = this.differentiateThreePoint(xvals, yvals, 0, 0,
|
||||
1, 2);
|
||||
firstDerivatives[1] = this.differentiateThreePoint(xvals, yvals, 1, 0,
|
||||
1, 2);
|
||||
firstDerivatives[xvals.length - 2] = this
|
||||
.differentiateThreePoint(xvals, yvals, xvals.length - 2,
|
||||
xvals.length - 3, xvals.length - 2,
|
||||
xvals.length - 1);
|
||||
firstDerivatives[xvals.length - 1] = this
|
||||
.differentiateThreePoint(xvals, yvals, xvals.length - 1,
|
||||
xvals.length - 3, xvals.length - 2,
|
||||
xvals.length - 1);
|
||||
firstDerivatives[0] = differentiateThreePoint(xvals, yvals, 0, 0, 1, 2);
|
||||
firstDerivatives[1] = differentiateThreePoint(xvals, yvals, 1, 0, 1, 2);
|
||||
firstDerivatives[xvals.length - 2] = differentiateThreePoint(xvals, yvals, xvals.length - 2,
|
||||
xvals.length - 3, xvals.length - 2,
|
||||
xvals.length - 1);
|
||||
firstDerivatives[xvals.length - 1] = differentiateThreePoint(xvals, yvals, xvals.length - 1,
|
||||
xvals.length - 3, xvals.length - 2,
|
||||
xvals.length - 1);
|
||||
|
||||
return this.interpolateHermiteSorted(xvals, yvals, firstDerivatives);
|
||||
return interpolateHermiteSorted(xvals, yvals, firstDerivatives);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -158,16 +145,17 @@ public class AkimaSplineInterpolator
|
|||
int indexOfFirstSample,
|
||||
int indexOfSecondsample,
|
||||
int indexOfThirdSample) {
|
||||
double x0 = yvals[indexOfFirstSample];
|
||||
double x1 = yvals[indexOfSecondsample];
|
||||
double x2 = yvals[indexOfThirdSample];
|
||||
final double x0 = yvals[indexOfFirstSample];
|
||||
final double x1 = yvals[indexOfSecondsample];
|
||||
final double x2 = yvals[indexOfThirdSample];
|
||||
|
||||
double t = xvals[indexOfDifferentiation] - xvals[indexOfFirstSample];
|
||||
double t1 = xvals[indexOfSecondsample] - xvals[indexOfFirstSample];
|
||||
double t2 = xvals[indexOfThirdSample] - xvals[indexOfFirstSample];
|
||||
final double t = xvals[indexOfDifferentiation] - xvals[indexOfFirstSample];
|
||||
final double t1 = xvals[indexOfSecondsample] - xvals[indexOfFirstSample];
|
||||
final double t2 = xvals[indexOfThirdSample] - xvals[indexOfFirstSample];
|
||||
|
||||
final double a = (x2 - x0 - (t2 / t1 * (x1 - x0))) / (t2 * t2 - t1 * t2);
|
||||
final double b = (x1 - x0 - a * t1 * t1) / t1;
|
||||
|
||||
double a = (x2 - x0 - (t2 / t1 * (x1 - x0))) / (t2 * t2 - t1 * t2);
|
||||
double b = (x1 - x0 - a * t1 * t1) / t1;
|
||||
return (2 * a * t) + b;
|
||||
}
|
||||
|
||||
|
@ -195,27 +183,29 @@ public class AkimaSplineInterpolator
|
|||
|
||||
final int minimumLength = 2;
|
||||
if (xvals.length < minimumLength) {
|
||||
throw new NumberIsTooSmallException(
|
||||
LocalizedFormats.NUMBER_OF_POINTS,
|
||||
throw new NumberIsTooSmallException(LocalizedFormats.NUMBER_OF_POINTS,
|
||||
xvals.length, minimumLength,
|
||||
true);
|
||||
}
|
||||
|
||||
int size = xvals.length - 1;
|
||||
final PolynomialFunction polynomials[] = new PolynomialFunction[size];
|
||||
final double coefficients[] = new double[4];
|
||||
final int size = xvals.length - 1;
|
||||
final PolynomialFunction[] polynomials = new PolynomialFunction[size];
|
||||
final double[] coefficients = new double[4];
|
||||
|
||||
for (int i = 0; i < polynomials.length; i++) {
|
||||
double w = xvals[i + 1] - xvals[i];
|
||||
double w2 = w * w;
|
||||
coefficients[0] = yvals[i];
|
||||
final double w = xvals[i + 1] - xvals[i];
|
||||
final double w2 = w * w;
|
||||
|
||||
final double yv = yvals[i];
|
||||
final double yvP = yvals[i + 1];
|
||||
|
||||
final double fd = firstDerivatives[i];
|
||||
final double fdP = firstDerivatives[i + 1];
|
||||
|
||||
coefficients[0] = yv;
|
||||
coefficients[1] = firstDerivatives[i];
|
||||
coefficients[2] = (3 * (yvals[i + 1] - yvals[i]) / w - 2 *
|
||||
firstDerivatives[i] - firstDerivatives[i + 1]) /
|
||||
w;
|
||||
coefficients[3] = (2 * (yvals[i] - yvals[i + 1]) / w +
|
||||
firstDerivatives[i] + firstDerivatives[i + 1]) /
|
||||
w2;
|
||||
coefficients[2] = (3 * (yvP - yv) / w - 2 * fd - fdP) / w;
|
||||
coefficients[3] = (2 * (yv - yvP) / w + fd + fdP) / w2;
|
||||
polynomials[i] = new PolynomialFunction(coefficients);
|
||||
}
|
||||
|
||||
|
|
|
@ -28,21 +28,24 @@ import org.apache.commons.math3.exception.NonMonotonicSequenceException;
|
|||
import org.apache.commons.math3.util.MathArrays;
|
||||
|
||||
/**
|
||||
* Function that implements the <a
|
||||
* href="http://www.paulinternet.nl/?page=bicubic"> bicubic spline
|
||||
* interpolation</a>.
|
||||
* Function that implements the
|
||||
* <a href="http://www.paulinternet.nl/?page=bicubic">bicubic spline</a>
|
||||
* interpolation.
|
||||
* This implementation currently uses {@link AkimaSplineInterpolator} as the
|
||||
* underlying one-dimensional interpolator, which requires 5 sample points;
|
||||
* insufficient data will raise an exception when the
|
||||
* {@link #value(double,double) value} method is called.
|
||||
*
|
||||
* @since 2.1
|
||||
* @since 3.4
|
||||
*/
|
||||
public class PiecewiseBicubicSplineInterpolatingFunction
|
||||
implements BivariateFunction {
|
||||
|
||||
/** The minimum number of points that are needed to compute the function. */
|
||||
private static final int MIN_NUM_POINTS = 5;
|
||||
/** Samples x-coordinates */
|
||||
private final double[] xval;
|
||||
|
||||
/** Samples y-coordinates */
|
||||
private final double[] yval;
|
||||
|
||||
/** Set of cubic splines patching the whole data grid */
|
||||
private final double[][] fval;
|
||||
|
||||
|
@ -58,27 +61,34 @@ public class PiecewiseBicubicSplineInterpolatingFunction
|
|||
* @throws DimensionMismatchException if the length of x and y don't match the row, column
|
||||
* height of f
|
||||
*/
|
||||
|
||||
public PiecewiseBicubicSplineInterpolatingFunction(double[] x, double[] y,
|
||||
double[][] f)
|
||||
throws DimensionMismatchException, NullArgumentException,
|
||||
NoDataException, NonMonotonicSequenceException {
|
||||
|
||||
final int minimumLength = AkimaSplineInterpolator.MINIMUM_NUMBER_POINTS;
|
||||
|
||||
if (x == null || y == null || f == null || f[0] == null) {
|
||||
public PiecewiseBicubicSplineInterpolatingFunction(double[] x,
|
||||
double[] y,
|
||||
double[][] f)
|
||||
throws DimensionMismatchException,
|
||||
NullArgumentException,
|
||||
NoDataException,
|
||||
NonMonotonicSequenceException {
|
||||
if (x == null ||
|
||||
y == null ||
|
||||
f == null ||
|
||||
f[0] == null) {
|
||||
throw new NullArgumentException();
|
||||
}
|
||||
|
||||
final int xLen = x.length;
|
||||
final int yLen = y.length;
|
||||
|
||||
if (xLen == 0 || yLen == 0 || f.length == 0 || f[0].length == 0) {
|
||||
if (xLen == 0 ||
|
||||
yLen == 0 ||
|
||||
f.length == 0 ||
|
||||
f[0].length == 0) {
|
||||
throw new NoDataException();
|
||||
}
|
||||
|
||||
if (xLen < minimumLength || yLen < minimumLength ||
|
||||
f.length < minimumLength || f[0].length < minimumLength) {
|
||||
if (xLen < MIN_NUM_POINTS ||
|
||||
yLen < MIN_NUM_POINTS ||
|
||||
f.length < MIN_NUM_POINTS ||
|
||||
f[0].length < MIN_NUM_POINTS) {
|
||||
throw new InsufficientDataException();
|
||||
}
|
||||
|
||||
|
@ -101,35 +111,34 @@ public class PiecewiseBicubicSplineInterpolatingFunction
|
|||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public double value(double x, double y)
|
||||
public double value(double x,
|
||||
double y)
|
||||
throws OutOfRangeException {
|
||||
int index;
|
||||
PolynomialSplineFunction spline;
|
||||
AkimaSplineInterpolator interpolator = new AkimaSplineInterpolator();
|
||||
final AkimaSplineInterpolator interpolator = new AkimaSplineInterpolator();
|
||||
final int offset = 2;
|
||||
final int count = offset + 3;
|
||||
final int i = searchIndex(x, xval, offset, count);
|
||||
final int j = searchIndex(y, yval, offset, count);
|
||||
|
||||
double xArray[] = new double[count];
|
||||
double yArray[] = new double[count];
|
||||
double zArray[] = new double[count];
|
||||
double interpArray[] = new double[count];
|
||||
final double xArray[] = new double[count];
|
||||
final double yArray[] = new double[count];
|
||||
final double zArray[] = new double[count];
|
||||
final double interpArray[] = new double[count];
|
||||
|
||||
for (index = 0; index < count; index++) {
|
||||
for (int index = 0; index < count; index++) {
|
||||
xArray[index] = xval[i + index];
|
||||
yArray[index] = yval[j + index];
|
||||
}
|
||||
|
||||
for (int zIndex = 0; zIndex < count; zIndex++) {
|
||||
for (index = 0; index < count; index++) {
|
||||
for (int index = 0; index < count; index++) {
|
||||
zArray[index] = fval[i + index][j + zIndex];
|
||||
}
|
||||
spline = interpolator.interpolate(xArray, zArray);
|
||||
final PolynomialSplineFunction spline = interpolator.interpolate(xArray, zArray);
|
||||
interpArray[zIndex] = spline.value(x);
|
||||
}
|
||||
|
||||
spline = interpolator.interpolate(yArray, interpArray);
|
||||
final PolynomialSplineFunction spline = interpolator.interpolate(yArray, interpArray);
|
||||
|
||||
double returnValue = spline.value(y);
|
||||
|
||||
|
@ -144,8 +153,11 @@ public class PiecewiseBicubicSplineInterpolatingFunction
|
|||
* @return {@code true} if (x, y) is a valid point.
|
||||
* @since 3.3
|
||||
*/
|
||||
public boolean isValidPoint(double x, double y) {
|
||||
if (x < xval[0] || x > xval[xval.length - 1] || y < yval[0] ||
|
||||
public boolean isValidPoint(double x,
|
||||
double y) {
|
||||
if (x < xval[0] ||
|
||||
x > xval[xval.length - 1] ||
|
||||
y < yval[0] ||
|
||||
y > yval[yval.length - 1]) {
|
||||
return false;
|
||||
} else {
|
||||
|
@ -164,7 +176,10 @@ public class PiecewiseBicubicSplineInterpolatingFunction
|
|||
* @throws OutOfRangeException if {@code c} is out of the range defined by
|
||||
* the boundary values of {@code val}.
|
||||
*/
|
||||
private int searchIndex(double c, double[] val, int offset, int count) {
|
||||
private int searchIndex(double c,
|
||||
double[] val,
|
||||
int offset,
|
||||
int count) {
|
||||
int r = Arrays.binarySearch(val, c);
|
||||
|
||||
if (r == -1 || r == -val.length - 1) {
|
||||
|
|
|
@ -28,31 +28,28 @@ import org.apache.commons.math3.util.MathArrays;
|
|||
* @since 2.2
|
||||
*/
|
||||
public class PiecewiseBicubicSplineInterpolator
|
||||
implements BivariateGridInterpolator
|
||||
{
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
*/
|
||||
public PiecewiseBicubicSplineInterpolator()
|
||||
{
|
||||
|
||||
}
|
||||
implements BivariateGridInterpolator {
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public PiecewiseBicubicSplineInterpolatingFunction interpolate( final double[] xval, final double[] yval,
|
||||
final double[][] fval)
|
||||
throws DimensionMismatchException, NullArgumentException, NoDataException, NonMonotonicSequenceException
|
||||
{
|
||||
if ( xval == null || yval == null || fval == null || fval[0] == null )
|
||||
{
|
||||
public PiecewiseBicubicSplineInterpolatingFunction interpolate( final double[] xval,
|
||||
final double[] yval,
|
||||
final double[][] fval)
|
||||
throws DimensionMismatchException,
|
||||
NullArgumentException,
|
||||
NoDataException,
|
||||
NonMonotonicSequenceException {
|
||||
if ( xval == null ||
|
||||
yval == null ||
|
||||
fval == null ||
|
||||
fval[0] == null ) {
|
||||
throw new NullArgumentException();
|
||||
}
|
||||
|
||||
if ( xval.length == 0 || yval.length == 0 || fval.length == 0 )
|
||||
{
|
||||
if ( xval.length == 0 ||
|
||||
yval.length == 0 ||
|
||||
fval.length == 0 ) {
|
||||
throw new NoDataException();
|
||||
}
|
||||
|
||||
|
|
|
@ -35,14 +35,12 @@ import org.junit.Test;
|
|||
/**
|
||||
* Test case for the piecewise bicubic function.
|
||||
*/
|
||||
public final class PiecewiseBicubicSplineInterpolatingFunctionTest
|
||||
{
|
||||
public final class PiecewiseBicubicSplineInterpolatingFunctionTest {
|
||||
/**
|
||||
* Test preconditions.
|
||||
*/
|
||||
@Test
|
||||
public void testPreconditions()
|
||||
{
|
||||
public void testPreconditions() {
|
||||
double[] xval = new double[] { 3, 4, 5, 6.5, 7.5 };
|
||||
double[] yval = new double[] { -4, -3, -1, 2.5, 3.5 };
|
||||
double[][] zval = new double[xval.length][yval.length];
|
||||
|
@ -50,112 +48,82 @@ public final class PiecewiseBicubicSplineInterpolatingFunctionTest
|
|||
@SuppressWarnings("unused")
|
||||
PiecewiseBicubicSplineInterpolatingFunction bcf = new PiecewiseBicubicSplineInterpolatingFunction( xval, yval, zval );
|
||||
|
||||
try
|
||||
{
|
||||
try {
|
||||
bcf = new PiecewiseBicubicSplineInterpolatingFunction( null, yval, zval );
|
||||
Assert.fail( "Failed to detect x null pointer" );
|
||||
}
|
||||
catch ( NullArgumentException iae )
|
||||
{
|
||||
} catch ( NullArgumentException iae ) {
|
||||
// Expected.
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
try {
|
||||
bcf = new PiecewiseBicubicSplineInterpolatingFunction( xval, null, zval );
|
||||
Assert.fail( "Failed to detect y null pointer" );
|
||||
}
|
||||
catch ( NullArgumentException iae )
|
||||
{
|
||||
} catch ( NullArgumentException iae ) {
|
||||
// Expected.
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
try {
|
||||
bcf = new PiecewiseBicubicSplineInterpolatingFunction( xval, yval, null );
|
||||
Assert.fail( "Failed to detect z null pointer" );
|
||||
}
|
||||
catch ( NullArgumentException iae )
|
||||
{
|
||||
} catch ( NullArgumentException iae ) {
|
||||
// Expected.
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
try {
|
||||
double xval1[] = { 0.0, 1.0, 2.0, 3.0 };
|
||||
bcf = new PiecewiseBicubicSplineInterpolatingFunction( xval1, yval, zval );
|
||||
Assert.fail( "Failed to detect insufficient x data" );
|
||||
}
|
||||
catch ( InsufficientDataException iae )
|
||||
{
|
||||
} catch ( InsufficientDataException iae ) {
|
||||
// Expected.
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
try {
|
||||
double yval1[] = { 0.0, 1.0, 2.0, 3.0 };
|
||||
bcf = new PiecewiseBicubicSplineInterpolatingFunction( xval, yval1, zval );
|
||||
Assert.fail( "Failed to detect insufficient y data" );
|
||||
}
|
||||
catch ( InsufficientDataException iae )
|
||||
{
|
||||
} catch ( InsufficientDataException iae ) {
|
||||
// Expected.
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
try {
|
||||
double zval1[][] = new double[4][4];
|
||||
bcf = new PiecewiseBicubicSplineInterpolatingFunction( xval, yval, zval1 );
|
||||
Assert.fail( "Failed to detect insufficient z data" );
|
||||
}
|
||||
catch ( InsufficientDataException iae )
|
||||
{
|
||||
} catch ( InsufficientDataException iae ) {
|
||||
// Expected.
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
try {
|
||||
double xval1[] = { 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0 };
|
||||
bcf = new PiecewiseBicubicSplineInterpolatingFunction( xval1, yval, zval );
|
||||
Assert.fail( "Failed to detect data set array with different sizes." );
|
||||
}
|
||||
catch ( DimensionMismatchException iae )
|
||||
{
|
||||
} catch ( DimensionMismatchException iae ) {
|
||||
// Expected.
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
try {
|
||||
double yval1[] = { 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0 };
|
||||
bcf = new PiecewiseBicubicSplineInterpolatingFunction( xval, yval1, zval );
|
||||
Assert.fail( "Failed to detect data set array with different sizes." );
|
||||
}
|
||||
catch ( DimensionMismatchException iae )
|
||||
{
|
||||
} catch ( DimensionMismatchException iae ) {
|
||||
// Expected.
|
||||
}
|
||||
}
|
||||
|
||||
// X values not sorted.
|
||||
try
|
||||
{
|
||||
try {
|
||||
double xval1[] = { 0.0, 1.0, 0.5, 7.0, 3.5 };
|
||||
bcf = new PiecewiseBicubicSplineInterpolatingFunction( xval1, yval, zval );
|
||||
Assert.fail( "Failed to detect unsorted x arguments." );
|
||||
}
|
||||
catch ( NonMonotonicSequenceException iae )
|
||||
{
|
||||
} catch ( NonMonotonicSequenceException iae ) {
|
||||
// Expected.
|
||||
}
|
||||
|
||||
// Y values not sorted.
|
||||
try
|
||||
{
|
||||
try {
|
||||
double yval1[] = { 0.0, 1.0, 1.5, 0.0, 3.0 };
|
||||
bcf = new PiecewiseBicubicSplineInterpolatingFunction( xval, yval1, zval );
|
||||
Assert.fail( "Failed to detect unsorted y arguments." );
|
||||
}
|
||||
catch ( NonMonotonicSequenceException iae )
|
||||
{
|
||||
} catch ( NonMonotonicSequenceException iae ) {
|
||||
// Expected.
|
||||
}
|
||||
}
|
||||
|
@ -166,8 +134,7 @@ public final class PiecewiseBicubicSplineInterpolatingFunctionTest
|
|||
* z = 2 x - 3 y + 5
|
||||
*/
|
||||
@Test
|
||||
public void testInterpolatePlane()
|
||||
{
|
||||
public void testInterpolatePlane() {
|
||||
final int numberOfElements = 10;
|
||||
final double minimumX = -10;
|
||||
final double maximumX = 10;
|
||||
|
@ -178,10 +145,8 @@ public final class PiecewiseBicubicSplineInterpolatingFunctionTest
|
|||
final double maxTolerance = 6e-14;
|
||||
|
||||
// Function values
|
||||
BivariateFunction f = new BivariateFunction()
|
||||
{
|
||||
public double value( double x, double y )
|
||||
{
|
||||
BivariateFunction f = new BivariateFunction() {
|
||||
public double value( double x, double y ) {
|
||||
return 2 * x - 3 * y + 5;
|
||||
}
|
||||
};
|
||||
|
@ -196,8 +161,7 @@ public final class PiecewiseBicubicSplineInterpolatingFunctionTest
|
|||
* z = 2 x<sup>2</sup> - 3 y<sup>2</sup> + 4 x y - 5
|
||||
*/
|
||||
@Test
|
||||
public void testInterpolationParabaloid()
|
||||
{
|
||||
public void testInterpolationParabaloid() {
|
||||
final int numberOfElements = 10;
|
||||
final double minimumX = -10;
|
||||
final double maximumX = 10;
|
||||
|
@ -208,22 +172,19 @@ public final class PiecewiseBicubicSplineInterpolatingFunctionTest
|
|||
final double maxTolerance = 6e-14;
|
||||
|
||||
// Function values
|
||||
BivariateFunction f = new BivariateFunction()
|
||||
{
|
||||
public double value( double x, double y )
|
||||
{
|
||||
BivariateFunction f = new BivariateFunction() {
|
||||
public double value( double x, double y ) {
|
||||
return 2 * x * x - 3 * y * y + 4 * x * y - 5;
|
||||
}
|
||||
};
|
||||
|
||||
testInterpolation( minimumX, maximumX, minimumY, maximumY, numberOfElements, numberOfSamples, f,
|
||||
interpolationTolerance, maxTolerance );
|
||||
}
|
||||
}
|
||||
|
||||
private void testInterpolation( double minimumX, double maximumX, double minimumY, double maximumY,
|
||||
int numberOfElements, int numberOfSamples, BivariateFunction f, double tolerance,
|
||||
double maxTolerance )
|
||||
{
|
||||
double maxTolerance ) {
|
||||
double expected;
|
||||
double actual;
|
||||
double currentX;
|
||||
|
@ -234,11 +195,9 @@ public final class PiecewiseBicubicSplineInterpolatingFunctionTest
|
|||
double yValues[] = new double[numberOfElements];
|
||||
double zValues[][] = new double[numberOfElements][numberOfElements];
|
||||
|
||||
for ( int i = 0; i < numberOfElements; i++ )
|
||||
{
|
||||
for ( int i = 0; i < numberOfElements; i++ ) {
|
||||
xValues[i] = minimumX + deltaX * (double) i;
|
||||
for ( int j = 0; j < numberOfElements; j++ )
|
||||
{
|
||||
for ( int j = 0; j < numberOfElements; j++ ) {
|
||||
yValues[j] = minimumY + deltaY * (double) j;
|
||||
zValues[i][j] = f.value( xValues[i], yValues[j] );
|
||||
}
|
||||
|
@ -246,11 +205,9 @@ public final class PiecewiseBicubicSplineInterpolatingFunctionTest
|
|||
|
||||
BivariateFunction interpolation = new PiecewiseBicubicSplineInterpolatingFunction( xValues, yValues, zValues );
|
||||
|
||||
for ( int i = 0; i < numberOfElements; i++ )
|
||||
{
|
||||
for ( int i = 0; i < numberOfElements; i++ ) {
|
||||
currentX = xValues[i];
|
||||
for ( int j = 0; j < numberOfElements; j++ )
|
||||
{
|
||||
for ( int j = 0; j < numberOfElements; j++ ) {
|
||||
currentY = yValues[j];
|
||||
expected = f.value( currentX, currentY );
|
||||
actual = interpolation.value( currentX, currentY );
|
||||
|
@ -259,21 +216,18 @@ public final class PiecewiseBicubicSplineInterpolatingFunctionTest
|
|||
}
|
||||
|
||||
final RandomGenerator rng = new Well19937c( 1234567L ); // "tol" depends on the seed.
|
||||
final UniformRealDistribution distX =
|
||||
new UniformRealDistribution( rng, xValues[0], xValues[xValues.length - 1] );
|
||||
final UniformRealDistribution distY =
|
||||
new UniformRealDistribution( rng, yValues[0], yValues[yValues.length - 1] );
|
||||
final UniformRealDistribution distX = new UniformRealDistribution( rng, xValues[0], xValues[xValues.length - 1] );
|
||||
final UniformRealDistribution distY = new UniformRealDistribution( rng, yValues[0], yValues[yValues.length - 1] );
|
||||
|
||||
double sumError = 0;
|
||||
for ( int i = 0; i < numberOfSamples; i++ )
|
||||
{
|
||||
for ( int i = 0; i < numberOfSamples; i++ ) {
|
||||
currentX = distX.sample();
|
||||
currentY = distY.sample();
|
||||
expected = f.value( currentX, currentY );
|
||||
actual = interpolation.value( currentX, currentY );
|
||||
sumError += FastMath.abs( actual - expected );
|
||||
assertEquals( expected, actual, maxTolerance );
|
||||
}
|
||||
}
|
||||
|
||||
assertEquals( 0.0, ( sumError / (double) numberOfSamples ), tolerance );
|
||||
}
|
||||
|
|
|
@ -31,14 +31,12 @@ import org.junit.Test;
|
|||
/**
|
||||
* Test case for the piecewise bicubic interpolator.
|
||||
*/
|
||||
public final class PiecewiseBicubicSplineInterpolatorTest
|
||||
{
|
||||
public final class PiecewiseBicubicSplineInterpolatorTest {
|
||||
/**
|
||||
* Test preconditions.
|
||||
*/
|
||||
@Test
|
||||
public void testPreconditions()
|
||||
{
|
||||
public void testPreconditions() {
|
||||
double[] xval = new double[] { 3, 4, 5, 6.5, 7.5 };
|
||||
double[] yval = new double[] { -4, -3, -1, 2.5, 3.5 };
|
||||
double[][] zval = new double[xval.length][yval.length];
|
||||
|
@ -46,115 +44,84 @@ public final class PiecewiseBicubicSplineInterpolatorTest
|
|||
@SuppressWarnings( "unused" )
|
||||
BivariateGridInterpolator interpolator = new PiecewiseBicubicSplineInterpolator();
|
||||
|
||||
try
|
||||
{
|
||||
try {
|
||||
interpolator.interpolate( null, yval, zval );
|
||||
Assert.fail( "Failed to detect x null pointer" );
|
||||
}
|
||||
catch ( NullArgumentException iae )
|
||||
{
|
||||
} catch ( NullArgumentException iae ) {
|
||||
// Expected.
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
try {
|
||||
interpolator.interpolate( xval, null, zval );
|
||||
Assert.fail( "Failed to detect y null pointer" );
|
||||
}
|
||||
catch ( NullArgumentException iae )
|
||||
{
|
||||
} catch ( NullArgumentException iae ) {
|
||||
// Expected.
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
try {
|
||||
interpolator.interpolate( xval, yval, null );
|
||||
Assert.fail( "Failed to detect z null pointer" );
|
||||
}
|
||||
catch ( NullArgumentException iae )
|
||||
{
|
||||
} catch ( NullArgumentException iae ) {
|
||||
// Expected.
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
try {
|
||||
double xval1[] = { 0.0, 1.0, 2.0, 3.0 };
|
||||
interpolator.interpolate( xval1, yval, zval );
|
||||
Assert.fail( "Failed to detect insufficient x data" );
|
||||
}
|
||||
catch ( InsufficientDataException iae )
|
||||
{
|
||||
} catch ( InsufficientDataException iae ) {
|
||||
// Expected.
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
try {
|
||||
double yval1[] = { 0.0, 1.0, 2.0, 3.0 };
|
||||
interpolator.interpolate( xval, yval1, zval );
|
||||
Assert.fail( "Failed to detect insufficient y data" );
|
||||
}
|
||||
catch ( InsufficientDataException iae )
|
||||
{
|
||||
} catch ( InsufficientDataException iae ) {
|
||||
// Expected.
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
try {
|
||||
double zval1[][] = new double[4][4];
|
||||
interpolator.interpolate( xval, yval, zval1 );
|
||||
Assert.fail( "Failed to detect insufficient z data" );
|
||||
}
|
||||
catch ( InsufficientDataException iae )
|
||||
{
|
||||
} catch ( InsufficientDataException iae ) {
|
||||
// Expected.
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
try {
|
||||
double xval1[] = { 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0 };
|
||||
interpolator.interpolate( xval1, yval, zval );
|
||||
Assert.fail( "Failed to detect data set array with different sizes." );
|
||||
}
|
||||
catch ( DimensionMismatchException iae )
|
||||
{
|
||||
} catch ( DimensionMismatchException iae ) {
|
||||
// Expected.
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
try {
|
||||
double yval1[] = { 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0 };
|
||||
interpolator.interpolate( xval, yval1, zval );
|
||||
Assert.fail( "Failed to detect data set array with different sizes." );
|
||||
}
|
||||
catch ( DimensionMismatchException iae )
|
||||
{
|
||||
} catch ( DimensionMismatchException iae ) {
|
||||
// Expected.
|
||||
}
|
||||
|
||||
// X values not sorted.
|
||||
try
|
||||
{
|
||||
try {
|
||||
double xval1[] = { 0.0, 1.0, 0.5, 7.0, 3.5 };
|
||||
interpolator.interpolate( xval1, yval, zval );
|
||||
Assert.fail( "Failed to detect unsorted x arguments." );
|
||||
}
|
||||
catch ( NonMonotonicSequenceException iae )
|
||||
{
|
||||
} catch ( NonMonotonicSequenceException iae ) {
|
||||
// Expected.
|
||||
}
|
||||
|
||||
// Y values not sorted.
|
||||
try
|
||||
{
|
||||
try {
|
||||
double yval1[] = { 0.0, 1.0, 1.5, 0.0, 3.0 };
|
||||
interpolator.interpolate( xval, yval1, zval );
|
||||
Assert.fail( "Failed to detect unsorted y arguments." );
|
||||
}
|
||||
catch ( NonMonotonicSequenceException iae )
|
||||
{
|
||||
} catch ( NonMonotonicSequenceException iae ) {
|
||||
// Expected.
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -163,32 +130,26 @@ public final class PiecewiseBicubicSplineInterpolatorTest
|
|||
* z = 2 x - 3 y + 5
|
||||
*/
|
||||
@Test
|
||||
public void testInterpolation1()
|
||||
{
|
||||
public void testInterpolation1() {
|
||||
final int sz = 21;
|
||||
double[] xval = new double[sz];
|
||||
double[] yval = new double[sz];
|
||||
// Coordinate values
|
||||
final double delta = 1d / (sz - 1);
|
||||
for ( int i = 0; i < sz; i++ )
|
||||
{
|
||||
for ( int i = 0; i < sz; i++ ){
|
||||
xval[i] = -1 + 15 * i * delta;
|
||||
yval[i] = -20 + 30 * i * delta;
|
||||
}
|
||||
|
||||
// Function values
|
||||
BivariateFunction f = new BivariateFunction()
|
||||
{
|
||||
public double value( double x, double y )
|
||||
{
|
||||
BivariateFunction f = new BivariateFunction() {
|
||||
public double value( double x, double y ) {
|
||||
return 2 * x - 3 * y + 5;
|
||||
}
|
||||
};
|
||||
double[][] zval = new double[xval.length][yval.length];
|
||||
for ( int i = 0; i < xval.length; i++ )
|
||||
{
|
||||
for ( int j = 0; j < yval.length; j++ )
|
||||
{
|
||||
for ( int i = 0; i < xval.length; i++ ) {
|
||||
for ( int j = 0; j < yval.length; j++ ) {
|
||||
zval[i][j] = f.value(xval[i], yval[j]);
|
||||
}
|
||||
}
|
||||
|
@ -203,11 +164,9 @@ public final class PiecewiseBicubicSplineInterpolatorTest
|
|||
|
||||
final int numSamples = 50;
|
||||
final double tol = 2e-14;
|
||||
for ( int i = 0; i < numSamples; i++ )
|
||||
{
|
||||
for ( int i = 0; i < numSamples; i++ ) {
|
||||
x = distX.sample();
|
||||
for ( int j = 0; j < numSamples; j++ )
|
||||
{
|
||||
for ( int j = 0; j < numSamples; j++ ) {
|
||||
y = distY.sample();
|
||||
// System.out.println(x + " " + y + " " + f.value(x, y) + " " + p.value(x, y));
|
||||
Assert.assertEquals(f.value(x, y), p.value(x, y), tol);
|
||||
|
@ -222,32 +181,26 @@ public final class PiecewiseBicubicSplineInterpolatorTest
|
|||
* z = 2 x<sup>2</sup> - 3 y<sup>2</sup> + 4 x y - 5
|
||||
*/
|
||||
@Test
|
||||
public void testInterpolation2()
|
||||
{
|
||||
public void testInterpolation2() {
|
||||
final int sz = 21;
|
||||
double[] xval = new double[sz];
|
||||
double[] yval = new double[sz];
|
||||
// Coordinate values
|
||||
final double delta = 1d / (sz - 1);
|
||||
for ( int i = 0; i < sz; i++ )
|
||||
{
|
||||
for ( int i = 0; i < sz; i++ ) {
|
||||
xval[i] = -1 + 15 * i * delta;
|
||||
yval[i] = -20 + 30 * i * delta;
|
||||
}
|
||||
|
||||
// Function values
|
||||
BivariateFunction f = new BivariateFunction()
|
||||
{
|
||||
public double value( double x, double y )
|
||||
{
|
||||
BivariateFunction f = new BivariateFunction() {
|
||||
public double value( double x, double y ) {
|
||||
return 2 * x * x - 3 * y * y + 4 * x * y - 5;
|
||||
}
|
||||
};
|
||||
double[][] zval = new double[xval.length][yval.length];
|
||||
for ( int i = 0; i < xval.length; i++ )
|
||||
{
|
||||
for ( int j = 0; j < yval.length; j++ )
|
||||
{
|
||||
for ( int i = 0; i < xval.length; i++ ) {
|
||||
for ( int j = 0; j < yval.length; j++ ) {
|
||||
zval[i][j] = f.value(xval[i], yval[j]);
|
||||
}
|
||||
}
|
||||
|
@ -262,11 +215,9 @@ public final class PiecewiseBicubicSplineInterpolatorTest
|
|||
|
||||
final int numSamples = 50;
|
||||
final double tol = 5e-13;
|
||||
for ( int i = 0; i < numSamples; i++ )
|
||||
{
|
||||
for ( int i = 0; i < numSamples; i++ ) {
|
||||
x = distX.sample();
|
||||
for ( int j = 0; j < numSamples; j++ )
|
||||
{
|
||||
for ( int j = 0; j < numSamples; j++ ) {
|
||||
y = distY.sample();
|
||||
// System.out.println(x + " " + y + " " + f.value(x, y) + " " + p.value(x, y));
|
||||
Assert.assertEquals(f.value(x, y), p.value(x, y), tol);
|
||||
|
|
Loading…
Reference in New Issue