annotate DEPENDENCIES/generic/include/boost/math/special_functions/bessel.hpp @ 125:34e428693f5d vext

Vext -> Repoint
author Chris Cannam
date Thu, 14 Jun 2018 11:15:39 +0100
parents c530137014c0
children
rev   line source
Chris@16 1 // Copyright (c) 2007, 2013 John Maddock
Chris@16 2 // Copyright Christopher Kormanyos 2013.
Chris@16 3 // Use, modification and distribution are subject to the
Chris@16 4 // Boost Software License, Version 1.0. (See accompanying file
Chris@16 5 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
Chris@16 6 //
Chris@16 7 // This header just defines the function entry points, and adds dispatch
Chris@16 8 // to the right implementation method. Most of the implementation details
Chris@16 9 // are in separate headers and copyright Xiaogang Zhang.
Chris@16 10 //
Chris@16 11 #ifndef BOOST_MATH_BESSEL_HPP
Chris@16 12 #define BOOST_MATH_BESSEL_HPP
Chris@16 13
Chris@16 14 #ifdef _MSC_VER
Chris@16 15 # pragma once
Chris@16 16 #endif
Chris@16 17
Chris@101 18 #include <limits>
Chris@101 19 #include <boost/math/special_functions/math_fwd.hpp>
Chris@16 20 #include <boost/math/special_functions/detail/bessel_jy.hpp>
Chris@16 21 #include <boost/math/special_functions/detail/bessel_jn.hpp>
Chris@16 22 #include <boost/math/special_functions/detail/bessel_yn.hpp>
Chris@16 23 #include <boost/math/special_functions/detail/bessel_jy_zero.hpp>
Chris@16 24 #include <boost/math/special_functions/detail/bessel_ik.hpp>
Chris@16 25 #include <boost/math/special_functions/detail/bessel_i0.hpp>
Chris@16 26 #include <boost/math/special_functions/detail/bessel_i1.hpp>
Chris@16 27 #include <boost/math/special_functions/detail/bessel_kn.hpp>
Chris@16 28 #include <boost/math/special_functions/detail/iconv.hpp>
Chris@16 29 #include <boost/math/special_functions/sin_pi.hpp>
Chris@16 30 #include <boost/math/special_functions/cos_pi.hpp>
Chris@16 31 #include <boost/math/special_functions/sinc.hpp>
Chris@16 32 #include <boost/math/special_functions/trunc.hpp>
Chris@16 33 #include <boost/math/special_functions/round.hpp>
Chris@16 34 #include <boost/math/tools/rational.hpp>
Chris@16 35 #include <boost/math/tools/promotion.hpp>
Chris@16 36 #include <boost/math/tools/series.hpp>
Chris@16 37 #include <boost/math/tools/roots.hpp>
Chris@16 38
Chris@16 39 namespace boost{ namespace math{
Chris@16 40
Chris@16 41 namespace detail{
Chris@16 42
Chris@16 43 template <class T, class Policy>
Chris@16 44 struct sph_bessel_j_small_z_series_term
Chris@16 45 {
Chris@16 46 typedef T result_type;
Chris@16 47
Chris@16 48 sph_bessel_j_small_z_series_term(unsigned v_, T x)
Chris@16 49 : N(0), v(v_)
Chris@16 50 {
Chris@16 51 BOOST_MATH_STD_USING
Chris@16 52 mult = x / 2;
Chris@16 53 if(v + 3 > max_factorial<T>::value)
Chris@16 54 {
Chris@16 55 term = v * log(mult) - boost::math::lgamma(v+1+T(0.5f), Policy());
Chris@16 56 term = exp(term);
Chris@16 57 }
Chris@16 58 else
Chris@16 59 term = pow(mult, T(v)) / boost::math::tgamma(v+1+T(0.5f), Policy());
Chris@16 60 mult *= -mult;
Chris@16 61 }
Chris@16 62 T operator()()
Chris@16 63 {
Chris@16 64 T r = term;
Chris@16 65 ++N;
Chris@16 66 term *= mult / (N * T(N + v + 0.5f));
Chris@16 67 return r;
Chris@16 68 }
Chris@16 69 private:
Chris@16 70 unsigned N;
Chris@16 71 unsigned v;
Chris@16 72 T mult;
Chris@16 73 T term;
Chris@16 74 };
Chris@16 75
Chris@16 76 template <class T, class Policy>
Chris@16 77 inline T sph_bessel_j_small_z_series(unsigned v, T x, const Policy& pol)
Chris@16 78 {
Chris@16 79 BOOST_MATH_STD_USING // ADL of std names
Chris@16 80 sph_bessel_j_small_z_series_term<T, Policy> s(v, x);
Chris@16 81 boost::uintmax_t max_iter = policies::get_max_series_iterations<Policy>();
Chris@16 82 #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582))
Chris@16 83 T zero = 0;
Chris@16 84 T result = boost::math::tools::sum_series(s, boost::math::policies::get_epsilon<T, Policy>(), max_iter, zero);
Chris@16 85 #else
Chris@16 86 T result = boost::math::tools::sum_series(s, boost::math::policies::get_epsilon<T, Policy>(), max_iter);
Chris@16 87 #endif
Chris@16 88 policies::check_series_iterations<T>("boost::math::sph_bessel_j_small_z_series<%1%>(%1%,%1%)", max_iter, pol);
Chris@16 89 return result * sqrt(constants::pi<T>() / 4);
Chris@16 90 }
Chris@16 91
Chris@16 92 template <class T, class Policy>
Chris@16 93 T cyl_bessel_j_imp(T v, T x, const bessel_no_int_tag& t, const Policy& pol)
Chris@16 94 {
Chris@16 95 BOOST_MATH_STD_USING
Chris@16 96 static const char* function = "boost::math::bessel_j<%1%>(%1%,%1%)";
Chris@16 97 if(x < 0)
Chris@16 98 {
Chris@16 99 // better have integer v:
Chris@16 100 if(floor(v) == v)
Chris@16 101 {
Chris@16 102 T r = cyl_bessel_j_imp(v, T(-x), t, pol);
Chris@16 103 if(iround(v, pol) & 1)
Chris@16 104 r = -r;
Chris@16 105 return r;
Chris@16 106 }
Chris@16 107 else
Chris@16 108 return policies::raise_domain_error<T>(
Chris@16 109 function,
Chris@16 110 "Got x = %1%, but we need x >= 0", x, pol);
Chris@16 111 }
Chris@16 112
Chris@16 113 T j, y;
Chris@16 114 bessel_jy(v, x, &j, &y, need_j, pol);
Chris@16 115 return j;
Chris@16 116 }
Chris@16 117
Chris@16 118 template <class T, class Policy>
Chris@16 119 inline T cyl_bessel_j_imp(T v, T x, const bessel_maybe_int_tag&, const Policy& pol)
Chris@16 120 {
Chris@16 121 BOOST_MATH_STD_USING // ADL of std names.
Chris@16 122 int ival = detail::iconv(v, pol);
Chris@16 123 // If v is an integer, use the integer recursion
Chris@16 124 // method, both that and Steeds method are O(v):
Chris@16 125 if((0 == v - ival))
Chris@16 126 {
Chris@16 127 return bessel_jn(ival, x, pol);
Chris@16 128 }
Chris@16 129 return cyl_bessel_j_imp(v, x, bessel_no_int_tag(), pol);
Chris@16 130 }
Chris@16 131
Chris@16 132 template <class T, class Policy>
Chris@16 133 inline T cyl_bessel_j_imp(int v, T x, const bessel_int_tag&, const Policy& pol)
Chris@16 134 {
Chris@16 135 BOOST_MATH_STD_USING
Chris@16 136 return bessel_jn(v, x, pol);
Chris@16 137 }
Chris@16 138
Chris@16 139 template <class T, class Policy>
Chris@16 140 inline T sph_bessel_j_imp(unsigned n, T x, const Policy& pol)
Chris@16 141 {
Chris@16 142 BOOST_MATH_STD_USING // ADL of std names
Chris@16 143 if(x < 0)
Chris@16 144 return policies::raise_domain_error<T>(
Chris@16 145 "boost::math::sph_bessel_j<%1%>(%1%,%1%)",
Chris@16 146 "Got x = %1%, but function requires x > 0.", x, pol);
Chris@16 147 //
Chris@16 148 // Special case, n == 0 resolves down to the sinus cardinal of x:
Chris@16 149 //
Chris@16 150 if(n == 0)
Chris@16 151 return boost::math::sinc_pi(x, pol);
Chris@16 152 //
Chris@16 153 // Special case for x == 0:
Chris@16 154 //
Chris@16 155 if(x == 0)
Chris@16 156 return 0;
Chris@16 157 //
Chris@16 158 // When x is small we may end up with 0/0, use series evaluation
Chris@16 159 // instead, especially as it converges rapidly:
Chris@16 160 //
Chris@16 161 if(x < 1)
Chris@16 162 return sph_bessel_j_small_z_series(n, x, pol);
Chris@16 163 //
Chris@16 164 // Default case is just a naive evaluation of the definition:
Chris@16 165 //
Chris@16 166 return sqrt(constants::pi<T>() / (2 * x))
Chris@16 167 * cyl_bessel_j_imp(T(T(n)+T(0.5f)), x, bessel_no_int_tag(), pol);
Chris@16 168 }
Chris@16 169
Chris@16 170 template <class T, class Policy>
Chris@16 171 T cyl_bessel_i_imp(T v, T x, const Policy& pol)
Chris@16 172 {
Chris@16 173 //
Chris@16 174 // This handles all the bessel I functions, note that we don't optimise
Chris@16 175 // for integer v, other than the v = 0 or 1 special cases, as Millers
Chris@16 176 // algorithm is at least as inefficient as the general case (the general
Chris@16 177 // case has better error handling too).
Chris@16 178 //
Chris@16 179 BOOST_MATH_STD_USING
Chris@16 180 if(x < 0)
Chris@16 181 {
Chris@16 182 // better have integer v:
Chris@16 183 if(floor(v) == v)
Chris@16 184 {
Chris@16 185 T r = cyl_bessel_i_imp(v, T(-x), pol);
Chris@16 186 if(iround(v, pol) & 1)
Chris@16 187 r = -r;
Chris@16 188 return r;
Chris@16 189 }
Chris@16 190 else
Chris@16 191 return policies::raise_domain_error<T>(
Chris@16 192 "boost::math::cyl_bessel_i<%1%>(%1%,%1%)",
Chris@16 193 "Got x = %1%, but we need x >= 0", x, pol);
Chris@16 194 }
Chris@16 195 if(x == 0)
Chris@16 196 {
Chris@101 197 return (v == 0) ? static_cast<T>(1) : static_cast<T>(0);
Chris@16 198 }
Chris@16 199 if(v == 0.5f)
Chris@16 200 {
Chris@16 201 // common special case, note try and avoid overflow in exp(x):
Chris@16 202 if(x >= tools::log_max_value<T>())
Chris@16 203 {
Chris@16 204 T e = exp(x / 2);
Chris@16 205 return e * (e / sqrt(2 * x * constants::pi<T>()));
Chris@16 206 }
Chris@16 207 return sqrt(2 / (x * constants::pi<T>())) * sinh(x);
Chris@16 208 }
Chris@16 209 if(policies::digits<T, Policy>() <= 64)
Chris@16 210 {
Chris@16 211 if(v == 0)
Chris@16 212 {
Chris@16 213 return bessel_i0(x);
Chris@16 214 }
Chris@16 215 if(v == 1)
Chris@16 216 {
Chris@16 217 return bessel_i1(x);
Chris@16 218 }
Chris@16 219 }
Chris@16 220 if((v > 0) && (x / v < 0.25))
Chris@16 221 return bessel_i_small_z_series(v, x, pol);
Chris@16 222 T I, K;
Chris@16 223 bessel_ik(v, x, &I, &K, need_i, pol);
Chris@16 224 return I;
Chris@16 225 }
Chris@16 226
Chris@16 227 template <class T, class Policy>
Chris@16 228 inline T cyl_bessel_k_imp(T v, T x, const bessel_no_int_tag& /* t */, const Policy& pol)
Chris@16 229 {
Chris@16 230 static const char* function = "boost::math::cyl_bessel_k<%1%>(%1%,%1%)";
Chris@16 231 BOOST_MATH_STD_USING
Chris@16 232 if(x < 0)
Chris@16 233 {
Chris@16 234 return policies::raise_domain_error<T>(
Chris@16 235 function,
Chris@16 236 "Got x = %1%, but we need x > 0", x, pol);
Chris@16 237 }
Chris@16 238 if(x == 0)
Chris@16 239 {
Chris@16 240 return (v == 0) ? policies::raise_overflow_error<T>(function, 0, pol)
Chris@16 241 : policies::raise_domain_error<T>(
Chris@16 242 function,
Chris@16 243 "Got x = %1%, but we need x > 0", x, pol);
Chris@16 244 }
Chris@16 245 T I, K;
Chris@16 246 bessel_ik(v, x, &I, &K, need_k, pol);
Chris@16 247 return K;
Chris@16 248 }
Chris@16 249
Chris@16 250 template <class T, class Policy>
Chris@16 251 inline T cyl_bessel_k_imp(T v, T x, const bessel_maybe_int_tag&, const Policy& pol)
Chris@16 252 {
Chris@16 253 BOOST_MATH_STD_USING
Chris@16 254 if((floor(v) == v))
Chris@16 255 {
Chris@16 256 return bessel_kn(itrunc(v), x, pol);
Chris@16 257 }
Chris@16 258 return cyl_bessel_k_imp(v, x, bessel_no_int_tag(), pol);
Chris@16 259 }
Chris@16 260
Chris@16 261 template <class T, class Policy>
Chris@16 262 inline T cyl_bessel_k_imp(int v, T x, const bessel_int_tag&, const Policy& pol)
Chris@16 263 {
Chris@16 264 return bessel_kn(v, x, pol);
Chris@16 265 }
Chris@16 266
Chris@16 267 template <class T, class Policy>
Chris@16 268 inline T cyl_neumann_imp(T v, T x, const bessel_no_int_tag&, const Policy& pol)
Chris@16 269 {
Chris@16 270 static const char* function = "boost::math::cyl_neumann<%1%>(%1%,%1%)";
Chris@16 271
Chris@16 272 BOOST_MATH_INSTRUMENT_VARIABLE(v);
Chris@16 273 BOOST_MATH_INSTRUMENT_VARIABLE(x);
Chris@16 274
Chris@16 275 if(x <= 0)
Chris@16 276 {
Chris@16 277 return (v == 0) && (x == 0) ?
Chris@16 278 policies::raise_overflow_error<T>(function, 0, pol)
Chris@16 279 : policies::raise_domain_error<T>(
Chris@16 280 function,
Chris@16 281 "Got x = %1%, but result is complex for x <= 0", x, pol);
Chris@16 282 }
Chris@16 283 T j, y;
Chris@16 284 bessel_jy(v, x, &j, &y, need_y, pol);
Chris@16 285 //
Chris@16 286 // Post evaluation check for internal overflow during evaluation,
Chris@16 287 // can occur when x is small and v is large, in which case the result
Chris@16 288 // is -INF:
Chris@16 289 //
Chris@16 290 if(!(boost::math::isfinite)(y))
Chris@16 291 return -policies::raise_overflow_error<T>(function, 0, pol);
Chris@16 292 return y;
Chris@16 293 }
Chris@16 294
Chris@16 295 template <class T, class Policy>
Chris@16 296 inline T cyl_neumann_imp(T v, T x, const bessel_maybe_int_tag&, const Policy& pol)
Chris@16 297 {
Chris@16 298 BOOST_MATH_STD_USING
Chris@16 299
Chris@16 300 BOOST_MATH_INSTRUMENT_VARIABLE(v);
Chris@16 301 BOOST_MATH_INSTRUMENT_VARIABLE(x);
Chris@16 302
Chris@16 303 if(floor(v) == v)
Chris@16 304 {
Chris@16 305 if(asymptotic_bessel_large_x_limit(v, x))
Chris@16 306 {
Chris@16 307 T r = asymptotic_bessel_y_large_x_2(static_cast<T>(abs(v)), x);
Chris@16 308 if((v < 0) && (itrunc(v, pol) & 1))
Chris@16 309 r = -r;
Chris@16 310 BOOST_MATH_INSTRUMENT_VARIABLE(r);
Chris@16 311 return r;
Chris@16 312 }
Chris@16 313 else
Chris@16 314 {
Chris@16 315 T r = bessel_yn(itrunc(v, pol), x, pol);
Chris@16 316 BOOST_MATH_INSTRUMENT_VARIABLE(r);
Chris@16 317 return r;
Chris@16 318 }
Chris@16 319 }
Chris@16 320 T r = cyl_neumann_imp<T>(v, x, bessel_no_int_tag(), pol);
Chris@16 321 BOOST_MATH_INSTRUMENT_VARIABLE(r);
Chris@16 322 return r;
Chris@16 323 }
Chris@16 324
Chris@16 325 template <class T, class Policy>
Chris@16 326 inline T cyl_neumann_imp(int v, T x, const bessel_int_tag&, const Policy& pol)
Chris@16 327 {
Chris@16 328 BOOST_MATH_STD_USING
Chris@16 329
Chris@16 330 BOOST_MATH_INSTRUMENT_VARIABLE(v);
Chris@16 331 BOOST_MATH_INSTRUMENT_VARIABLE(x);
Chris@16 332
Chris@16 333 if(asymptotic_bessel_large_x_limit(T(v), x))
Chris@16 334 {
Chris@16 335 T r = asymptotic_bessel_y_large_x_2(static_cast<T>(abs(v)), x);
Chris@16 336 if((v < 0) && (v & 1))
Chris@16 337 r = -r;
Chris@16 338 return r;
Chris@16 339 }
Chris@16 340 else
Chris@16 341 return bessel_yn(v, x, pol);
Chris@16 342 }
Chris@16 343
Chris@16 344 template <class T, class Policy>
Chris@16 345 inline T sph_neumann_imp(unsigned v, T x, const Policy& pol)
Chris@16 346 {
Chris@16 347 BOOST_MATH_STD_USING // ADL of std names
Chris@16 348 static const char* function = "boost::math::sph_neumann<%1%>(%1%,%1%)";
Chris@16 349 //
Chris@16 350 // Nothing much to do here but check for errors, and
Chris@16 351 // evaluate the function's definition directly:
Chris@16 352 //
Chris@16 353 if(x < 0)
Chris@16 354 return policies::raise_domain_error<T>(
Chris@16 355 function,
Chris@16 356 "Got x = %1%, but function requires x > 0.", x, pol);
Chris@16 357
Chris@16 358 if(x < 2 * tools::min_value<T>())
Chris@16 359 return -policies::raise_overflow_error<T>(function, 0, pol);
Chris@16 360
Chris@16 361 T result = cyl_neumann_imp(T(T(v)+0.5f), x, bessel_no_int_tag(), pol);
Chris@16 362 T tx = sqrt(constants::pi<T>() / (2 * x));
Chris@16 363
Chris@16 364 if((tx > 1) && (tools::max_value<T>() / tx < result))
Chris@16 365 return -policies::raise_overflow_error<T>(function, 0, pol);
Chris@16 366
Chris@16 367 return result * tx;
Chris@16 368 }
Chris@16 369
Chris@16 370 template <class T, class Policy>
Chris@16 371 inline T cyl_bessel_j_zero_imp(T v, int m, const Policy& pol)
Chris@16 372 {
Chris@16 373 BOOST_MATH_STD_USING // ADL of std names, needed for floor.
Chris@16 374
Chris@16 375 static const char* function = "boost::math::cyl_bessel_j_zero<%1%>(%1%, int)";
Chris@16 376
Chris@16 377 const T half_epsilon(boost::math::tools::epsilon<T>() / 2U);
Chris@16 378
Chris@16 379 // Handle non-finite order.
Chris@16 380 if (!(boost::math::isfinite)(v) )
Chris@16 381 {
Chris@16 382 return policies::raise_domain_error<T>(function, "Order argument is %1%, but must be finite >= 0 !", v, pol);
Chris@16 383 }
Chris@16 384
Chris@16 385 // Handle negative rank.
Chris@16 386 if(m < 0)
Chris@16 387 {
Chris@16 388 // Zeros of Jv(x) with negative rank are not defined and requesting one raises a domain error.
Chris@101 389 return policies::raise_domain_error<T>(function, "Requested the %1%'th zero, but the rank must be positive !", static_cast<T>(m), pol);
Chris@16 390 }
Chris@16 391
Chris@16 392 // Get the absolute value of the order.
Chris@16 393 const bool order_is_negative = (v < 0);
Chris@16 394 const T vv((!order_is_negative) ? v : T(-v));
Chris@16 395
Chris@16 396 // Check if the order is very close to zero or very close to an integer.
Chris@16 397 const bool order_is_zero = (vv < half_epsilon);
Chris@16 398 const bool order_is_integer = ((vv - floor(vv)) < half_epsilon);
Chris@16 399
Chris@16 400 if(m == 0)
Chris@16 401 {
Chris@16 402 if(order_is_zero)
Chris@16 403 {
Chris@16 404 // The zero'th zero of J0(x) is not defined and requesting it raises a domain error.
Chris@101 405 return policies::raise_domain_error<T>(function, "Requested the %1%'th zero of J0, but the rank must be > 0 !", static_cast<T>(m), pol);
Chris@16 406 }
Chris@16 407
Chris@16 408 // The zero'th zero of Jv(x) for v < 0 is not defined
Chris@16 409 // unless the order is a negative integer.
Chris@16 410 if(order_is_negative && (!order_is_integer))
Chris@16 411 {
Chris@16 412 // For non-integer, negative order, requesting the zero'th zero raises a domain error.
Chris@101 413 return policies::raise_domain_error<T>(function, "Requested the %1%'th zero of Jv for negative, non-integer order, but the rank must be > 0 !", static_cast<T>(m), pol);
Chris@16 414 }
Chris@16 415
Chris@16 416 // The zero'th zero does exist and its value is zero.
Chris@16 417 return T(0);
Chris@16 418 }
Chris@16 419
Chris@16 420 // Set up the initial guess for the upcoming root-finding.
Chris@16 421 // If the order is a negative integer, then use the corresponding
Chris@16 422 // positive integer for the order.
Chris@16 423 const T guess_root = boost::math::detail::bessel_zero::cyl_bessel_j_zero_detail::initial_guess<T, Policy>((order_is_integer ? vv : v), m, pol);
Chris@16 424
Chris@16 425 // Select the maximum allowed iterations from the policy.
Chris@16 426 boost::uintmax_t number_of_iterations = policies::get_max_root_iterations<Policy>();
Chris@16 427
Chris@16 428 const T delta_lo = ((guess_root > 0.2F) ? T(0.2) : T(guess_root / 2U));
Chris@16 429
Chris@16 430 // Perform the root-finding using Newton-Raphson iteration from Boost.Math.
Chris@16 431 const T jvm =
Chris@16 432 boost::math::tools::newton_raphson_iterate(
Chris@16 433 boost::math::detail::bessel_zero::cyl_bessel_j_zero_detail::function_object_jv_and_jv_prime<T, Policy>((order_is_integer ? vv : v), order_is_zero, pol),
Chris@16 434 guess_root,
Chris@16 435 T(guess_root - delta_lo),
Chris@16 436 T(guess_root + 0.2F),
Chris@101 437 policies::digits<T, Policy>(),
Chris@16 438 number_of_iterations);
Chris@16 439
Chris@16 440 if(number_of_iterations >= policies::get_max_root_iterations<Policy>())
Chris@16 441 {
Chris@101 442 return policies::raise_evaluation_error<T>(function, "Unable to locate root in a reasonable time:"
Chris@16 443 " Current best guess is %1%", jvm, Policy());
Chris@16 444 }
Chris@16 445
Chris@16 446 return jvm;
Chris@16 447 }
Chris@16 448
Chris@16 449 template <class T, class Policy>
Chris@16 450 inline T cyl_neumann_zero_imp(T v, int m, const Policy& pol)
Chris@16 451 {
Chris@16 452 BOOST_MATH_STD_USING // ADL of std names, needed for floor.
Chris@16 453
Chris@16 454 static const char* function = "boost::math::cyl_neumann_zero<%1%>(%1%, int)";
Chris@16 455
Chris@16 456 // Handle non-finite order.
Chris@16 457 if (!(boost::math::isfinite)(v) )
Chris@16 458 {
Chris@16 459 return policies::raise_domain_error<T>(function, "Order argument is %1%, but must be finite >= 0 !", v, pol);
Chris@16 460 }
Chris@16 461
Chris@16 462 // Handle negative rank.
Chris@16 463 if(m < 0)
Chris@16 464 {
Chris@101 465 return policies::raise_domain_error<T>(function, "Requested the %1%'th zero, but the rank must be positive !", static_cast<T>(m), pol);
Chris@16 466 }
Chris@16 467
Chris@16 468 const T half_epsilon(boost::math::tools::epsilon<T>() / 2U);
Chris@16 469
Chris@16 470 // Get the absolute value of the order.
Chris@16 471 const bool order_is_negative = (v < 0);
Chris@16 472 const T vv((!order_is_negative) ? v : T(-v));
Chris@16 473
Chris@16 474 const bool order_is_integer = ((vv - floor(vv)) < half_epsilon);
Chris@16 475
Chris@16 476 // For negative integers, use reflection to positive integer order.
Chris@16 477 if(order_is_negative && order_is_integer)
Chris@16 478 return boost::math::detail::cyl_neumann_zero_imp(vv, m, pol);
Chris@16 479
Chris@16 480 // Check if the order is very close to a negative half-integer.
Chris@16 481 const T delta_half_integer(vv - (floor(vv) + 0.5F));
Chris@16 482
Chris@16 483 const bool order_is_negative_half_integer =
Chris@16 484 (order_is_negative && ((delta_half_integer > -half_epsilon) && (delta_half_integer < +half_epsilon)));
Chris@16 485
Chris@16 486 // The zero'th zero of Yv(x) for v < 0 is not defined
Chris@16 487 // unless the order is a negative integer.
Chris@16 488 if((m == 0) && (!order_is_negative_half_integer))
Chris@16 489 {
Chris@16 490 // For non-integer, negative order, requesting the zero'th zero raises a domain error.
Chris@101 491 return policies::raise_domain_error<T>(function, "Requested the %1%'th zero of Yv for negative, non-half-integer order, but the rank must be > 0 !", static_cast<T>(m), pol);
Chris@16 492 }
Chris@16 493
Chris@16 494 // For negative half-integers, use the corresponding
Chris@16 495 // spherical Bessel function of positive half-integer order.
Chris@16 496 if(order_is_negative_half_integer)
Chris@16 497 return boost::math::detail::cyl_bessel_j_zero_imp(vv, m, pol);
Chris@16 498
Chris@16 499 // Set up the initial guess for the upcoming root-finding.
Chris@16 500 // If the order is a negative integer, then use the corresponding
Chris@16 501 // positive integer for the order.
Chris@16 502 const T guess_root = boost::math::detail::bessel_zero::cyl_neumann_zero_detail::initial_guess<T, Policy>(v, m, pol);
Chris@16 503
Chris@16 504 // Select the maximum allowed iterations from the policy.
Chris@16 505 boost::uintmax_t number_of_iterations = policies::get_max_root_iterations<Policy>();
Chris@16 506
Chris@16 507 const T delta_lo = ((guess_root > 0.2F) ? T(0.2) : T(guess_root / 2U));
Chris@16 508
Chris@16 509 // Perform the root-finding using Newton-Raphson iteration from Boost.Math.
Chris@16 510 const T yvm =
Chris@16 511 boost::math::tools::newton_raphson_iterate(
Chris@16 512 boost::math::detail::bessel_zero::cyl_neumann_zero_detail::function_object_yv_and_yv_prime<T, Policy>(v, pol),
Chris@16 513 guess_root,
Chris@16 514 T(guess_root - delta_lo),
Chris@16 515 T(guess_root + 0.2F),
Chris@101 516 policies::digits<T, Policy>(),
Chris@16 517 number_of_iterations);
Chris@16 518
Chris@16 519 if(number_of_iterations >= policies::get_max_root_iterations<Policy>())
Chris@16 520 {
Chris@101 521 return policies::raise_evaluation_error<T>(function, "Unable to locate root in a reasonable time:"
Chris@16 522 " Current best guess is %1%", yvm, Policy());
Chris@16 523 }
Chris@16 524
Chris@16 525 return yvm;
Chris@16 526 }
Chris@16 527
Chris@16 528 } // namespace detail
Chris@16 529
Chris@16 530 template <class T1, class T2, class Policy>
Chris@16 531 inline typename detail::bessel_traits<T1, T2, Policy>::result_type cyl_bessel_j(T1 v, T2 x, const Policy& /* pol */)
Chris@16 532 {
Chris@16 533 BOOST_FPU_EXCEPTION_GUARD
Chris@16 534 typedef typename detail::bessel_traits<T1, T2, Policy>::result_type result_type;
Chris@16 535 typedef typename detail::bessel_traits<T1, T2, Policy>::optimisation_tag tag_type;
Chris@16 536 typedef typename policies::evaluation<result_type, Policy>::type value_type;
Chris@16 537 typedef typename policies::normalise<
Chris@16 538 Policy,
Chris@16 539 policies::promote_float<false>,
Chris@16 540 policies::promote_double<false>,
Chris@16 541 policies::discrete_quantile<>,
Chris@16 542 policies::assert_undefined<> >::type forwarding_policy;
Chris@16 543 return policies::checked_narrowing_cast<result_type, Policy>(detail::cyl_bessel_j_imp<value_type>(v, static_cast<value_type>(x), tag_type(), forwarding_policy()), "boost::math::cyl_bessel_j<%1%>(%1%,%1%)");
Chris@16 544 }
Chris@16 545
Chris@16 546 template <class T1, class T2>
Chris@16 547 inline typename detail::bessel_traits<T1, T2, policies::policy<> >::result_type cyl_bessel_j(T1 v, T2 x)
Chris@16 548 {
Chris@16 549 return cyl_bessel_j(v, x, policies::policy<>());
Chris@16 550 }
Chris@16 551
Chris@16 552 template <class T, class Policy>
Chris@16 553 inline typename detail::bessel_traits<T, T, Policy>::result_type sph_bessel(unsigned v, T x, const Policy& /* pol */)
Chris@16 554 {
Chris@16 555 BOOST_FPU_EXCEPTION_GUARD
Chris@16 556 typedef typename detail::bessel_traits<T, T, Policy>::result_type result_type;
Chris@16 557 typedef typename policies::evaluation<result_type, Policy>::type value_type;
Chris@16 558 typedef typename policies::normalise<
Chris@16 559 Policy,
Chris@16 560 policies::promote_float<false>,
Chris@16 561 policies::promote_double<false>,
Chris@16 562 policies::discrete_quantile<>,
Chris@16 563 policies::assert_undefined<> >::type forwarding_policy;
Chris@16 564 return policies::checked_narrowing_cast<result_type, Policy>(detail::sph_bessel_j_imp<value_type>(v, static_cast<value_type>(x), forwarding_policy()), "boost::math::sph_bessel<%1%>(%1%,%1%)");
Chris@16 565 }
Chris@16 566
Chris@16 567 template <class T>
Chris@16 568 inline typename detail::bessel_traits<T, T, policies::policy<> >::result_type sph_bessel(unsigned v, T x)
Chris@16 569 {
Chris@16 570 return sph_bessel(v, x, policies::policy<>());
Chris@16 571 }
Chris@16 572
Chris@16 573 template <class T1, class T2, class Policy>
Chris@16 574 inline typename detail::bessel_traits<T1, T2, Policy>::result_type cyl_bessel_i(T1 v, T2 x, const Policy& /* pol */)
Chris@16 575 {
Chris@16 576 BOOST_FPU_EXCEPTION_GUARD
Chris@16 577 typedef typename detail::bessel_traits<T1, T2, Policy>::result_type result_type;
Chris@16 578 typedef typename policies::evaluation<result_type, Policy>::type value_type;
Chris@16 579 typedef typename policies::normalise<
Chris@16 580 Policy,
Chris@16 581 policies::promote_float<false>,
Chris@16 582 policies::promote_double<false>,
Chris@16 583 policies::discrete_quantile<>,
Chris@16 584 policies::assert_undefined<> >::type forwarding_policy;
Chris@16 585 return policies::checked_narrowing_cast<result_type, Policy>(detail::cyl_bessel_i_imp<value_type>(v, static_cast<value_type>(x), forwarding_policy()), "boost::math::cyl_bessel_i<%1%>(%1%,%1%)");
Chris@16 586 }
Chris@16 587
Chris@16 588 template <class T1, class T2>
Chris@16 589 inline typename detail::bessel_traits<T1, T2, policies::policy<> >::result_type cyl_bessel_i(T1 v, T2 x)
Chris@16 590 {
Chris@16 591 return cyl_bessel_i(v, x, policies::policy<>());
Chris@16 592 }
Chris@16 593
Chris@16 594 template <class T1, class T2, class Policy>
Chris@16 595 inline typename detail::bessel_traits<T1, T2, Policy>::result_type cyl_bessel_k(T1 v, T2 x, const Policy& /* pol */)
Chris@16 596 {
Chris@16 597 BOOST_FPU_EXCEPTION_GUARD
Chris@16 598 typedef typename detail::bessel_traits<T1, T2, Policy>::result_type result_type;
Chris@16 599 typedef typename detail::bessel_traits<T1, T2, Policy>::optimisation_tag tag_type;
Chris@16 600 typedef typename policies::evaluation<result_type, Policy>::type value_type;
Chris@16 601 typedef typename policies::normalise<
Chris@16 602 Policy,
Chris@16 603 policies::promote_float<false>,
Chris@16 604 policies::promote_double<false>,
Chris@16 605 policies::discrete_quantile<>,
Chris@16 606 policies::assert_undefined<> >::type forwarding_policy;
Chris@16 607 return policies::checked_narrowing_cast<result_type, Policy>(detail::cyl_bessel_k_imp<value_type>(v, static_cast<value_type>(x), tag_type(), forwarding_policy()), "boost::math::cyl_bessel_k<%1%>(%1%,%1%)");
Chris@16 608 }
Chris@16 609
Chris@16 610 template <class T1, class T2>
Chris@16 611 inline typename detail::bessel_traits<T1, T2, policies::policy<> >::result_type cyl_bessel_k(T1 v, T2 x)
Chris@16 612 {
Chris@16 613 return cyl_bessel_k(v, x, policies::policy<>());
Chris@16 614 }
Chris@16 615
Chris@16 616 template <class T1, class T2, class Policy>
Chris@16 617 inline typename detail::bessel_traits<T1, T2, Policy>::result_type cyl_neumann(T1 v, T2 x, const Policy& /* pol */)
Chris@16 618 {
Chris@16 619 BOOST_FPU_EXCEPTION_GUARD
Chris@16 620 typedef typename detail::bessel_traits<T1, T2, Policy>::result_type result_type;
Chris@16 621 typedef typename detail::bessel_traits<T1, T2, Policy>::optimisation_tag tag_type;
Chris@16 622 typedef typename policies::evaluation<result_type, Policy>::type value_type;
Chris@16 623 typedef typename policies::normalise<
Chris@16 624 Policy,
Chris@16 625 policies::promote_float<false>,
Chris@16 626 policies::promote_double<false>,
Chris@16 627 policies::discrete_quantile<>,
Chris@16 628 policies::assert_undefined<> >::type forwarding_policy;
Chris@16 629 return policies::checked_narrowing_cast<result_type, Policy>(detail::cyl_neumann_imp<value_type>(v, static_cast<value_type>(x), tag_type(), forwarding_policy()), "boost::math::cyl_neumann<%1%>(%1%,%1%)");
Chris@16 630 }
Chris@16 631
Chris@16 632 template <class T1, class T2>
Chris@16 633 inline typename detail::bessel_traits<T1, T2, policies::policy<> >::result_type cyl_neumann(T1 v, T2 x)
Chris@16 634 {
Chris@16 635 return cyl_neumann(v, x, policies::policy<>());
Chris@16 636 }
Chris@16 637
Chris@16 638 template <class T, class Policy>
Chris@16 639 inline typename detail::bessel_traits<T, T, Policy>::result_type sph_neumann(unsigned v, T x, const Policy& /* pol */)
Chris@16 640 {
Chris@16 641 BOOST_FPU_EXCEPTION_GUARD
Chris@16 642 typedef typename detail::bessel_traits<T, T, Policy>::result_type result_type;
Chris@16 643 typedef typename policies::evaluation<result_type, Policy>::type value_type;
Chris@16 644 typedef typename policies::normalise<
Chris@16 645 Policy,
Chris@16 646 policies::promote_float<false>,
Chris@16 647 policies::promote_double<false>,
Chris@16 648 policies::discrete_quantile<>,
Chris@16 649 policies::assert_undefined<> >::type forwarding_policy;
Chris@16 650 return policies::checked_narrowing_cast<result_type, Policy>(detail::sph_neumann_imp<value_type>(v, static_cast<value_type>(x), forwarding_policy()), "boost::math::sph_neumann<%1%>(%1%,%1%)");
Chris@16 651 }
Chris@16 652
Chris@16 653 template <class T>
Chris@16 654 inline typename detail::bessel_traits<T, T, policies::policy<> >::result_type sph_neumann(unsigned v, T x)
Chris@16 655 {
Chris@16 656 return sph_neumann(v, x, policies::policy<>());
Chris@16 657 }
Chris@16 658
Chris@16 659 template <class T, class Policy>
Chris@16 660 inline typename detail::bessel_traits<T, T, Policy>::result_type cyl_bessel_j_zero(T v, int m, const Policy& /* pol */)
Chris@16 661 {
Chris@16 662 BOOST_FPU_EXCEPTION_GUARD
Chris@16 663 typedef typename detail::bessel_traits<T, T, Policy>::result_type result_type;
Chris@16 664 typedef typename policies::evaluation<result_type, Policy>::type value_type;
Chris@16 665 typedef typename policies::normalise<
Chris@16 666 Policy,
Chris@16 667 policies::promote_float<false>,
Chris@16 668 policies::promote_double<false>,
Chris@16 669 policies::discrete_quantile<>,
Chris@16 670 policies::assert_undefined<> >::type forwarding_policy;
Chris@101 671
Chris@101 672 BOOST_STATIC_ASSERT_MSG( false == std::numeric_limits<T>::is_specialized
Chris@101 673 || ( true == std::numeric_limits<T>::is_specialized
Chris@101 674 && false == std::numeric_limits<T>::is_integer),
Chris@101 675 "Order must be a floating-point type.");
Chris@101 676
Chris@16 677 return policies::checked_narrowing_cast<result_type, Policy>(detail::cyl_bessel_j_zero_imp<value_type>(v, m, forwarding_policy()), "boost::math::cyl_bessel_j_zero<%1%>(%1%,%1%)");
Chris@16 678 }
Chris@16 679
Chris@16 680 template <class T>
Chris@16 681 inline typename detail::bessel_traits<T, T, policies::policy<> >::result_type cyl_bessel_j_zero(T v, int m)
Chris@16 682 {
Chris@101 683 BOOST_STATIC_ASSERT_MSG( false == std::numeric_limits<T>::is_specialized
Chris@101 684 || ( true == std::numeric_limits<T>::is_specialized
Chris@101 685 && false == std::numeric_limits<T>::is_integer),
Chris@101 686 "Order must be a floating-point type.");
Chris@101 687
Chris@16 688 return cyl_bessel_j_zero<T, policies::policy<> >(v, m, policies::policy<>());
Chris@16 689 }
Chris@16 690
Chris@16 691 template <class T, class OutputIterator, class Policy>
Chris@16 692 inline OutputIterator cyl_bessel_j_zero(T v,
Chris@16 693 int start_index,
Chris@16 694 unsigned number_of_zeros,
Chris@16 695 OutputIterator out_it,
Chris@16 696 const Policy& pol)
Chris@16 697 {
Chris@101 698 BOOST_STATIC_ASSERT_MSG( false == std::numeric_limits<T>::is_specialized
Chris@101 699 || ( true == std::numeric_limits<T>::is_specialized
Chris@101 700 && false == std::numeric_limits<T>::is_integer),
Chris@101 701 "Order must be a floating-point type.");
Chris@101 702
Chris@101 703 for(int i = 0; i < static_cast<int>(number_of_zeros); ++i)
Chris@16 704 {
Chris@16 705 *out_it = boost::math::cyl_bessel_j_zero(v, start_index + i, pol);
Chris@16 706 ++out_it;
Chris@16 707 }
Chris@16 708 return out_it;
Chris@16 709 }
Chris@16 710
Chris@16 711 template <class T, class OutputIterator>
Chris@16 712 inline OutputIterator cyl_bessel_j_zero(T v,
Chris@16 713 int start_index,
Chris@16 714 unsigned number_of_zeros,
Chris@16 715 OutputIterator out_it)
Chris@16 716 {
Chris@16 717 return cyl_bessel_j_zero(v, start_index, number_of_zeros, out_it, policies::policy<>());
Chris@16 718 }
Chris@16 719
Chris@16 720 template <class T, class Policy>
Chris@16 721 inline typename detail::bessel_traits<T, T, Policy>::result_type cyl_neumann_zero(T v, int m, const Policy& /* pol */)
Chris@16 722 {
Chris@16 723 BOOST_FPU_EXCEPTION_GUARD
Chris@16 724 typedef typename detail::bessel_traits<T, T, Policy>::result_type result_type;
Chris@16 725 typedef typename policies::evaluation<result_type, Policy>::type value_type;
Chris@16 726 typedef typename policies::normalise<
Chris@16 727 Policy,
Chris@16 728 policies::promote_float<false>,
Chris@16 729 policies::promote_double<false>,
Chris@16 730 policies::discrete_quantile<>,
Chris@16 731 policies::assert_undefined<> >::type forwarding_policy;
Chris@101 732
Chris@101 733 BOOST_STATIC_ASSERT_MSG( false == std::numeric_limits<T>::is_specialized
Chris@101 734 || ( true == std::numeric_limits<T>::is_specialized
Chris@101 735 && false == std::numeric_limits<T>::is_integer),
Chris@101 736 "Order must be a floating-point type.");
Chris@101 737
Chris@16 738 return policies::checked_narrowing_cast<result_type, Policy>(detail::cyl_neumann_zero_imp<value_type>(v, m, forwarding_policy()), "boost::math::cyl_neumann_zero<%1%>(%1%,%1%)");
Chris@16 739 }
Chris@16 740
Chris@16 741 template <class T>
Chris@16 742 inline typename detail::bessel_traits<T, T, policies::policy<> >::result_type cyl_neumann_zero(T v, int m)
Chris@16 743 {
Chris@101 744 BOOST_STATIC_ASSERT_MSG( false == std::numeric_limits<T>::is_specialized
Chris@101 745 || ( true == std::numeric_limits<T>::is_specialized
Chris@101 746 && false == std::numeric_limits<T>::is_integer),
Chris@101 747 "Order must be a floating-point type.");
Chris@101 748
Chris@16 749 return cyl_neumann_zero<T, policies::policy<> >(v, m, policies::policy<>());
Chris@16 750 }
Chris@16 751
Chris@16 752 template <class T, class OutputIterator, class Policy>
Chris@16 753 inline OutputIterator cyl_neumann_zero(T v,
Chris@16 754 int start_index,
Chris@16 755 unsigned number_of_zeros,
Chris@16 756 OutputIterator out_it,
Chris@16 757 const Policy& pol)
Chris@16 758 {
Chris@101 759 BOOST_STATIC_ASSERT_MSG( false == std::numeric_limits<T>::is_specialized
Chris@101 760 || ( true == std::numeric_limits<T>::is_specialized
Chris@101 761 && false == std::numeric_limits<T>::is_integer),
Chris@101 762 "Order must be a floating-point type.");
Chris@101 763
Chris@101 764 for(int i = 0; i < static_cast<int>(number_of_zeros); ++i)
Chris@16 765 {
Chris@16 766 *out_it = boost::math::cyl_neumann_zero(v, start_index + i, pol);
Chris@16 767 ++out_it;
Chris@16 768 }
Chris@16 769 return out_it;
Chris@16 770 }
Chris@16 771
Chris@16 772 template <class T, class OutputIterator>
Chris@16 773 inline OutputIterator cyl_neumann_zero(T v,
Chris@16 774 int start_index,
Chris@16 775 unsigned number_of_zeros,
Chris@16 776 OutputIterator out_it)
Chris@16 777 {
Chris@16 778 return cyl_neumann_zero(v, start_index, number_of_zeros, out_it, policies::policy<>());
Chris@16 779 }
Chris@16 780
Chris@16 781 } // namespace math
Chris@16 782 } // namespace boost
Chris@16 783
Chris@16 784 #endif // BOOST_MATH_BESSEL_HPP
Chris@16 785
Chris@16 786