001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017 package org.apache.commons.math3.analysis.interpolation;
018
019 import org.apache.commons.math3.exception.NonMonotonicSequenceException;
020 import org.apache.commons.math3.exception.DimensionMismatchException;
021 import org.apache.commons.math3.exception.NumberIsTooSmallException;
022 import org.apache.commons.math3.TestUtils;
023 import org.apache.commons.math3.analysis.UnivariateFunction;
024 import org.apache.commons.math3.analysis.polynomials.PolynomialFunction;
025 import org.apache.commons.math3.analysis.polynomials.PolynomialSplineFunction;
026 import org.junit.Assert;
027 import org.junit.Test;
028
029 /**
030 * Test the LinearInterpolator.
031 */
032 public class LinearInterpolatorTest {
033
034 /** error tolerance for spline interpolator value at knot points */
035 protected double knotTolerance = 1E-12;
036
037 /** error tolerance for interpolating polynomial coefficients */
038 protected double coefficientTolerance = 1E-6;
039
040 /** error tolerance for interpolated values */
041 protected double interpolationTolerance = 1E-12;
042
043 @Test
044 public void testInterpolateLinearDegenerateTwoSegment()
045 {
046 double x[] = { 0.0, 0.5, 1.0 };
047 double y[] = { 0.0, 0.5, 1.0 };
048 UnivariateInterpolator i = new LinearInterpolator();
049 UnivariateFunction f = i.interpolate(x, y);
050 verifyInterpolation(f, x, y);
051
052 // Verify coefficients using analytical values
053 PolynomialFunction polynomials[] = ((PolynomialSplineFunction) f).getPolynomials();
054 double target[] = {y[0], 1d};
055 TestUtils.assertEquals(polynomials[0].getCoefficients(), target, coefficientTolerance);
056 target = new double[]{y[1], 1d};
057 TestUtils.assertEquals(polynomials[1].getCoefficients(), target, coefficientTolerance);
058
059 // Check interpolation
060 Assert.assertEquals(0.0,f.value(0.0), interpolationTolerance);
061 Assert.assertEquals(0.4,f.value(0.4), interpolationTolerance);
062 Assert.assertEquals(1.0,f.value(1.0), interpolationTolerance);
063 }
064
065 @Test
066 public void testInterpolateLinearDegenerateThreeSegment()
067 {
068 double x[] = { 0.0, 0.5, 1.0, 1.5 };
069 double y[] = { 0.0, 0.5, 1.0, 1.5 };
070 UnivariateInterpolator i = new LinearInterpolator();
071 UnivariateFunction f = i.interpolate(x, y);
072 verifyInterpolation(f, x, y);
073
074 // Verify coefficients using analytical values
075 PolynomialFunction polynomials[] = ((PolynomialSplineFunction) f).getPolynomials();
076 double target[] = {y[0], 1d};
077 TestUtils.assertEquals(polynomials[0].getCoefficients(), target, coefficientTolerance);
078 target = new double[]{y[1], 1d};
079 TestUtils.assertEquals(polynomials[1].getCoefficients(), target, coefficientTolerance);
080 target = new double[]{y[2], 1d};
081 TestUtils.assertEquals(polynomials[2].getCoefficients(), target, coefficientTolerance);
082
083 // Check interpolation
084 Assert.assertEquals(0,f.value(0), interpolationTolerance);
085 Assert.assertEquals(1.4,f.value(1.4), interpolationTolerance);
086 Assert.assertEquals(1.5,f.value(1.5), interpolationTolerance);
087 }
088
089 @Test
090 public void testInterpolateLinear() {
091 double x[] = { 0.0, 0.5, 1.0 };
092 double y[] = { 0.0, 0.5, 0.0 };
093 UnivariateInterpolator i = new LinearInterpolator();
094 UnivariateFunction f = i.interpolate(x, y);
095 verifyInterpolation(f, x, y);
096
097 // Verify coefficients using analytical values
098 PolynomialFunction polynomials[] = ((PolynomialSplineFunction) f).getPolynomials();
099 double target[] = {y[0], 1d};
100 TestUtils.assertEquals(polynomials[0].getCoefficients(), target, coefficientTolerance);
101 target = new double[]{y[1], -1d};
102 TestUtils.assertEquals(polynomials[1].getCoefficients(), target, coefficientTolerance);
103 }
104
105 @Test
106 public void testIllegalArguments() {
107 // Data set arrays of different size.
108 UnivariateInterpolator i = new LinearInterpolator();
109 try {
110 double xval[] = { 0.0, 1.0 };
111 double yval[] = { 0.0, 1.0, 2.0 };
112 i.interpolate(xval, yval);
113 Assert.fail("Failed to detect data set array with different sizes.");
114 } catch (DimensionMismatchException iae) {
115 // Expected.
116 }
117 // X values not sorted.
118 try {
119 double xval[] = { 0.0, 1.0, 0.5 };
120 double yval[] = { 0.0, 1.0, 2.0 };
121 i.interpolate(xval, yval);
122 Assert.fail("Failed to detect unsorted arguments.");
123 } catch (NonMonotonicSequenceException iae) {
124 // Expected.
125 }
126 // Not enough data to interpolate.
127 try {
128 double xval[] = { 0.0 };
129 double yval[] = { 0.0 };
130 i.interpolate(xval, yval);
131 Assert.fail("Failed to detect unsorted arguments.");
132 } catch (NumberIsTooSmallException iae) {
133 // Expected.
134 }
135 }
136
137 /**
138 * verifies that f(x[i]) = y[i] for i = 0..n-1 where n is common length.
139 */
140 protected void verifyInterpolation(UnivariateFunction f, double x[], double y[])
141 {
142 for (int i = 0; i < x.length; i++) {
143 Assert.assertEquals(f.value(x[i]), y[i], knotTolerance);
144 }
145 }
146
147 }