/*******************************************************************************
 * Copyright (c) 2010 Haifeng Li
 *   
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *  
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *******************************************************************************/

package smile.interpolation;

/**
 * Cubic spline interpolation. Spline interpolation uses low-degree polynomials
 * in each of the intervals, and chooses the polynomial pieces such that they
 * fit smoothly together. The resulting function is called a spline.
 * 

* The natural cubic spline is piecewise cubic and twice continuously * differentiable. Furthermore, its second derivative is zero at the end * points. *

* Like polynomial interpolation, spline interpolation incurs a smaller * error than linear interpolation and the interpolant is smoother. However, * the interpolant is easier to evaluate than the high-degree polynomials * used in polynomial interpolation. It also does not suffer from Runge's * phenomenon. * * @author Haifeng Li */ public class CubicSplineInterpolation1D extends AbstractInterpolation { /** * Second derivatives of the interpolating function at the tabulated points. */ private double[] y2; /** * Constructor. */ public CubicSplineInterpolation1D(double[] x, double[] y) { super(x, y); y2 = new double[x.length]; sety2(x, y); } @Override double rawinterp(int j, double x) { int klo = j, khi = j + 1; double h = xx[khi] - xx[klo]; if (h == 0.0) { throw new IllegalArgumentException("Nearby control points take same x value: " + xx[khi]); } double a = (xx[khi] - x) / h; double b = (x - xx[klo]) / h; double y = a * yy[klo] + b * yy[khi] + ((a * a * a - a) * y2[klo] + (b * b * b - b) * y2[khi]) * (h * h) / 6.0; return y; } /** * Calculate the second derivatives of the interpolating function at the * tabulated points. At the endpoints, we use a natural spline * with zero second derivative on that boundary. */ private void sety2(double[] x, double[] y) { double p, qn, sig, un; double[] u = new double[n - 1]; y2[0] = u[0] = 0.0; for (int i = 1; i < n - 1; i++) { sig = (x[i] - x[i - 1]) / (x[i + 1] - x[i - 1]); p = sig * y2[i - 1] + 2.0; y2[i] = (sig - 1.0) / p; u[i] = (y[i + 1] - y[i]) / (x[i + 1] - x[i]) - (y[i] - y[i - 1]) / (x[i] - x[i - 1]); u[i] = (6.0 * u[i] / (x[i + 1] - x[i - 1]) - sig * u[i - 1]) / p; } qn = un = 0.0; y2[n - 1] = (un - qn * u[n - 2]) / (qn * y2[n - 2] + 1.0); for (int k = n - 2; k >= 0; k--) { y2[k] = y2[k] * y2[k + 1] + u[k]; } } }

Ads help maintain this website.