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    }