Concept
The basis function defined as
where is given point then
Also we can define as
Codes
Lagrange interpolation
import numpy as np
def lagrange(t_vals, f_vals, t):
"""
`t_vals`: argument values used to construct the interpolants.
`f_vals`: function values used to construct the interpolants.
`t`: Values at which to evaluate the interpolant
"""
m = len(t_vals)
res = np.empty_like(t)
for i in range(len(t)):
res[i] = 0
for j in range(m):
sum_up = 1
sum_down = 1
for k in range(m):
if k != j:
sum_up *= t[i] - t_vals[k]
sum_down *= t_vals[j] - t_vals[k]
res[i] += sum_up * f_vals[j] / sum_down
return res
Fast Lagrange interpolation
import numpy as np
def update_w(w, old_m, m):
for j in range(old_m):
for k in range(old_m, m):
if j != k:
w[j] = w[j] / (t_vals[j] - t_vals[k])
for j in range(old_m, m):
w[j] = 1
for k in range(m):
if j != k:
w[j] *= t_vals[j] - t_vals[k]
w[j] = 1 / w[j]
return w
def improved_lagrange(t_vals, f_vals, t):
m = len(t_vals)
res = np.empty_like(t)
for i in range(len(t)):
w = np.empty_like(f_vals)
w = update_w(w, 0, m)
right = 1
for j in range(0, m):
right *= t[i] - t_vals[j]
s = 0
for j in range(m):
s += f_vals[j] * w[j] / (t[i] - t_vals[j])
res[i] = right * s
return res
barycentric Lagrange interpolation
import numpy as np
def update_w(w, old_m, m):
for j in range(old_m):
for k in range(old_m, m):
if j != k:
w[j] = w[j] / (t_vals[j] - t_vals[k])
for j in range(old_m, m):
w[j] = 1
for k in range(m):
if j != k:
w[j] *= t_vals[j] - t_vals[k]
w[j] = 1 / w[j]
return w
def barycentric(t_vals, f_vals, t):
res = np.empty_like(t)
m = len(t_vals)
for i in range(len(t)):
w = np.empty_like(f_vals)
w = update_w(w, 0, m)
s_up = 0
s_down = 0
for j in range(m):
s_up += w[j] * f_vals[j] / (t[i] - t_vals[j])
s_down += w[j] / (t[i] - t_vals[j])
res[i] = s_up / s_down
return res
Lagrange with Newton table
import numpy as np
def lagrange(t_vals, f_vals, t):
def newton_table(x, y, m):
x = np.copy(x[:m])
a = np.copy(y[:m])
for k in range(1, m):
a[k:m] = (a[k:m] - a[k - 1]) / (x[k:m] - x[k - 1])
return a
res = np.empty_like(t)
m = len(t_vals)
for i in range(len(t)):
tab = newton_table(t_vals, f_vals, m)
right = np.empty_like(t_vals)
right[0] = 1
for iii in range(1, m):
right[iii] = right[iii - 1] * (t[i] - t_vals[iii - 1])
res[i] = tab @ right[:m].T
return res