-
-
Save cmaes/1269709 to your computer and use it in GitHub Desktop.
function cubic_driver(num_points) | |
% cubic_driver(n) computes a cubic spline | |
% interpolant of the runge function | |
% | |
% f(x) = 1/(1+25*x^2) | |
% | |
% based on n linearly spaced | |
% points in the interval [-1,1] | |
runge = @(x) 1./(1+ 25*x.^2); | |
x = linspace(-1,1,num_points); | |
y = runge(x); | |
[s0,s1,s2,s3] = cubic_spline(x',y'); | |
plot_points = 1000; | |
xx = linspace(-1,1,plot_points); | |
yy = runge(xx); | |
plot(xx,yy,'g'); | |
hold on; | |
plot_cubic_spline(x,s0,s1,s2,s3); | |
function [s0,s1,s2,s3]=cubic_spline(x,y) | |
% [s0,s1,s2,s3]=cubic_spline(x,y) | |
% | |
% computes the coefficents of a cubic spline | |
% interpolant through the data points (x,y) | |
% | |
% The spline is defined as the piecewise cubic | |
% polynomial | |
% | |
% S(x) = { Sk(x) x(k) <= x <= x(k+1) | |
% = { 0 otherwise | |
% | |
% The cubic polynomial Sk(x) is given by | |
% | |
% Sk(x) = sk0 + sk1*(x-x(k)) + sk2*(x-x(k))^2 + sk3*(x-x(k))^3 | |
% | |
% The coefficents sk0, sk1, sk2, and sk3 for each of the | |
% polynomials are returned in the vectors s0,s1,s2, and s3 | |
% respectively. | |
if any(size(x) ~= size(y)) || size(x,2) ~= 1 | |
error('inputs x and y must be column vectors of equal length'); | |
end | |
n = length(x) | |
h = x(2:n) - x(1:n-1); | |
d = (y(2:n) - y(1:n-1))./h; | |
lower = h(1:end-1); | |
main = 2*(h(1:end-1) + h(2:end)); | |
upper = h(2:end); | |
T = spdiags([lower main upper], [-1 0 1], n-2, n-2); | |
rhs = 6*(d(2:end)-d(1:end-1)); | |
m = T\rhs; | |
% Use natural boundary conditions where second derivative | |
% is zero at the endpoints | |
m = [ 0; m; 0]; | |
s0 = y; | |
s1 = d - h.*(2*m(1:end-1) + m(2:end))/6; | |
s2 = m/2; | |
s3 =(m(2:end)-m(1:end-1))./(6*h); |
function plot_cubic_spline(x,s0,s1,s2,s3) | |
% plot_cubic_spline(x,s0,s1,s2,s3) | |
% | |
% plots a cubic spline with break points x | |
% and coefficents s0, s1, s2, s3 | |
n = length(x); | |
inner_points = 20; | |
for i=1:n-1 | |
xx = linspace(x(i),x(i+1),inner_points); | |
xi = repmat(x(i),1,inner_points); | |
yy = s0(i) + s1(i)*(xx-xi) + ... | |
s2(i)*(xx-xi).^2 + s3(i)*(xx - xi).^3; | |
plot(xx,yy,'b') | |
plot(x(i),0,'r'); | |
end |
Hi
thanks for the code, however when i run it with an example of mine it does not coincide. I found
https://stackoverflow.com/questions/7642921/cubic-spline-program
lower = h(2:end);
main = 2*(h(1:end-1) + h(2:end));
upper = h(1:end-1);
which gives the correct result. Could you please correct here also?
Your code and my calculations do not agree with matlab. here is a simple example
x=[-3 -2 1 4 6]
y=[2 0 3 1 4]
[s0,s1,s2,s3]=cubic_spline(x',y')
comment the length of the vectors is not consistent
s3 s2 s1 s0
0.5044 0 -2.5044 2.0000
-0.2831 1.5132 -0.9912 0
0.2217 -1.0351 0.4430 3.0000
-0.1601 0.9605 0.2193 1.0000
however matlab gives using
clear all
x=[-3 -2 1 4 6]
y=[2 0 3 1 4]
pspl=spline(x,[0 y 0])
[breaks,coefs,l,k,d] = unmkpp(pspl)
s3 s2 s1 s0
2.0595 -4.0595 0 2.0000
-0.3796 2.1190 -1.9405 0
0.3003 -1.2976 0.5238 3.0000
-0.5387 1.4048 0.8452 1.0000
any ideas why this is so?
thanks
Uwe Brauer
A tiny Matlab implementation of cubic spline interpolation, based on work done for the 18.310 class at MIT. This gist was motivated by the answer to this question on stack overflow.