001: /*
002: * Copyright 2003-2004 The Apache Software Foundation.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: package org.apache.commons.math.analysis;
017:
018: import java.io.Serializable;
019:
020: /**
021: * Immutable representation of a real polynomial function with real coefficients.
022: * <p>
023: * <a href="http://mathworld.wolfram.com/HornersMethod.html">Horner's Method</a>
024: * is used to evaluate the function.
025: *
026: * @version $Revision: 348519 $ $Date: 2005-11-23 12:12:18 -0700 (Wed, 23 Nov 2005) $
027: */
028: public class PolynomialFunction implements
029: DifferentiableUnivariateRealFunction, Serializable {
030:
031: /** Serializable version identifier */
032: private static final long serialVersionUID = 3322454535052136809L;
033:
034: /**
035: * The coefficients of the polynomial, ordered by degree -- i.e.,
036: * coefficients[0] is the constant term and coefficients[n] is the
037: * coefficient of x^n where n is the degree of the polynomial.
038: */
039: private double coefficients[];
040:
041: /**
042: * Construct a polynomial with the given coefficients. The first element
043: * of the coefficients array is the constant term. Higher degree
044: * coefficients follow in sequence. The degree of the resulting polynomial
045: * is the length of the array minus 1.
046: * <p>
047: * The constructor makes a copy of the input array and assigns the copy to
048: * the coefficients property.
049: *
050: * @param c polynominal coefficients
051: * @throws NullPointerException if c is null
052: * @throws IllegalArgumentException if c is empty
053: */
054: public PolynomialFunction(double c[]) {
055: super ();
056: if (c.length < 1) {
057: throw new IllegalArgumentException(
058: "Polynomial coefficient array must have postive length.");
059: }
060: this .coefficients = new double[c.length];
061: System.arraycopy(c, 0, this .coefficients, 0, c.length);
062: }
063:
064: /**
065: * Compute the value of the function for the given argument.
066: * <p>
067: * The value returned is <br>
068: * <code>coefficients[n] * x^n + ... + coefficients[1] * x + coefficients[0]</code>
069: *
070: * @param x the argument for which the function value should be computed
071: * @return the value of the polynomial at the given point
072: * @see UnivariateRealFunction#value(double)
073: */
074: public double value(double x) {
075: return evaluate(coefficients, x);
076: }
077:
078: /**
079: * Returns the degree of the polynomial
080: *
081: * @return the degree of the polynomial
082: */
083: public int degree() {
084: return coefficients.length - 1;
085: }
086:
087: /**
088: * Returns a copy of the coefficients array.
089: * <p>
090: * Changes made to the returned copy will not affect the coefficients of
091: * the polynomial.
092: *
093: * @return a fresh copy of the coefficients array
094: */
095: public double[] getCoefficients() {
096: double[] out = new double[coefficients.length];
097: System.arraycopy(coefficients, 0, out, 0, coefficients.length);
098: return out;
099: }
100:
101: /**
102: * Uses Horner's Method to evaluate the polynomial with the given coefficients at
103: * the argument.
104: *
105: * @param coefficients the coefficients of the polynomial to evaluate
106: * @param argument the input value
107: * @return the value of the polynomial
108: * @throws IllegalArgumentException if coefficients is empty
109: * @throws NullPointerException if coefficients is null
110: */
111: protected static double evaluate(double[] coefficients,
112: double argument) {
113: int n = coefficients.length;
114: if (n < 1) {
115: throw new IllegalArgumentException(
116: "Coefficient array must have positive length for evaluation");
117: }
118: double result = coefficients[n - 1];
119: for (int j = n - 2; j >= 0; j--) {
120: result = argument * result + coefficients[j];
121: }
122: return result;
123: }
124:
125: /**
126: * Returns the coefficients of the derivative of the polynomial with the given coefficients.
127: *
128: * @param coefficients the coefficients of the polynomial to differentiate
129: * @return the coefficients of the derivative or null if coefficients has length 1.
130: * @throws IllegalArgumentException if coefficients is empty
131: * @throws NullPointerException if coefficients is null
132: */
133: protected static double[] differentiate(double[] coefficients) {
134: int n = coefficients.length;
135: if (n < 1) {
136: throw new IllegalArgumentException(
137: "Coefficient array must have positive length for differentiation");
138: }
139: if (n == 1) {
140: return new double[] { 0 };
141: }
142: double[] result = new double[n - 1];
143: for (int i = n - 1; i > 0; i--) {
144: result[i - 1] = (double) i * coefficients[i];
145: }
146: return result;
147: }
148:
149: /**
150: * Returns the derivative as a PolynomialRealFunction
151: *
152: * @return the derivative polynomial
153: */
154: public PolynomialFunction polynomialDerivative() {
155: return new PolynomialFunction(differentiate(coefficients));
156: }
157:
158: /**
159: * Returns the derivative as a UnivariateRealFunction
160: *
161: * @return the derivative function
162: */
163: public UnivariateRealFunction derivative() {
164: return polynomialDerivative();
165: }
166:
167: }
|