Skip to content

Commit 4c4c227

Browse files
author
Gilles Sadowski
committed
MATH-1650: Add unit tests file.
Thanks to Michael Scholz.
1 parent ab25a02 commit 4c4c227

1 file changed

Lines changed: 175 additions & 0 deletions

File tree

Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
package org.apache.commons.math4.legacy.analysis.interpolation;
18+
19+
import org.apache.commons.math4.legacy.TestUtils;
20+
import org.apache.commons.math4.legacy.analysis.integration.SimpsonIntegrator;
21+
import org.apache.commons.math4.legacy.analysis.polynomials.PolynomialFunction;
22+
import org.apache.commons.math4.legacy.analysis.polynomials.PolynomialSplineFunction;
23+
import org.apache.commons.math4.legacy.exception.DimensionMismatchException;
24+
import org.apache.commons.math4.legacy.exception.NonMonotonicSequenceException;
25+
import org.apache.commons.math4.legacy.exception.NumberIsTooSmallException;
26+
import org.junit.Assert;
27+
import org.junit.Test;
28+
29+
/**
30+
* Test the ClampedSplineInterpolator.
31+
*/
32+
public class ClampedSplineInterpolatorTest {
33+
/** Error tolerance for spline interpolator value at knot points. */
34+
private static final double KNOT_TOL = 1e-14;
35+
/** Error tolerance for interpolating polynomial coefficients. */
36+
private static final double COEF_TOL = 1e-14;
37+
38+
@Test
39+
public void testInterpolateLinearDegenerateTwoSegment() {
40+
final double[] x = {0, 0.5, 1};
41+
final double[] y = {1, Math.exp(0.5), Math.exp(1)};
42+
final double fpo = 1;
43+
final double fpn = Math.exp(1);
44+
final ClampedSplineInterpolator i = new ClampedSplineInterpolator();
45+
final PolynomialSplineFunction f = i.interpolate(x, y, fpo, fpn);
46+
verifyInterpolation(f, x, y);
47+
verifyConsistency(f, x);
48+
49+
// Verify coefficients using analytical values
50+
final PolynomialFunction[] polynomials = f.getPolynomials();
51+
52+
final double[] target0 = {1, 1, 0.4889506772539256, 0.21186881109317435};
53+
final double[] target1 = {1.6487212707001282, 1.6478522855738063, 0.8067538938936871, 0.35156753198873575};
54+
TestUtils.assertEquals(polynomials[0].getCoefficients(), target0, COEF_TOL);
55+
TestUtils.assertEquals(polynomials[1].getCoefficients(), target1, COEF_TOL);
56+
}
57+
58+
@Test
59+
public void testInterpolateLinearDegenerateThreeSegment() {
60+
final double[] x = {0, 1, 2, 3};
61+
final double[] y = {1, Math.exp(1), Math.exp(2), Math.exp(3)};
62+
final double fpo = 1;
63+
final double fpn = Math.exp(3);
64+
final ClampedSplineInterpolator i = new ClampedSplineInterpolator();
65+
final PolynomialSplineFunction f = i.interpolate(x, y, fpo, fpn);
66+
verifyInterpolation(f, x, y);
67+
verifyConsistency(f, x);
68+
69+
// Verify coefficients using analytical values
70+
final PolynomialFunction[] polynomials = f.getPolynomials();
71+
72+
final double[] target0 = {1, 0.9999999999999999, 0.4446824969658283, 0.27359933149321697};
73+
final double[] target1 = {2.718281828459045, 2.710162988411307, 1.2654804914454791, 0.6951307906148195};
74+
final double[] target2 = {7.38905609893065, 7.326516343146723, 3.3508728632899376, 2.019091617820356};
75+
TestUtils.assertEquals(polynomials[0].getCoefficients(), target0, COEF_TOL);
76+
TestUtils.assertEquals(polynomials[1].getCoefficients(), target1, COEF_TOL);
77+
TestUtils.assertEquals(polynomials[2].getCoefficients(), target2, COEF_TOL);
78+
}
79+
80+
@Test(expected=DimensionMismatchException.class)
81+
public void testArrayLengthMismatch() {
82+
// Data set arrays of different size.
83+
new ClampedSplineInterpolator().interpolate(new double[] {1, 2, 3, 4},
84+
new double[] {2, 3, 5},
85+
2, 1);
86+
}
87+
@Test(expected=NonMonotonicSequenceException.class)
88+
public void testUnsortedArray() {
89+
// Knot values not sorted.
90+
new ClampedSplineInterpolator().interpolate(new double[] {1, 3, 2 },
91+
new double[] {2, 3, 5},
92+
2, 1);
93+
}
94+
@Test(expected=NumberIsTooSmallException.class)
95+
public void testInsufficientData() {
96+
// Not enough data to interpolate.
97+
new ClampedSplineInterpolator().interpolate(new double[] {1, 2 },
98+
new double[] {2, 3},
99+
2, 1);
100+
}
101+
102+
/**
103+
* Verifies that a clamped spline <i>without</i> specified boundary conditions behaves similar to a natural
104+
* ("unclamped") spline.
105+
*
106+
* <p>
107+
* Using the exponential function <code>e<sup>x</sup></code> over the interval <code>[0, 3]</code>, the test
108+
* evaluates:
109+
* <ol>
110+
* <li>The integral of a clamped spline with specified boundary conditions (endpoint slopes/derivatives).</li>
111+
* <li>The integral of a clamped spline without specified boundary conditions.</li>
112+
* <li>The integral of a natural spline (without boundary conditions by default).</li>
113+
* </ol>
114+
*
115+
* These integrals are compared against the direct integral of the function <code>e<sup>x</sup></code> over the same
116+
* interval.</p>
117+
*
118+
* <p>
119+
* This test is based on "Example 4" in R.L. Burden, J.D. Faires,
120+
* <u>Numerical Analysis</u>, 9th Ed., 2010, Cengage Learning, ISBN 0-538-73351-9, pp 156-157.
121+
* </p>
122+
*/
123+
@Test
124+
public void testIntegral() {
125+
final double[] x = {0, 1, 2, 3};
126+
final double[] y = {1, Math.exp(1), Math.exp(2), Math.exp(3)};
127+
final double fpo = 1;
128+
final double fpn = Math.exp(3);
129+
130+
final ClampedSplineInterpolator clampedSplineInterpolator = new ClampedSplineInterpolator();
131+
final PolynomialSplineFunction clampedSpline = clampedSplineInterpolator.interpolate(x, y, fpo, fpn);
132+
final PolynomialSplineFunction clampedSplineAsNaturalSpline = clampedSplineInterpolator.interpolate(x, y);
133+
134+
final SplineInterpolator naturalSplineInterpolator = new SplineInterpolator();
135+
final PolynomialSplineFunction naturalSpline = naturalSplineInterpolator.interpolate(x, y);
136+
137+
final SimpsonIntegrator integrator = new SimpsonIntegrator();
138+
139+
final double clampedSplineIntegral = integrator.integrate(1000, clampedSpline, 0, 3);
140+
final double clampedSplineAsNaturalSplineIntegral = integrator.integrate(1000, clampedSplineAsNaturalSpline, 0, 3);
141+
final double naturalSplineIntegral = integrator.integrate(1000, naturalSpline, 0, 3);
142+
final double exponentialFunctionIntegral = integrator.integrate(1000, arg -> Math.exp(arg), 0, 3);
143+
144+
Assert.assertEquals(Math.abs(clampedSplineAsNaturalSplineIntegral - naturalSplineIntegral), 0, 0);
145+
Assert.assertEquals(Math.abs(exponentialFunctionIntegral - clampedSplineIntegral), 0.02589, 0.1);
146+
Assert.assertEquals(Math.abs(exponentialFunctionIntegral - naturalSplineIntegral), 0.46675, 0.1);
147+
}
148+
149+
/**
150+
* Verifies that f(x[i]) = y[i] for i = 0, ..., n-1 (where n is common length).
151+
*/
152+
private void verifyInterpolation(PolynomialSplineFunction f,
153+
double[] x, double[] y) {
154+
for (int i = 0; i < x.length; i++) {
155+
Assert.assertEquals(f.value(x[i]), y[i], KNOT_TOL);
156+
}
157+
}
158+
159+
/**
160+
* Verifies that interpolating polynomials satisfy consistency requirement: adjacent polynomials must agree through
161+
* two derivatives at knot points.
162+
*/
163+
private void verifyConsistency(PolynomialSplineFunction f,
164+
double[] x) {
165+
PolynomialFunction polynomials[] = f.getPolynomials();
166+
for (int i = 1; i < x.length - 2; i++) {
167+
// evaluate polynomials and derivatives at x[i + 1]
168+
Assert.assertEquals(polynomials[i].value(x[i + 1] - x[i]), polynomials[i + 1].value(0), 0.1);
169+
Assert.assertEquals(polynomials[i].polynomialDerivative().value(x[i + 1] - x[i]),
170+
polynomials[i + 1].polynomialDerivative().value(0), 0.5);
171+
Assert.assertEquals(polynomials[i].polynomialDerivative().polynomialDerivative().value(x[i + 1] - x[i]),
172+
polynomials[i + 1].polynomialDerivative().polynomialDerivative().value(0), 0.5);
173+
}
174+
}
175+
}

0 commit comments

Comments
 (0)