// Copyright Christopher Kormanyos 2013. // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or // copy at http://www.boost.org/LICENSE_1_0.txt). #ifdef _MSC_VER # pragma warning (disable : 4512) // assignment operator could not be generated. # pragma warning (disable : 4996) // assignment operator could not be generated. #endif #include #include #include #include #include #include #include #include #include /* using template inline void cyl_bessel_j_zero( output_iterator out_it, T v, unsigned number_of_zeros, unsigned start_index) */ // Weisstein, Eric W. "Bessel Function Zeros." From MathWorld--A Wolfram Web Resource. // http://mathworld.wolfram.com/BesselFunctionZeros.html // See also http://dlmf.nist.gov/10.21 // To use the Boost.Multiprecision 50 decimal digits type. typedef boost::multiprecision::cpp_dec_float_50 float_type; using namespace boost::math; /*`This example shows obtaining both a single zero or root of the Bessel function, and placing multiple zeros into a container like `std::vector` by providing an iterator. The signature of the single value function is: template inline typename detail::bessel_traits >::result_type cyl_bessel_j_zero(T v, // Floating-point value for Jv. unsigned m); // start index. The result type is controlled by the floating-point type of parameter `v` (but subject to the usual policy and promotion rules). and for multiple zeros: template inline OutputIterator cyl_bessel_j_zero(T v, // Floating-point value for Jv. unsigned number_of_zeros, unsigned start_index, OutputIterator out_it); // There is also a version which allows control of the policy for error handling and precision. template inline OutputIterator cyl_bessel_j_zero(T v, // Floating-point value for Jv. unsigned number_of_zeros, unsigned start_index, OutputIterator out_it, const Policy& pol); This exmaple also shows how to use the output iterator to create a sum of 1/zeros^2. */ template struct output_summation_iterator { output_summation_iterator(T* p) : p_sum(p) { } output_summation_iterator& operator*() { return *this; } output_summation_iterator& operator = (T const& val) { *p_sum += 1./ (val * val); // 1/zero^2 //std::cout << *p_sum << ", "; return *this; } output_summation_iterator& operator++() { return *this; } output_summation_iterator& operator++(int) { return *this; } private: T* p_sum; }; double s_m_nu(int m, int nu) { switch(m) { case 2: return 1./(4 * (nu + 1)); case 4: return 1./(16 * (nu+1)*(nu+1)*(nu+2)); default: return 0; } } // double s_m_nu(int m, int nu) int main() { { // Evaluate a single Bessel zero. // T cyl_bessel_j_zero(T v, unsigned int index) // The precision is controlled by the float-point type of template parameter T of v. // so this example has double precision, at least 15 but up to 17 decimal digits. double root = boost::math::cyl_bessel_j_zero(0.0, 1U); // Using default precision of 6 decimal digits: std::cout << "boost::math::cyl_bessel_j_zero(0.0, 1U) " << root << std::endl; // 2.40483 std::cout.precision(std::numeric_limits::digits10); std::cout << "boost::math::cyl_bessel_j_zero(0.0, 1U) " << root << std::endl; // 2.40482555769577 /*`But note that because the parameter v controls the precision of the result, it *must* be a [[floating-point type]. So if you provide an integer type, say 0, rather than 0.0, then it will fail to compile thus: `` root = boost::math::cyl_bessel_j_zero(0, 1U); `` error C2338: Order must be a floating-point type. */ } { // IAN N. SNEDDON, Infinite sums of Bessel Zeros. // page 150 equation 40. using boost::math::cyl_bessel_j_zero; std::cout.precision(std::numeric_limits::digits10); double nu = 1.; double sum = 0; output_summation_iterator it(&sum); // sum of 1/zeros^2 cyl_bessel_j_zero(nu, 100000U, 1U, it); std::cout << "Final " << sum << std::endl; // 0.0 Final 0.249999 // 1.0 Final 0.124998986795763 double s = 1/(4 * (nu + 1)); // 0.125 = 1/8 is exact analytical solution. std::cout << s << std::endl; } { /*`The Neumann functions zeros are evaluated very similarly: */ using boost::math::cyl_neumann_zero; double sum = 0; output_summation_iterator it(&sum); cyl_neumann_zero(2.5, 1, 10, it); std::cout << sum << std::endl; } /*`Another version allows calculation of multiple zeros with one call, placing the results in a container, often `std::vector`. For example, generate five double roots of Jv for integral order 2. */ { double azero = boost::math::cyl_bessel_j_zero(0.0, 1U); unsigned int n_roots = 5U; std::vector roots; boost::math::cyl_bessel_j_zero(0.0, n_roots, 1U, std::back_inserter(roots)); // Note must provide an floating-point type, not an integer type, so v = 2.0, not 2. //boost::math::cyl_bessel_j_zero(std::back_inserter(roots_3), 2, 3U, 1U); // error C2338: Order must be a floating-point type. std::copy(roots.begin(), roots.end(), std::ostream_iterator(std::cout, "\n")); // 5 roots v = 0.0 // 1.#QNAN //2.40483 //5.52008 //8.65373 //11.7915 //14.9309 } /*`Or generate 20 roots of Jv for non-integral order v=71/19. */ { // Set the precision of the output stream. std::cout << std::showpoint << std::endl; // Show trailing zeros. std::cout.precision(std::numeric_limits::digits10); float_type x = float_type(71) / 19; float_type r = boost::math::cyl_bessel_j_zero(x, 1U); std::cout << "x = " << x << ", r = " << r << std::endl; r = boost::math::cyl_bessel_j_zero(x, 50U); std::cout << "x = " << x << ", r = " << r << std::endl; std::vector roots(20U); boost::math::cyl_bessel_j_zero(float_type(71) / 19, unsigned(roots.size()), 1U, roots.begin()); // Print the roots to the output stream. std::copy(roots.begin(), roots.end(), std::ostream_iterator(std::cout, "\n")); } /* */ /*`Test some corner cases: */ try { /* [N[BesselJZero[0, 1000], 50]] 3140.8072952250786288955454534711266789940767025137 3.140807295225079e+003 j 1000(x = 0), r = 3.140807295225079e+003 j 1000(x = 0.000000000000000), r = 3140.80729522508 [N[BesselJZero[0, 1000000], 50]] 3.1415918681916696297600539252789979000145664979511×10^6 3.141591868191670e+006 j 1000000(x = 0.000000000000000), r = 3141591.86819167 [N[BesselJZero[0, 1000000000], 50]] 3.1415926528043950751049838094467630562626412341405×10^9 3.141592652804395e+009 j 1000000000(x = 0), r = 3.141592652804395e+009 j 1000000000(x = 0), r = 3141592652.8044 */ // [N[BesselJZero[0, 4294967295], 50]] std::cout.precision(std::numeric_limits::digits10); double x = 0.; // double r = boost::math::cyl_bessel_j_zero(x, 1U); // 2.4 // double r = boost::math::cyl_bessel_j_zero(x, 0U); // NAN unsigned int j = std::numeric_limits::max(); j = 1000U; double r = boost::math::cyl_bessel_j_zero(x, j); std::cout << "j " << j << "(x = " << x << "), r = " << std::scientific << r << std::endl; // j 4294967295(x = 0.000000000000000), r = 6746518848.33402 // 1.3493037700595028141621005137780845320949701145378×10^10 } catch (std::exception ex) { std::cout << "Throw exception " << ex.what() << std::endl; } } // int main() /* Mathematica: Table[N[BesselJZero[71/19, n], 50], {n, 1, 20, 1}] 7.2731751938316489503185694262290765588963196701623, \ 10.724858308883141732536172745851416647110749599085, \ 14.018504599452388106120459558042660282427471931581, \ 17.252498459170417182162487166549777349195903838610, \ 20.456678874044517595180234083894285885460502077814, \ 23.643630897142345224945514227147319599854051725040, \ 26.819671140255087745421311470965019261522390519297, \ 29.988343117423674742679141796661432043878868194142, \ 33.151796897690520871250862469973445265444791966114, \ 36.311416000216207415724354035039386081316520184200, \ 39.468132467505236587945197808083337887765967032029, \ 42.622597801391236474855034831297954018844433480227, \ 45.775281464536847753390206207806726581495950012439, \ 48.926530489173566198367766817478553992471739894799, \ 52.076607045343002794279746041878924876873478063472, \ 55.225712944912571393594224327817265689059002890192, \ 58.374006101538886436775188150439025201735151418932, \ 61.521611873000965273726742659353136266390944103571, \ 64.668631053790930368346482214873660794565966287160, \ 67.815145619696290925556791375555951165111460585458 7.2731751938316489503185694262290765588963196701623 10.724858308883141732536172745851416647110749599085 14.018504599452388106120459558042660282427471931581 17.25249845917041718216248716654977734919590383861 20.456678874044517595180234083894285885460502077814 23.64363089714234522494551422714731959985405172504 26.819671140255087745421311470965019261522390519297 29.988343117423674742679141796661432043878868194142 33.151796897690520871250862469973445265444791966114 36.3114160002162074157243540350393860813165201842 39.468132467505236587945197808083337887765967032029 42.622597801391236474855034831297954018844433480227 45.775281464536847753390206207806726581495950012439 48.926530489173566198367766817478553992471739894799 52.076607045343002794279746041878924876873478063472 55.225712944912571393594224327817265689059002890192 58.374006101538886436775188150439025201735151418932 61.521611873000965273726742659353136266390944103571 64.66863105379093036834648221487366079456596628716 67.815145619696290925556791375555951165111460585458 */ /* ------ Rebuild All started: Project: bessel_zeros_example, Configuration: Debug Win32 ------ Build started 27-Jan-2013 17:55:44. _PrepareForClean: Deleting file "Debug\bessel_zeros_example.lastbuildstate". InitializeBuildStatus: Creating "Debug\bessel_zeros_example.unsuccessfulbuild" because "AlwaysCreate" was specified. ClCompile: bessel_zeros_example.cpp I:\boost-trunk\boost/math/special_functions/bessel.hpp(418): warning C4244: '=' : conversion from 'value_type' to 'double', possible loss of data I:\boost-trunk\boost/math/special_functions/bessel.hpp(610) : see reference to function template instantiation 'void boost::math::detail::cyl_bessel_j_zero_imp>(output_iterator,T,unsigned int,unsigned int,const Policy &)' being compiled with [ output_iterator=std::_Vector_iterator>>, T=value_type, Policy=boost::math::policies::policy ] I:\boost-trunk\libs\math\example\bessel_zeros_example.cpp(46) : see reference to function template instantiation 'void boost::math::cyl_bessel_j_zero,int>(output_iterator,T,unsigned int,unsigned int)' being compiled with [ _Myvec=std::_Vector_val>, output_iterator=std::_Vector_iterator>>, T=int ] Manifest: Deleting file "Debug\bessel_zeros_example.exe.embed.manifest". LinkEmbedManifest: bessel_zeros_example.vcxproj -> J:\Cpp\big_number\Debug\bessel_zeros_example.exe CustomBuildStep: Description: Autorun "J:\Cpp\big_number\Debug\bessel_zeros_example.exe" 1st root = 5.13562 2nd root = 8.41724 3rd root = 11.6198 7.2731751938316489503185694262290765588963196701623 10.724858308883141732536172745851416647110749599085 14.018504599452388106120459558042660282427471931581 17.25249845917041718216248716654977734919590383861 20.456678874044517595180234083894285885460502077814 23.64363089714234522494551422714731959985405172504 26.819671140255087745421311470965019261522390519297 29.988343117423674742679141796661432043878868194142 33.151796897690520871250862469973445265444791966114 36.3114160002162074157243540350393860813165201842 39.468132467505236587945197808083337887765967032029 42.622597801391236474855034831297954018844433480227 45.775281464536847753390206207806726581495950012439 48.926530489173566198367766817478553992471739894799 52.076607045343002794279746041878924876873478063472 55.225712944912571393594224327817265689059002890192 58.374006101538886436775188150439025201735151418932 61.521611873000965273726742659353136266390944103571 64.66863105379093036834648221487366079456596628716 67.815145619696290925556791375555951165111460585458 FinalizeBuildStatus: Deleting file "Debug\bessel_zeros_example.unsuccessfulbuild". Touching "Debug\bessel_zeros_example.lastbuildstate". Build succeeded. Time Elapsed 00:00:22.68 */