224 lines
		
	
	
		
			6.6 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
		
		
			
		
	
	
			224 lines
		
	
	
		
			6.6 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| 
								 | 
							
								//  Copyright (c) 2007 John Maddock
							 | 
						||
| 
								 | 
							
								//  Use, modification and distribution are subject to 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)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// This is a partial header, do not include on it's own!!!
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// Contains asymptotic expansions for Bessel J(v,x) and Y(v,x)
							 | 
						||
| 
								 | 
							
								// functions, as x -> INF.
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								#ifndef BOOST_MATH_SF_DETAIL_BESSEL_JY_ASYM_HPP
							 | 
						||
| 
								 | 
							
								#define BOOST_MATH_SF_DETAIL_BESSEL_JY_ASYM_HPP
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef _MSC_VER
							 | 
						||
| 
								 | 
							
								#pragma once
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include <boost/math/special_functions/factorials.hpp>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								namespace boost{ namespace math{ namespace detail{
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template <class T>
							 | 
						||
| 
								 | 
							
								inline T asymptotic_bessel_amplitude(T v, T x)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								   // Calculate the amplitude of J(v, x) and Y(v, x) for large
							 | 
						||
| 
								 | 
							
								   // x: see A&S 9.2.28.
							 | 
						||
| 
								 | 
							
								   BOOST_MATH_STD_USING
							 | 
						||
| 
								 | 
							
								   T s = 1;
							 | 
						||
| 
								 | 
							
								   T mu = 4 * v * v;
							 | 
						||
| 
								 | 
							
								   T txq = 2 * x;
							 | 
						||
| 
								 | 
							
								   txq *= txq;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   s += (mu - 1) / (2 * txq);
							 | 
						||
| 
								 | 
							
								   s += 3 * (mu - 1) * (mu - 9) / (txq * txq * 8);
							 | 
						||
| 
								 | 
							
								   s += 15 * (mu - 1) * (mu - 9) * (mu - 25) / (txq * txq * txq * 8 * 6);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   return sqrt(s * 2 / (constants::pi<T>() * x));
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template <class T>
							 | 
						||
| 
								 | 
							
								T asymptotic_bessel_phase_mx(T v, T x)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								   //
							 | 
						||
| 
								 | 
							
								   // Calculate the phase of J(v, x) and Y(v, x) for large x.
							 | 
						||
| 
								 | 
							
								   // See A&S 9.2.29.
							 | 
						||
| 
								 | 
							
								   // Note that the result returned is the phase less (x - PI(v/2 + 1/4))
							 | 
						||
| 
								 | 
							
								   // which we'll factor in later when we calculate the sines/cosines of the result:
							 | 
						||
| 
								 | 
							
								   //
							 | 
						||
| 
								 | 
							
								   T mu = 4 * v * v;
							 | 
						||
| 
								 | 
							
								   T denom = 4 * x;
							 | 
						||
| 
								 | 
							
								   T denom_mult = denom * denom;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   T s = 0;
							 | 
						||
| 
								 | 
							
								   s += (mu - 1) / (2 * denom);
							 | 
						||
| 
								 | 
							
								   denom *= denom_mult;
							 | 
						||
| 
								 | 
							
								   s += (mu - 1) * (mu - 25) / (6 * denom);
							 | 
						||
| 
								 | 
							
								   denom *= denom_mult;
							 | 
						||
| 
								 | 
							
								   s += (mu - 1) * (mu * mu - 114 * mu + 1073) / (5 * denom);
							 | 
						||
| 
								 | 
							
								   denom *= denom_mult;
							 | 
						||
| 
								 | 
							
								   s += (mu - 1) * (5 * mu * mu * mu - 1535 * mu * mu + 54703 * mu - 375733) / (14 * denom);
							 | 
						||
| 
								 | 
							
								   return s;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template <class T>
							 | 
						||
| 
								 | 
							
								inline T asymptotic_bessel_y_large_x_2(T v, T x)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								   // See A&S 9.2.19.
							 | 
						||
| 
								 | 
							
								   BOOST_MATH_STD_USING
							 | 
						||
| 
								 | 
							
								   // Get the phase and amplitude:
							 | 
						||
| 
								 | 
							
								   T ampl = asymptotic_bessel_amplitude(v, x);
							 | 
						||
| 
								 | 
							
								   T phase = asymptotic_bessel_phase_mx(v, x);
							 | 
						||
| 
								 | 
							
								   BOOST_MATH_INSTRUMENT_VARIABLE(ampl);
							 | 
						||
| 
								 | 
							
								   BOOST_MATH_INSTRUMENT_VARIABLE(phase);
							 | 
						||
| 
								 | 
							
								   //
							 | 
						||
| 
								 | 
							
								   // Calculate the sine of the phase, using
							 | 
						||
| 
								 | 
							
								   // sine/cosine addition rules to factor in
							 | 
						||
| 
								 | 
							
								   // the x - PI(v/2 + 1/4) term not added to the
							 | 
						||
| 
								 | 
							
								   // phase when we calculated it.
							 | 
						||
| 
								 | 
							
								   //
							 | 
						||
| 
								 | 
							
								   T cx = cos(x);
							 | 
						||
| 
								 | 
							
								   T sx = sin(x);
							 | 
						||
| 
								 | 
							
								   T ci = cos_pi(v / 2 + 0.25f);
							 | 
						||
| 
								 | 
							
								   T si = sin_pi(v / 2 + 0.25f);
							 | 
						||
| 
								 | 
							
								   T sin_phase = sin(phase) * (cx * ci + sx * si) + cos(phase) * (sx * ci - cx * si);
							 | 
						||
| 
								 | 
							
								   BOOST_MATH_INSTRUMENT_CODE(sin(phase));
							 | 
						||
| 
								 | 
							
								   BOOST_MATH_INSTRUMENT_CODE(cos(x));
							 | 
						||
| 
								 | 
							
								   BOOST_MATH_INSTRUMENT_CODE(cos(phase));
							 | 
						||
| 
								 | 
							
								   BOOST_MATH_INSTRUMENT_CODE(sin(x));
							 | 
						||
| 
								 | 
							
								   return sin_phase * ampl;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template <class T>
							 | 
						||
| 
								 | 
							
								inline T asymptotic_bessel_j_large_x_2(T v, T x)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								   // See A&S 9.2.19.
							 | 
						||
| 
								 | 
							
								   BOOST_MATH_STD_USING
							 | 
						||
| 
								 | 
							
								   // Get the phase and amplitude:
							 | 
						||
| 
								 | 
							
								   T ampl = asymptotic_bessel_amplitude(v, x);
							 | 
						||
| 
								 | 
							
								   T phase = asymptotic_bessel_phase_mx(v, x);
							 | 
						||
| 
								 | 
							
								   BOOST_MATH_INSTRUMENT_VARIABLE(ampl);
							 | 
						||
| 
								 | 
							
								   BOOST_MATH_INSTRUMENT_VARIABLE(phase);
							 | 
						||
| 
								 | 
							
								   //
							 | 
						||
| 
								 | 
							
								   // Calculate the sine of the phase, using
							 | 
						||
| 
								 | 
							
								   // sine/cosine addition rules to factor in
							 | 
						||
| 
								 | 
							
								   // the x - PI(v/2 + 1/4) term not added to the
							 | 
						||
| 
								 | 
							
								   // phase when we calculated it.
							 | 
						||
| 
								 | 
							
								   //
							 | 
						||
| 
								 | 
							
								   BOOST_MATH_INSTRUMENT_CODE(cos(phase));
							 | 
						||
| 
								 | 
							
								   BOOST_MATH_INSTRUMENT_CODE(cos(x));
							 | 
						||
| 
								 | 
							
								   BOOST_MATH_INSTRUMENT_CODE(sin(phase));
							 | 
						||
| 
								 | 
							
								   BOOST_MATH_INSTRUMENT_CODE(sin(x));
							 | 
						||
| 
								 | 
							
								   T cx = cos(x);
							 | 
						||
| 
								 | 
							
								   T sx = sin(x);
							 | 
						||
| 
								 | 
							
								   T ci = cos_pi(v / 2 + 0.25f);
							 | 
						||
| 
								 | 
							
								   T si = sin_pi(v / 2 + 0.25f);
							 | 
						||
| 
								 | 
							
								   T sin_phase = cos(phase) * (cx * ci + sx * si) - sin(phase) * (sx * ci - cx * si);
							 | 
						||
| 
								 | 
							
								   BOOST_MATH_INSTRUMENT_VARIABLE(sin_phase);
							 | 
						||
| 
								 | 
							
								   return sin_phase * ampl;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template <class T>
							 | 
						||
| 
								 | 
							
								inline bool asymptotic_bessel_large_x_limit(int v, const T& x)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								   BOOST_MATH_STD_USING
							 | 
						||
| 
								 | 
							
								      //
							 | 
						||
| 
								 | 
							
								      // Determines if x is large enough compared to v to take the asymptotic
							 | 
						||
| 
								 | 
							
								      // forms above.  From A&S 9.2.28 we require: 
							 | 
						||
| 
								 | 
							
								      //    v < x * eps^1/8
							 | 
						||
| 
								 | 
							
								      // and from A&S 9.2.29 we require:
							 | 
						||
| 
								 | 
							
								      //    v^12/10 < 1.5 * x * eps^1/10
							 | 
						||
| 
								 | 
							
								      // using the former seems to work OK in practice with broadly similar 
							 | 
						||
| 
								 | 
							
								      // error rates either side of the divide for v < 10000.
							 | 
						||
| 
								 | 
							
								      // At double precision eps^1/8 ~= 0.01.
							 | 
						||
| 
								 | 
							
								      //
							 | 
						||
| 
								 | 
							
								      BOOST_ASSERT(v >= 0);
							 | 
						||
| 
								 | 
							
								      return (v ? v : 1) < x * 0.004f;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template <class T>
							 | 
						||
| 
								 | 
							
								inline bool asymptotic_bessel_large_x_limit(const T& v, const T& x)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								   BOOST_MATH_STD_USING
							 | 
						||
| 
								 | 
							
								   //
							 | 
						||
| 
								 | 
							
								   // Determines if x is large enough compared to v to take the asymptotic
							 | 
						||
| 
								 | 
							
								   // forms above.  From A&S 9.2.28 we require: 
							 | 
						||
| 
								 | 
							
								   //    v < x * eps^1/8
							 | 
						||
| 
								 | 
							
								   // and from A&S 9.2.29 we require:
							 | 
						||
| 
								 | 
							
								   //    v^12/10 < 1.5 * x * eps^1/10
							 | 
						||
| 
								 | 
							
								   // using the former seems to work OK in practice with broadly similar 
							 | 
						||
| 
								 | 
							
								   // error rates either side of the divide for v < 10000.
							 | 
						||
| 
								 | 
							
								   // At double precision eps^1/8 ~= 0.01.
							 | 
						||
| 
								 | 
							
								   //
							 | 
						||
| 
								 | 
							
								   return (std::max)(T(fabs(v)), T(1)) < x * sqrt(tools::forth_root_epsilon<T>());
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template <class T, class Policy>
							 | 
						||
| 
								 | 
							
								void temme_asyptotic_y_small_x(T v, T x, T* Y, T* Y1, const Policy& pol)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								   T c = 1;
							 | 
						||
| 
								 | 
							
								   T p = (v / boost::math::sin_pi(v, pol)) * pow(x / 2, -v) / boost::math::tgamma(1 - v, pol);
							 | 
						||
| 
								 | 
							
								   T q = (v / boost::math::sin_pi(v, pol)) * pow(x / 2, v) / boost::math::tgamma(1 + v, pol);
							 | 
						||
| 
								 | 
							
								   T f = (p - q) / v;
							 | 
						||
| 
								 | 
							
								   T g_prefix = boost::math::sin_pi(v / 2, pol);
							 | 
						||
| 
								 | 
							
								   g_prefix *= g_prefix * 2 / v;
							 | 
						||
| 
								 | 
							
								   T g = f + g_prefix * q;
							 | 
						||
| 
								 | 
							
								   T h = p;
							 | 
						||
| 
								 | 
							
								   T c_mult = -x * x / 4;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   T y(c * g), y1(c * h);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   for(int k = 1; k < policies::get_max_series_iterations<Policy>(); ++k)
							 | 
						||
| 
								 | 
							
								   {
							 | 
						||
| 
								 | 
							
								      f = (k * f + p + q) / (k*k - v*v);
							 | 
						||
| 
								 | 
							
								      p /= k - v;
							 | 
						||
| 
								 | 
							
								      q /= k + v;
							 | 
						||
| 
								 | 
							
								      c *= c_mult / k;
							 | 
						||
| 
								 | 
							
								      T c1 = pow(-x * x / 4, k) / factorial<T>(k, pol);
							 | 
						||
| 
								 | 
							
								      g = f + g_prefix * q;
							 | 
						||
| 
								 | 
							
								      h = -k * g + p;
							 | 
						||
| 
								 | 
							
								      y += c * g;
							 | 
						||
| 
								 | 
							
								      y1 += c * h;
							 | 
						||
| 
								 | 
							
								      if(c * g / tools::epsilon<T>() < y)
							 | 
						||
| 
								 | 
							
								         break;
							 | 
						||
| 
								 | 
							
								   }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   *Y = -y;
							 | 
						||
| 
								 | 
							
								   *Y1 = (-2 / x) * y1;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template <class T, class Policy>
							 | 
						||
| 
								 | 
							
								T asymptotic_bessel_i_large_x(T v, T x, const Policy& pol)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								   BOOST_MATH_STD_USING  // ADL of std names
							 | 
						||
| 
								 | 
							
								   T s = 1;
							 | 
						||
| 
								 | 
							
								   T mu = 4 * v * v;
							 | 
						||
| 
								 | 
							
								   T ex = 8 * x;
							 | 
						||
| 
								 | 
							
								   T num = mu - 1;
							 | 
						||
| 
								 | 
							
								   T denom = ex;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   s -= num / denom;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   num *= mu - 9;
							 | 
						||
| 
								 | 
							
								   denom *= ex * 2;
							 | 
						||
| 
								 | 
							
								   s += num / denom;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   num *= mu - 25;
							 | 
						||
| 
								 | 
							
								   denom *= ex * 3;
							 | 
						||
| 
								 | 
							
								   s -= num / denom;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   // Try and avoid overflow to the last minute:
							 | 
						||
| 
								 | 
							
								   T e = exp(x/2);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   s = e * (e * s / sqrt(2 * x * constants::pi<T>()));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   return (boost::math::isfinite)(s) ? 
							 | 
						||
| 
								 | 
							
								      s : policies::raise_overflow_error<T>("boost::math::asymptotic_bessel_i_large_x<%1%>(%1%,%1%)", 0, pol);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								}}} // namespaces
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 |