using Plots
"""
Evaluate the polynomial interpolant in Lagrange form.
xi is a vector of length n+1
fi are the values f(xi) for each point xi
x is the value where we compute
p(x)
which is the degree n+1 polynomial interpolating f at each point xi
The values xi must be distinct
Note that x can be a matrix or vector
"""
function lagrange_interp(x, xi, fi)
f = zeros(size(x))
for i=1:length(fi)
elli = ones(size(x))
for j=1:length(xi)
if i==j continue; end
elli = elli.*(x .- xi[j])/(xi[i] - xi[j])
end
f = f + fi[i]*elli
end
return f
end
# The polynomial
fi = [2,.33,-1];
xi = [1,2,3];
xx = collect(range(0,stop=4,length=100))
plot(xx,lagrange_interp(xx,xi,fi))
scatter!(xi,fi,marker=:diamond)
lagrange_interp([2],xi,fi)
function compute_barycentric_weights(xi)
ws = zeros(size(xi))
for i=1:length(xi)
w = 1
# TODO, add check if x == xi, and just return fi in that case.
for j=1:length(xi)
if j==i continue; end
w = w*1 ./ (xi[i] - xi[j]);
end
ws[i] = w;
end
return ws
end
function barycentric_interp_with_weights(x,xi,fi,wi)
fnumer = zeros(size(x))
fdenom = zeros(size(x))
for i=1:length(xi)
fnumer += fi[i] .* wi[i] ./ (x .- xi[i])
fdenom += wi[i] ./ (x .- xi[i])
end
f = fnumer./fdenom
end
function barycentric_interp(x,xi,fi)
return barycentric_interp_with_weights(x,xi,fi,compute_barycentric_weights(xi))
end
# The polynomial
fi = [2,3,6];
xi = [1,2,3];
xx = collect(range(0,stop=4,length=100));
plot(xx,barycentric_interp(xx,xi,fi))
barycentric_interp([nextfloat(2.0)],xi,fi)
# show Trefethen's demo
fun(x) = abs.(x) + .5 .* x- x.^2;
n = 10
xi = cos.(pi .* (0:n)./n);
fi = fun(xi)
xx = range(-1,stop=1,length=5000)
plot(xx,barycentric_interp(xx,xi,fi))
scatter!(xi,fi)
using Blink,Interact
fun(x) = abs.(x) + .5 .* x- x.^2;
ui = @manipulate for n=10:10:1000
xi = cos.(pi*(0:n)/n);
fi = fun(xi)
xx = collect(range(-1,stop=1,length=5000))
plot(xx,barycentric_interp(xx,xi,fi))
plot!(xi,fi,seriestype = :scatter,markersize=1.)
end
w = Window()
body!(w, ui)
fun(x) = abs.(x) + .5 .* x- x.^2;
ui2 = @manipulate for n=5:5:50
xi = collect(-1.:(2/n):1.)
fi = fun(xi)
xx = collect(range(-1,stop=1,length=5000))
plot(xx,barycentric_interp(xx,xi,fi))
plot!(xi,fi,seriestype = :scatter,markersize=1.)
ylims!(-1.,1.)
end
w2 = Window()
body!(w2, ui2)