3 <meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
4 <title>Chebyshev Polynomials</title>
5 <link rel="stylesheet" href="../../math.css" type="text/css">
6 <meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
7 <link rel="home" href="../../index.html" title="Math Toolkit 2.11.0">
8 <link rel="up" href="../sf_poly.html" title="Polynomials">
9 <link rel="prev" href="hermite.html" title="Hermite Polynomials">
10 <link rel="next" href="sph_harm.html" title="Spherical Harmonics">
12 <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
13 <table cellpadding="2" width="100%"><tr>
14 <td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../boost.png"></td>
15 <td align="center"><a href="../../../../../../index.html">Home</a></td>
16 <td align="center"><a href="../../../../../../libs/libraries.htm">Libraries</a></td>
17 <td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
18 <td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
19 <td align="center"><a href="../../../../../../more/index.htm">More</a></td>
22 <div class="spirit-nav">
23 <a accesskey="p" href="hermite.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../sf_poly.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="sph_harm.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>
26 <div class="titlepage"><div><div><h3 class="title">
27 <a name="math_toolkit.sf_poly.chebyshev"></a><a class="link" href="chebyshev.html" title="Chebyshev Polynomials">Chebyshev Polynomials</a>
28 </h3></div></div></div>
30 <a name="math_toolkit.sf_poly.chebyshev.h0"></a>
31 <span class="phrase"><a name="math_toolkit.sf_poly.chebyshev.synopsis"></a></span><a class="link" href="chebyshev.html#math_toolkit.sf_poly.chebyshev.synopsis">Synopsis</a>
33 <pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">math</span><span class="special">/</span><span class="identifier">special_functions</span><span class="special">/</span><span class="identifier">chebyshev</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
35 <pre class="programlisting"><span class="keyword">namespace</span> <span class="identifier">boost</span><span class="special">{</span> <span class="keyword">namespace</span> <span class="identifier">math</span><span class="special">{</span>
37 <span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">Real1</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">Real2</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">Real3</span><span class="special">></span>
38 <a class="link" href="../result_type.html" title="Calculation of the Type of the Result"><span class="emphasis"><em>calculated-result-type</em></span></a> <span class="identifier">chebyshev_next</span><span class="special">(</span><span class="identifier">Real1</span> <span class="keyword">const</span> <span class="special">&</span> <span class="identifier">x</span><span class="special">,</span> <span class="identifier">Real2</span> <span class="keyword">const</span> <span class="special">&</span> <span class="identifier">Tn</span><span class="special">,</span> <span class="identifier">Real3</span> <span class="keyword">const</span> <span class="special">&</span> <span class="identifier">Tn_1</span><span class="special">);</span>
40 <span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">Real</span><span class="special">></span>
41 <a class="link" href="../result_type.html" title="Calculation of the Type of the Result"><span class="emphasis"><em>calculated-result-type</em></span></a> <span class="identifier">chebyshev_t</span><span class="special">(</span><span class="keyword">unsigned</span> <span class="identifier">n</span><span class="special">,</span> <span class="identifier">Real</span> <span class="keyword">const</span> <span class="special">&</span> <span class="identifier">x</span><span class="special">);</span>
43 <span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">Real</span><span class="special">,</span> <span class="keyword">class</span> <a class="link" href="../../policy.html" title="Chapter 20. Policies: Controlling Precision, Error Handling etc">Policy</a><span class="special">></span>
44 <a class="link" href="../result_type.html" title="Calculation of the Type of the Result"><span class="emphasis"><em>calculated-result-type</em></span></a> <span class="identifier">chebyshev_t</span><span class="special">(</span><span class="keyword">unsigned</span> <span class="identifier">n</span><span class="special">,</span> <span class="identifier">Real</span> <span class="keyword">const</span> <span class="special">&</span> <span class="identifier">x</span><span class="special">,</span> <span class="keyword">const</span> <a class="link" href="../../policy.html" title="Chapter 20. Policies: Controlling Precision, Error Handling etc">Policy</a><span class="special">&);</span>
46 <span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">Real</span><span class="special">></span>
47 <a class="link" href="../result_type.html" title="Calculation of the Type of the Result"><span class="emphasis"><em>calculated-result-type</em></span></a> <span class="identifier">chebyshev_u</span><span class="special">(</span><span class="keyword">unsigned</span> <span class="identifier">n</span><span class="special">,</span> <span class="identifier">Real</span> <span class="keyword">const</span> <span class="special">&</span> <span class="identifier">x</span><span class="special">);</span>
49 <span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">Real</span><span class="special">,</span> <span class="keyword">class</span> <a class="link" href="../../policy.html" title="Chapter 20. Policies: Controlling Precision, Error Handling etc">Policy</a><span class="special">></span>
50 <a class="link" href="../result_type.html" title="Calculation of the Type of the Result"><span class="emphasis"><em>calculated-result-type</em></span></a> <span class="identifier">chebyshev_u</span><span class="special">(</span><span class="keyword">unsigned</span> <span class="identifier">n</span><span class="special">,</span> <span class="identifier">Real</span> <span class="keyword">const</span> <span class="special">&</span> <span class="identifier">x</span><span class="special">,</span> <span class="keyword">const</span> <a class="link" href="../../policy.html" title="Chapter 20. Policies: Controlling Precision, Error Handling etc">Policy</a><span class="special">&);</span>
52 <span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">Real</span><span class="special">></span>
53 <a class="link" href="../result_type.html" title="Calculation of the Type of the Result"><span class="emphasis"><em>calculated-result-type</em></span></a> <span class="identifier">chebyshev_t_prime</span><span class="special">(</span><span class="keyword">unsigned</span> <span class="identifier">n</span><span class="special">,</span> <span class="identifier">Real</span> <span class="keyword">const</span> <span class="special">&</span> <span class="identifier">x</span><span class="special">);</span>
55 <span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">Real1</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">Real2</span><span class="special">></span>
56 <a class="link" href="../result_type.html" title="Calculation of the Type of the Result"><span class="emphasis"><em>calculated-result-type</em></span></a> <span class="identifier">chebyshev_clenshaw_recurrence</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">Real</span><span class="special">*</span> <span class="keyword">const</span> <span class="identifier">c</span><span class="special">,</span> <span class="identifier">size_t</span> <span class="identifier">length</span><span class="special">,</span> <span class="identifier">Real2</span> <span class="identifier">x</span><span class="special">);</span>
58 <span class="special">}}</span> <span class="comment">// namespaces</span>
61 <span class="emphasis"><em>"Real analysts cannot do without Fourier, complex analysts
62 cannot do without Laurent, and numerical analysts cannot do without Chebyshev"</em></span>
66 The Chebyshev polynomials of the first kind are defined by the recurrence
67 <span class="emphasis"><em>T</em></span><sub>n+1</sub>(<span class="emphasis"><em>x</em></span>) := <span class="emphasis"><em>2xT</em></span><sub>n</sub>(<span class="emphasis"><em>x</em></span>)
68 - <span class="emphasis"><em>T</em></span><sub>n-1</sub>(<span class="emphasis"><em>x</em></span>), <span class="emphasis"><em>n > 0</em></span>,
69 where <span class="emphasis"><em>T</em></span><sub>0</sub>(<span class="emphasis"><em>x</em></span>) := 1 and <span class="emphasis"><em>T</em></span><sub>1</sub>(<span class="emphasis"><em>x</em></span>)
70 := <span class="emphasis"><em>x</em></span>. These can be calculated in Boost using the following
73 <pre class="programlisting"><span class="keyword">double</span> <span class="identifier">x</span> <span class="special">=</span> <span class="number">0.5</span><span class="special">;</span>
74 <span class="keyword">double</span> <span class="identifier">T12</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">math</span><span class="special">::</span><span class="identifier">chebyshev_t</span><span class="special">(</span><span class="number">12</span><span class="special">,</span> <span class="identifier">x</span><span class="special">);</span>
77 Calculation of derivatives is also straightforward:
79 <pre class="programlisting"><span class="keyword">double</span> <span class="identifier">T12_prime</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">math</span><span class="special">::</span><span class="identifier">chebyshev_t_prime</span><span class="special">(</span><span class="number">12</span><span class="special">,</span> <span class="identifier">x</span><span class="special">);</span>
82 The complexity of evaluation of the <span class="emphasis"><em>n</em></span>-th Chebyshev polynomial
83 by these functions is linear. So they are unsuitable for use in calculation
84 of (say) a Chebyshev series, as a sum of linear scaling functions scales
85 quadratically. Though there are very sophisticated algorithms for the evaluation
86 of Chebyshev series, a linear time algorithm is presented below:
88 <pre class="programlisting"><span class="keyword">double</span> <span class="identifier">x</span> <span class="special">=</span> <span class="number">0.5</span><span class="special">;</span>
89 <span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special"><</span><span class="keyword">double</span><span class="special">></span> <span class="identifier">c</span><span class="special">{</span><span class="number">14.2</span><span class="special">,</span> <span class="special">-</span><span class="number">13.7</span><span class="special">,</span> <span class="number">82.3</span><span class="special">,</span> <span class="number">96</span><span class="special">};</span>
90 <span class="keyword">double</span> <span class="identifier">T0</span> <span class="special">=</span> <span class="number">1</span><span class="special">;</span>
91 <span class="keyword">double</span> <span class="identifier">T1</span> <span class="special">=</span> <span class="identifier">x</span><span class="special">;</span>
92 <span class="keyword">double</span> <span class="identifier">f</span> <span class="special">=</span> <span class="identifier">c</span><span class="special">[</span><span class="number">0</span><span class="special">]*</span><span class="identifier">T0</span><span class="special">/</span><span class="number">2</span><span class="special">;</span>
93 <span class="keyword">unsigned</span> <span class="identifier">l</span> <span class="special">=</span> <span class="number">1</span><span class="special">;</span>
94 <span class="keyword">while</span><span class="special">(</span><span class="identifier">l</span> <span class="special"><</span> <span class="identifier">c</span><span class="special">.</span><span class="identifier">size</span><span class="special">())</span>
95 <span class="special">{</span>
96 <span class="identifier">f</span> <span class="special">+=</span> <span class="identifier">c</span><span class="special">[</span><span class="identifier">l</span><span class="special">]*</span><span class="identifier">T1</span><span class="special">;</span>
97 <span class="identifier">std</span><span class="special">::</span><span class="identifier">swap</span><span class="special">(</span><span class="identifier">T0</span><span class="special">,</span> <span class="identifier">T1</span><span class="special">);</span>
98 <span class="identifier">T1</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">math</span><span class="special">::</span><span class="identifier">chebyshev_next</span><span class="special">(</span><span class="identifier">x</span><span class="special">,</span> <span class="identifier">T0</span><span class="special">,</span> <span class="identifier">T1</span><span class="special">);</span>
99 <span class="special">++</span><span class="identifier">l</span><span class="special">;</span>
100 <span class="special">}</span>
103 This uses the <code class="computeroutput"><span class="identifier">chebyshev_next</span></code>
104 function to evaluate each term of the Chebyshev series in constant time.
105 However, this naive algorithm has a catastrophic loss of precision as <span class="emphasis"><em>x</em></span>
106 approaches 1. A method to mitigate this way given by <a href="http://www.ams.org/journals/mcom/1955-09-051/S0025-5718-1955-0071856-0/S0025-5718-1955-0071856-0.pdf" target="_top">Clenshaw</a>,
107 and is implemented in boost as
109 <pre class="programlisting"><span class="keyword">double</span> <span class="identifier">x</span> <span class="special">=</span> <span class="number">0.5</span><span class="special">;</span>
110 <span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special"><</span><span class="keyword">double</span><span class="special">></span> <span class="identifier">c</span><span class="special">{</span><span class="number">14.2</span><span class="special">,</span> <span class="special">-</span><span class="number">13.7</span><span class="special">,</span> <span class="number">82.3</span><span class="special">,</span> <span class="number">96</span><span class="special">};</span>
111 <span class="keyword">double</span> <span class="identifier">f</span> <span class="special">=</span> <span class="identifier">chebyshev_clenshaw_recurrence</span><span class="special">(</span><span class="identifier">c</span><span class="special">.</span><span class="identifier">data</span><span class="special">(),</span> <span class="identifier">c</span><span class="special">.</span><span class="identifier">size</span><span class="special">(),</span> <span class="identifier">Real</span> <span class="identifier">x</span><span class="special">);</span>
114 N.B.: There is factor of <span class="emphasis"><em>2</em></span> difference in our definition
115 of the first coefficient in the Chebyshev series from Clenshaw's original
116 work. This is because two traditions exist in notation for the Chebyshev
119 <div class="blockquote"><blockquote class="blockquote"><p>
120 <span class="emphasis"><em>f</em></span>(<span class="emphasis"><em>x</em></span>) ≈ ∑<sub>n=0</sub><sup>N-1</sup> <span class="emphasis"><em>a</em></span><sub>n</sub><span class="emphasis"><em>T</em></span><sub>n</sub>(<span class="emphasis"><em>x</em></span>)
121 </p></blockquote></div>
125 <div class="blockquote"><blockquote class="blockquote"><p>
126 <span class="emphasis"><em>f</em></span>(<span class="emphasis"><em>x</em></span>) ≈ <span class="emphasis"><em>c</em></span><sub>0</sub>/2
127 + ∑<sub>n=1</sub><sup>N-1</sup> <span class="emphasis"><em>c</em></span><sub>n</sub><span class="emphasis"><em>T</em></span><sub>n</sub>(<span class="emphasis"><em>x</em></span>)
128 </p></blockquote></div>
130 <span class="emphasis"><em><span class="bold"><strong>boost math always uses the second convention,
131 with the factor of 1/2 on the first coefficient.</strong></span></em></span>
134 Chebyshev polynomials of the second kind can be evaluated via <code class="computeroutput"><span class="identifier">chebyshev_u</span></code>:
136 <pre class="programlisting"><span class="keyword">double</span> <span class="identifier">x</span> <span class="special">=</span> <span class="special">-</span><span class="number">0.23</span><span class="special">;</span>
137 <span class="keyword">double</span> <span class="identifier">U1</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">math</span><span class="special">::</span><span class="identifier">chebyshev_u</span><span class="special">(</span><span class="number">1</span><span class="special">,</span> <span class="identifier">x</span><span class="special">);</span>
140 The evaluation of Chebyshev polynomials by a three-term recurrence is known
141 to be <a href="https://link.springer.com/article/10.1007/s11075-014-9925-x" target="_top">mixed
142 forward-backward stable</a> for <span class="emphasis"><em>x</em></span> ∊ [-1,
143 1]. However, the author does not know of a similar result for <span class="emphasis"><em>x</em></span>
144 outside [-1, 1]. For this reason, evaluation of Chebyshev polynomials outside
145 of [-1, 1] is strongly discouraged. That said, small rounding errors in the
146 course of a computation will often lead to this situation, and termination
147 of the computation due to these small problems is very discouraging. For
148 this reason, <code class="computeroutput"><span class="identifier">chebyshev_t</span></code>
149 and <code class="computeroutput"><span class="identifier">chebyshev_u</span></code> have code
150 paths for <span class="emphasis"><em>x > 1</em></span> and <span class="emphasis"><em>x < -1</em></span>
151 which do not use three-term recurrences. These code paths are <span class="emphasis"><em>much
152 slower</em></span>, and should be avoided if at all possible.
155 Evaluation of a Chebyshev series is relatively simple. The real challenge
156 is <span class="emphasis"><em>generation</em></span> of the Chebyshev series. For this purpose,
157 boost provides a <span class="emphasis"><em>Chebyshev transform</em></span>, a projection operator
158 which projects a function onto a finite-dimensional span of Chebyshev polynomials.
159 But before we discuss the API, let's analyze why we might want to project
160 a function onto a span of Chebyshev polynomials.
162 <div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; ">
163 <li class="listitem">
164 We want a numerically stable way to evaluate the function's derivative.
166 <li class="listitem">
167 Our function is expensive to evaluate, and we wish to find a less expensive
168 way to estimate its value. An example are the standard library transcendental
169 functions: These functions are guaranteed to evaluate to within 1 ulp
170 of the exact value, but often this accuracy is not needed. A projection
171 onto the Chebyshev polynomials with a low accuracy requirement can vastly
172 accelerate the computation of these functions.
174 <li class="listitem">
175 We wish to numerically integrate the function.
179 The API is given below.
181 <pre class="programlisting"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">math</span><span class="special">/</span><span class="identifier">special_functions</span><span class="special">/</span><span class="identifier">chebyshev_transform</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span>
183 <pre class="programlisting"><span class="keyword">namespace</span> <span class="identifier">boost</span><span class="special">{</span> <span class="keyword">namespace</span> <span class="identifier">math</span><span class="special">{</span>
185 <span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">Real</span><span class="special">></span>
186 <span class="keyword">class</span> <span class="identifier">chebyshev_transform</span>
187 <span class="special">{</span>
188 <span class="keyword">public</span><span class="special">:</span>
189 <span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">F</span><span class="special">></span>
190 <span class="identifier">chebyshev_transform</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">F</span><span class="special">&</span> <span class="identifier">f</span><span class="special">,</span> <span class="identifier">Real</span> <span class="identifier">a</span><span class="special">,</span> <span class="identifier">Real</span> <span class="identifier">b</span><span class="special">,</span> <span class="identifier">Real</span> <span class="identifier">tol</span><span class="special">=</span><span class="number">500</span><span class="special">*</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">numeric_limits</span><span class="special"><</span><span class="identifier">Real</span><span class="special">>::</span><span class="identifier">epsilon</span><span class="special">());</span>
192 <span class="identifier">Real</span> <span class="keyword">operator</span><span class="special">()(</span><span class="identifier">Real</span> <span class="identifier">x</span><span class="special">)</span> <span class="keyword">const</span>
194 <span class="identifier">Real</span> <span class="identifier">integrate</span><span class="special">()</span> <span class="keyword">const</span>
196 <span class="keyword">const</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">vector</span><span class="special"><</span><span class="identifier">Real</span><span class="special">>&</span> <span class="identifier">coefficients</span><span class="special">()</span> <span class="keyword">const</span>
198 <span class="identifier">Real</span> <span class="identifier">prime</span><span class="special">(</span><span class="identifier">Real</span> <span class="identifier">x</span><span class="special">)</span> <span class="keyword">const</span>
199 <span class="special">};</span>
201 <span class="special">}}//</span> <span class="identifier">end</span> <span class="identifier">namespaces</span>
204 The Chebyshev transform takes a function <span class="emphasis"><em>f</em></span> and returns
205 a <span class="emphasis"><em>near-minimax</em></span> approximation to <span class="emphasis"><em>f</em></span>
206 in terms of Chebyshev polynomials. By <span class="emphasis"><em>near-minimax</em></span>,
207 we mean that the resulting Chebyshev polynomial is "very close"
208 the polynomial <span class="emphasis"><em>p</em></span><sub>n</sub> which minimizes the uniform norm of
209 <span class="emphasis"><em>f</em></span> - <span class="emphasis"><em>p</em></span><sub>n</sub>. The notion of "very
210 close" can be made rigorous; see Trefethen's "Approximation Theory
211 and Approximation Practice" for details.
214 The Chebyshev transform works by creating a vector of values by evaluating
215 the input function at the Chebyshev points, and then performing a discrete
216 cosine transform on the resulting vector. In order to do this efficiently,
217 we have used <a href="http://www.fftw.org/" target="_top">FFTW3</a>. So to compile,
218 you must have <code class="computeroutput"><span class="identifier">FFTW3</span></code> installed,
219 and link with <code class="computeroutput"><span class="special">-</span><span class="identifier">lfftw3</span></code>
220 for double precision, <code class="computeroutput"><span class="special">-</span><span class="identifier">lfftw3f</span></code>
221 for float precision, <code class="computeroutput"><span class="special">-</span><span class="identifier">lfftw3l</span></code>
222 for long double precision, and -lfftwq for quad (<code class="computeroutput"><span class="identifier">__float128</span></code>)
223 precision. After the coefficients of the Chebyshev series are known, the
224 routine goes back through them and filters out all the coefficients whose
225 absolute ratio to the largest coefficient are less than the tolerance requested
229 <table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
230 <td align="left"></td>
231 <td align="right"><div class="copyright-footer">Copyright © 2006-2019 Nikhar
232 Agrawal, Anton Bikineev, Paul A. Bristow, Marco Guazzone, Christopher Kormanyos,
233 Hubert Holin, Bruno Lalande, John Maddock, Jeremy Murphy, Matthew Pulver, Johan
234 Råde, Gautam Sewani, Benjamin Sobotta, Nicholas Thompson, Thijs van den Berg,
235 Daryle Walker and Xiaogang Zhang<p>
236 Distributed under the Boost Software License, Version 1.0. (See accompanying
237 file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
242 <div class="spirit-nav">
243 <a accesskey="p" href="hermite.html"><img src="../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../sf_poly.html"><img src="../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="sph_harm.html"><img src="../../../../../../doc/src/images/next.png" alt="Next"></a>