]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | [/ |
2 | Copyright (c) 2012 John Maddock | |
3 | Use, modification and distribution are subject to the | |
4 | Boost Software License, Version 1.0. (See accompanying file | |
5 | LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
6 | ] | |
7 | ||
8 | [section:airy Airy Functions] | |
9 | ||
10 | [section:ai Airy Ai Function] | |
11 | ||
12 | [heading Synopsis] | |
13 | ||
14 | `` | |
15 | #include <boost/math/special_functions/airy.hpp> | |
16 | `` | |
17 | ||
18 | namespace boost { namespace math { | |
19 | ||
20 | template <class T> | |
21 | ``__sf_result`` airy_ai(T x); | |
22 | ||
23 | template <class T, class Policy> | |
24 | ``__sf_result`` airy_ai(T x, const Policy&); | |
25 | ||
26 | }} // namespaces | |
27 | ||
28 | [heading Description] | |
29 | ||
30 | The function __airy_ai calculates the Airy function Ai which is the first solution | |
31 | to the differential equation: | |
32 | ||
33 | [equation airy] | |
34 | ||
35 | See Weisstein, Eric W. "Airy Functions." From MathWorld--A Wolfram Web Resource. | |
36 | [@http://mathworld.wolfram.com/AiryFunctions.html]; | |
37 | ||
38 | ||
39 | [optional_policy] | |
40 | ||
41 | The following graph illustrates how this function changes as /x/ changes: for negative /x/ | |
42 | the function is cyclic, while for positive /x/ the value tends to zero: | |
43 | ||
44 | [graph airy_ai] | |
45 | ||
46 | [heading Accuracy] | |
47 | ||
48 | This function is implemented entirely in terms of the Bessel functions | |
49 | __cyl_bessel_j and __cyl_bessel_k - refer to those functions for detailed accuracy information. | |
50 | ||
51 | In general though, the relative error is low (less than 100 [epsilon]) for /x > 0/ while | |
52 | only the absolute error is low for /x < 0/. | |
53 | ||
54 | [heading Testing] | |
55 | ||
56 | Since this function is implemented in terms of other special functions, there are only a few | |
57 | basic sanity checks, using test values from [@http://functions.wolfram.com/ Wolfram Airy Functions]. | |
58 | ||
59 | [heading Implementation] | |
60 | ||
61 | This function is implemented in terms of the Bessel functions using the relations: | |
62 | ||
63 | [equation airy_ai] | |
64 | ||
65 | [endsect] | |
66 | ||
67 | [section:bi Airy Bi Function] | |
68 | ||
69 | [heading Synopsis] | |
70 | ||
71 | `` | |
72 | #include <boost/math/special_functions/airy.hpp> | |
73 | `` | |
74 | ||
75 | namespace boost { namespace math { | |
76 | ||
77 | template <class T> | |
78 | ``__sf_result`` airy_bi(T x); | |
79 | ||
80 | template <class T, class Policy> | |
81 | ``__sf_result`` airy_bi(T x, const Policy&); | |
82 | ||
83 | }} // namespaces | |
84 | ||
85 | [heading Description] | |
86 | ||
87 | The function __airy_bi calculates the Airy function Bi which is the second solution to the differential equation: | |
88 | ||
89 | [equation airy] | |
90 | ||
91 | [optional_policy] | |
92 | ||
93 | The following graph illustrates how this function changes as /x/ changes: for negative /x/ | |
94 | the function is cyclic, while for positive /x/ the value tends to infinity: | |
95 | ||
96 | [graph airy_bi] | |
97 | ||
98 | [heading Accuracy] | |
99 | ||
100 | This function is implemented entirely in terms of the Bessel functions | |
101 | __cyl_bessel_i and __cyl_bessel_j - refer to those functions for detailed accuracy information. | |
102 | ||
103 | In general though, the relative error is low (less than 100 [epsilon]) for /x > 0/ while | |
104 | only the absolute error is low for /x < 0/. | |
105 | ||
106 | [heading Testing] | |
107 | ||
108 | Since this function is implemented in terms of other special functions, there are only a few | |
109 | basic sanity checks, using test values from [@http://functions.wolfram.com functions.wolfram.com]. | |
110 | ||
111 | [heading Implementation] | |
112 | ||
113 | This function is implemented in terms of the Bessel functions using the relations: | |
114 | ||
115 | [equation airy_bi] | |
116 | ||
117 | [endsect] | |
118 | ||
119 | [section:aip Airy Ai' Function] | |
120 | ||
121 | [heading Synopsis] | |
122 | ||
123 | `` | |
124 | #include <boost/math/special_functions/airy.hpp> | |
125 | `` | |
126 | ||
127 | namespace boost { namespace math { | |
128 | ||
129 | template <class T> | |
130 | ``__sf_result`` airy_ai_prime(T x); | |
131 | ||
132 | template <class T, class Policy> | |
133 | ``__sf_result`` airy_ai_prime(T x, const Policy&); | |
134 | ||
135 | }} // namespaces | |
136 | ||
137 | [heading Description] | |
138 | ||
139 | The function __airy_ai_prime calculates the Airy function Ai' which is the derivative of the first solution to the differential equation: | |
140 | ||
141 | [equation airy] | |
142 | ||
143 | [optional_policy] | |
144 | ||
145 | The following graph illustrates how this function changes as /x/ changes: for negative /x/ | |
146 | the function is cyclic, while for positive /x/ the value tends to zero: | |
147 | ||
148 | [graph airy_aip] | |
149 | ||
150 | [heading Accuracy] | |
151 | ||
152 | This function is implemented entirely in terms of the Bessel functions | |
153 | __cyl_bessel_j and __cyl_bessel_k - refer to those functions for detailed accuracy information. | |
154 | ||
155 | In general though, the relative error is low (less than 100 [epsilon]) for /x > 0/ while | |
156 | only the absolute error is low for /x < 0/. | |
157 | ||
158 | [heading Testing] | |
159 | ||
160 | Since this function is implemented in terms of other special functions, there are only a few | |
161 | basic sanity checks, using test values from [@http://functions.wolfram.com functions.wolfram.com]. | |
162 | ||
163 | [heading Implementation] | |
164 | ||
165 | This function is implemented in terms of the Bessel functions using the relations: | |
166 | ||
167 | [equation airy_aip] | |
168 | ||
169 | [endsect] | |
170 | ||
171 | [section:bip Airy Bi' Function] | |
172 | ||
173 | [heading Synopsis] | |
174 | ||
175 | `` | |
176 | #include <boost/math/special_functions/airy.hpp> | |
177 | `` | |
178 | ||
179 | namespace boost { namespace math { | |
180 | ||
181 | template <class T> | |
182 | ``__sf_result`` airy_bi_prime(T x); | |
183 | ||
184 | template <class T, class Policy> | |
185 | ``__sf_result`` airy_bi_prime(T x, const Policy&); | |
186 | ||
187 | }} // namespaces | |
188 | ||
189 | [heading Description] | |
190 | ||
191 | The function __airy_bi_prime calculates the Airy function Bi' which is the derivative of the second solution to the differential equation: | |
192 | ||
193 | [equation airy] | |
194 | ||
195 | [optional_policy] | |
196 | ||
197 | The following graph illustrates how this function changes as /x/ changes: for negative /x/ | |
198 | the function is cyclic, while for positive /x/ the value tends to infinity: | |
199 | ||
200 | [graph airy_bi] | |
201 | ||
202 | [heading Accuracy] | |
203 | ||
204 | This function is implemented entirely in terms of the Bessel functions | |
205 | __cyl_bessel_i and __cyl_bessel_j - refer to those functions for detailed accuracy information. | |
206 | ||
207 | In general though, the relative error is low (less than 100 [epsilon]) for /x > 0/ while | |
208 | only the absolute error is low for /x < 0/. | |
209 | ||
210 | [heading Testing] | |
211 | ||
212 | Since this function is implemented in terms of other special functions, there are only a few | |
213 | basic sanity checks, using test values from [@http://functions.wolfram.com functions.wolfram.com]. | |
214 | ||
215 | [heading Implementation] | |
216 | ||
217 | This function is implemented in terms of the Bessel functions using the relations: | |
218 | ||
219 | [equation airy_bip] | |
220 | ||
221 | [endsect] | |
222 | ||
223 | [section:airy_root Finding Zeros of Airy Functions] | |
224 | ||
225 | [h4 Synopsis] | |
226 | ||
227 | `#include <boost/math/special_functions/airy.hpp>` | |
228 | ||
229 | Functions for obtaining both a single zero or root of the Airy functions, | |
230 | and placing multiple zeros into a container like `std::vector` | |
231 | by providing an output iterator. | |
232 | ||
233 | The signature of the single value functions are: | |
234 | ||
235 | template <class T> | |
236 | T airy_ai_zero( | |
237 | int m); // 1-based index of zero. | |
238 | ||
239 | template <class T> | |
240 | T airy_bi_zero( | |
241 | int m); // 1-based index of zero. | |
242 | ||
243 | and for multiple zeros: | |
244 | ||
245 | template <class T, class OutputIterator> | |
246 | OutputIterator airy_ai_zero( | |
247 | int start_index, // 1-based index of first zero. | |
248 | unsigned number_of_zeros, // How many zeros to generate. | |
249 | OutputIterator out_it); // Destination for zeros. | |
250 | ||
251 | template <class T, class OutputIterator> | |
252 | OutputIterator airy_bi_zero( | |
253 | int start_index, // 1-based index of zero. | |
254 | unsigned number_of_zeros, // How many zeros to generate | |
255 | OutputIterator out_it); // Destination for zeros. | |
256 | ||
257 | There are also versions which allow control of the __policy_section for error handling and precision. | |
258 | ||
259 | template <class T> | |
260 | T airy_ai_zero( | |
261 | int m, // 1-based index of zero. | |
262 | const Policy&); // Policy to use. | |
263 | ||
264 | template <class T> | |
265 | T airy_bi_zero( | |
266 | int m, // 1-based index of zero. | |
267 | const Policy&); // Policy to use. | |
268 | ||
269 | ||
270 | template <class T, class OutputIterator> | |
271 | OutputIterator airy_ai_zero( | |
272 | int start_index, // 1-based index of first zero. | |
273 | unsigned number_of_zeros, // How many zeros to generate. | |
274 | OutputIterator out_it, // Destination for zeros. | |
275 | const Policy& pol); // Policy to use. | |
276 | ||
277 | template <class T, class OutputIterator> | |
278 | OutputIterator airy_bi_zero( | |
279 | int start_index, // 1-based index of zero. | |
280 | unsigned number_of_zeros, // How many zeros to generate. | |
281 | OutputIterator out_it, // Destination for zeros. | |
282 | const Policy& pol); // Policy to use. | |
283 | ||
284 | [h4 Description] | |
285 | ||
286 | The Airy Ai and Bi functions have an infinite | |
287 | number of zeros on the negative real axis. The real zeros on the negative real | |
288 | axis can be found by solving for the roots of | |
289 | ||
290 | [emquad] ['Ai(x[sub m]) = 0] | |
291 | ||
292 | [emquad] ['Bi(y[sub m]) = 0] | |
293 | ||
294 | Here, ['x[sub m]] represents the ['m[super th]] | |
295 | root of the Airy Ai function, | |
296 | and ['y[sub m]] represents the ['m[super th]] | |
297 | root of the Airy Bi function. | |
298 | ||
299 | The zeros or roots (values of `x` where the function crosses the horizontal `y = 0` axis) | |
300 | of the Airy Ai and Bi functions are computed by two functions, | |
301 | `airy_ai_zero` and `airy_bi_zero`. | |
302 | ||
303 | In each case the index or rank of the zero | |
304 | returned is 1-based, which is to say: | |
305 | ||
306 | airy_ai_zero(1); | |
307 | ||
308 | returns the first zero of Ai. | |
309 | ||
310 | Passing an `start_index <= 0` results in a __domain_error being raised. | |
311 | ||
312 | The first few zeros returned by these functions have approximate values as follows: | |
313 | ||
314 | [table | |
315 | [[m][Ai][Bi]] | |
316 | [[1][-2.33811...][-1.17371...]] | |
317 | [[2][-4.08795...][-3.27109...]] | |
318 | [[3][-5.52056...][-4.83074...]] | |
319 | [[4][-6.78671...][-6.16985...]] | |
320 | [[5][-7.94413...][-7.37676...]] | |
321 | [[6][-9.02265...][-8.49195...]] | |
322 | ] | |
323 | ||
324 | [graph airy_zeros] | |
325 | ||
326 | ||
327 | [h4 Examples of finding Airy Zeros] | |
328 | ||
329 | [import ../../example/airy_zeros_example.cpp] | |
330 | ||
331 | [airy_zeros_example_1] | |
332 | [airy_zeros_example_2] | |
333 | ||
334 | Produces the program output: | |
335 | [pre | |
336 | boost::math::airy_ai_zero<double>(1) = -2.33811 | |
337 | boost::math::airy_ai_zero<double>(2) = -4.08795 | |
338 | boost::math::airy_bi_zero<double>(3) = -4.83074 | |
339 | airy_ai_zeros: | |
340 | -2.33811 | |
341 | -4.08795 | |
342 | -5.52056 | |
343 | -6.78671 | |
344 | -7.94413 | |
345 | ||
346 | boost::math::airy_bi_zero<float_type>(1) = -2.3381074104597670384891972524467354406385401456711 | |
347 | boost::math::airy_bi_zero<float_type>(2) = -4.0879494441309706166369887014573910602247646991085 | |
348 | boost::math::airy_bi_zero<float_type>(7) = -9.5381943793462388866329885451560196208390720763825 | |
349 | airy_ai_zeros: | |
350 | -2.3381074104597670384891972524467354406385401456711 | |
351 | -4.0879494441309706166369887014573910602247646991085 | |
352 | -5.5205598280955510591298555129312935737972142806175 | |
353 | ] | |
354 | ||
355 | The full code (and output) for this example is at | |
356 | [@../../example/airy_zeros_example.cpp airy_zeros_example.cpp], | |
357 | ||
358 | [h3 Implementation] | |
359 | ||
360 | Given the following function (A&S 10.4.105): | |
361 | ||
362 | [equation airy_zero_1] | |
363 | ||
364 | Then an initial estimate for the n[super th] zero a[sub n] of Ai is given by (A&S 10.4.94): | |
365 | ||
366 | [equation airy_zero_2] | |
367 | ||
368 | and an initial estimate for the n[super th] zero b[sub n] of Bi is given by (A&S 10.4.98): | |
369 | ||
370 | [equation airy_zero_3] | |
371 | ||
372 | Thereafter the roots are refined using Newton iteration. | |
373 | ||
374 | ||
375 | [h3 Testing] | |
376 | ||
377 | The precision of evaluation of zeros was tested at 50 decimal digits using `cpp_dec_float_50` | |
378 | and found identical with spot values computed by __WolframAlpha. | |
379 | ||
380 | [endsect] [/section:bessel Finding Zeros of Bessel Functions of the First and Second Kinds] | |
381 | ||
382 | ||
383 | [endsect] | |
384 |