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.math.analysis.polynomials; 018 019 import java.util.Arrays; 020 import junit.framework.TestCase; 021 022 import org.apache.commons.math.FunctionEvaluationException; 023 import org.apache.commons.math.analysis.UnivariateRealFunction; 024 025 /** 026 * Tests the PolynomialSplineFunction implementation. 027 * 028 * @version $Revision: 799857 $ 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 051 /** Knot points */ 052 protected double[] knots = {-1, 0, 1, 2}; 053 054 /** Derivative of test polynomials -- 2x + 1 */ 055 protected PolynomialFunction dp = 056 new PolynomialFunction(new double[] {1d, 2d}); 057 058 059 public void testConstructor() { 060 PolynomialSplineFunction spline = 061 new PolynomialSplineFunction(knots, polynomials); 062 assertTrue(Arrays.equals(knots, spline.getKnots())); 063 assertEquals(1d, spline.getPolynomials()[0].getCoefficients()[2], 0); 064 assertEquals(3, spline.getN()); 065 066 try { // too few knots 067 new PolynomialSplineFunction(new double[] {0}, polynomials); 068 fail("Expecting IllegalArgumentException"); 069 } catch (IllegalArgumentException ex) { 070 // expected 071 } 072 073 try { // too many knots 074 new PolynomialSplineFunction(new double[] {0,1,2,3,4}, polynomials); 075 fail("Expecting IllegalArgumentException"); 076 } catch (IllegalArgumentException ex) { 077 // expected 078 } 079 080 try { // knots not increasing 081 new PolynomialSplineFunction(new double[] {0,1, 3, 2}, polynomials); 082 fail("Expecting IllegalArgumentException"); 083 } catch (IllegalArgumentException ex) { 084 // expected 085 } 086 } 087 088 public void testValues() throws Exception { 089 PolynomialSplineFunction spline = 090 new PolynomialSplineFunction(knots, polynomials); 091 UnivariateRealFunction dSpline = spline.derivative(); 092 093 /** 094 * interior points -- spline value at x should equal p(x - knot) 095 * where knot is the largest knot point less than or equal to x and p 096 * is the polynomial defined over the knot segment to which x belongs. 097 */ 098 double x = -1; 099 int index = 0; 100 for (int i = 0; i < 10; i++) { 101 x+=0.25; 102 index = findKnot(knots, x); 103 assertEquals("spline function evaluation failed for x=" + x, 104 polynomials[index].value(x - knots[index]), spline.value(x), tolerance); 105 assertEquals("spline derivative evaluation failed for x=" + x, 106 dp.value(x - knots[index]), dSpline.value(x), tolerance); 107 } 108 109 // knot points -- centering should zero arguments 110 for (int i = 0; i < 3; i++) { 111 assertEquals("spline function evaluation failed for knot=" + knots[i], 112 polynomials[i].value(0), spline.value(knots[i]), tolerance); 113 assertEquals("spline function evaluation failed for knot=" + knots[i], 114 dp.value(0), dSpline.value(knots[i]), tolerance); 115 } 116 117 try { //outside of domain -- under min 118 x = spline.value(-1.5); 119 fail("Expecting IllegalArgumentException"); 120 } catch (FunctionEvaluationException ex) { 121 // expected 122 } 123 124 try { //outside of domain -- over max 125 x = spline.value(2.5); 126 fail("Expecting IllegalArgumentException"); 127 } catch (FunctionEvaluationException ex) { 128 // expected 129 } 130 } 131 132 /** 133 * Do linear search to find largest knot point less than or equal to x. 134 * Implementation does binary search. 135 */ 136 protected int findKnot(double[] knots, double x) { 137 if (x < knots[0] || x >= knots[knots.length -1]) { 138 throw new IllegalArgumentException("x is out of range"); 139 } 140 for (int i = 0; i < knots.length; i++) { 141 if (knots[i] > x) { 142 return i -1; 143 } 144 } 145 throw new IllegalArgumentException("x is out of range"); 146 } 147 } 148