comparison DEPENDENCIES/generic/include/boost/math/special_functions/airy.hpp @ 101:c530137014c0

Update Boost headers (1.58.0)
author Chris Cannam
date Mon, 07 Sep 2015 11:12:49 +0100
parents 2665513ce2d3
children
comparison
equal deleted inserted replaced
100:793467b5e61c 101:c530137014c0
5 // or copy at http://www.boost.org/LICENSE_1_0.txt) 5 // or copy at http://www.boost.org/LICENSE_1_0.txt)
6 6
7 #ifndef BOOST_MATH_AIRY_HPP 7 #ifndef BOOST_MATH_AIRY_HPP
8 #define BOOST_MATH_AIRY_HPP 8 #define BOOST_MATH_AIRY_HPP
9 9
10 #include <limits>
11 #include <boost/math/special_functions/math_fwd.hpp>
10 #include <boost/math/special_functions/bessel.hpp> 12 #include <boost/math/special_functions/bessel.hpp>
11 #include <boost/math/special_functions/cbrt.hpp> 13 #include <boost/math/special_functions/cbrt.hpp>
12 #include <boost/math/special_functions/detail/airy_ai_bi_zero.hpp> 14 #include <boost/math/special_functions/detail/airy_ai_bi_zero.hpp>
13 #include <boost/math/tools/roots.hpp> 15 #include <boost/math/tools/roots.hpp>
14 16
152 return aip; 154 return aip;
153 } 155 }
154 } 156 }
155 157
156 template <class T, class Policy> 158 template <class T, class Policy>
157 T airy_ai_zero_imp(unsigned m, const Policy& pol) 159 T airy_ai_zero_imp(int m, const Policy& pol)
158 { 160 {
159 BOOST_MATH_STD_USING // ADL of std names, needed for log, sqrt. 161 BOOST_MATH_STD_USING // ADL of std names, needed for log, sqrt.
162
163 // Handle cases when a negative zero (negative rank) is requested.
164 if(m < 0)
165 {
166 return policies::raise_domain_error<T>("boost::math::airy_ai_zero<%1%>(%1%, int)",
167 "Requested the %1%'th zero, but the rank must be 1 or more !", static_cast<T>(m), pol);
168 }
160 169
161 // Handle case when the zero'th zero is requested. 170 // Handle case when the zero'th zero is requested.
162 if(m == 0U) 171 if(m == 0U)
163 { 172 {
164 return policies::raise_domain_error<T>("boost::math::airy_ai_zero<%1%>(%1%,%1%)", 173 return policies::raise_domain_error<T>("boost::math::airy_ai_zero<%1%>(%1%,%1%)",
166 } 175 }
167 176
168 // Set up the initial guess for the upcoming root-finding. 177 // Set up the initial guess for the upcoming root-finding.
169 const T guess_root = boost::math::detail::airy_zero::airy_ai_zero_detail::initial_guess<T>(m); 178 const T guess_root = boost::math::detail::airy_zero::airy_ai_zero_detail::initial_guess<T>(m);
170 179
171 // Select the maximum allowed iterations, being at least 24. 180 // Select the maximum allowed iterations based on the number
172 boost::uintmax_t number_of_iterations = (std::max)(24, int(std::numeric_limits<T>::digits10)); 181 // of decimal digits in the numeric type T, being at least 12.
173 182 const int my_digits10 = static_cast<int>(static_cast<float>(policies::digits<T, Policy>() * 0.301F));
174 // Select the desired number of binary digits of precision. 183
175 // Account for the radix of number representations having non-two radix! 184 const boost::uintmax_t iterations_allowed = static_cast<boost::uintmax_t>((std::max)(12, my_digits10 * 2));
176 const int my_digits2 = int(float(std::numeric_limits<T>::digits) 185
177 * ( log(float(std::numeric_limits<T>::radix)) 186 boost::uintmax_t iterations_used = iterations_allowed;
178 / log(2.0F)));
179 187
180 // Use a dynamic tolerance because the roots get closer the higher m gets. 188 // Use a dynamic tolerance because the roots get closer the higher m gets.
181 T tolerance; 189 T tolerance;
182 190
183 if (m <= 10U) { tolerance = T(0.3F); } 191 if (m <= 10) { tolerance = T(0.3F); }
184 else if(m <= 100U) { tolerance = T(0.1F); } 192 else if(m <= 100) { tolerance = T(0.1F); }
185 else if(m <= 1000U) { tolerance = T(0.05F); } 193 else if(m <= 1000) { tolerance = T(0.05F); }
186 else { tolerance = T(1) / sqrt(T(m)); } 194 else { tolerance = T(1) / sqrt(T(m)); }
187 195
188 // Perform the root-finding using Newton-Raphson iteration from Boost.Math. 196 // Perform the root-finding using Newton-Raphson iteration from Boost.Math.
189 const T am = 197 const T am =
190 boost::math::tools::newton_raphson_iterate( 198 boost::math::tools::newton_raphson_iterate(
191 boost::math::detail::airy_zero::airy_ai_zero_detail::function_object_ai_and_ai_prime<T, Policy>(pol), 199 boost::math::detail::airy_zero::airy_ai_zero_detail::function_object_ai_and_ai_prime<T, Policy>(pol),
192 guess_root, 200 guess_root,
193 T(guess_root - tolerance), 201 T(guess_root - tolerance),
194 T(guess_root + tolerance), 202 T(guess_root + tolerance),
195 my_digits2, 203 policies::digits<T, Policy>(),
196 number_of_iterations); 204 iterations_used);
197 205
198 static_cast<void>(number_of_iterations); 206 static_cast<void>(iterations_used);
199 207
200 return am; 208 return am;
201 } 209 }
202 210
203 template <class T, class Policy> 211 template <class T, class Policy>
204 T airy_bi_zero_imp(unsigned m, const Policy& pol) 212 T airy_bi_zero_imp(int m, const Policy& pol)
205 { 213 {
206 BOOST_MATH_STD_USING // ADL of std names, needed for log, sqrt. 214 BOOST_MATH_STD_USING // ADL of std names, needed for log, sqrt.
215
216 // Handle cases when a negative zero (negative rank) is requested.
217 if(m < 0)
218 {
219 return policies::raise_domain_error<T>("boost::math::airy_bi_zero<%1%>(%1%, int)",
220 "Requested the %1%'th zero, but the rank must 1 or more !", static_cast<T>(m), pol);
221 }
207 222
208 // Handle case when the zero'th zero is requested. 223 // Handle case when the zero'th zero is requested.
209 if(m == 0U) 224 if(m == 0U)
210 { 225 {
211 return policies::raise_domain_error<T>("boost::math::airy_bi_zero<%1%>(%1%,%1%)", 226 return policies::raise_domain_error<T>("boost::math::airy_bi_zero<%1%>(%1%,%1%)",
212 "The requested rank of the zero is %1%, but must be 1 or more !", static_cast<T>(m), pol); 227 "The requested rank of the zero is %1%, but must be 1 or more !", static_cast<T>(m), pol);
213 } 228 }
214 // Set up the initial guess for the upcoming root-finding. 229 // Set up the initial guess for the upcoming root-finding.
215 const T guess_root = boost::math::detail::airy_zero::airy_bi_zero_detail::initial_guess<T>(m); 230 const T guess_root = boost::math::detail::airy_zero::airy_bi_zero_detail::initial_guess<T>(m);
216 231
217 // Select the maximum allowed iterations, being at least 24. 232 // Select the maximum allowed iterations based on the number
218 boost::uintmax_t number_of_iterations = (std::max)(24, int(std::numeric_limits<T>::digits10)); 233 // of decimal digits in the numeric type T, being at least 12.
219 234 const int my_digits10 = static_cast<int>(static_cast<float>(policies::digits<T, Policy>() * 0.301F));
220 // Select the desired number of binary digits of precision. 235
221 // Account for the radix of number representations having non-two radix! 236 const boost::uintmax_t iterations_allowed = static_cast<boost::uintmax_t>((std::max)(12, my_digits10 * 2));
222 const int my_digits2 = int(float(std::numeric_limits<T>::digits) 237
223 * ( log(float(std::numeric_limits<T>::radix)) 238 boost::uintmax_t iterations_used = iterations_allowed;
224 / log(2.0F)));
225 239
226 // Use a dynamic tolerance because the roots get closer the higher m gets. 240 // Use a dynamic tolerance because the roots get closer the higher m gets.
227 T tolerance; 241 T tolerance;
228 242
229 if (m <= 10U) { tolerance = T(0.3F); } 243 if (m <= 10) { tolerance = T(0.3F); }
230 else if(m <= 100U) { tolerance = T(0.1F); } 244 else if(m <= 100) { tolerance = T(0.1F); }
231 else if(m <= 1000U) { tolerance = T(0.05F); } 245 else if(m <= 1000) { tolerance = T(0.05F); }
232 else { tolerance = T(1) / sqrt(T(m)); } 246 else { tolerance = T(1) / sqrt(T(m)); }
233 247
234 // Perform the root-finding using Newton-Raphson iteration from Boost.Math. 248 // Perform the root-finding using Newton-Raphson iteration from Boost.Math.
235 const T bm = 249 const T bm =
236 boost::math::tools::newton_raphson_iterate( 250 boost::math::tools::newton_raphson_iterate(
237 boost::math::detail::airy_zero::airy_bi_zero_detail::function_object_bi_and_bi_prime<T, Policy>(pol), 251 boost::math::detail::airy_zero::airy_bi_zero_detail::function_object_bi_and_bi_prime<T, Policy>(pol),
238 guess_root, 252 guess_root,
239 T(guess_root - tolerance), 253 T(guess_root - tolerance),
240 T(guess_root + tolerance), 254 T(guess_root + tolerance),
241 my_digits2, 255 policies::digits<T, Policy>(),
242 number_of_iterations); 256 iterations_used);
243 257
244 static_cast<void>(number_of_iterations); 258 static_cast<void>(iterations_used);
245 259
246 return bm; 260 return bm;
247 } 261 }
248 262
249 } // namespace detail 263 } // namespace detail
335 { 349 {
336 return airy_bi_prime(x, policies::policy<>()); 350 return airy_bi_prime(x, policies::policy<>());
337 } 351 }
338 352
339 template <class T, class Policy> 353 template <class T, class Policy>
340 inline T airy_ai_zero(unsigned m, const Policy& /*pol*/) 354 inline T airy_ai_zero(int m, const Policy& /*pol*/)
341 { 355 {
342 BOOST_FPU_EXCEPTION_GUARD 356 BOOST_FPU_EXCEPTION_GUARD
343 typedef typename policies::evaluation<T, Policy>::type value_type; 357 typedef typename policies::evaluation<T, Policy>::type value_type;
344 typedef typename policies::normalise< 358 typedef typename policies::normalise<
345 Policy, 359 Policy,
346 policies::promote_float<false>, 360 policies::promote_float<false>,
347 policies::promote_double<false>, 361 policies::promote_double<false>,
348 policies::discrete_quantile<>, 362 policies::discrete_quantile<>,
349 policies::assert_undefined<> >::type forwarding_policy; 363 policies::assert_undefined<> >::type forwarding_policy;
350 BOOST_STATIC_ASSERT_MSG(false == std::numeric_limits<T>::is_integer, "Airy return type must be a floating-point type."); 364
365 BOOST_STATIC_ASSERT_MSG( false == std::numeric_limits<T>::is_specialized
366 || ( true == std::numeric_limits<T>::is_specialized
367 && false == std::numeric_limits<T>::is_integer),
368 "Airy value type must be a floating-point type.");
369
351 return policies::checked_narrowing_cast<T, Policy>(detail::airy_ai_zero_imp<value_type>(m, forwarding_policy()), "boost::math::airy_ai_zero<%1%>(unsigned)"); 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)");
352 } 371 }
353 372
354 template <class T> 373 template <class T>
355 inline T airy_ai_zero(unsigned m) 374 inline T airy_ai_zero(int m)
356 { 375 {
357 return airy_ai_zero<T>(m, policies::policy<>()); 376 return airy_ai_zero<T>(m, policies::policy<>());
358 } 377 }
359 378
360 template <class T, class OutputIterator, class Policy> 379 template <class T, class OutputIterator, class Policy>
361 inline OutputIterator airy_ai_zero( 380 inline OutputIterator airy_ai_zero(
362 unsigned start_index, 381 int start_index,
363 unsigned number_of_zeros, 382 unsigned number_of_zeros,
364 OutputIterator out_it, 383 OutputIterator out_it,
365 const Policy& pol) 384 const Policy& pol)
366 { 385 {
367 typedef T result_type; 386 typedef T result_type;
368 BOOST_STATIC_ASSERT_MSG(false == std::numeric_limits<result_type>::is_integer, "Airy return type must be a floating-point type."); 387
388 BOOST_STATIC_ASSERT_MSG( false == std::numeric_limits<T>::is_specialized
389 || ( true == std::numeric_limits<T>::is_specialized
390 && false == std::numeric_limits<T>::is_integer),
391 "Airy value type must be a floating-point type.");
369 392
370 for(unsigned i = 0; i < number_of_zeros; ++i) 393 for(unsigned i = 0; i < number_of_zeros; ++i)
371 { 394 {
372 *out_it = boost::math::airy_ai_zero<result_type>(start_index + i, pol); 395 *out_it = boost::math::airy_ai_zero<result_type>(start_index + i, pol);
373 ++out_it; 396 ++out_it;
375 return out_it; 398 return out_it;
376 } 399 }
377 400
378 template <class T, class OutputIterator> 401 template <class T, class OutputIterator>
379 inline OutputIterator airy_ai_zero( 402 inline OutputIterator airy_ai_zero(
380 unsigned start_index, 403 int start_index,
381 unsigned number_of_zeros, 404 unsigned number_of_zeros,
382 OutputIterator out_it) 405 OutputIterator out_it)
383 { 406 {
384 return airy_ai_zero<T>(start_index, number_of_zeros, out_it, policies::policy<>()); 407 return airy_ai_zero<T>(start_index, number_of_zeros, out_it, policies::policy<>());
385 } 408 }
386 409
387 template <class T, class Policy> 410 template <class T, class Policy>
388 inline T airy_bi_zero(unsigned m, const Policy& /*pol*/) 411 inline T airy_bi_zero(int m, const Policy& /*pol*/)
389 { 412 {
390 BOOST_FPU_EXCEPTION_GUARD 413 BOOST_FPU_EXCEPTION_GUARD
391 typedef typename policies::evaluation<T, Policy>::type value_type; 414 typedef typename policies::evaluation<T, Policy>::type value_type;
392 typedef typename policies::normalise< 415 typedef typename policies::normalise<
393 Policy, 416 Policy,
394 policies::promote_float<false>, 417 policies::promote_float<false>,
395 policies::promote_double<false>, 418 policies::promote_double<false>,
396 policies::discrete_quantile<>, 419 policies::discrete_quantile<>,
397 policies::assert_undefined<> >::type forwarding_policy; 420 policies::assert_undefined<> >::type forwarding_policy;
398 BOOST_STATIC_ASSERT_MSG(false == std::numeric_limits<T>::is_integer, "Airy return type must be a floating-point type."); 421
422 BOOST_STATIC_ASSERT_MSG( false == std::numeric_limits<T>::is_specialized
423 || ( true == std::numeric_limits<T>::is_specialized
424 && false == std::numeric_limits<T>::is_integer),
425 "Airy value type must be a floating-point type.");
426
399 return policies::checked_narrowing_cast<T, Policy>(detail::airy_bi_zero_imp<value_type>(m, forwarding_policy()), "boost::math::airy_bi_zero<%1%>(unsigned)"); 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)");
400 } 428 }
401 429
402 template <typename T> 430 template <typename T>
403 inline T airy_bi_zero(unsigned m) 431 inline T airy_bi_zero(int m)
404 { 432 {
405 return airy_bi_zero<T>(m, policies::policy<>()); 433 return airy_bi_zero<T>(m, policies::policy<>());
406 } 434 }
407 435
408 template <class T, class OutputIterator, class Policy> 436 template <class T, class OutputIterator, class Policy>
409 inline OutputIterator airy_bi_zero( 437 inline OutputIterator airy_bi_zero(
410 unsigned start_index, 438 int start_index,
411 unsigned number_of_zeros, 439 unsigned number_of_zeros,
412 OutputIterator out_it, 440 OutputIterator out_it,
413 const Policy& pol) 441 const Policy& pol)
414 { 442 {
415 typedef T result_type; 443 typedef T result_type;
416 BOOST_STATIC_ASSERT_MSG(false == std::numeric_limits<result_type>::is_integer, "Airy return type must be a floating-point type."); 444
445 BOOST_STATIC_ASSERT_MSG( false == std::numeric_limits<T>::is_specialized
446 || ( true == std::numeric_limits<T>::is_specialized
447 && false == std::numeric_limits<T>::is_integer),
448 "Airy value type must be a floating-point type.");
417 449
418 for(unsigned i = 0; i < number_of_zeros; ++i) 450 for(unsigned i = 0; i < number_of_zeros; ++i)
419 { 451 {
420 *out_it = boost::math::airy_bi_zero<result_type>(start_index + i, pol); 452 *out_it = boost::math::airy_bi_zero<result_type>(start_index + i, pol);
421 ++out_it; 453 ++out_it;
423 return out_it; 455 return out_it;
424 } 456 }
425 457
426 template <class T, class OutputIterator> 458 template <class T, class OutputIterator>
427 inline OutputIterator airy_bi_zero( 459 inline OutputIterator airy_bi_zero(
428 unsigned start_index, 460 int start_index,
429 unsigned number_of_zeros, 461 unsigned number_of_zeros,
430 OutputIterator out_it) 462 OutputIterator out_it)
431 { 463 {
432 return airy_bi_zero<T>(start_index, number_of_zeros, out_it, policies::policy<>()); 464 return airy_bi_zero<T>(start_index, number_of_zeros, out_it, policies::policy<>());
433 } 465 }