Submitted by:	Matt Cliff
  Reviewed by:	Mark Diggory


git-svn-id: https://svn.apache.org/repos/asf/jakarta/commons/proper/math/trunk@141020 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Dirk Verbeeck 2003-11-15 18:44:52 +00:00
parent d26b4d28f8
commit c9a0955115
6 changed files with 392 additions and 47 deletions

View File

@ -64,7 +64,7 @@ import org.apache.commons.math.MathException;
* polynominal coefficents are used.
* Arguments outside of the domain cause an IllegalArgumentException.
*
* @version $Revision: 1.7 $ $Date: 2003/11/14 22:22:17 $
* @version $Revision: 1.8 $ $Date: 2003/11/15 18:44:52 $
*/
public class CubicSplineFunction implements UnivariateRealFunction {
/** Spline segment interval delimiters. Size is N+1 for N segments. */
@ -122,7 +122,6 @@ public class CubicSplineFunction implements UnivariateRealFunction {
* @param x the point for which the first derivative should be computed
* @return the value
* @throws MathException if the derivative couldn't be computed.
* @see UnivariateRealFunction#firstDerivative(double)
*/
public double firstDerivative(double x) throws MathException {
if (x < xval[0] || x > xval[xval.length - 1]) {
@ -145,7 +144,6 @@ public class CubicSplineFunction implements UnivariateRealFunction {
* @param x the point for which the first derivative should be computed
* @return the value
* @throws MathException if the second derivative couldn't be computed.
* @see UnivariateRealFunction#secondDerivative(double)
*/
public double secondDerivative(double x) throws MathException {
if (x < xval[0] || x > xval[xval.length - 1]) {

View File

@ -0,0 +1,193 @@
/* ====================================================================
* The Apache Software License, Version 1.1
*
* Copyright (c) 2003 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution, if
* any, must include the following acknowledgement:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgement may appear in the software itself,
* if and wherever such third-party acknowledgements normally appear.
*
* 4. The names "The Jakarta Project", "Commons", and "Apache Software
* Foundation" must not be used to endorse or promote products derived
* from this software without prior written permission. For written
* permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache"
* nor may "Apache" appear in their name without prior written
* permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
package org.apache.commons.math.analysis;
import org.apache.commons.math.MathException;
/**
* Represents a Polynomial function.
* Spline functions map a certain interval of real numbers to real numbers.
* A cubic spline consists of segments of cubic functions. For this class,
* polynominal coefficents are used.
* Arguments outside of the domain cause an IllegalArgumentException.
*
* @version $Revision: 1.1 $ $Date: 2003/11/15 18:44:52 $
*/
public class PolynomialFunction implements UnivariateRealFunction {
/**
* The polynominal coefficients.
* The index represents the coefficients of the polynomail, with
* index 0 being the absolute coefficient and index N the coefficient
* for the Nth power.
*/
private double c[];
/**
* Construct a function with the given segment delimiters and polynomial
* coefficients.
* @param c polynominal coefficients
*/
public PolynomialFunction(double c[]) {
super();
// TODO: should copy the arguments here, for safety. This could be a major overhead.
this.c = c;
}
/**
* Compute the value for the function.
*
* <p>This can be explicitly determined by
* <tt>c_n * x^n + ... + c_1 * x + c_0</tt>
* </p>
*
* @param x the point for which the function value should be computed
* @return the value
* @throws MathException if the function couldn't be computed due to
* missing additional data or other environmental problems.
* @see UnivariateRealFunction#value(double)
*/
public double value(double x) throws MathException {
double value = c[0];
for (int i=1; i < c.length; i++ ) {
value += c[i] * Math.pow( x, (int)i);
}
return value;
}
/**
* Compute the value for the first derivative of the function.
*
* <p>This can be explicitly determined by
* <tt>n * c_n * x^(n-1) + ... + 2 * c_2 * x + c_1</tt>
* </p>
*
* @param x the point for which the first derivative should be computed
* @return the value
* @throws MathException if the derivative couldn't be computed.
*/
public double firstDerivative(double x) throws MathException {
double value = c[1];
if ( c.length > 1 ) {
for (int i=2; i < c.length; i++ ) {
value += i * c[i] * Math.pow( x, (int)i-1);
}
}
return value;
}
/**
* Compute the value for the second derivative of the function.
*
* <p>This can be explicitly determined by
* <tt>n * (n-1) * c_n * x^(n-2) + ... + 3 * 2 * c_3 * x + 2 * c_2</tt>
* </p>
*
* @param x the point for which the first derivative should be computed
* @return the value
* @throws MathException if the second derivative couldn't be computed.
*/
public double secondDerivative(double x) throws MathException {
double value = 2.0 * c[2];
if ( c.length > 2 ) {
for (int i=3; i < c.length; i++ ) {
value += i * (i-1) * c[i] * Math.pow( x, (int)i-2);
}
}
return value;
}
/**
* local power function using integer powers.
* <p>The Math.pow() function always returns absolute value,
* and is a bit 'heavier' since it can handle double values
* for the exponential value.</p>
* @param x any double value
* @param n must be 0 or greater
* @return x^n (or 0 if n < 0 ).
* @throws MathException if n < 0.
*/
// private double pow( double x, int n ) throws MathException {
// double value = x;
// if ( n < 0 ) {
// throw new MathException( "power n must be 0 or greater" );
// } else if ( n == 0 ) {
// // x^0 = 1 always.
// value = 1.0;
// } else {
// // only multiply for powers > 1.
// for (int i=1; i < n; i++) {
// value *= x;
// }
// }
// System.out.println("pow:"+x+"^"+n+"="+value);
// return value;
// }
}

View File

@ -62,7 +62,7 @@ import org.apache.commons.math.MathException;
* that derivatives are evaluated after the value, the evaluation algorithm
* should throw an InvalidStateException if it can't cope with this.
*
* @version $Revision: 1.8 $ $Date: 2003/11/14 22:22:17 $
* @version $Revision: 1.9 $ $Date: 2003/11/15 18:44:52 $
*/
public interface UnivariateRealFunction {
/**
@ -74,27 +74,4 @@ public interface UnivariateRealFunction {
*/
public double value(double x) throws MathException;
/**
* Compute the value for the first derivative of the function.
* It is recommended to provide this method only if the first derivative is
* analytical. Numerical derivatives may be acceptable in some cases.
* An implementation should throw an UnsupportedOperationException if
* this method is not implemented.
* @param x the point for which the first derivative should be computed
* @return the value
* @throws MathException if the derivative couldn't be computed.
*/
public double firstDerivative(double x) throws MathException;
/**
* Compute the value for the second derivative of the function.
* It is recommended to provide this method only if the second derivative is
* analytical. Numerical derivatives may be acceptable in some cases.
* An implementation should throw an UnsupportedOperationException if
* this method is not implemented.
* @param x the point for which the first derivative should be computed
* @return the value
* @throws MathException if the second derivative couldn't be computed.
*/
public double secondDerivative(double x) throws MathException;
}

View File

@ -0,0 +1,195 @@
/* ====================================================================
* The Apache Software License, Version 1.1
*
* Copyright (c) 2003 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution, if
* any, must include the following acknowledgement:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgement may appear in the software itself,
* if and wherever such third-party acknowledgements normally appear.
*
* 4. The names "The Jakarta Project", "Commons", and "Apache Software
* Foundation" must not be used to endorse or promote products derived
* from this software without prior written permission. For written
* permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache"
* nor may "Apache" appear in their name without prior written
* permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
package org.apache.commons.math.analysis;
// commons-math
import org.apache.commons.math.MathException;
// junit
import junit.framework.TestCase;
/**
* Tests the PolynomialFunction implementation of a UnivariateRealFunction.
*
* @version $Revision: 1.1 $
* @author Matt Cliff <matt@mattcliff.com>
*/
public final class PolynomialFunctionTest extends TestCase {
// all values are known precisely accept 15 digit precision error
final double error = 1.0e-15;
/**
* tests the value of a constant polynomial.
*
* <p>value of this is 2.5 everywhere.</p>
*/
public void testConstants() throws MathException {
double[] c = { 2.5 };
UnivariateRealFunction f = new PolynomialFunction( c );
// verify that we are equal to c[0] at several (nonsymmetric) places
assertEquals( f.value( 0.0), c[0], error );
assertEquals( f.value( -1.0), c[0], error );
assertEquals( f.value( -123.5), c[0], error );
assertEquals( f.value( 3.0), c[0], error );
assertEquals( f.value( 456.89), c[0], error );
}
/**
* tests the value of a linear polynomial.
*
* <p>This will test the function f(x) = 3*x - 1.5</p>
* <p>This will have the values
* <tt>f(0.0) = -1.5, f(-1.0) = -4.5, f(-2.5) = -9.0,
* f(0.5) = 0.0, f(1.5) = 3.0</tt> and <tt>f(3.0) = 7.5</tt>
* </p>
*/
public void testLinear() throws MathException {
double[] c = { -1.5, 3.0 };
UnivariateRealFunction f = new PolynomialFunction( c );
// verify that we are equal to c[0] when x=0
assertEquals( f.value( 0.0), c[0], error );
// now check a few other places
assertEquals( -4.5, f.value( -1.0), error );
assertEquals( -9.0, f.value( -2.5), error );
assertEquals( 0.0, f.value( 0.5), error );
assertEquals( 3.0, f.value( 1.5), error );
assertEquals( 7.5, f.value( 3.0), error );
}
/**
* Tests a second order polynomial.
* <p> This will test the function f(x) = 2x^2 - 3x -2 = (2x+1)(x-2)</p>
*
*/
public void testQuadratic() throws MathException {
double[] c = { -2.0, -3.0, 2.0 };
UnivariateRealFunction f = new PolynomialFunction( c );
// verify that we are equal to c[0] when x=0
assertEquals( f.value( 0.0), c[0], error );
// now check a few other places
assertEquals( 0.0, f.value( -0.5), error );
assertEquals( 0.0, f.value( 2.0), error );
assertEquals( -2.0, f.value( 1.5), error );
assertEquals( 7.0, f.value( -1.5), error );
assertEquals( 265.5312, f.value( 12.34), error );
}
/**
* This will test the quintic function
* f(x) = x^2(x-5)(x+3)(x-1) = x^5 - 3x^4 -13x^3 + 15x^2</p>
*
*/
public void testQuintic() throws MathException {
double[] c = { 0.0, 0.0, 15.0, -13.0, -3.0, 1.0 };
UnivariateRealFunction f = new PolynomialFunction( c );
// verify that we are equal to c[0] when x=0
assertEquals( f.value( 0.0), c[0], error );
// now check a few other places
assertEquals( 0.0, f.value( 5.0), error );
assertEquals( 0.0, f.value( 1.0), error );
assertEquals( 0.0, f.value( -3.0), error );
assertEquals( 54.84375, f.value( -1.5), error );
assertEquals( -8.06637, f.value( 1.3), error );
}
/**
* tests the derivative function by comparision
*
* <p>This will test the functions
* <tt>f(x) = x^3 - 2x^2 + 6x + 3, g(x) = 3x^2 - 4x + 6</tt>
* and <tt>h(x) = 6x - 4</tt>
*/
public void testDerivativeComparision() throws MathException {
double[] f_coeff = { 3.0, 6.0, -2.0, 1.0 };
double[] g_coeff = { 6.0, -4.0, 3.0 };
double[] h_coeff = { -4.0, 6.0 };
PolynomialFunction f = new PolynomialFunction( f_coeff );
PolynomialFunction g = new PolynomialFunction( g_coeff );
PolynomialFunction h = new PolynomialFunction( h_coeff );
// compare f' = g
assertEquals( f.firstDerivative(0.0), g.value(0.0), error );
assertEquals( f.firstDerivative(1.0), g.value(1.0), error );
assertEquals( f.firstDerivative(100.0), g.value(100.0), error );
assertEquals( f.firstDerivative(4.1), g.value(4.1), error );
assertEquals( f.firstDerivative(-3.25), g.value(-3.25), error );
// compare g' = h
// compare f'' = h
}
}

View File

@ -58,7 +58,7 @@ import org.apache.commons.math.MathException;
/**
* Auxillary class for testing solvers.
*
* @version $Revision: 1.8 $ $Date: 2003/11/14 22:22:17 $
* @version $Revision: 1.9 $ $Date: 2003/11/15 18:44:52 $
*/
public class QuinticFunction implements UnivariateRealFunction {
@ -70,18 +70,9 @@ public class QuinticFunction implements UnivariateRealFunction {
}
/* First derivative of quintic.
* @see org.apache.commons.math.UnivariateRealFunction#firstDerivative(double)
*/
public double firstDerivative(double x) throws MathException {
return (5*x*x-3.75)*x*x+0.25;
}
/* Second order derivative of quintic.
* Unsupported.
* @see org.apache.commons.math.UnivariateRealFunction#secondDerivative(double)
*/
public double secondDerivative(double x) throws MathException {
throw new UnsupportedOperationException();
}
}

View File

@ -63,7 +63,7 @@ import org.apache.commons.math.MathException;
* which means linear approximation (Regula Falsi) will converge
* quadratically.
*
* @version $Revision: 1.8 $ $Date: 2003/11/14 22:22:17 $
* @version $Revision: 1.9 $ $Date: 2003/11/15 18:44:52 $
*/
public class SinFunction implements UnivariateRealFunction {
@ -75,18 +75,9 @@ public class SinFunction implements UnivariateRealFunction {
}
/* First derivative of sinus function
* @see org.apache.commons.math.UnivariateRealFunction#firstDerivative(double)
*/
public double firstDerivative(double x) throws MathException {
return Math.cos(x);
}
/* Second derivative of sinus function.
* Unsupported.
* @see org.apache.commons.math.UnivariateRealFunction#secondDerivative(double)
*/
public double secondDerivative(double x) throws MathException {
throw new UnsupportedOperationException();
}
}