using Plots
"""
Compute the divided difference tables to get the Newton coefficients.
This function stores the whole table for pedagogical reasons, not
a good general purpose implementation.
The final set of coefficients to use are those on the diagonal
"""
function compute_newton_coeffs(xi,fi)
npts = length(xi)
T = zeros(npts,npts)
T[:,1] = fi # the first column becomes fi.
for j=2:npts
for i=j:npts
# the value in the table is
# made by looking left (i,j-1) and left-up (i-1,j-1)
# divided by the region x_i - ...
T[i,j] = (T[i,j-1] - T[i-1,j-1])/(xi[i] - xi[i-j+1])
end
end
return T
end
# This is the example from Gautschi, page 96
# f(x) = 3+x^2
xi = [0., 1., 2., 4., 8. ]
fi = [3., 4., 7., 19., 67.]
compute_newton_coeffs(xi,fi)
function newton_interp(xx,xi,fi)
T = compute_newton_coeffs(xi,fi)
xv = ones(size(xx))
f = T[1,1] .* xv
for i=2:size(T,1)
xv = xv .* (xx .- xi[i-1])
f += T[i,i] * xv
end
f
end
# Reuse the same example
xx = collect(range(-1.,stop=5.,length=100));
plot(xx,newton_interp(xx,xi,fi))
The next scenario is fun because it's reflective of what might happen in an experiment.
fun(x) = 3 .+ 0.5*x.^2 .+ exp.(-x)
h = 0.000001
#xi = [1.;2 .+ collect(range(0.,stop=0.00001,length=3)); 3.; 4.; ]
xi = [1.;2 .+ collect(range(0.,stop=h,length=3)); 3.; 4.; ]
fi = fun(xi)
@show xi
T = compute_newton_coeffs(xi,fi)
As the points get closer (i.e. change h above from 0.1 to 0.00001), the entries in the table become the same (to a few decimal points. We will see that these points actually become the derivatives!
# What is the derivative of $fun(x) at x=2$?
fprime = 2-exp(-2)
T[3,2]
plot(xx,newton_interp(xx,xi,fi))