e_float.hpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809
  1. // Copyright John Maddock 2008.
  2. // Use, modification and distribution are subject to the
  3. // Boost Software License, Version 1.0. (See accompanying file
  4. // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  5. //
  6. // Wrapper that works with mpfr_class defined in gmpfrxx.h
  7. // See http://math.berkeley.edu/~wilken/code/gmpfrxx/
  8. // Also requires the gmp and mpfr libraries.
  9. //
  10. #ifndef BOOST_MATH_E_FLOAT_BINDINGS_HPP
  11. #define BOOST_MATH_E_FLOAT_BINDINGS_HPP
  12. #include <boost/config.hpp>
  13. #include <e_float/e_float.h>
  14. #include <functions/functions.h>
  15. #include <boost/math/tools/precision.hpp>
  16. #include <boost/math/tools/real_cast.hpp>
  17. #include <boost/math/policies/policy.hpp>
  18. #include <boost/math/distributions/fwd.hpp>
  19. #include <boost/math/special_functions/math_fwd.hpp>
  20. #include <boost/math/special_functions/fpclassify.hpp>
  21. #include <boost/math/bindings/detail/big_digamma.hpp>
  22. #include <boost/math/bindings/detail/big_lanczos.hpp>
  23. #include <boost/lexical_cast.hpp>
  24. namespace boost{ namespace math{ namespace ef{
  25. class e_float
  26. {
  27. public:
  28. // Constructors:
  29. e_float() {}
  30. e_float(const ::e_float& c) : m_value(c){}
  31. e_float(char c)
  32. {
  33. m_value = ::e_float(c);
  34. }
  35. #ifndef BOOST_NO_INTRINSIC_WCHAR_T
  36. e_float(wchar_t c)
  37. {
  38. m_value = ::e_float(c);
  39. }
  40. #endif
  41. e_float(unsigned char c)
  42. {
  43. m_value = ::e_float(c);
  44. }
  45. e_float(signed char c)
  46. {
  47. m_value = ::e_float(c);
  48. }
  49. e_float(unsigned short c)
  50. {
  51. m_value = ::e_float(c);
  52. }
  53. e_float(short c)
  54. {
  55. m_value = ::e_float(c);
  56. }
  57. e_float(unsigned int c)
  58. {
  59. m_value = ::e_float(c);
  60. }
  61. e_float(int c)
  62. {
  63. m_value = ::e_float(c);
  64. }
  65. e_float(unsigned long c)
  66. {
  67. m_value = ::e_float((UINT64)c);
  68. }
  69. e_float(long c)
  70. {
  71. m_value = ::e_float((INT64)c);
  72. }
  73. #ifdef BOOST_HAS_LONG_LONG
  74. e_float(boost::ulong_long_type c)
  75. {
  76. m_value = ::e_float(c);
  77. }
  78. e_float(boost::long_long_type c)
  79. {
  80. m_value = ::e_float(c);
  81. }
  82. #endif
  83. e_float(float c)
  84. {
  85. assign_large_real(c);
  86. }
  87. e_float(double c)
  88. {
  89. assign_large_real(c);
  90. }
  91. e_float(long double c)
  92. {
  93. assign_large_real(c);
  94. }
  95. // Assignment:
  96. e_float& operator=(char c) { m_value = ::e_float(c); return *this; }
  97. e_float& operator=(unsigned char c) { m_value = ::e_float(c); return *this; }
  98. e_float& operator=(signed char c) { m_value = ::e_float(c); return *this; }
  99. #ifndef BOOST_NO_INTRINSIC_WCHAR_T
  100. e_float& operator=(wchar_t c) { m_value = ::e_float(c); return *this; }
  101. #endif
  102. e_float& operator=(short c) { m_value = ::e_float(c); return *this; }
  103. e_float& operator=(unsigned short c) { m_value = ::e_float(c); return *this; }
  104. e_float& operator=(int c) { m_value = ::e_float(c); return *this; }
  105. e_float& operator=(unsigned int c) { m_value = ::e_float(c); return *this; }
  106. e_float& operator=(long c) { m_value = ::e_float((INT64)c); return *this; }
  107. e_float& operator=(unsigned long c) { m_value = ::e_float((UINT64)c); return *this; }
  108. #ifdef BOOST_HAS_LONG_LONG
  109. e_float& operator=(boost::long_long_type c) { m_value = ::e_float(c); return *this; }
  110. e_float& operator=(boost::ulong_long_type c) { m_value = ::e_float(c); return *this; }
  111. #endif
  112. e_float& operator=(float c) { assign_large_real(c); return *this; }
  113. e_float& operator=(double c) { assign_large_real(c); return *this; }
  114. e_float& operator=(long double c) { assign_large_real(c); return *this; }
  115. // Access:
  116. ::e_float& value(){ return m_value; }
  117. ::e_float const& value()const{ return m_value; }
  118. // Member arithmetic:
  119. e_float& operator+=(const e_float& other)
  120. { m_value += other.value(); return *this; }
  121. e_float& operator-=(const e_float& other)
  122. { m_value -= other.value(); return *this; }
  123. e_float& operator*=(const e_float& other)
  124. { m_value *= other.value(); return *this; }
  125. e_float& operator/=(const e_float& other)
  126. { m_value /= other.value(); return *this; }
  127. e_float operator-()const
  128. { return -m_value; }
  129. e_float const& operator+()const
  130. { return *this; }
  131. private:
  132. ::e_float m_value;
  133. template <class V>
  134. void assign_large_real(const V& a)
  135. {
  136. using std::frexp;
  137. using std::ldexp;
  138. using std::floor;
  139. if (a == 0) {
  140. m_value = ::ef::zero();
  141. return;
  142. }
  143. if (a == 1) {
  144. m_value = ::ef::one();
  145. return;
  146. }
  147. if ((boost::math::isinf)(a))
  148. {
  149. m_value = a > 0 ? m_value.my_value_inf() : -m_value.my_value_inf();
  150. return;
  151. }
  152. if((boost::math::isnan)(a))
  153. {
  154. m_value = m_value.my_value_nan();
  155. return;
  156. }
  157. int e;
  158. long double f, term;
  159. ::e_float t;
  160. m_value = ::ef::zero();
  161. f = frexp(a, &e);
  162. ::e_float shift = ::ef::pow2(30);
  163. while(f)
  164. {
  165. // extract 30 bits from f:
  166. f = ldexp(f, 30);
  167. term = floor(f);
  168. e -= 30;
  169. m_value *= shift;
  170. m_value += ::e_float(static_cast<INT64>(term));
  171. f -= term;
  172. }
  173. m_value *= ::ef::pow2(e);
  174. }
  175. };
  176. // Non-member arithmetic:
  177. inline e_float operator+(const e_float& a, const e_float& b)
  178. {
  179. e_float result(a);
  180. result += b;
  181. return result;
  182. }
  183. inline e_float operator-(const e_float& a, const e_float& b)
  184. {
  185. e_float result(a);
  186. result -= b;
  187. return result;
  188. }
  189. inline e_float operator*(const e_float& a, const e_float& b)
  190. {
  191. e_float result(a);
  192. result *= b;
  193. return result;
  194. }
  195. inline e_float operator/(const e_float& a, const e_float& b)
  196. {
  197. e_float result(a);
  198. result /= b;
  199. return result;
  200. }
  201. // Comparison:
  202. inline bool operator == (const e_float& a, const e_float& b)
  203. { return a.value() == b.value() ? true : false; }
  204. inline bool operator != (const e_float& a, const e_float& b)
  205. { return a.value() != b.value() ? true : false;}
  206. inline bool operator < (const e_float& a, const e_float& b)
  207. { return a.value() < b.value() ? true : false; }
  208. inline bool operator <= (const e_float& a, const e_float& b)
  209. { return a.value() <= b.value() ? true : false; }
  210. inline bool operator > (const e_float& a, const e_float& b)
  211. { return a.value() > b.value() ? true : false; }
  212. inline bool operator >= (const e_float& a, const e_float& b)
  213. { return a.value() >= b.value() ? true : false; }
  214. std::istream& operator >> (std::istream& is, e_float& f)
  215. {
  216. return is >> f.value();
  217. }
  218. std::ostream& operator << (std::ostream& os, const e_float& f)
  219. {
  220. return os << f.value();
  221. }
  222. inline e_float fabs(const e_float& v)
  223. {
  224. return ::ef::fabs(v.value());
  225. }
  226. inline e_float abs(const e_float& v)
  227. {
  228. return ::ef::fabs(v.value());
  229. }
  230. inline e_float floor(const e_float& v)
  231. {
  232. return ::ef::floor(v.value());
  233. }
  234. inline e_float ceil(const e_float& v)
  235. {
  236. return ::ef::ceil(v.value());
  237. }
  238. inline e_float pow(const e_float& v, const e_float& w)
  239. {
  240. return ::ef::pow(v.value(), w.value());
  241. }
  242. inline e_float pow(const e_float& v, int i)
  243. {
  244. return ::ef::pow(v.value(), ::e_float(i));
  245. }
  246. inline e_float exp(const e_float& v)
  247. {
  248. return ::ef::exp(v.value());
  249. }
  250. inline e_float log(const e_float& v)
  251. {
  252. return ::ef::log(v.value());
  253. }
  254. inline e_float sqrt(const e_float& v)
  255. {
  256. return ::ef::sqrt(v.value());
  257. }
  258. inline e_float sin(const e_float& v)
  259. {
  260. return ::ef::sin(v.value());
  261. }
  262. inline e_float cos(const e_float& v)
  263. {
  264. return ::ef::cos(v.value());
  265. }
  266. inline e_float tan(const e_float& v)
  267. {
  268. return ::ef::tan(v.value());
  269. }
  270. inline e_float acos(const e_float& v)
  271. {
  272. return ::ef::acos(v.value());
  273. }
  274. inline e_float asin(const e_float& v)
  275. {
  276. return ::ef::asin(v.value());
  277. }
  278. inline e_float atan(const e_float& v)
  279. {
  280. return ::ef::atan(v.value());
  281. }
  282. inline e_float atan2(const e_float& v, const e_float& u)
  283. {
  284. return ::ef::atan2(v.value(), u.value());
  285. }
  286. inline e_float ldexp(const e_float& v, int e)
  287. {
  288. return v.value() * ::ef::pow2(e);
  289. }
  290. inline e_float frexp(const e_float& v, int* expon)
  291. {
  292. double d;
  293. INT64 i;
  294. v.value().extract_parts(d, i);
  295. *expon = static_cast<int>(i);
  296. return v.value() * ::ef::pow2(-i);
  297. }
  298. inline e_float sinh (const e_float& x)
  299. {
  300. return ::ef::sinh(x.value());
  301. }
  302. inline e_float cosh (const e_float& x)
  303. {
  304. return ::ef::cosh(x.value());
  305. }
  306. inline e_float tanh (const e_float& x)
  307. {
  308. return ::ef::tanh(x.value());
  309. }
  310. inline e_float asinh (const e_float& x)
  311. {
  312. return ::ef::asinh(x.value());
  313. }
  314. inline e_float acosh (const e_float& x)
  315. {
  316. return ::ef::acosh(x.value());
  317. }
  318. inline e_float atanh (const e_float& x)
  319. {
  320. return ::ef::atanh(x.value());
  321. }
  322. e_float fmod(const e_float& v1, const e_float& v2)
  323. {
  324. e_float n;
  325. if(v1 < 0)
  326. n = ceil(v1 / v2);
  327. else
  328. n = floor(v1 / v2);
  329. return v1 - n * v2;
  330. }
  331. } namespace detail{
  332. template <>
  333. inline int fpclassify_imp< boost::math::ef::e_float> BOOST_NO_MACRO_EXPAND(boost::math::ef::e_float x, const generic_tag<true>&)
  334. {
  335. if(x.value().isnan())
  336. return FP_NAN;
  337. if(x.value().isinf())
  338. return FP_INFINITE;
  339. if(x == 0)
  340. return FP_ZERO;
  341. return FP_NORMAL;
  342. }
  343. } namespace ef{
  344. template <class Policy>
  345. inline int itrunc(const e_float& v, const Policy& pol)
  346. {
  347. BOOST_MATH_STD_USING
  348. e_float r = boost::math::trunc(v, pol);
  349. if(fabs(r) > (std::numeric_limits<int>::max)())
  350. return static_cast<int>(policies::raise_rounding_error("boost::math::itrunc<%1%>(%1%)", 0, 0, v, pol));
  351. return static_cast<int>(r.value().extract_int64());
  352. }
  353. template <class Policy>
  354. inline long ltrunc(const e_float& v, const Policy& pol)
  355. {
  356. BOOST_MATH_STD_USING
  357. e_float r = boost::math::trunc(v, pol);
  358. if(fabs(r) > (std::numeric_limits<long>::max)())
  359. return static_cast<long>(policies::raise_rounding_error("boost::math::ltrunc<%1%>(%1%)", 0, 0L, v, pol));
  360. return static_cast<long>(r.value().extract_int64());
  361. }
  362. #ifdef BOOST_HAS_LONG_LONG
  363. template <class Policy>
  364. inline boost::long_long_type lltrunc(const e_float& v, const Policy& pol)
  365. {
  366. BOOST_MATH_STD_USING
  367. e_float r = boost::math::trunc(v, pol);
  368. if(fabs(r) > (std::numeric_limits<boost::long_long_type>::max)())
  369. return static_cast<boost::long_long_type>(policies::raise_rounding_error("boost::math::lltrunc<%1%>(%1%)", 0, v, 0LL, pol).value().extract_int64());
  370. return static_cast<boost::long_long_type>(r.value().extract_int64());
  371. }
  372. #endif
  373. template <class Policy>
  374. inline int iround(const e_float& v, const Policy& pol)
  375. {
  376. BOOST_MATH_STD_USING
  377. e_float r = boost::math::round(v, pol);
  378. if(fabs(r) > (std::numeric_limits<int>::max)())
  379. return static_cast<int>(policies::raise_rounding_error("boost::math::iround<%1%>(%1%)", 0, v, 0, pol).value().extract_int64());
  380. return static_cast<int>(r.value().extract_int64());
  381. }
  382. template <class Policy>
  383. inline long lround(const e_float& v, const Policy& pol)
  384. {
  385. BOOST_MATH_STD_USING
  386. e_float r = boost::math::round(v, pol);
  387. if(fabs(r) > (std::numeric_limits<long>::max)())
  388. return static_cast<long int>(policies::raise_rounding_error("boost::math::lround<%1%>(%1%)", 0, v, 0L, pol).value().extract_int64());
  389. return static_cast<long int>(r.value().extract_int64());
  390. }
  391. #ifdef BOOST_HAS_LONG_LONG
  392. template <class Policy>
  393. inline boost::long_long_type llround(const e_float& v, const Policy& pol)
  394. {
  395. BOOST_MATH_STD_USING
  396. e_float r = boost::math::round(v, pol);
  397. if(fabs(r) > (std::numeric_limits<boost::long_long_type>::max)())
  398. return static_cast<boost::long_long_type>(policies::raise_rounding_error("boost::math::llround<%1%>(%1%)", 0, v, 0LL, pol).value().extract_int64());
  399. return static_cast<boost::long_long_type>(r.value().extract_int64());
  400. }
  401. #endif
  402. }}}
  403. namespace std{
  404. template<>
  405. class numeric_limits< ::boost::math::ef::e_float> : public numeric_limits< ::e_float>
  406. {
  407. public:
  408. static const ::boost::math::ef::e_float (min) (void)
  409. {
  410. return (numeric_limits< ::e_float>::min)();
  411. }
  412. static const ::boost::math::ef::e_float (max) (void)
  413. {
  414. return (numeric_limits< ::e_float>::max)();
  415. }
  416. static const ::boost::math::ef::e_float epsilon (void)
  417. {
  418. return (numeric_limits< ::e_float>::epsilon)();
  419. }
  420. static const ::boost::math::ef::e_float round_error(void)
  421. {
  422. return (numeric_limits< ::e_float>::round_error)();
  423. }
  424. static const ::boost::math::ef::e_float infinity (void)
  425. {
  426. return (numeric_limits< ::e_float>::infinity)();
  427. }
  428. static const ::boost::math::ef::e_float quiet_NaN (void)
  429. {
  430. return (numeric_limits< ::e_float>::quiet_NaN)();
  431. }
  432. //
  433. // e_float's supplied digits member is wrong
  434. // - it should be same the same as digits 10
  435. // - given that radix is 10.
  436. //
  437. static const int digits = digits10;
  438. };
  439. } // namespace std
  440. namespace boost{ namespace math{
  441. namespace policies{
  442. template <class Policy>
  443. struct precision< ::boost::math::ef::e_float, Policy>
  444. {
  445. typedef typename Policy::precision_type precision_type;
  446. typedef digits2<((::std::numeric_limits< ::boost::math::ef::e_float>::digits10 + 1) * 1000L) / 301L> digits_2;
  447. typedef typename mpl::if_c<
  448. ((digits_2::value <= precision_type::value)
  449. || (Policy::precision_type::value <= 0)),
  450. // Default case, full precision for RealType:
  451. digits_2,
  452. // User customised precision:
  453. precision_type
  454. >::type type;
  455. };
  456. }
  457. namespace tools{
  458. template <>
  459. inline int digits< ::boost::math::ef::e_float>(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC( ::boost::math::ef::e_float))
  460. {
  461. return ((::std::numeric_limits< ::boost::math::ef::e_float>::digits10 + 1) * 1000L) / 301L;
  462. }
  463. template <>
  464. inline ::boost::math::ef::e_float root_epsilon< ::boost::math::ef::e_float>()
  465. {
  466. return detail::root_epsilon_imp(static_cast< ::boost::math::ef::e_float const*>(0), mpl::int_<0>());
  467. }
  468. template <>
  469. inline ::boost::math::ef::e_float forth_root_epsilon< ::boost::math::ef::e_float>()
  470. {
  471. return detail::forth_root_epsilon_imp(static_cast< ::boost::math::ef::e_float const*>(0), mpl::int_<0>());
  472. }
  473. }
  474. namespace lanczos{
  475. template<class Policy>
  476. struct lanczos<boost::math::ef::e_float, Policy>
  477. {
  478. typedef typename mpl::if_c<
  479. std::numeric_limits< ::e_float>::digits10 < 22,
  480. lanczos13UDT,
  481. typename mpl::if_c<
  482. std::numeric_limits< ::e_float>::digits10 < 36,
  483. lanczos22UDT,
  484. typename mpl::if_c<
  485. std::numeric_limits< ::e_float>::digits10 < 50,
  486. lanczos31UDT,
  487. typename mpl::if_c<
  488. std::numeric_limits< ::e_float>::digits10 < 110,
  489. lanczos61UDT,
  490. undefined_lanczos
  491. >::type
  492. >::type
  493. >::type
  494. >::type type;
  495. };
  496. } // namespace lanczos
  497. template <class Policy>
  498. inline boost::math::ef::e_float skewness(const extreme_value_distribution<boost::math::ef::e_float, Policy>& /*dist*/)
  499. {
  500. //
  501. // This is 12 * sqrt(6) * zeta(3) / pi^3:
  502. // See http://mathworld.wolfram.com/ExtremeValueDistribution.html
  503. //
  504. return boost::lexical_cast<boost::math::ef::e_float>("1.1395470994046486574927930193898461120875997958366");
  505. }
  506. template <class Policy>
  507. inline boost::math::ef::e_float skewness(const rayleigh_distribution<boost::math::ef::e_float, Policy>& /*dist*/)
  508. {
  509. // using namespace boost::math::constants;
  510. return boost::lexical_cast<boost::math::ef::e_float>("0.63111065781893713819189935154422777984404221106391");
  511. // Computed using NTL at 150 bit, about 50 decimal digits.
  512. // return 2 * root_pi<RealType>() * pi_minus_three<RealType>() / pow23_four_minus_pi<RealType>();
  513. }
  514. template <class Policy>
  515. inline boost::math::ef::e_float kurtosis(const rayleigh_distribution<boost::math::ef::e_float, Policy>& /*dist*/)
  516. {
  517. // using namespace boost::math::constants;
  518. return boost::lexical_cast<boost::math::ef::e_float>("3.2450893006876380628486604106197544154170667057995");
  519. // Computed using NTL at 150 bit, about 50 decimal digits.
  520. // return 3 - (6 * pi<RealType>() * pi<RealType>() - 24 * pi<RealType>() + 16) /
  521. // (four_minus_pi<RealType>() * four_minus_pi<RealType>());
  522. }
  523. template <class Policy>
  524. inline boost::math::ef::e_float kurtosis_excess(const rayleigh_distribution<boost::math::ef::e_float, Policy>& /*dist*/)
  525. {
  526. //using namespace boost::math::constants;
  527. // Computed using NTL at 150 bit, about 50 decimal digits.
  528. return boost::lexical_cast<boost::math::ef::e_float>("0.2450893006876380628486604106197544154170667057995");
  529. // return -(6 * pi<RealType>() * pi<RealType>() - 24 * pi<RealType>() + 16) /
  530. // (four_minus_pi<RealType>() * four_minus_pi<RealType>());
  531. } // kurtosis
  532. namespace detail{
  533. //
  534. // Version of Digamma accurate to ~100 decimal digits.
  535. //
  536. template <class Policy>
  537. boost::math::ef::e_float digamma_imp(boost::math::ef::e_float x, const mpl::int_<0>* , const Policy& pol)
  538. {
  539. //
  540. // This handles reflection of negative arguments, and all our
  541. // eboost::math::ef::e_floator handling, then forwards to the T-specific approximation.
  542. //
  543. BOOST_MATH_STD_USING // ADL of std functions.
  544. boost::math::ef::e_float result = 0;
  545. //
  546. // Check for negative arguments and use reflection:
  547. //
  548. if(x < 0)
  549. {
  550. // Reflect:
  551. x = 1 - x;
  552. // Argument reduction for tan:
  553. boost::math::ef::e_float remainder = x - floor(x);
  554. // Shift to negative if > 0.5:
  555. if(remainder > 0.5)
  556. {
  557. remainder -= 1;
  558. }
  559. //
  560. // check for evaluation at a negative pole:
  561. //
  562. if(remainder == 0)
  563. {
  564. return policies::raise_pole_error<boost::math::ef::e_float>("boost::math::digamma<%1%>(%1%)", 0, (1-x), pol);
  565. }
  566. result = constants::pi<boost::math::ef::e_float>() / tan(constants::pi<boost::math::ef::e_float>() * remainder);
  567. }
  568. result += big_digamma(x);
  569. return result;
  570. }
  571. boost::math::ef::e_float bessel_i0(boost::math::ef::e_float x)
  572. {
  573. static const boost::math::ef::e_float P1[] = {
  574. boost::lexical_cast<boost::math::ef::e_float>("-2.2335582639474375249e+15"),
  575. boost::lexical_cast<boost::math::ef::e_float>("-5.5050369673018427753e+14"),
  576. boost::lexical_cast<boost::math::ef::e_float>("-3.2940087627407749166e+13"),
  577. boost::lexical_cast<boost::math::ef::e_float>("-8.4925101247114157499e+11"),
  578. boost::lexical_cast<boost::math::ef::e_float>("-1.1912746104985237192e+10"),
  579. boost::lexical_cast<boost::math::ef::e_float>("-1.0313066708737980747e+08"),
  580. boost::lexical_cast<boost::math::ef::e_float>("-5.9545626019847898221e+05"),
  581. boost::lexical_cast<boost::math::ef::e_float>("-2.4125195876041896775e+03"),
  582. boost::lexical_cast<boost::math::ef::e_float>("-7.0935347449210549190e+00"),
  583. boost::lexical_cast<boost::math::ef::e_float>("-1.5453977791786851041e-02"),
  584. boost::lexical_cast<boost::math::ef::e_float>("-2.5172644670688975051e-05"),
  585. boost::lexical_cast<boost::math::ef::e_float>("-3.0517226450451067446e-08"),
  586. boost::lexical_cast<boost::math::ef::e_float>("-2.6843448573468483278e-11"),
  587. boost::lexical_cast<boost::math::ef::e_float>("-1.5982226675653184646e-14"),
  588. boost::lexical_cast<boost::math::ef::e_float>("-5.2487866627945699800e-18"),
  589. };
  590. static const boost::math::ef::e_float Q1[] = {
  591. boost::lexical_cast<boost::math::ef::e_float>("-2.2335582639474375245e+15"),
  592. boost::lexical_cast<boost::math::ef::e_float>("7.8858692566751002988e+12"),
  593. boost::lexical_cast<boost::math::ef::e_float>("-1.2207067397808979846e+10"),
  594. boost::lexical_cast<boost::math::ef::e_float>("1.0377081058062166144e+07"),
  595. boost::lexical_cast<boost::math::ef::e_float>("-4.8527560179962773045e+03"),
  596. boost::lexical_cast<boost::math::ef::e_float>("1.0"),
  597. };
  598. static const boost::math::ef::e_float P2[] = {
  599. boost::lexical_cast<boost::math::ef::e_float>("-2.2210262233306573296e-04"),
  600. boost::lexical_cast<boost::math::ef::e_float>("1.3067392038106924055e-02"),
  601. boost::lexical_cast<boost::math::ef::e_float>("-4.4700805721174453923e-01"),
  602. boost::lexical_cast<boost::math::ef::e_float>("5.5674518371240761397e+00"),
  603. boost::lexical_cast<boost::math::ef::e_float>("-2.3517945679239481621e+01"),
  604. boost::lexical_cast<boost::math::ef::e_float>("3.1611322818701131207e+01"),
  605. boost::lexical_cast<boost::math::ef::e_float>("-9.6090021968656180000e+00"),
  606. };
  607. static const boost::math::ef::e_float Q2[] = {
  608. boost::lexical_cast<boost::math::ef::e_float>("-5.5194330231005480228e-04"),
  609. boost::lexical_cast<boost::math::ef::e_float>("3.2547697594819615062e-02"),
  610. boost::lexical_cast<boost::math::ef::e_float>("-1.1151759188741312645e+00"),
  611. boost::lexical_cast<boost::math::ef::e_float>("1.3982595353892851542e+01"),
  612. boost::lexical_cast<boost::math::ef::e_float>("-6.0228002066743340583e+01"),
  613. boost::lexical_cast<boost::math::ef::e_float>("8.5539563258012929600e+01"),
  614. boost::lexical_cast<boost::math::ef::e_float>("-3.1446690275135491500e+01"),
  615. boost::lexical_cast<boost::math::ef::e_float>("1.0"),
  616. };
  617. boost::math::ef::e_float value, factor, r;
  618. BOOST_MATH_STD_USING
  619. using namespace boost::math::tools;
  620. if (x < 0)
  621. {
  622. x = -x; // even function
  623. }
  624. if (x == 0)
  625. {
  626. return static_cast<boost::math::ef::e_float>(1);
  627. }
  628. if (x <= 15) // x in (0, 15]
  629. {
  630. boost::math::ef::e_float y = x * x;
  631. value = evaluate_polynomial(P1, y) / evaluate_polynomial(Q1, y);
  632. }
  633. else // x in (15, \infty)
  634. {
  635. boost::math::ef::e_float y = 1 / x - boost::math::ef::e_float(1) / 15;
  636. r = evaluate_polynomial(P2, y) / evaluate_polynomial(Q2, y);
  637. factor = exp(x) / sqrt(x);
  638. value = factor * r;
  639. }
  640. return value;
  641. }
  642. boost::math::ef::e_float bessel_i1(boost::math::ef::e_float x)
  643. {
  644. static const boost::math::ef::e_float P1[] = {
  645. lexical_cast<boost::math::ef::e_float>("-1.4577180278143463643e+15"),
  646. lexical_cast<boost::math::ef::e_float>("-1.7732037840791591320e+14"),
  647. lexical_cast<boost::math::ef::e_float>("-6.9876779648010090070e+12"),
  648. lexical_cast<boost::math::ef::e_float>("-1.3357437682275493024e+11"),
  649. lexical_cast<boost::math::ef::e_float>("-1.4828267606612366099e+09"),
  650. lexical_cast<boost::math::ef::e_float>("-1.0588550724769347106e+07"),
  651. lexical_cast<boost::math::ef::e_float>("-5.1894091982308017540e+04"),
  652. lexical_cast<boost::math::ef::e_float>("-1.8225946631657315931e+02"),
  653. lexical_cast<boost::math::ef::e_float>("-4.7207090827310162436e-01"),
  654. lexical_cast<boost::math::ef::e_float>("-9.1746443287817501309e-04"),
  655. lexical_cast<boost::math::ef::e_float>("-1.3466829827635152875e-06"),
  656. lexical_cast<boost::math::ef::e_float>("-1.4831904935994647675e-09"),
  657. lexical_cast<boost::math::ef::e_float>("-1.1928788903603238754e-12"),
  658. lexical_cast<boost::math::ef::e_float>("-6.5245515583151902910e-16"),
  659. lexical_cast<boost::math::ef::e_float>("-1.9705291802535139930e-19"),
  660. };
  661. static const boost::math::ef::e_float Q1[] = {
  662. lexical_cast<boost::math::ef::e_float>("-2.9154360556286927285e+15"),
  663. lexical_cast<boost::math::ef::e_float>("9.7887501377547640438e+12"),
  664. lexical_cast<boost::math::ef::e_float>("-1.4386907088588283434e+10"),
  665. lexical_cast<boost::math::ef::e_float>("1.1594225856856884006e+07"),
  666. lexical_cast<boost::math::ef::e_float>("-5.1326864679904189920e+03"),
  667. lexical_cast<boost::math::ef::e_float>("1.0"),
  668. };
  669. static const boost::math::ef::e_float P2[] = {
  670. lexical_cast<boost::math::ef::e_float>("1.4582087408985668208e-05"),
  671. lexical_cast<boost::math::ef::e_float>("-8.9359825138577646443e-04"),
  672. lexical_cast<boost::math::ef::e_float>("2.9204895411257790122e-02"),
  673. lexical_cast<boost::math::ef::e_float>("-3.4198728018058047439e-01"),
  674. lexical_cast<boost::math::ef::e_float>("1.3960118277609544334e+00"),
  675. lexical_cast<boost::math::ef::e_float>("-1.9746376087200685843e+00"),
  676. lexical_cast<boost::math::ef::e_float>("8.5591872901933459000e-01"),
  677. lexical_cast<boost::math::ef::e_float>("-6.0437159056137599999e-02"),
  678. };
  679. static const boost::math::ef::e_float Q2[] = {
  680. lexical_cast<boost::math::ef::e_float>("3.7510433111922824643e-05"),
  681. lexical_cast<boost::math::ef::e_float>("-2.2835624489492512649e-03"),
  682. lexical_cast<boost::math::ef::e_float>("7.4212010813186530069e-02"),
  683. lexical_cast<boost::math::ef::e_float>("-8.5017476463217924408e-01"),
  684. lexical_cast<boost::math::ef::e_float>("3.2593714889036996297e+00"),
  685. lexical_cast<boost::math::ef::e_float>("-3.8806586721556593450e+00"),
  686. lexical_cast<boost::math::ef::e_float>("1.0"),
  687. };
  688. boost::math::ef::e_float value, factor, r, w;
  689. BOOST_MATH_STD_USING
  690. using namespace boost::math::tools;
  691. w = abs(x);
  692. if (x == 0)
  693. {
  694. return static_cast<boost::math::ef::e_float>(0);
  695. }
  696. if (w <= 15) // w in (0, 15]
  697. {
  698. boost::math::ef::e_float y = x * x;
  699. r = evaluate_polynomial(P1, y) / evaluate_polynomial(Q1, y);
  700. factor = w;
  701. value = factor * r;
  702. }
  703. else // w in (15, \infty)
  704. {
  705. boost::math::ef::e_float y = 1 / w - boost::math::ef::e_float(1) / 15;
  706. r = evaluate_polynomial(P2, y) / evaluate_polynomial(Q2, y);
  707. factor = exp(w) / sqrt(w);
  708. value = factor * r;
  709. }
  710. if (x < 0)
  711. {
  712. value *= -value; // odd function
  713. }
  714. return value;
  715. }
  716. } // namespace detail
  717. }}
  718. #endif // BOOST_MATH_E_FLOAT_BINDINGS_HPP