30
30
* The approximated function should be smooth enough for Lagrange polynomial
31
31
* to work well. Otherwise, consider using splines instead.</p>
33
* @version $Revision: 799857 $ $Date: 2009-08-01 09:07:12 -0400 (Sat, 01 Aug 2009) $
33
* @version $Revision: 922708 $ $Date: 2010-03-13 20:15:47 -0500 (Sat, 13 Mar 2010) $
36
36
public class PolynomialFunctionLagrangeForm implements UnivariateRealFunction {
39
39
* The coefficients of the polynomial, ordered by degree -- i.e.
40
* coefficients[0] is the constant term and coefficients[n] is the
40
* coefficients[0] is the constant term and coefficients[n] is the
41
41
* coefficient of x^n where n is the degree of the polynomial.
43
43
private double coefficients[];
46
* Interpolating points (abscissas) and the function values at these points.
48
private double x[], y[];
46
* Interpolating points (abscissas).
48
private final double x[];
51
* Function values at interpolating points.
53
private final double y[];
51
56
* Whether the polynomial coefficients are available.
57
62
* values. The order of interpolating points are not important.
59
64
* The constructor makes copy of the input arrays and assigns them.</p>
61
66
* @param x interpolating points
62
67
* @param y function values at interpolating points
63
68
* @throws IllegalArgumentException if input arrays are not valid
102
107
* Returns a copy of the interpolating points array.
104
109
* Changes made to the returned copy will not affect the polynomial.</p>
106
111
* @return a fresh copy of the interpolating points array
108
113
public double[] getInterpolatingPoints() {
115
120
* Returns a copy of the interpolating values array.
117
122
* Changes made to the returned copy will not affect the polynomial.</p>
119
124
* @return a fresh copy of the interpolating values array
121
126
public double[] getInterpolatingValues() {
128
133
* Returns a copy of the coefficients array.
130
135
* Changes made to the returned copy will not affect the polynomial.</p>
137
* Note that coefficients computation can be ill-conditioned. Use with caution
138
* and only when it is necessary.</p>
132
140
* @return a fresh copy of the coefficients array
134
142
public double[] getCoefficients() {
158
166
public static double evaluate(double x[], double y[], double z) throws
159
167
DuplicateSampleAbscissaException, IllegalArgumentException {
161
int i, j, n, nearest = 0;
162
double value, c[], d[], tc, td, divider, w, dist, min_dist;
164
169
verifyInterpolationArray(x, y);
169
min_dist = Double.POSITIVE_INFINITY;
170
for (i = 0; i < n; i++) {
172
final int n = x.length;
173
final double[] c = new double[n];
174
final double[] d = new double[n];
175
double min_dist = Double.POSITIVE_INFINITY;
176
for (int i = 0; i < n; i++) {
171
177
// initialize the difference arrays
174
180
// find out the abscissa closest to z
175
dist = Math.abs(z - x[i]);
181
final double dist = Math.abs(z - x[i]);
176
182
if (dist < min_dist) {
182
188
// initial approximation to the function value at z
189
double value = y[nearest];
185
for (i = 1; i < n; i++) {
186
for (j = 0; j < n-i; j++) {
189
divider = x[j] - x[i+j];
191
for (int i = 1; i < n; i++) {
192
for (int j = 0; j < n-i; j++) {
193
final double tc = x[j] - z;
194
final double td = x[i+j] - z;
195
final double divider = x[j] - x[i+j];
190
196
if (divider == 0.0) {
191
197
// This happens only when two abscissas are identical.
192
198
throw new DuplicateSampleAbscissaException(x[i], i, i+j);
194
200
// update the difference arrays
195
w = (c[j+1] - d[j]) / divider;
201
final double w = (c[j+1] - d[j]) / divider;
218
224
* @throws ArithmeticException if any abscissas coincide
220
226
protected void computeCoefficients() throws ArithmeticException {
222
double c[], tc[], d, t;
228
final int n = degree() + 1;
225
229
coefficients = new double[n];
226
for (i = 0; i < n; i++) {
230
for (int i = 0; i < n; i++) {
227
231
coefficients[i] = 0.0;
230
234
// c[] are the coefficients of P(x) = (x-x[0])(x-x[1])...(x-x[n-1])
235
final double[] c = new double[n+1];
233
for (i = 0; i < n; i++) {
234
for (j = i; j > 0; j--) {
237
for (int i = 0; i < n; i++) {
238
for (int j = i; j > 0; j--) {
235
239
c[j] = c[j-1] - c[j] * x[i];
242
for (i = 0; i < n; i++) {
245
final double[] tc = new double[n];
246
for (int i = 0; i < n; i++) {
243
247
// d = (x[i]-x[0])...(x[i]-x[i-1])(x[i]-x[i+1])...(x[i]-x[n-1])
245
for (j = 0; j < n; j++) {
249
for (int j = 0; j < n; j++) {
263
final double t = y[i] / d;
260
264
// Lagrange polynomial is the sum of n terms, each of which is a
261
265
// polynomial of degree n-1. tc[] are the coefficients of the i-th
262
266
// numerator Pi(x) = (x-x[0])...(x-x[i-1])(x-x[i+1])...(x-x[n-1]).
263
267
tc[n-1] = c[n]; // actually c[n] = 1
264
268
coefficients[n-1] += t * tc[n-1];
265
for (j = n-2; j >= 0; j--) {
269
for (int j = n-2; j >= 0; j--) {
266
270
tc[j] = c[j+1] + tc[j+1] * x[i];
267
271
coefficients[j] += t * tc[j];
275
279
* Verifies that the interpolation arrays are valid.
281
* The arrays features checked by this method are that both arrays have the
282
* same length and this length is at least 2.
277
285
* The interpolating points must be distinct. However it is not
278
* verified here, it is checked in evaluate() and computeCoefficients().</p>
286
* verified here, it is checked in evaluate() and computeCoefficients().
280
289
* @param x the interpolating points array
281
290
* @param y the interpolating values array
282
291
* @throws IllegalArgumentException if not valid
283
292
* @see #evaluate(double[], double[], double)
284
293
* @see #computeCoefficients()
286
public static void verifyInterpolationArray(double x[], double y[]) throws
287
IllegalArgumentException {
295
public static void verifyInterpolationArray(double x[], double y[])
296
throws IllegalArgumentException {
289
if (Math.min(x.length, y.length) < 2) {
290
throw MathRuntimeException.createIllegalArgumentException(
291
"{0} points are required, got only {1}",
292
2, Math.min(x.length, y.length));
294
298
if (x.length != y.length) {
295
299
throw MathRuntimeException.createIllegalArgumentException(
296
300
"dimension mismatch {0} != {1}", x.length, y.length);
304
throw MathRuntimeException.createIllegalArgumentException(
305
"{0} points are required, got only {1}", 2, x.length);