Chris@16
|
1 // Copyright John Maddock 2012.
|
Chris@16
|
2 // Use, modification and distribution are subject to the
|
Chris@16
|
3 // Boost Software License, Version 1.0.
|
Chris@16
|
4 // (See accompanying file LICENSE_1_0.txt
|
Chris@16
|
5 // or copy at http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
6
|
Chris@16
|
7 #ifndef BOOST_MATH_AIRY_HPP
|
Chris@16
|
8 #define BOOST_MATH_AIRY_HPP
|
Chris@16
|
9
|
Chris@101
|
10 #include <limits>
|
Chris@101
|
11 #include <boost/math/special_functions/math_fwd.hpp>
|
Chris@16
|
12 #include <boost/math/special_functions/bessel.hpp>
|
Chris@16
|
13 #include <boost/math/special_functions/cbrt.hpp>
|
Chris@16
|
14 #include <boost/math/special_functions/detail/airy_ai_bi_zero.hpp>
|
Chris@16
|
15 #include <boost/math/tools/roots.hpp>
|
Chris@16
|
16
|
Chris@16
|
17 namespace boost{ namespace math{
|
Chris@16
|
18
|
Chris@16
|
19 namespace detail{
|
Chris@16
|
20
|
Chris@16
|
21 template <class T, class Policy>
|
Chris@16
|
22 T airy_ai_imp(T x, const Policy& pol)
|
Chris@16
|
23 {
|
Chris@16
|
24 BOOST_MATH_STD_USING
|
Chris@16
|
25
|
Chris@16
|
26 if(x < 0)
|
Chris@16
|
27 {
|
Chris@16
|
28 T p = (-x * sqrt(-x) * 2) / 3;
|
Chris@16
|
29 T v = T(1) / 3;
|
Chris@16
|
30 T j1 = boost::math::cyl_bessel_j(v, p, pol);
|
Chris@16
|
31 T j2 = boost::math::cyl_bessel_j(-v, p, pol);
|
Chris@16
|
32 T ai = sqrt(-x) * (j1 + j2) / 3;
|
Chris@16
|
33 //T bi = sqrt(-x / 3) * (j2 - j1);
|
Chris@16
|
34 return ai;
|
Chris@16
|
35 }
|
Chris@16
|
36 else if(fabs(x * x * x) / 6 < tools::epsilon<T>())
|
Chris@16
|
37 {
|
Chris@16
|
38 T tg = boost::math::tgamma(constants::twothirds<T>(), pol);
|
Chris@16
|
39 T ai = 1 / (pow(T(3), constants::twothirds<T>()) * tg);
|
Chris@16
|
40 //T bi = 1 / (sqrt(boost::math::cbrt(T(3))) * tg);
|
Chris@16
|
41 return ai;
|
Chris@16
|
42 }
|
Chris@16
|
43 else
|
Chris@16
|
44 {
|
Chris@16
|
45 T p = 2 * x * sqrt(x) / 3;
|
Chris@16
|
46 T v = T(1) / 3;
|
Chris@16
|
47 //T j1 = boost::math::cyl_bessel_i(-v, p, pol);
|
Chris@16
|
48 //T j2 = boost::math::cyl_bessel_i(v, p, pol);
|
Chris@16
|
49 //
|
Chris@16
|
50 // Note that although we can calculate ai from j1 and j2, the accuracy is horrible
|
Chris@16
|
51 // as we're subtracting two very large values, so use the Bessel K relation instead:
|
Chris@16
|
52 //
|
Chris@16
|
53 T ai = cyl_bessel_k(v, p, pol) * sqrt(x / 3) / boost::math::constants::pi<T>(); //sqrt(x) * (j1 - j2) / 3;
|
Chris@16
|
54 //T bi = sqrt(x / 3) * (j1 + j2);
|
Chris@16
|
55 return ai;
|
Chris@16
|
56 }
|
Chris@16
|
57 }
|
Chris@16
|
58
|
Chris@16
|
59 template <class T, class Policy>
|
Chris@16
|
60 T airy_bi_imp(T x, const Policy& pol)
|
Chris@16
|
61 {
|
Chris@16
|
62 BOOST_MATH_STD_USING
|
Chris@16
|
63
|
Chris@16
|
64 if(x < 0)
|
Chris@16
|
65 {
|
Chris@16
|
66 T p = (-x * sqrt(-x) * 2) / 3;
|
Chris@16
|
67 T v = T(1) / 3;
|
Chris@16
|
68 T j1 = boost::math::cyl_bessel_j(v, p, pol);
|
Chris@16
|
69 T j2 = boost::math::cyl_bessel_j(-v, p, pol);
|
Chris@16
|
70 //T ai = sqrt(-x) * (j1 + j2) / 3;
|
Chris@16
|
71 T bi = sqrt(-x / 3) * (j2 - j1);
|
Chris@16
|
72 return bi;
|
Chris@16
|
73 }
|
Chris@16
|
74 else if(fabs(x * x * x) / 6 < tools::epsilon<T>())
|
Chris@16
|
75 {
|
Chris@16
|
76 T tg = boost::math::tgamma(constants::twothirds<T>(), pol);
|
Chris@16
|
77 //T ai = 1 / (pow(T(3), constants::twothirds<T>()) * tg);
|
Chris@16
|
78 T bi = 1 / (sqrt(boost::math::cbrt(T(3))) * tg);
|
Chris@16
|
79 return bi;
|
Chris@16
|
80 }
|
Chris@16
|
81 else
|
Chris@16
|
82 {
|
Chris@16
|
83 T p = 2 * x * sqrt(x) / 3;
|
Chris@16
|
84 T v = T(1) / 3;
|
Chris@16
|
85 T j1 = boost::math::cyl_bessel_i(-v, p, pol);
|
Chris@16
|
86 T j2 = boost::math::cyl_bessel_i(v, p, pol);
|
Chris@16
|
87 T bi = sqrt(x / 3) * (j1 + j2);
|
Chris@16
|
88 return bi;
|
Chris@16
|
89 }
|
Chris@16
|
90 }
|
Chris@16
|
91
|
Chris@16
|
92 template <class T, class Policy>
|
Chris@16
|
93 T airy_ai_prime_imp(T x, const Policy& pol)
|
Chris@16
|
94 {
|
Chris@16
|
95 BOOST_MATH_STD_USING
|
Chris@16
|
96
|
Chris@16
|
97 if(x < 0)
|
Chris@16
|
98 {
|
Chris@16
|
99 T p = (-x * sqrt(-x) * 2) / 3;
|
Chris@16
|
100 T v = T(2) / 3;
|
Chris@16
|
101 T j1 = boost::math::cyl_bessel_j(v, p, pol);
|
Chris@16
|
102 T j2 = boost::math::cyl_bessel_j(-v, p, pol);
|
Chris@16
|
103 T aip = -x * (j1 - j2) / 3;
|
Chris@16
|
104 return aip;
|
Chris@16
|
105 }
|
Chris@16
|
106 else if(fabs(x * x) / 2 < tools::epsilon<T>())
|
Chris@16
|
107 {
|
Chris@16
|
108 T tg = boost::math::tgamma(constants::third<T>(), pol);
|
Chris@16
|
109 T aip = 1 / (boost::math::cbrt(T(3)) * tg);
|
Chris@16
|
110 return -aip;
|
Chris@16
|
111 }
|
Chris@16
|
112 else
|
Chris@16
|
113 {
|
Chris@16
|
114 T p = 2 * x * sqrt(x) / 3;
|
Chris@16
|
115 T v = T(2) / 3;
|
Chris@16
|
116 //T j1 = boost::math::cyl_bessel_i(-v, p, pol);
|
Chris@16
|
117 //T j2 = boost::math::cyl_bessel_i(v, p, pol);
|
Chris@16
|
118 //
|
Chris@16
|
119 // Note that although we can calculate ai from j1 and j2, the accuracy is horrible
|
Chris@16
|
120 // as we're subtracting two very large values, so use the Bessel K relation instead:
|
Chris@16
|
121 //
|
Chris@16
|
122 T aip = -cyl_bessel_k(v, p, pol) * x / (boost::math::constants::root_three<T>() * boost::math::constants::pi<T>());
|
Chris@16
|
123 return aip;
|
Chris@16
|
124 }
|
Chris@16
|
125 }
|
Chris@16
|
126
|
Chris@16
|
127 template <class T, class Policy>
|
Chris@16
|
128 T airy_bi_prime_imp(T x, const Policy& pol)
|
Chris@16
|
129 {
|
Chris@16
|
130 BOOST_MATH_STD_USING
|
Chris@16
|
131
|
Chris@16
|
132 if(x < 0)
|
Chris@16
|
133 {
|
Chris@16
|
134 T p = (-x * sqrt(-x) * 2) / 3;
|
Chris@16
|
135 T v = T(2) / 3;
|
Chris@16
|
136 T j1 = boost::math::cyl_bessel_j(v, p, pol);
|
Chris@16
|
137 T j2 = boost::math::cyl_bessel_j(-v, p, pol);
|
Chris@16
|
138 T aip = -x * (j1 + j2) / constants::root_three<T>();
|
Chris@16
|
139 return aip;
|
Chris@16
|
140 }
|
Chris@16
|
141 else if(fabs(x * x) / 2 < tools::epsilon<T>())
|
Chris@16
|
142 {
|
Chris@16
|
143 T tg = boost::math::tgamma(constants::third<T>(), pol);
|
Chris@16
|
144 T bip = sqrt(boost::math::cbrt(T(3))) / tg;
|
Chris@16
|
145 return bip;
|
Chris@16
|
146 }
|
Chris@16
|
147 else
|
Chris@16
|
148 {
|
Chris@16
|
149 T p = 2 * x * sqrt(x) / 3;
|
Chris@16
|
150 T v = T(2) / 3;
|
Chris@16
|
151 T j1 = boost::math::cyl_bessel_i(-v, p, pol);
|
Chris@16
|
152 T j2 = boost::math::cyl_bessel_i(v, p, pol);
|
Chris@16
|
153 T aip = x * (j1 + j2) / boost::math::constants::root_three<T>();
|
Chris@16
|
154 return aip;
|
Chris@16
|
155 }
|
Chris@16
|
156 }
|
Chris@16
|
157
|
Chris@16
|
158 template <class T, class Policy>
|
Chris@101
|
159 T airy_ai_zero_imp(int m, const Policy& pol)
|
Chris@16
|
160 {
|
Chris@16
|
161 BOOST_MATH_STD_USING // ADL of std names, needed for log, sqrt.
|
Chris@16
|
162
|
Chris@101
|
163 // Handle cases when a negative zero (negative rank) is requested.
|
Chris@101
|
164 if(m < 0)
|
Chris@101
|
165 {
|
Chris@101
|
166 return policies::raise_domain_error<T>("boost::math::airy_ai_zero<%1%>(%1%, int)",
|
Chris@101
|
167 "Requested the %1%'th zero, but the rank must be 1 or more !", static_cast<T>(m), pol);
|
Chris@101
|
168 }
|
Chris@101
|
169
|
Chris@16
|
170 // Handle case when the zero'th zero is requested.
|
Chris@16
|
171 if(m == 0U)
|
Chris@16
|
172 {
|
Chris@16
|
173 return policies::raise_domain_error<T>("boost::math::airy_ai_zero<%1%>(%1%,%1%)",
|
Chris@16
|
174 "The requested rank of the zero is %1%, but must be 1 or more !", static_cast<T>(m), pol);
|
Chris@16
|
175 }
|
Chris@16
|
176
|
Chris@16
|
177 // Set up the initial guess for the upcoming root-finding.
|
Chris@16
|
178 const T guess_root = boost::math::detail::airy_zero::airy_ai_zero_detail::initial_guess<T>(m);
|
Chris@16
|
179
|
Chris@101
|
180 // Select the maximum allowed iterations based on the number
|
Chris@101
|
181 // of decimal digits in the numeric type T, being at least 12.
|
Chris@101
|
182 const int my_digits10 = static_cast<int>(static_cast<float>(policies::digits<T, Policy>() * 0.301F));
|
Chris@16
|
183
|
Chris@101
|
184 const boost::uintmax_t iterations_allowed = static_cast<boost::uintmax_t>((std::max)(12, my_digits10 * 2));
|
Chris@101
|
185
|
Chris@101
|
186 boost::uintmax_t iterations_used = iterations_allowed;
|
Chris@16
|
187
|
Chris@16
|
188 // Use a dynamic tolerance because the roots get closer the higher m gets.
|
Chris@16
|
189 T tolerance;
|
Chris@16
|
190
|
Chris@101
|
191 if (m <= 10) { tolerance = T(0.3F); }
|
Chris@101
|
192 else if(m <= 100) { tolerance = T(0.1F); }
|
Chris@101
|
193 else if(m <= 1000) { tolerance = T(0.05F); }
|
Chris@101
|
194 else { tolerance = T(1) / sqrt(T(m)); }
|
Chris@16
|
195
|
Chris@16
|
196 // Perform the root-finding using Newton-Raphson iteration from Boost.Math.
|
Chris@16
|
197 const T am =
|
Chris@16
|
198 boost::math::tools::newton_raphson_iterate(
|
Chris@16
|
199 boost::math::detail::airy_zero::airy_ai_zero_detail::function_object_ai_and_ai_prime<T, Policy>(pol),
|
Chris@16
|
200 guess_root,
|
Chris@16
|
201 T(guess_root - tolerance),
|
Chris@16
|
202 T(guess_root + tolerance),
|
Chris@101
|
203 policies::digits<T, Policy>(),
|
Chris@101
|
204 iterations_used);
|
Chris@16
|
205
|
Chris@101
|
206 static_cast<void>(iterations_used);
|
Chris@16
|
207
|
Chris@16
|
208 return am;
|
Chris@16
|
209 }
|
Chris@16
|
210
|
Chris@16
|
211 template <class T, class Policy>
|
Chris@101
|
212 T airy_bi_zero_imp(int m, const Policy& pol)
|
Chris@16
|
213 {
|
Chris@16
|
214 BOOST_MATH_STD_USING // ADL of std names, needed for log, sqrt.
|
Chris@16
|
215
|
Chris@101
|
216 // Handle cases when a negative zero (negative rank) is requested.
|
Chris@101
|
217 if(m < 0)
|
Chris@101
|
218 {
|
Chris@101
|
219 return policies::raise_domain_error<T>("boost::math::airy_bi_zero<%1%>(%1%, int)",
|
Chris@101
|
220 "Requested the %1%'th zero, but the rank must 1 or more !", static_cast<T>(m), pol);
|
Chris@101
|
221 }
|
Chris@101
|
222
|
Chris@16
|
223 // Handle case when the zero'th zero is requested.
|
Chris@16
|
224 if(m == 0U)
|
Chris@16
|
225 {
|
Chris@16
|
226 return policies::raise_domain_error<T>("boost::math::airy_bi_zero<%1%>(%1%,%1%)",
|
Chris@16
|
227 "The requested rank of the zero is %1%, but must be 1 or more !", static_cast<T>(m), pol);
|
Chris@16
|
228 }
|
Chris@16
|
229 // Set up the initial guess for the upcoming root-finding.
|
Chris@16
|
230 const T guess_root = boost::math::detail::airy_zero::airy_bi_zero_detail::initial_guess<T>(m);
|
Chris@16
|
231
|
Chris@101
|
232 // Select the maximum allowed iterations based on the number
|
Chris@101
|
233 // of decimal digits in the numeric type T, being at least 12.
|
Chris@101
|
234 const int my_digits10 = static_cast<int>(static_cast<float>(policies::digits<T, Policy>() * 0.301F));
|
Chris@16
|
235
|
Chris@101
|
236 const boost::uintmax_t iterations_allowed = static_cast<boost::uintmax_t>((std::max)(12, my_digits10 * 2));
|
Chris@101
|
237
|
Chris@101
|
238 boost::uintmax_t iterations_used = iterations_allowed;
|
Chris@16
|
239
|
Chris@16
|
240 // Use a dynamic tolerance because the roots get closer the higher m gets.
|
Chris@16
|
241 T tolerance;
|
Chris@16
|
242
|
Chris@101
|
243 if (m <= 10) { tolerance = T(0.3F); }
|
Chris@101
|
244 else if(m <= 100) { tolerance = T(0.1F); }
|
Chris@101
|
245 else if(m <= 1000) { tolerance = T(0.05F); }
|
Chris@101
|
246 else { tolerance = T(1) / sqrt(T(m)); }
|
Chris@16
|
247
|
Chris@16
|
248 // Perform the root-finding using Newton-Raphson iteration from Boost.Math.
|
Chris@16
|
249 const T bm =
|
Chris@16
|
250 boost::math::tools::newton_raphson_iterate(
|
Chris@16
|
251 boost::math::detail::airy_zero::airy_bi_zero_detail::function_object_bi_and_bi_prime<T, Policy>(pol),
|
Chris@16
|
252 guess_root,
|
Chris@16
|
253 T(guess_root - tolerance),
|
Chris@16
|
254 T(guess_root + tolerance),
|
Chris@101
|
255 policies::digits<T, Policy>(),
|
Chris@101
|
256 iterations_used);
|
Chris@16
|
257
|
Chris@101
|
258 static_cast<void>(iterations_used);
|
Chris@16
|
259
|
Chris@16
|
260 return bm;
|
Chris@16
|
261 }
|
Chris@16
|
262
|
Chris@16
|
263 } // namespace detail
|
Chris@16
|
264
|
Chris@16
|
265 template <class T, class Policy>
|
Chris@16
|
266 inline typename tools::promote_args<T>::type airy_ai(T x, const Policy&)
|
Chris@16
|
267 {
|
Chris@16
|
268 BOOST_FPU_EXCEPTION_GUARD
|
Chris@16
|
269 typedef typename tools::promote_args<T>::type result_type;
|
Chris@16
|
270 typedef typename policies::evaluation<result_type, Policy>::type value_type;
|
Chris@16
|
271 typedef typename policies::normalise<
|
Chris@16
|
272 Policy,
|
Chris@16
|
273 policies::promote_float<false>,
|
Chris@16
|
274 policies::promote_double<false>,
|
Chris@16
|
275 policies::discrete_quantile<>,
|
Chris@16
|
276 policies::assert_undefined<> >::type forwarding_policy;
|
Chris@16
|
277
|
Chris@16
|
278 return policies::checked_narrowing_cast<result_type, Policy>(detail::airy_ai_imp<value_type>(static_cast<value_type>(x), forwarding_policy()), "boost::math::airy<%1%>(%1%)");
|
Chris@16
|
279 }
|
Chris@16
|
280
|
Chris@16
|
281 template <class T>
|
Chris@16
|
282 inline typename tools::promote_args<T>::type airy_ai(T x)
|
Chris@16
|
283 {
|
Chris@16
|
284 return airy_ai(x, policies::policy<>());
|
Chris@16
|
285 }
|
Chris@16
|
286
|
Chris@16
|
287 template <class T, class Policy>
|
Chris@16
|
288 inline typename tools::promote_args<T>::type airy_bi(T x, const Policy&)
|
Chris@16
|
289 {
|
Chris@16
|
290 BOOST_FPU_EXCEPTION_GUARD
|
Chris@16
|
291 typedef typename tools::promote_args<T>::type result_type;
|
Chris@16
|
292 typedef typename policies::evaluation<result_type, Policy>::type value_type;
|
Chris@16
|
293 typedef typename policies::normalise<
|
Chris@16
|
294 Policy,
|
Chris@16
|
295 policies::promote_float<false>,
|
Chris@16
|
296 policies::promote_double<false>,
|
Chris@16
|
297 policies::discrete_quantile<>,
|
Chris@16
|
298 policies::assert_undefined<> >::type forwarding_policy;
|
Chris@16
|
299
|
Chris@16
|
300 return policies::checked_narrowing_cast<result_type, Policy>(detail::airy_bi_imp<value_type>(static_cast<value_type>(x), forwarding_policy()), "boost::math::airy<%1%>(%1%)");
|
Chris@16
|
301 }
|
Chris@16
|
302
|
Chris@16
|
303 template <class T>
|
Chris@16
|
304 inline typename tools::promote_args<T>::type airy_bi(T x)
|
Chris@16
|
305 {
|
Chris@16
|
306 return airy_bi(x, policies::policy<>());
|
Chris@16
|
307 }
|
Chris@16
|
308
|
Chris@16
|
309 template <class T, class Policy>
|
Chris@16
|
310 inline typename tools::promote_args<T>::type airy_ai_prime(T x, const Policy&)
|
Chris@16
|
311 {
|
Chris@16
|
312 BOOST_FPU_EXCEPTION_GUARD
|
Chris@16
|
313 typedef typename tools::promote_args<T>::type result_type;
|
Chris@16
|
314 typedef typename policies::evaluation<result_type, Policy>::type value_type;
|
Chris@16
|
315 typedef typename policies::normalise<
|
Chris@16
|
316 Policy,
|
Chris@16
|
317 policies::promote_float<false>,
|
Chris@16
|
318 policies::promote_double<false>,
|
Chris@16
|
319 policies::discrete_quantile<>,
|
Chris@16
|
320 policies::assert_undefined<> >::type forwarding_policy;
|
Chris@16
|
321
|
Chris@16
|
322 return policies::checked_narrowing_cast<result_type, Policy>(detail::airy_ai_prime_imp<value_type>(static_cast<value_type>(x), forwarding_policy()), "boost::math::airy<%1%>(%1%)");
|
Chris@16
|
323 }
|
Chris@16
|
324
|
Chris@16
|
325 template <class T>
|
Chris@16
|
326 inline typename tools::promote_args<T>::type airy_ai_prime(T x)
|
Chris@16
|
327 {
|
Chris@16
|
328 return airy_ai_prime(x, policies::policy<>());
|
Chris@16
|
329 }
|
Chris@16
|
330
|
Chris@16
|
331 template <class T, class Policy>
|
Chris@16
|
332 inline typename tools::promote_args<T>::type airy_bi_prime(T x, const Policy&)
|
Chris@16
|
333 {
|
Chris@16
|
334 BOOST_FPU_EXCEPTION_GUARD
|
Chris@16
|
335 typedef typename tools::promote_args<T>::type result_type;
|
Chris@16
|
336 typedef typename policies::evaluation<result_type, Policy>::type value_type;
|
Chris@16
|
337 typedef typename policies::normalise<
|
Chris@16
|
338 Policy,
|
Chris@16
|
339 policies::promote_float<false>,
|
Chris@16
|
340 policies::promote_double<false>,
|
Chris@16
|
341 policies::discrete_quantile<>,
|
Chris@16
|
342 policies::assert_undefined<> >::type forwarding_policy;
|
Chris@16
|
343
|
Chris@16
|
344 return policies::checked_narrowing_cast<result_type, Policy>(detail::airy_bi_prime_imp<value_type>(static_cast<value_type>(x), forwarding_policy()), "boost::math::airy<%1%>(%1%)");
|
Chris@16
|
345 }
|
Chris@16
|
346
|
Chris@16
|
347 template <class T>
|
Chris@16
|
348 inline typename tools::promote_args<T>::type airy_bi_prime(T x)
|
Chris@16
|
349 {
|
Chris@16
|
350 return airy_bi_prime(x, policies::policy<>());
|
Chris@16
|
351 }
|
Chris@16
|
352
|
Chris@16
|
353 template <class T, class Policy>
|
Chris@101
|
354 inline T airy_ai_zero(int m, const Policy& /*pol*/)
|
Chris@16
|
355 {
|
Chris@16
|
356 BOOST_FPU_EXCEPTION_GUARD
|
Chris@16
|
357 typedef typename policies::evaluation<T, Policy>::type value_type;
|
Chris@16
|
358 typedef typename policies::normalise<
|
Chris@16
|
359 Policy,
|
Chris@16
|
360 policies::promote_float<false>,
|
Chris@16
|
361 policies::promote_double<false>,
|
Chris@16
|
362 policies::discrete_quantile<>,
|
Chris@16
|
363 policies::assert_undefined<> >::type forwarding_policy;
|
Chris@101
|
364
|
Chris@101
|
365 BOOST_STATIC_ASSERT_MSG( false == std::numeric_limits<T>::is_specialized
|
Chris@101
|
366 || ( true == std::numeric_limits<T>::is_specialized
|
Chris@101
|
367 && false == std::numeric_limits<T>::is_integer),
|
Chris@101
|
368 "Airy value type must be a floating-point type.");
|
Chris@101
|
369
|
Chris@16
|
370 return policies::checked_narrowing_cast<T, Policy>(detail::airy_ai_zero_imp<value_type>(m, forwarding_policy()), "boost::math::airy_ai_zero<%1%>(unsigned)");
|
Chris@16
|
371 }
|
Chris@16
|
372
|
Chris@16
|
373 template <class T>
|
Chris@101
|
374 inline T airy_ai_zero(int m)
|
Chris@16
|
375 {
|
Chris@16
|
376 return airy_ai_zero<T>(m, policies::policy<>());
|
Chris@16
|
377 }
|
Chris@16
|
378
|
Chris@16
|
379 template <class T, class OutputIterator, class Policy>
|
Chris@16
|
380 inline OutputIterator airy_ai_zero(
|
Chris@101
|
381 int start_index,
|
Chris@16
|
382 unsigned number_of_zeros,
|
Chris@16
|
383 OutputIterator out_it,
|
Chris@16
|
384 const Policy& pol)
|
Chris@16
|
385 {
|
Chris@16
|
386 typedef T result_type;
|
Chris@101
|
387
|
Chris@101
|
388 BOOST_STATIC_ASSERT_MSG( false == std::numeric_limits<T>::is_specialized
|
Chris@101
|
389 || ( true == std::numeric_limits<T>::is_specialized
|
Chris@101
|
390 && false == std::numeric_limits<T>::is_integer),
|
Chris@101
|
391 "Airy value type must be a floating-point type.");
|
Chris@16
|
392
|
Chris@16
|
393 for(unsigned i = 0; i < number_of_zeros; ++i)
|
Chris@16
|
394 {
|
Chris@16
|
395 *out_it = boost::math::airy_ai_zero<result_type>(start_index + i, pol);
|
Chris@16
|
396 ++out_it;
|
Chris@16
|
397 }
|
Chris@16
|
398 return out_it;
|
Chris@16
|
399 }
|
Chris@16
|
400
|
Chris@16
|
401 template <class T, class OutputIterator>
|
Chris@16
|
402 inline OutputIterator airy_ai_zero(
|
Chris@101
|
403 int start_index,
|
Chris@16
|
404 unsigned number_of_zeros,
|
Chris@16
|
405 OutputIterator out_it)
|
Chris@16
|
406 {
|
Chris@16
|
407 return airy_ai_zero<T>(start_index, number_of_zeros, out_it, policies::policy<>());
|
Chris@16
|
408 }
|
Chris@16
|
409
|
Chris@16
|
410 template <class T, class Policy>
|
Chris@101
|
411 inline T airy_bi_zero(int m, const Policy& /*pol*/)
|
Chris@16
|
412 {
|
Chris@16
|
413 BOOST_FPU_EXCEPTION_GUARD
|
Chris@16
|
414 typedef typename policies::evaluation<T, Policy>::type value_type;
|
Chris@16
|
415 typedef typename policies::normalise<
|
Chris@16
|
416 Policy,
|
Chris@16
|
417 policies::promote_float<false>,
|
Chris@16
|
418 policies::promote_double<false>,
|
Chris@16
|
419 policies::discrete_quantile<>,
|
Chris@16
|
420 policies::assert_undefined<> >::type forwarding_policy;
|
Chris@101
|
421
|
Chris@101
|
422 BOOST_STATIC_ASSERT_MSG( false == std::numeric_limits<T>::is_specialized
|
Chris@101
|
423 || ( true == std::numeric_limits<T>::is_specialized
|
Chris@101
|
424 && false == std::numeric_limits<T>::is_integer),
|
Chris@101
|
425 "Airy value type must be a floating-point type.");
|
Chris@101
|
426
|
Chris@16
|
427 return policies::checked_narrowing_cast<T, Policy>(detail::airy_bi_zero_imp<value_type>(m, forwarding_policy()), "boost::math::airy_bi_zero<%1%>(unsigned)");
|
Chris@16
|
428 }
|
Chris@16
|
429
|
Chris@16
|
430 template <typename T>
|
Chris@101
|
431 inline T airy_bi_zero(int m)
|
Chris@16
|
432 {
|
Chris@16
|
433 return airy_bi_zero<T>(m, policies::policy<>());
|
Chris@16
|
434 }
|
Chris@16
|
435
|
Chris@16
|
436 template <class T, class OutputIterator, class Policy>
|
Chris@16
|
437 inline OutputIterator airy_bi_zero(
|
Chris@101
|
438 int start_index,
|
Chris@16
|
439 unsigned number_of_zeros,
|
Chris@16
|
440 OutputIterator out_it,
|
Chris@16
|
441 const Policy& pol)
|
Chris@16
|
442 {
|
Chris@16
|
443 typedef T result_type;
|
Chris@101
|
444
|
Chris@101
|
445 BOOST_STATIC_ASSERT_MSG( false == std::numeric_limits<T>::is_specialized
|
Chris@101
|
446 || ( true == std::numeric_limits<T>::is_specialized
|
Chris@101
|
447 && false == std::numeric_limits<T>::is_integer),
|
Chris@101
|
448 "Airy value type must be a floating-point type.");
|
Chris@16
|
449
|
Chris@16
|
450 for(unsigned i = 0; i < number_of_zeros; ++i)
|
Chris@16
|
451 {
|
Chris@16
|
452 *out_it = boost::math::airy_bi_zero<result_type>(start_index + i, pol);
|
Chris@16
|
453 ++out_it;
|
Chris@16
|
454 }
|
Chris@16
|
455 return out_it;
|
Chris@16
|
456 }
|
Chris@16
|
457
|
Chris@16
|
458 template <class T, class OutputIterator>
|
Chris@16
|
459 inline OutputIterator airy_bi_zero(
|
Chris@101
|
460 int start_index,
|
Chris@16
|
461 unsigned number_of_zeros,
|
Chris@16
|
462 OutputIterator out_it)
|
Chris@16
|
463 {
|
Chris@16
|
464 return airy_bi_zero<T>(start_index, number_of_zeros, out_it, policies::policy<>());
|
Chris@16
|
465 }
|
Chris@16
|
466
|
Chris@16
|
467 }} // namespaces
|
Chris@16
|
468
|
Chris@16
|
469 #endif // BOOST_MATH_AIRY_HPP
|