Concept

basically in order to use orthogonal polynomial for interpolation, we setup the orthogonal polynomial coefficient matrix with selected polynomials and solve it for coefficients.

𝐴=[𝑃0(𝑥0)𝑃0(𝑥1)𝑃0(𝑥𝑛1)𝑃1(𝑥0)𝑃1(𝑥1)𝑃1(𝑥𝑛1)𝑃𝑛1(𝑥0)𝑃𝑛1(𝑥1)𝑃𝑛1(𝑥𝑛1)] 𝐴𝑐=𝑏

Or we can use

𝑝𝑛1(𝑥)=𝑗=1𝑐𝑗𝑃𝑗(𝑥)

where 𝑃 is the selected polynomial. Then

𝑐𝑗=(𝑓,𝑃𝑗)𝑤(𝑃𝑗,𝑃𝑗)𝑤=11𝑤(𝑥)𝑓(𝑥)𝑃𝑗(𝑥)𝑑𝑥11𝑤(𝑥)𝑃2𝑗(𝑥)𝑑𝑥=11𝑤(𝑥)𝑓(𝑥)𝑃𝑗(𝑥)𝑑𝑥𝑃𝑗2

where (𝑓,𝑃𝑗)𝑤 is weighted inner-product.

interpolation error

𝑓𝑝=𝑓(𝑛)(𝜉)𝑛!𝑞(𝑥)

where

𝑞(𝑥)=(𝑥𝑥1)(𝑥𝑥2)(𝑥𝑥𝑛)

Crude Error

assume 𝑡1<𝑡2<<𝑡𝑛 we have

max|𝑓(𝑡)𝑝𝑛1(𝑡)|𝑀𝑛4𝑛

where =max𝑖Δ𝑡𝑖 and 𝑀 is constant with |𝑓(𝑛)|𝑀.

Code

import numpy as np
 
def T(j, x):
    """Compute Chebyshev polynomial T_j(x) = cos(j * arccos(x))"""
    return np.cos(j * np.arccos(x))
 
def chebyshev_interp(f, n, t):
    """
    Use Chebyshev polynomials T_j(x) and Gauss-Chebyshev quadrature
    to interpolate function f on interval [-1, 1].
    
    f: function to interpolate
    n: number of basis functions
    t: array of evaluation points
    """
    # chebyshev_nodes
    x_nodes = np.empty(n)
    for i in range(n):
        x_nodes[i] = np.cos((2 * i + 1) * np.pi / (2 * n))
    
    f_vals = np.empty(n)
    for i in range(n):
        f_vals[i] = f(x_nodes[i])
    
    coeffs = np.empty(n)
    for j in range(n):
        num = 0
        denom = 0
        for i in range(n):
            Tij = T(j, x_nodes[i])
            num += f_vals[i] * Tij
            denom += Tij * Tij
        num *= np.pi / n
        denom *= np.pi / n
        coeffs[j] = num / denom
    
    res = np.empty_like(t)
    for i in range(len(t)):
        s = 0
        for j in range(n):
            s += coeffs[j] * T(j, t[i])
        res[i] = s
    
    return res