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    // commons-math
020    import org.apache.commons.math.MathException;
021    import org.apache.commons.math.TestUtils;
022    // junit
023    import junit.framework.TestCase;
024    
025    /**
026     * Tests the PolynomialFunction implementation of a UnivariateRealFunction.
027     *
028     * @version $Revision: 799857 $
029     * @author Matt Cliff <matt@mattcliff.com>
030     */
031    public final class PolynomialFunctionTest extends TestCase {
032    
033        /** Error tolerance for tests */
034        protected double tolerance = 1.0e-12;
035    
036        /**
037         * tests the value of a constant polynomial.
038         *
039         * <p>value of this is 2.5 everywhere.</p>
040         */
041        public void testConstants() throws MathException {
042            double[] c = { 2.5 };
043            PolynomialFunction f = new PolynomialFunction( c );
044    
045            // verify that we are equal to c[0] at several (nonsymmetric) places
046            assertEquals( f.value( 0.0), c[0], tolerance );
047            assertEquals( f.value( -1.0), c[0], tolerance );
048            assertEquals( f.value( -123.5), c[0], tolerance );
049            assertEquals( f.value( 3.0), c[0], tolerance );
050            assertEquals( f.value( 456.89), c[0], tolerance );
051            
052            assertEquals(f.degree(), 0);
053            assertEquals(f.derivative().value(0), 0, tolerance);
054            
055            assertEquals(f.polynomialDerivative().derivative().value(0), 0, tolerance);
056        }
057    
058        /**
059         * tests the value of a linear polynomial.
060         *
061         * <p>This will test the function f(x) = 3*x - 1.5</p>
062         * <p>This will have the values 
063         *  <tt>f(0.0) = -1.5, f(-1.0) = -4.5, f(-2.5) = -9.0,
064         *      f(0.5) = 0.0, f(1.5) = 3.0</tt> and <tt>f(3.0) = 7.5</tt>
065         * </p>
066         */
067        public void testLinear() throws MathException {
068            double[] c = { -1.5, 3.0 };
069            PolynomialFunction f = new PolynomialFunction( c );
070    
071            // verify that we are equal to c[0] when x=0
072            assertEquals( f.value( 0.0), c[0], tolerance );
073    
074            // now check a few other places
075            assertEquals( -4.5, f.value( -1.0), tolerance );
076            assertEquals( -9.0, f.value( -2.5), tolerance );
077            assertEquals( 0.0, f.value( 0.5), tolerance );
078            assertEquals( 3.0, f.value( 1.5), tolerance );
079            assertEquals( 7.5, f.value( 3.0), tolerance );
080            
081            assertEquals(f.degree(), 1);
082            
083            assertEquals(f.polynomialDerivative().derivative().value(0), 0, tolerance);
084        
085        }
086    
087    
088        /**
089         * Tests a second order polynomial.
090         * <p> This will test the function f(x) = 2x^2 - 3x -2 = (2x+1)(x-2)</p>
091         *
092         */
093        public void testQuadratic() {
094            double[] c = { -2.0, -3.0, 2.0 };
095            PolynomialFunction f = new PolynomialFunction( c );
096    
097            // verify that we are equal to c[0] when x=0
098            assertEquals( f.value( 0.0), c[0], tolerance );
099    
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    }