001: /*
002: *
003: * Copyright (c) 2004 The Apache Software Foundation. All rights reserved.
004: *
005: * Licensed under the Apache License, Version 2.0 (the "License"); you may not
006: * use this file except in compliance with the License. You may obtain a copy
007: * 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, WITHOUT
013: * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
014: * License for the specific language governing permissions and limitations
015: * under the License.
016: *
017: */
018: package org.apache.commons.math.analysis;
019:
020: import java.util.Arrays;
021: import junit.framework.TestCase;
022:
023: import org.apache.commons.math.FunctionEvaluationException;
024:
025: /**
026: * Tests the PolynomialSplineFunction implementation.
027: *
028: * @version $Revision: 155427 $
029: */
030: public class PolynomialSplineFunctionTest extends TestCase {
031:
032: /** Error tolerance for tests */
033: protected double tolerance = 1.0e-12;
034:
035: /**
036: * Quadratic polynomials used in tests:
037: *
038: * x^2 + x [-1, 0)
039: * x^2 + x + 2 [0, 1)
040: * x^2 + x + 4 [1, 2)
041: *
042: * Defined so that evaluation using PolynomialSplineFunction evaluation
043: * algorithm agrees at knot point boundaries.
044: */
045: protected PolynomialFunction[] polynomials = {
046: new PolynomialFunction(new double[] { 0d, 1d, 1d }),
047: new PolynomialFunction(new double[] { 2d, 1d, 1d }),
048: new PolynomialFunction(new double[] { 4d, 1d, 1d }) };
049:
050: /** Knot points */
051: protected double[] knots = { -1, 0, 1, 2 };
052:
053: /** Derivative of test polynomials -- 2x + 1 */
054: protected PolynomialFunction dp = new PolynomialFunction(
055: new double[] { 1d, 2d });
056:
057: public void testConstructor() {
058: PolynomialSplineFunction spline = new PolynomialSplineFunction(
059: knots, polynomials);
060: assertTrue(Arrays.equals(knots, spline.getKnots()));
061: assertEquals(1d,
062: spline.getPolynomials()[0].getCoefficients()[2], 0);
063: assertEquals(3, spline.getN());
064:
065: try { // too few knots
066: spline = new PolynomialSplineFunction(new double[] { 0 },
067: polynomials);
068: fail("Expecting IllegalArgumentException");
069: } catch (IllegalArgumentException ex) {
070: // expected
071: }
072:
073: try { // too many knots
074: spline = new PolynomialSplineFunction(new double[] { 0, 1,
075: 2, 3, 4 }, polynomials);
076: fail("Expecting IllegalArgumentException");
077: } catch (IllegalArgumentException ex) {
078: // expected
079: }
080:
081: try { // knots not increasing
082: spline = new PolynomialSplineFunction(new double[] { 0, 1,
083: 3, 2 }, polynomials);
084: fail("Expecting IllegalArgumentException");
085: } catch (IllegalArgumentException ex) {
086: // expected
087: }
088: }
089:
090: public void testValues() throws Exception {
091: PolynomialSplineFunction spline = new PolynomialSplineFunction(
092: knots, polynomials);
093: UnivariateRealFunction dSpline = spline.derivative();
094:
095: /**
096: * interior points -- spline value at x should equal p(x - knot)
097: * where knot is the largest knot point less than or equal to x and p
098: * is the polynomial defined over the knot segment to which x belongs.
099: */
100: double x = -1;
101: int index = 0;
102: for (int i = 0; i < 10; i++) {
103: x += 0.25;
104: index = findKnot(knots, x);
105: assertEquals(
106: "spline function evaluation failed for x=" + x,
107: polynomials[index].value(x - knots[index]), spline
108: .value(x), tolerance);
109: assertEquals("spline derivative evaluation failed for x="
110: + x, dp.value(x - knots[index]), dSpline.value(x),
111: tolerance);
112: }
113:
114: // knot points -- centering should zero arguments
115: for (int i = 0; i < 3; i++) {
116: assertEquals("spline function evaluation failed for knot="
117: + knots[i], polynomials[i].value(0), spline
118: .value(knots[i]), tolerance);
119: assertEquals("spline function evaluation failed for knot="
120: + knots[i], dp.value(0), dSpline.value(knots[i]),
121: tolerance);
122: }
123:
124: try { //outside of domain -- under min
125: x = spline.value(-1.5);
126: fail("Expecting IllegalArgumentException");
127: } catch (FunctionEvaluationException ex) {
128: // expected
129: }
130:
131: try { //outside of domain -- over max
132: x = spline.value(2.5);
133: fail("Expecting IllegalArgumentException");
134: } catch (FunctionEvaluationException ex) {
135: // expected
136: }
137: }
138:
139: /**
140: * Do linear search to find largest knot point less than or equal to x.
141: * Implementation does binary search.
142: */
143: protected int findKnot(double[] knots, double x) {
144: if (x < knots[0] || x >= knots[knots.length - 1]) {
145: throw new IllegalArgumentException("x is out of range");
146: }
147: for (int i = 0; i < knots.length; i++) {
148: if (knots[i] > x) {
149: return i - 1;
150: }
151: }
152: throw new IllegalArgumentException("x is out of range");
153: }
154: }
|