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.math.analysis.polynomials;
18  
19  // commons-math
20  import org.apache.commons.math.MathException;
21  import org.apache.commons.math.TestUtils;
22  // junit
23  import junit.framework.TestCase;
24  
25  /**
26   * Tests the PolynomialFunction implementation of a UnivariateRealFunction.
27   *
28   * @version $Revision: 799857 $
29   * @author Matt Cliff <matt@mattcliff.com>
30   */
31  public final class PolynomialFunctionTest extends TestCase {
32  
33      /** Error tolerance for tests */
34      protected double tolerance = 1.0e-12;
35  
36      /**
37       * tests the value of a constant polynomial.
38       *
39       * <p>value of this is 2.5 everywhere.</p>
40       */
41      public void testConstants() throws MathException {
42          double[] c = { 2.5 };
43          PolynomialFunction f = new PolynomialFunction( c );
44  
45          // verify that we are equal to c[0] at several (nonsymmetric) places
46          assertEquals( f.value( 0.0), c[0], tolerance );
47          assertEquals( f.value( -1.0), c[0], tolerance );
48          assertEquals( f.value( -123.5), c[0], tolerance );
49          assertEquals( f.value( 3.0), c[0], tolerance );
50          assertEquals( f.value( 456.89), c[0], tolerance );
51          
52          assertEquals(f.degree(), 0);
53          assertEquals(f.derivative().value(0), 0, tolerance);
54          
55          assertEquals(f.polynomialDerivative().derivative().value(0), 0, tolerance);
56      }
57  
58      /**
59       * tests the value of a linear polynomial.
60       *
61       * <p>This will test the function f(x) = 3*x - 1.5</p>
62       * <p>This will have the values 
63       *  <tt>f(0.0) = -1.5, f(-1.0) = -4.5, f(-2.5) = -9.0,
64       *      f(0.5) = 0.0, f(1.5) = 3.0</tt> and <tt>f(3.0) = 7.5</tt>
65       * </p>
66       */
67      public void testLinear() throws MathException {
68          double[] c = { -1.5, 3.0 };
69          PolynomialFunction f = new PolynomialFunction( c );
70  
71          // verify that we are equal to c[0] when x=0
72          assertEquals( f.value( 0.0), c[0], tolerance );
73  
74          // now check a few other places
75          assertEquals( -4.5, f.value( -1.0), tolerance );
76          assertEquals( -9.0, f.value( -2.5), tolerance );
77          assertEquals( 0.0, f.value( 0.5), tolerance );
78          assertEquals( 3.0, f.value( 1.5), tolerance );
79          assertEquals( 7.5, f.value( 3.0), tolerance );
80          
81          assertEquals(f.degree(), 1);
82          
83          assertEquals(f.polynomialDerivative().derivative().value(0), 0, tolerance);
84      
85      }
86  
87  
88      /**
89       * Tests a second order polynomial.
90       * <p> This will test the function f(x) = 2x^2 - 3x -2 = (2x+1)(x-2)</p>
91       *
92       */
93      public void testQuadratic() {
94          double[] c = { -2.0, -3.0, 2.0 };
95          PolynomialFunction f = new PolynomialFunction( c );
96  
97          // verify that we are equal to c[0] when x=0
98          assertEquals( f.value( 0.0), c[0], tolerance );
99  
100         // now check a few other places
101         assertEquals( 0.0, f.value( -0.5), tolerance );
102         assertEquals( 0.0, f.value( 2.0), tolerance );
103         assertEquals( -2.0, f.value( 1.5), tolerance );
104         assertEquals( 7.0, f.value( -1.5), tolerance );
105         assertEquals( 265.5312, f.value( 12.34), tolerance );
106     
107     }    
108 
109 
110     /** 
111      * This will test the quintic function 
112      *   f(x) = x^2(x-5)(x+3)(x-1) = x^5 - 3x^4 -13x^3 + 15x^2</p>
113      *
114      */
115     public void testQuintic() {
116         double[] c = { 0.0, 0.0, 15.0, -13.0, -3.0, 1.0 };
117         PolynomialFunction f = new PolynomialFunction( c );
118 
119         // verify that we are equal to c[0] when x=0
120         assertEquals( f.value( 0.0), c[0], tolerance );
121 
122         // now check a few other places
123         assertEquals( 0.0, f.value( 5.0), tolerance );
124         assertEquals( 0.0, f.value( 1.0), tolerance );
125         assertEquals( 0.0, f.value( -3.0), tolerance );
126         assertEquals( 54.84375, f.value( -1.5), tolerance );
127         assertEquals( -8.06637, f.value( 1.3), tolerance );
128         
129         assertEquals(f.degree(), 5);
130     
131     }    
132 
133 
134     /**
135      * tests the firstDerivative function by comparison
136      *
137      * <p>This will test the functions 
138      * <tt>f(x) = x^3 - 2x^2 + 6x + 3, g(x) = 3x^2 - 4x + 6</tt>
139      * and <tt>h(x) = 6x - 4</tt>
140      */
141     public void testfirstDerivativeComparison() throws MathException {
142         double[] f_coeff = { 3.0, 6.0, -2.0, 1.0 };
143         double[] g_coeff = { 6.0, -4.0, 3.0 };
144         double[] h_coeff = { -4.0, 6.0 };
145 
146         PolynomialFunction f = new PolynomialFunction( f_coeff );
147         PolynomialFunction g = new PolynomialFunction( g_coeff );
148         PolynomialFunction h = new PolynomialFunction( h_coeff );
149 
150         // compare f' = g
151         assertEquals( f.derivative().value(0.0), g.value(0.0), tolerance );
152         assertEquals( f.derivative().value(1.0), g.value(1.0), tolerance );
153         assertEquals( f.derivative().value(100.0), g.value(100.0), tolerance );
154         assertEquals( f.derivative().value(4.1), g.value(4.1), tolerance );
155         assertEquals( f.derivative().value(-3.25), g.value(-3.25), tolerance );
156 
157         // compare g' = h
158         assertEquals( g.derivative().value(Math.PI), h.value(Math.PI), tolerance );
159         assertEquals( g.derivative().value(Math.E),  h.value(Math.E),  tolerance );
160 
161     }
162 
163     public void testString() {
164         PolynomialFunction p = new PolynomialFunction(new double[] { -5.0, 3.0, 1.0 });
165         checkPolynomial(p, "-5.0 + 3.0 x + x^2");
166         checkPolynomial(new PolynomialFunction(new double[] { 0.0, -2.0, 3.0 }),
167                         "-2.0 x + 3.0 x^2");
168         checkPolynomial(new PolynomialFunction(new double[] { 1.0, -2.0, 3.0 }),
169                       "1.0 - 2.0 x + 3.0 x^2");
170         checkPolynomial(new PolynomialFunction(new double[] { 0.0,  2.0, 3.0 }),
171                        "2.0 x + 3.0 x^2");
172         checkPolynomial(new PolynomialFunction(new double[] { 1.0,  2.0, 3.0 }),
173                      "1.0 + 2.0 x + 3.0 x^2");
174         checkPolynomial(new PolynomialFunction(new double[] { 1.0,  0.0, 3.0 }),
175                      "1.0 + 3.0 x^2");
176         checkPolynomial(new PolynomialFunction(new double[] { 0.0 }),
177                      "0");
178     }
179 
180     public void testAddition() {
181 
182         PolynomialFunction p1 = new PolynomialFunction(new double[] { -2.0, 1.0 });
183         PolynomialFunction p2 = new PolynomialFunction(new double[] { 2.0, -1.0, 0.0 });
184         checkNullPolynomial(p1.add(p2));
185 
186         p2 = p1.add(p1);
187         checkPolynomial(p2, "-4.0 + 2.0 x");
188 
189         p1 = new PolynomialFunction(new double[] { 1.0, -4.0, 2.0 });
190         p2 = new PolynomialFunction(new double[] { -1.0, 3.0, -2.0 });
191         p1 = p1.add(p2);
192         assertEquals(1, p1.degree());
193         checkPolynomial(p1, "-x");
194 
195     }
196 
197     public void testSubtraction() {
198 
199         PolynomialFunction p1 = new PolynomialFunction(new double[] { -2.0, 1.0 });
200         checkNullPolynomial(p1.subtract(p1));
201 
202         PolynomialFunction p2 = new PolynomialFunction(new double[] { -2.0, 6.0 });
203         p2 = p2.subtract(p1);
204         checkPolynomial(p2, "5.0 x");
205 
206         p1 = new PolynomialFunction(new double[] { 1.0, -4.0, 2.0 });
207         p2 = new PolynomialFunction(new double[] { -1.0, 3.0, 2.0 });
208         p1 = p1.subtract(p2);
209         assertEquals(1, p1.degree());
210         checkPolynomial(p1, "2.0 - 7.0 x");
211 
212     }
213 
214     public void testMultiplication() {
215 
216         PolynomialFunction p1 = new PolynomialFunction(new double[] { -3.0, 2.0 });
217         PolynomialFunction p2 = new PolynomialFunction(new double[] { 3.0, 2.0, 1.0 });
218         checkPolynomial(p1.multiply(p2), "-9.0 + x^2 + 2.0 x^3");
219 
220         p1 = new PolynomialFunction(new double[] { 0.0, 1.0 });
221         p2 = p1;
222         for (int i = 2; i < 10; ++i) {
223             p2 = p2.multiply(p1);
224             checkPolynomial(p2, "x^" + i);
225         }
226 
227     }
228 
229     public void testSerial() {
230         PolynomialFunction p2 = new PolynomialFunction(new double[] { 3.0, 2.0, 1.0 });
231         assertEquals(p2, TestUtils.serializeAndRecover(p2));
232     }
233     
234     public void checkPolynomial(PolynomialFunction p, String reference) {
235         assertEquals(reference, p.toString());
236     }
237 
238     private void checkNullPolynomial(PolynomialFunction p) {
239         for (double coefficient : p.getCoefficients()) {
240             assertEquals(0.0, coefficient, 1.0e-15);
241         }
242     }
243 
244 }