Chebyshev polynomials are defined on the interval ๐ฅ โ [โ1, +1]:
๐โ(๐ฅ) = 1 ๐โ(๐ฅ) = ๐ฅ ๐โ(๐ฅ) = 2๐ฅ ๐โโโ(๐ฅ) โ ๐โโโ(๐ฅ)
๐โ(๐ฅ) = ๐๐๐ (๐ ๐๐๐๐ (๐ฅ))
These are orthogonal:
________ / 0 if n != m
โซโโโบยน ๐โ(๐ฅ)๐โ(๐ฅ) / โ 1 โ ๐ฅยฒ ๐๐ฅ = { ฯ if n = m = 0
\ ฯ/2 if n = m != 0
/ 0 if i != j
โ โโโแดบโปยน ๐แตข(๐ฅโ) ๐โฑผ(๐ฅโ) = { ๐ if i = j = 0
\ ๐/2 if i = j != 0
๐ฅโ = ๐๐๐ ((2๐ + 1) ฯ / (2๐)) ๐ = 0, 1, ... , ๐ โ 1
This is your secret new superpower! Use it to approximate ๐๐ฅ๐(โ๐ฅยฒ). How quickly do coefficients of the Chebyshev series vanish?
So far, we have used Chebyshev polynomials of the first kind, ๐โ(๐ฅ). There are also Chebyshev polynomials of the second kind, ๐โ(๐ฅ):
๐โ(๐ฅ) = 1 ๐โ(๐ฅ) = ๐ฅ ๐โ(๐ฅ) = 2๐ฅ ๐โโโ(๐ฅ) โ ๐โโโ(๐ฅ)
๐โ(๐ฅ) = 1 ๐โ(๐ฅ) = 2๐ฅ ๐โ(๐ฅ) = 2๐ฅ ๐โโโ(๐ฅ) โ ๐โโโ(๐ฅ)
๐โ(๐ฅ) = ๐๐๐ (๐ ๐๐๐๐ (๐ฅ)) ๐โ(๐ฅ) = ๐ ๐๐((๐ + 1) ๐๐๐๐ (๐ฅ)) / ๐ ๐๐(๐๐๐๐ (๐ฅ))
There are similar orthogonality relations for ๐โ(๐ฅ) - check a reference. Moreover, there are relations for derivatives and integrals:
(๐ + 1) ๐โโโ(๐ฅ) โ ๐ฅ๐โ(๐ฅ))
๐๐โ(๐ฅ)/๐๐ฅ = ๐ ๐โโโ(๐ฅ) ๐๐โ(๐ฅ)/๐๐ฅ = -------------------------
(๐ฅยฒ โ 1)
๐โโโ(๐ฅ) ๐โโโ(๐ฅ)
โซ๐โ(๐ฅ)๐๐ฅ = --------- - --------- โซ๐โ(๐ฅ)๐๐ฅ = ๐โโโ(๐ฅ) / (๐ + 1)
2 (๐ + 1) 2 (๐ โ 1)
๐โโโ(๐ฅ) ๐โโโ(๐ฅ)
โซ ๐โ(๐ฅ) ๐๐ฅ = --------- - ---------
2 (๐ + 1) 2 (๐ โ 1)
Use your Chebyshev approximation of ๐๐ฅ๐(โ๐ฅยฒ) to derive the integral of the function.
When this is used for numerical integration of functions, it’s also known as Clenshaw-Curtis quadrature.
You can find the code in C++ in day5-ex1.cxx
.
If you look at the coefficients, every other coefficient is zero because ๐๐ฅ๐(โ๐ฅยฒ) is an even function. One easy way to deal with this is to exploit this symmetry, and use something like ๐๐ฅ๐(โ(2.5 + 2.5๐ฅ)ยฒ) for ๐ฅ > 0 instead.
For high precision work, it’s useful to calculate with higher numerical
precision. One could use the long double
data type in C/C++, or use an
arbitary precision floating point library or calculator (like calc,
see day5-ex1.calc
).
In many applications, you need both sin(x) and cos(x) with ๐ฅ โ [โฯ, ฯ], and you
need it for many different values of x. In the C/C++ standard library, there is
the sincos
function which calculates both simultaneously. Pick one or
more of the following problems:
What’s the accuracy and how does speed compare?
Example code can be found in day5-ex2.cxx
.
In the code, we aim for ๐ช(10โปโท) precision (although not all algorithms reach it). When compiled with g++ (or clang++), results similar to these can be obtained:
routine | error sin/cos | time/call | time/call |
---|---|---|---|
(g++) [ns] | (clang++) [ns] | ||
libc sin/cos | 0/0 | 20.4 | 32.7 |
Cheb. for ๐ฅโ[โฯ,ฯ] | 3.6e-7/3.0e-7 | 33.7 | 3.6 |
Cheb. for sin for ๐ฅโ[0,ฯ] | 3.0e-7/1.9e-4 | 50.1 | 5.4 |
8-fold arg. doubling, Taylor | 8.0e-5/5.6e-5 | 18.7 | 3.3 |
Cheb. for ๐ฅโ[0,ฯ/2] | 9.5e-7/1.3e-6 | 29.8 | 3.7 |
In the code, we aim for ๐ช(10โปโท) precision (although not all algorithms reach it). When compiled with g++ (or clang++), results similar to these can be obtained:
routine | error sin/cos | time/call | time/call |
---|---|---|---|
(g++) [ns] | (clang++) [ns] | ||
libc sin/cos | 0/0 | 20.4 | 32.7 |
Cheb. for ๐ฅโ[โฯ,ฯ] | 3.6e-7/3.0e-7 | 33.7 | 3.6 |
Cheb. for sin for ๐ฅโ[0,ฯ] | 3.0e-7/1.9e-4 | 50.1 | 5.4 |
8-fold arg. doubling, Taylor | 8.0e-5/5.6e-5 | 18.7 | 3.3 |
Cheb. for ๐ฅโ[0,ฯ/2] | 9.5e-7/1.3e-6 | 29.8 | 3.7 |
Observations: