25 #include <boost/math/constants/constants.hpp>
27 #ifndef MATH_FUNCTIONS_HPP_INCLUDED
28 #define MATH_FUNCTIONS_HPP_INCLUDED
45 return (T(0) < val) - (val < T(0));
55 static T sinc(T
const &x)
57 if (std::abs(x) > 1e-3)
58 return std::sin(x) / x;
60 return 1. - x*x/6. * (1. - x*x/20.);
70 typedef std::complex<T> type;
76 typedef std::complex<T> type;
93 using namespace boost::math::double_constants;
101 5.8486995697021484375,
102 -1.06886793971061706543e2,
103 2.96814293784275650978e3
110 -7.7399539947509765625,
111 1.32761824250221252441e2,
112 -3.54330366536602377892e3
127 6.51041666666666712926e-2,
128 -2.09570312499999994449e-1,
129 1.63806588309151779370,
130 -2.34751277499728736586e1,
131 5.35640519510615945364e2,
132 -1.78372796889474739146e4
137 3.70898437500000011102e-1,
138 -2.36939784458705338110,
139 3.06240119934082031250e1,
140 -6.59185221823778988437e2,
141 2.11563140455278044101e4
156 for (
int m =
sizeof(mag[0])/
sizeof(
double)-1; m >= 0; --m)
158 u = q * u + mag[nu][m];
159 phi = q * phi + arg[nu][m];
161 phi = phi/z + z - (nu/2.+.25)*pi;
171 template <
int nu,
class T>
175 int N = (int)(3+2.*std::abs(z));
180 for (
int k = N; k > 0; --k)
181 res = 1. - q2*(1./(k*(k+nu)))*res;
182 for (
int k = 1; k <= nu; ++k)
194 template <
int nu,
class T>
197 using boost::math::double_constants::pi;
199 static_assert(nu >= 0 && nu <= 2 ,
"unimplemented Bessel J order");
202 if (std::real(z) < 0)
204 double const C(nu%2==0 ? 1. : -1);
206 return std::sqrt(2./(pi * -z)) * mag * std::cos(arg) *
C;
211 return std::sqrt(2./(pi * z)) * mag * std::cos(arg);
222 template <
int nu,
class T>
225 return std::abs(z) <
large_lim ? J_small<nu>(z) : J_large<nu>(z);
236 std::complex<double>
Y_small(std::complex<double>
const &z)
238 using boost::math::double_constants::pi;
239 using boost::math::double_constants::euler;
242 int const N = (int)(4+2.*std::abs(z));
244 std::complex<double> q(z/2.0), q2(q*q);
245 std::complex<double> first(2.0*J_small<nu>(z)*(std::log(q) + euler));
246 std::complex<double> second;
249 case 0: second = 0.;
break;
250 case 1: second = -1./q;
break;
251 case 2: second = -1. -1./q2;
break;
254 std::complex<double> third(0.0);
255 std::complex<double> q2pow(-std::pow(q, nu));
258 for (
int k = 1; k <= nu; ++k)
262 for (
int k = 1; k <= nu; ++k)
265 for (
int k = 0; k < N; ++k)
267 third += div*q2pow*a;
269 div /= -(k+1)*(k+nu+1);
271 a += 1./(k+1.) + 1./(k+nu+1.);
274 return 1./pi * (first + second + third);
284 std::complex<double>
Y_large(std::complex<double>
const &z)
286 using boost::math::double_constants::pi;
288 static_assert(nu >= 0 || nu <= 2,
"unimplemented Bessel Y order");
290 std::complex<double> mag, arg;
291 if (std::real(z) < 0)
293 double const C1(nu%2 == 0 ? 1. : -1.);
294 std::complex<double>
const C2(0., std::imag(z) < 0 ? -2. : 2.);
295 std::complex<double>
const MAG(std::sqrt(C2*C2+1.));
296 std::complex<double>
const ARG(std::atan(1./C2));
298 return std::sqrt(2./(pi * -z)) * mag * MAG * std::cos(arg-ARG) * C1;
303 return std::sqrt(2./(pi * z)) * mag * std::sin(arg);
315 std::complex<double>
Y(std::complex<double>
const &z)
317 return std::abs(z) <
large_lim ? Y_small<nu>(z) : Y_large<nu>(z);
327 template <
int nu,
int kind,
class T>
328 typename make_complex<T>::type
H_large(T
const &z)
330 using namespace std::complex_literals;
331 using boost::math::double_constants::pi;
333 static_assert((kind == 1) || (kind == 2),
"invalid kind argument of bessel::H");
334 double const C = (kind == 2 ? -1. : 1.);
336 typename make_complex<T>::type mag, arg;
338 if (std::real(z) < 0 && std::abs(std::imag(z)) < 8.)
340 double const C1(nu%2 == 0 ? 1. : -1.);
344 double sgn = std::imag(z) < 0 ? -1. : 1.;
345 double MAG(-
sgn*std::sqrt(3.));
346 std::complex<double>
const ARG(std::atan(-
sgn*.5i));
348 return std::sqrt(2./(pi * -z)) * mag * (std::cos(arg) +
C * MAG * std::cos(arg-ARG)) * C1;
353 return std::sqrt(2./pi/z) * mag * std::exp(
C*1.i*arg);
364 template <
int nu,
int kind,
class T>
365 typename make_complex<T>::type
H(T
const &z)
367 using namespace std::complex_literals;
368 static_assert(kind == 1 || kind == 2,
"invalid kind argument of bessel::H");
369 double const C = (kind == 2 ? -1. : 1.);
371 return J_small<nu>(z) +
C * 1.i * Y_small<nu>(z);
373 return H_large<nu, kind>(z);
383 template <
int nu,
class T>
384 typename make_complex<T>::type
K(T
const &z);
394 template <
class T =
double>
397 using boost::math::double_constants::pi;
398 return std::cos(pi / 2. * (2 * (n - i) - 1) / T(n));
412 for (
unsigned i = 0; i < exp; ++i)
422 template <
unsigned Base,
unsigned Exp >
425 static unsigned const value =
IpowC<Base, Exp - 1>::value * Base;
429 template <
unsigned Base>
432 static unsigned const value = 1U;
436 template <
unsigned Exp>
439 static unsigned const value = 0U;