trig.hpp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845
  1. // Copyright Christopher Kormanyos 2002 - 2011.
  2. // Copyright 2011 John Maddock. Distributed under the Boost
  3. // Distributed under the Boost Software License, Version 1.0.
  4. // (See accompanying file LICENSE_1_0.txt or copy at
  5. // http://www.boost.org/LICENSE_1_0.txt)
  6. // This work is based on an earlier work:
  7. // "Algorithm 910: A Portable C++ Multiple-Precision System for Special-Function Calculations",
  8. // in ACM TOMS, {VOL 37, ISSUE 4, (February 2011)} (C) ACM, 2011. http://doi.acm.org/10.1145/1916461.1916469
  9. //
  10. // This file has no include guards or namespaces - it's expanded inline inside default_ops.hpp
  11. //
  12. #ifdef BOOST_MSVC
  13. #pragma warning(push)
  14. #pragma warning(disable : 6326) // comparison of two constants
  15. #endif
  16. template <class T>
  17. void hyp0F1(T& result, const T& b, const T& x)
  18. {
  19. typedef typename boost::multiprecision::detail::canonical<boost::int32_t, T>::type si_type;
  20. typedef typename boost::multiprecision::detail::canonical<boost::uint32_t, T>::type ui_type;
  21. // Compute the series representation of Hypergeometric0F1 taken from
  22. // http://functions.wolfram.com/HypergeometricFunctions/Hypergeometric0F1/06/01/01/
  23. // There are no checks on input range or parameter boundaries.
  24. T x_pow_n_div_n_fact(x);
  25. T pochham_b(b);
  26. T bp(b);
  27. eval_divide(result, x_pow_n_div_n_fact, pochham_b);
  28. eval_add(result, ui_type(1));
  29. si_type n;
  30. T tol;
  31. tol = ui_type(1);
  32. eval_ldexp(tol, tol, 1 - boost::multiprecision::detail::digits2<number<T, et_on> >::value());
  33. eval_multiply(tol, result);
  34. if (eval_get_sign(tol) < 0)
  35. tol.negate();
  36. T term;
  37. const int series_limit =
  38. boost::multiprecision::detail::digits2<number<T, et_on> >::value() < 100
  39. ? 100
  40. : boost::multiprecision::detail::digits2<number<T, et_on> >::value();
  41. // Series expansion of hyperg_0f1(; b; x).
  42. for (n = 2; n < series_limit; ++n)
  43. {
  44. eval_multiply(x_pow_n_div_n_fact, x);
  45. eval_divide(x_pow_n_div_n_fact, n);
  46. eval_increment(bp);
  47. eval_multiply(pochham_b, bp);
  48. eval_divide(term, x_pow_n_div_n_fact, pochham_b);
  49. eval_add(result, term);
  50. bool neg_term = eval_get_sign(term) < 0;
  51. if (neg_term)
  52. term.negate();
  53. if (term.compare(tol) <= 0)
  54. break;
  55. }
  56. if (n >= series_limit)
  57. BOOST_THROW_EXCEPTION(std::runtime_error("H0F1 Failed to Converge"));
  58. }
  59. template <class T>
  60. void eval_sin(T& result, const T& x)
  61. {
  62. BOOST_STATIC_ASSERT_MSG(number_category<T>::value == number_kind_floating_point, "The sin function is only valid for floating point types.");
  63. if (&result == &x)
  64. {
  65. T temp;
  66. eval_sin(temp, x);
  67. result = temp;
  68. return;
  69. }
  70. typedef typename boost::multiprecision::detail::canonical<boost::int32_t, T>::type si_type;
  71. typedef typename boost::multiprecision::detail::canonical<boost::uint32_t, T>::type ui_type;
  72. typedef typename mpl::front<typename T::float_types>::type fp_type;
  73. switch (eval_fpclassify(x))
  74. {
  75. case FP_INFINITE:
  76. case FP_NAN:
  77. if (std::numeric_limits<number<T, et_on> >::has_quiet_NaN)
  78. {
  79. result = std::numeric_limits<number<T, et_on> >::quiet_NaN().backend();
  80. errno = EDOM;
  81. }
  82. else
  83. BOOST_THROW_EXCEPTION(std::domain_error("Result is undefined or complex and there is no NaN for this number type."));
  84. return;
  85. case FP_ZERO:
  86. result = x;
  87. return;
  88. default:;
  89. }
  90. // Local copy of the argument
  91. T xx = x;
  92. // Analyze and prepare the phase of the argument.
  93. // Make a local, positive copy of the argument, xx.
  94. // The argument xx will be reduced to 0 <= xx <= pi/2.
  95. bool b_negate_sin = false;
  96. if (eval_get_sign(x) < 0)
  97. {
  98. xx.negate();
  99. b_negate_sin = !b_negate_sin;
  100. }
  101. T n_pi, t;
  102. // Remove even multiples of pi.
  103. if (xx.compare(get_constant_pi<T>()) > 0)
  104. {
  105. eval_divide(n_pi, xx, get_constant_pi<T>());
  106. eval_trunc(n_pi, n_pi);
  107. t = ui_type(2);
  108. eval_fmod(t, n_pi, t);
  109. const bool b_n_pi_is_even = eval_get_sign(t) == 0;
  110. eval_multiply(n_pi, get_constant_pi<T>());
  111. if (n_pi.compare(get_constant_one_over_epsilon<T>()) > 0)
  112. {
  113. result = ui_type(0);
  114. return;
  115. }
  116. else
  117. eval_subtract(xx, n_pi);
  118. BOOST_MATH_INSTRUMENT_CODE(xx.str(0, std::ios_base::scientific));
  119. BOOST_MATH_INSTRUMENT_CODE(n_pi.str(0, std::ios_base::scientific));
  120. // Adjust signs if the multiple of pi is not even.
  121. if (!b_n_pi_is_even)
  122. {
  123. b_negate_sin = !b_negate_sin;
  124. }
  125. }
  126. // Reduce the argument to 0 <= xx <= pi/2.
  127. eval_ldexp(t, get_constant_pi<T>(), -1);
  128. if (xx.compare(t) > 0)
  129. {
  130. eval_subtract(xx, get_constant_pi<T>(), xx);
  131. BOOST_MATH_INSTRUMENT_CODE(xx.str(0, std::ios_base::scientific));
  132. }
  133. eval_subtract(t, xx);
  134. const bool b_zero = eval_get_sign(xx) == 0;
  135. const bool b_pi_half = eval_get_sign(t) == 0;
  136. // Check if the reduced argument is very close to 0 or pi/2.
  137. const bool b_near_zero = xx.compare(fp_type(1e-1)) < 0;
  138. const bool b_near_pi_half = t.compare(fp_type(1e-1)) < 0;
  139. ;
  140. if (b_zero)
  141. {
  142. result = ui_type(0);
  143. }
  144. else if (b_pi_half)
  145. {
  146. result = ui_type(1);
  147. }
  148. else if (b_near_zero)
  149. {
  150. eval_multiply(t, xx, xx);
  151. eval_divide(t, si_type(-4));
  152. T t2;
  153. t2 = fp_type(1.5);
  154. hyp0F1(result, t2, t);
  155. BOOST_MATH_INSTRUMENT_CODE(result.str(0, std::ios_base::scientific));
  156. eval_multiply(result, xx);
  157. }
  158. else if (b_near_pi_half)
  159. {
  160. eval_multiply(t, t);
  161. eval_divide(t, si_type(-4));
  162. T t2;
  163. t2 = fp_type(0.5);
  164. hyp0F1(result, t2, t);
  165. BOOST_MATH_INSTRUMENT_CODE(result.str(0, std::ios_base::scientific));
  166. }
  167. else
  168. {
  169. // Scale to a small argument for an efficient Taylor series,
  170. // implemented as a hypergeometric function. Use a standard
  171. // divide by three identity a certain number of times.
  172. // Here we use division by 3^9 --> (19683 = 3^9).
  173. static const si_type n_scale = 9;
  174. static const si_type n_three_pow_scale = static_cast<si_type>(19683L);
  175. eval_divide(xx, n_three_pow_scale);
  176. // Now with small arguments, we are ready for a series expansion.
  177. eval_multiply(t, xx, xx);
  178. eval_divide(t, si_type(-4));
  179. T t2;
  180. t2 = fp_type(1.5);
  181. hyp0F1(result, t2, t);
  182. BOOST_MATH_INSTRUMENT_CODE(result.str(0, std::ios_base::scientific));
  183. eval_multiply(result, xx);
  184. // Convert back using multiple angle identity.
  185. for (boost::int32_t k = static_cast<boost::int32_t>(0); k < n_scale; k++)
  186. {
  187. // Rescale the cosine value using the multiple angle identity.
  188. eval_multiply(t2, result, ui_type(3));
  189. eval_multiply(t, result, result);
  190. eval_multiply(t, result);
  191. eval_multiply(t, ui_type(4));
  192. eval_subtract(result, t2, t);
  193. }
  194. }
  195. if (b_negate_sin)
  196. result.negate();
  197. }
  198. template <class T>
  199. void eval_cos(T& result, const T& x)
  200. {
  201. BOOST_STATIC_ASSERT_MSG(number_category<T>::value == number_kind_floating_point, "The cos function is only valid for floating point types.");
  202. if (&result == &x)
  203. {
  204. T temp;
  205. eval_cos(temp, x);
  206. result = temp;
  207. return;
  208. }
  209. typedef typename boost::multiprecision::detail::canonical<boost::int32_t, T>::type si_type;
  210. typedef typename boost::multiprecision::detail::canonical<boost::uint32_t, T>::type ui_type;
  211. typedef typename mpl::front<typename T::float_types>::type fp_type;
  212. switch (eval_fpclassify(x))
  213. {
  214. case FP_INFINITE:
  215. case FP_NAN:
  216. if (std::numeric_limits<number<T, et_on> >::has_quiet_NaN)
  217. {
  218. result = std::numeric_limits<number<T, et_on> >::quiet_NaN().backend();
  219. errno = EDOM;
  220. }
  221. else
  222. BOOST_THROW_EXCEPTION(std::domain_error("Result is undefined or complex and there is no NaN for this number type."));
  223. return;
  224. case FP_ZERO:
  225. result = ui_type(1);
  226. return;
  227. default:;
  228. }
  229. // Local copy of the argument
  230. T xx = x;
  231. // Analyze and prepare the phase of the argument.
  232. // Make a local, positive copy of the argument, xx.
  233. // The argument xx will be reduced to 0 <= xx <= pi/2.
  234. bool b_negate_cos = false;
  235. if (eval_get_sign(x) < 0)
  236. {
  237. xx.negate();
  238. }
  239. T n_pi, t;
  240. // Remove even multiples of pi.
  241. if (xx.compare(get_constant_pi<T>()) > 0)
  242. {
  243. eval_divide(t, xx, get_constant_pi<T>());
  244. eval_trunc(n_pi, t);
  245. BOOST_MATH_INSTRUMENT_CODE(n_pi.str(0, std::ios_base::scientific));
  246. eval_multiply(t, n_pi, get_constant_pi<T>());
  247. BOOST_MATH_INSTRUMENT_CODE(t.str(0, std::ios_base::scientific));
  248. //
  249. // If t is so large that all digits cancel the result of this subtraction
  250. // is completely meaningless, just assume the result is zero for now...
  251. //
  252. // TODO We should of course do much better, see:
  253. // "ARGUMENT REDUCTION FOR HUGE ARGUMENTS" K C Ng 1992
  254. //
  255. if (n_pi.compare(get_constant_one_over_epsilon<T>()) > 0)
  256. {
  257. result = ui_type(1);
  258. return;
  259. }
  260. else
  261. eval_subtract(xx, t);
  262. BOOST_MATH_INSTRUMENT_CODE(xx.str(0, std::ios_base::scientific));
  263. // Adjust signs if the multiple of pi is not even.
  264. t = ui_type(2);
  265. eval_fmod(t, n_pi, t);
  266. const bool b_n_pi_is_even = eval_get_sign(t) == 0;
  267. if (!b_n_pi_is_even)
  268. {
  269. b_negate_cos = !b_negate_cos;
  270. }
  271. }
  272. // Reduce the argument to 0 <= xx <= pi/2.
  273. eval_ldexp(t, get_constant_pi<T>(), -1);
  274. int com = xx.compare(t);
  275. if (com > 0)
  276. {
  277. eval_subtract(xx, get_constant_pi<T>(), xx);
  278. b_negate_cos = !b_negate_cos;
  279. BOOST_MATH_INSTRUMENT_CODE(xx.str(0, std::ios_base::scientific));
  280. }
  281. const bool b_zero = eval_get_sign(xx) == 0;
  282. const bool b_pi_half = com == 0;
  283. // Check if the reduced argument is very close to 0.
  284. const bool b_near_zero = xx.compare(fp_type(1e-1)) < 0;
  285. if (b_zero)
  286. {
  287. result = si_type(1);
  288. }
  289. else if (b_pi_half)
  290. {
  291. result = si_type(0);
  292. }
  293. else if (b_near_zero)
  294. {
  295. eval_multiply(t, xx, xx);
  296. eval_divide(t, si_type(-4));
  297. n_pi = fp_type(0.5f);
  298. hyp0F1(result, n_pi, t);
  299. BOOST_MATH_INSTRUMENT_CODE(result.str(0, std::ios_base::scientific));
  300. }
  301. else
  302. {
  303. eval_subtract(t, xx);
  304. eval_sin(result, t);
  305. }
  306. if (b_negate_cos)
  307. result.negate();
  308. }
  309. template <class T>
  310. void eval_tan(T& result, const T& x)
  311. {
  312. BOOST_STATIC_ASSERT_MSG(number_category<T>::value == number_kind_floating_point, "The tan function is only valid for floating point types.");
  313. if (&result == &x)
  314. {
  315. T temp;
  316. eval_tan(temp, x);
  317. result = temp;
  318. return;
  319. }
  320. T t;
  321. eval_sin(result, x);
  322. eval_cos(t, x);
  323. eval_divide(result, t);
  324. }
  325. template <class T>
  326. void hyp2F1(T& result, const T& a, const T& b, const T& c, const T& x)
  327. {
  328. // Compute the series representation of hyperg_2f1 taken from
  329. // Abramowitz and Stegun 15.1.1.
  330. // There are no checks on input range or parameter boundaries.
  331. typedef typename boost::multiprecision::detail::canonical<boost::uint32_t, T>::type ui_type;
  332. T x_pow_n_div_n_fact(x);
  333. T pochham_a(a);
  334. T pochham_b(b);
  335. T pochham_c(c);
  336. T ap(a);
  337. T bp(b);
  338. T cp(c);
  339. eval_multiply(result, pochham_a, pochham_b);
  340. eval_divide(result, pochham_c);
  341. eval_multiply(result, x_pow_n_div_n_fact);
  342. eval_add(result, ui_type(1));
  343. T lim;
  344. eval_ldexp(lim, result, 1 - boost::multiprecision::detail::digits2<number<T, et_on> >::value());
  345. if (eval_get_sign(lim) < 0)
  346. lim.negate();
  347. ui_type n;
  348. T term;
  349. const unsigned series_limit =
  350. boost::multiprecision::detail::digits2<number<T, et_on> >::value() < 100
  351. ? 100
  352. : boost::multiprecision::detail::digits2<number<T, et_on> >::value();
  353. // Series expansion of hyperg_2f1(a, b; c; x).
  354. for (n = 2; n < series_limit; ++n)
  355. {
  356. eval_multiply(x_pow_n_div_n_fact, x);
  357. eval_divide(x_pow_n_div_n_fact, n);
  358. eval_increment(ap);
  359. eval_multiply(pochham_a, ap);
  360. eval_increment(bp);
  361. eval_multiply(pochham_b, bp);
  362. eval_increment(cp);
  363. eval_multiply(pochham_c, cp);
  364. eval_multiply(term, pochham_a, pochham_b);
  365. eval_divide(term, pochham_c);
  366. eval_multiply(term, x_pow_n_div_n_fact);
  367. eval_add(result, term);
  368. if (eval_get_sign(term) < 0)
  369. term.negate();
  370. if (lim.compare(term) >= 0)
  371. break;
  372. }
  373. if (n > series_limit)
  374. BOOST_THROW_EXCEPTION(std::runtime_error("H2F1 failed to converge."));
  375. }
  376. template <class T>
  377. void eval_asin(T& result, const T& x)
  378. {
  379. BOOST_STATIC_ASSERT_MSG(number_category<T>::value == number_kind_floating_point, "The asin function is only valid for floating point types.");
  380. typedef typename boost::multiprecision::detail::canonical<boost::uint32_t, T>::type ui_type;
  381. typedef typename mpl::front<typename T::float_types>::type fp_type;
  382. if (&result == &x)
  383. {
  384. T t(x);
  385. eval_asin(result, t);
  386. return;
  387. }
  388. switch (eval_fpclassify(x))
  389. {
  390. case FP_NAN:
  391. case FP_INFINITE:
  392. if (std::numeric_limits<number<T, et_on> >::has_quiet_NaN)
  393. {
  394. result = std::numeric_limits<number<T, et_on> >::quiet_NaN().backend();
  395. errno = EDOM;
  396. }
  397. else
  398. BOOST_THROW_EXCEPTION(std::domain_error("Result is undefined or complex and there is no NaN for this number type."));
  399. return;
  400. case FP_ZERO:
  401. result = x;
  402. return;
  403. default:;
  404. }
  405. const bool b_neg = eval_get_sign(x) < 0;
  406. T xx(x);
  407. if (b_neg)
  408. xx.negate();
  409. int c = xx.compare(ui_type(1));
  410. if (c > 0)
  411. {
  412. if (std::numeric_limits<number<T, et_on> >::has_quiet_NaN)
  413. {
  414. result = std::numeric_limits<number<T, et_on> >::quiet_NaN().backend();
  415. errno = EDOM;
  416. }
  417. else
  418. BOOST_THROW_EXCEPTION(std::domain_error("Result is undefined or complex and there is no NaN for this number type."));
  419. return;
  420. }
  421. else if (c == 0)
  422. {
  423. result = get_constant_pi<T>();
  424. eval_ldexp(result, result, -1);
  425. if (b_neg)
  426. result.negate();
  427. return;
  428. }
  429. if (xx.compare(fp_type(1e-4)) < 0)
  430. {
  431. // http://functions.wolfram.com/ElementaryFunctions/ArcSin/26/01/01/
  432. eval_multiply(xx, xx);
  433. T t1, t2;
  434. t1 = fp_type(0.5f);
  435. t2 = fp_type(1.5f);
  436. hyp2F1(result, t1, t1, t2, xx);
  437. eval_multiply(result, x);
  438. return;
  439. }
  440. else if (xx.compare(fp_type(1 - 1e-4f)) > 0)
  441. {
  442. T dx1;
  443. T t1, t2;
  444. eval_subtract(dx1, ui_type(1), xx);
  445. t1 = fp_type(0.5f);
  446. t2 = fp_type(1.5f);
  447. eval_ldexp(dx1, dx1, -1);
  448. hyp2F1(result, t1, t1, t2, dx1);
  449. eval_ldexp(dx1, dx1, 2);
  450. eval_sqrt(t1, dx1);
  451. eval_multiply(result, t1);
  452. eval_ldexp(t1, get_constant_pi<T>(), -1);
  453. result.negate();
  454. eval_add(result, t1);
  455. if (b_neg)
  456. result.negate();
  457. return;
  458. }
  459. #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
  460. typedef typename boost::multiprecision::detail::canonical<long double, T>::type guess_type;
  461. #else
  462. typedef fp_type guess_type;
  463. #endif
  464. // Get initial estimate using standard math function asin.
  465. guess_type dd;
  466. eval_convert_to(&dd, xx);
  467. result = (guess_type)(std::asin(dd));
  468. // Newton-Raphson iteration, we should double our precision with each iteration,
  469. // in practice this seems to not quite work in all cases... so terminate when we
  470. // have at least 2/3 of the digits correct on the assumption that the correction
  471. // we've just added will finish the job...
  472. boost::intmax_t current_precision = eval_ilogb(result);
  473. boost::intmax_t target_precision = current_precision - 1 - (std::numeric_limits<number<T> >::digits * 2) / 3;
  474. // Newton-Raphson iteration
  475. while (current_precision > target_precision)
  476. {
  477. T sine, cosine;
  478. eval_sin(sine, result);
  479. eval_cos(cosine, result);
  480. eval_subtract(sine, xx);
  481. eval_divide(sine, cosine);
  482. eval_subtract(result, sine);
  483. current_precision = eval_ilogb(sine);
  484. if (current_precision <= (std::numeric_limits<typename T::exponent_type>::min)() + 1)
  485. break;
  486. }
  487. if (b_neg)
  488. result.negate();
  489. }
  490. template <class T>
  491. inline void eval_acos(T& result, const T& x)
  492. {
  493. BOOST_STATIC_ASSERT_MSG(number_category<T>::value == number_kind_floating_point, "The acos function is only valid for floating point types.");
  494. typedef typename boost::multiprecision::detail::canonical<boost::uint32_t, T>::type ui_type;
  495. switch (eval_fpclassify(x))
  496. {
  497. case FP_NAN:
  498. case FP_INFINITE:
  499. if (std::numeric_limits<number<T, et_on> >::has_quiet_NaN)
  500. {
  501. result = std::numeric_limits<number<T, et_on> >::quiet_NaN().backend();
  502. errno = EDOM;
  503. }
  504. else
  505. BOOST_THROW_EXCEPTION(std::domain_error("Result is undefined or complex and there is no NaN for this number type."));
  506. return;
  507. case FP_ZERO:
  508. result = get_constant_pi<T>();
  509. eval_ldexp(result, result, -1); // divide by two.
  510. return;
  511. }
  512. eval_abs(result, x);
  513. int c = result.compare(ui_type(1));
  514. if (c > 0)
  515. {
  516. if (std::numeric_limits<number<T, et_on> >::has_quiet_NaN)
  517. {
  518. result = std::numeric_limits<number<T, et_on> >::quiet_NaN().backend();
  519. errno = EDOM;
  520. }
  521. else
  522. BOOST_THROW_EXCEPTION(std::domain_error("Result is undefined or complex and there is no NaN for this number type."));
  523. return;
  524. }
  525. else if (c == 0)
  526. {
  527. if (eval_get_sign(x) < 0)
  528. result = get_constant_pi<T>();
  529. else
  530. result = ui_type(0);
  531. return;
  532. }
  533. eval_asin(result, x);
  534. T t;
  535. eval_ldexp(t, get_constant_pi<T>(), -1);
  536. eval_subtract(result, t);
  537. result.negate();
  538. }
  539. template <class T>
  540. void eval_atan(T& result, const T& x)
  541. {
  542. BOOST_STATIC_ASSERT_MSG(number_category<T>::value == number_kind_floating_point, "The atan function is only valid for floating point types.");
  543. typedef typename boost::multiprecision::detail::canonical<boost::int32_t, T>::type si_type;
  544. typedef typename boost::multiprecision::detail::canonical<boost::uint32_t, T>::type ui_type;
  545. typedef typename mpl::front<typename T::float_types>::type fp_type;
  546. switch (eval_fpclassify(x))
  547. {
  548. case FP_NAN:
  549. result = x;
  550. errno = EDOM;
  551. return;
  552. case FP_ZERO:
  553. result = x;
  554. return;
  555. case FP_INFINITE:
  556. if (eval_get_sign(x) < 0)
  557. {
  558. eval_ldexp(result, get_constant_pi<T>(), -1);
  559. result.negate();
  560. }
  561. else
  562. eval_ldexp(result, get_constant_pi<T>(), -1);
  563. return;
  564. default:;
  565. }
  566. const bool b_neg = eval_get_sign(x) < 0;
  567. T xx(x);
  568. if (b_neg)
  569. xx.negate();
  570. if (xx.compare(fp_type(0.1)) < 0)
  571. {
  572. T t1, t2, t3;
  573. t1 = ui_type(1);
  574. t2 = fp_type(0.5f);
  575. t3 = fp_type(1.5f);
  576. eval_multiply(xx, xx);
  577. xx.negate();
  578. hyp2F1(result, t1, t2, t3, xx);
  579. eval_multiply(result, x);
  580. return;
  581. }
  582. if (xx.compare(fp_type(10)) > 0)
  583. {
  584. T t1, t2, t3;
  585. t1 = fp_type(0.5f);
  586. t2 = ui_type(1u);
  587. t3 = fp_type(1.5f);
  588. eval_multiply(xx, xx);
  589. eval_divide(xx, si_type(-1), xx);
  590. hyp2F1(result, t1, t2, t3, xx);
  591. eval_divide(result, x);
  592. if (!b_neg)
  593. result.negate();
  594. eval_ldexp(t1, get_constant_pi<T>(), -1);
  595. eval_add(result, t1);
  596. if (b_neg)
  597. result.negate();
  598. return;
  599. }
  600. // Get initial estimate using standard math function atan.
  601. fp_type d;
  602. eval_convert_to(&d, xx);
  603. result = fp_type(std::atan(d));
  604. // Newton-Raphson iteration, we should double our precision with each iteration,
  605. // in practice this seems to not quite work in all cases... so terminate when we
  606. // have at least 2/3 of the digits correct on the assumption that the correction
  607. // we've just added will finish the job...
  608. boost::intmax_t current_precision = eval_ilogb(result);
  609. boost::intmax_t target_precision = current_precision - 1 - (std::numeric_limits<number<T> >::digits * 2) / 3;
  610. T s, c, t;
  611. while (current_precision > target_precision)
  612. {
  613. eval_sin(s, result);
  614. eval_cos(c, result);
  615. eval_multiply(t, xx, c);
  616. eval_subtract(t, s);
  617. eval_multiply(s, t, c);
  618. eval_add(result, s);
  619. current_precision = eval_ilogb(s);
  620. if (current_precision <= (std::numeric_limits<typename T::exponent_type>::min)() + 1)
  621. break;
  622. }
  623. if (b_neg)
  624. result.negate();
  625. }
  626. template <class T>
  627. void eval_atan2(T& result, const T& y, const T& x)
  628. {
  629. BOOST_STATIC_ASSERT_MSG(number_category<T>::value == number_kind_floating_point, "The atan2 function is only valid for floating point types.");
  630. if (&result == &y)
  631. {
  632. T temp(y);
  633. eval_atan2(result, temp, x);
  634. return;
  635. }
  636. else if (&result == &x)
  637. {
  638. T temp(x);
  639. eval_atan2(result, y, temp);
  640. return;
  641. }
  642. typedef typename boost::multiprecision::detail::canonical<boost::uint32_t, T>::type ui_type;
  643. switch (eval_fpclassify(y))
  644. {
  645. case FP_NAN:
  646. result = y;
  647. errno = EDOM;
  648. return;
  649. case FP_ZERO:
  650. {
  651. if (eval_signbit(x))
  652. {
  653. result = get_constant_pi<T>();
  654. if (eval_signbit(y))
  655. result.negate();
  656. }
  657. else
  658. {
  659. result = y; // Note we allow atan2(0,0) to be +-zero, even though it's mathematically undefined
  660. }
  661. return;
  662. }
  663. case FP_INFINITE:
  664. {
  665. if (eval_fpclassify(x) == FP_INFINITE)
  666. {
  667. if (eval_signbit(x))
  668. {
  669. // 3Pi/4
  670. eval_ldexp(result, get_constant_pi<T>(), -2);
  671. eval_subtract(result, get_constant_pi<T>());
  672. if (eval_get_sign(y) >= 0)
  673. result.negate();
  674. }
  675. else
  676. {
  677. // Pi/4
  678. eval_ldexp(result, get_constant_pi<T>(), -2);
  679. if (eval_get_sign(y) < 0)
  680. result.negate();
  681. }
  682. }
  683. else
  684. {
  685. eval_ldexp(result, get_constant_pi<T>(), -1);
  686. if (eval_get_sign(y) < 0)
  687. result.negate();
  688. }
  689. return;
  690. }
  691. }
  692. switch (eval_fpclassify(x))
  693. {
  694. case FP_NAN:
  695. result = x;
  696. errno = EDOM;
  697. return;
  698. case FP_ZERO:
  699. {
  700. eval_ldexp(result, get_constant_pi<T>(), -1);
  701. if (eval_get_sign(y) < 0)
  702. result.negate();
  703. return;
  704. }
  705. case FP_INFINITE:
  706. if (eval_get_sign(x) > 0)
  707. result = ui_type(0);
  708. else
  709. result = get_constant_pi<T>();
  710. if (eval_get_sign(y) < 0)
  711. result.negate();
  712. return;
  713. }
  714. T xx;
  715. eval_divide(xx, y, x);
  716. if (eval_get_sign(xx) < 0)
  717. xx.negate();
  718. eval_atan(result, xx);
  719. // Determine quadrant (sign) based on signs of x, y
  720. const bool y_neg = eval_get_sign(y) < 0;
  721. const bool x_neg = eval_get_sign(x) < 0;
  722. if (y_neg != x_neg)
  723. result.negate();
  724. if (x_neg)
  725. {
  726. if (y_neg)
  727. eval_subtract(result, get_constant_pi<T>());
  728. else
  729. eval_add(result, get_constant_pi<T>());
  730. }
  731. }
  732. template <class T, class A>
  733. inline typename enable_if<is_arithmetic<A>, void>::type eval_atan2(T& result, const T& x, const A& a)
  734. {
  735. typedef typename boost::multiprecision::detail::canonical<A, T>::type canonical_type;
  736. typedef typename mpl::if_<is_same<A, canonical_type>, T, canonical_type>::type cast_type;
  737. cast_type c;
  738. c = a;
  739. eval_atan2(result, x, c);
  740. }
  741. template <class T, class A>
  742. inline typename enable_if<is_arithmetic<A>, void>::type eval_atan2(T& result, const A& x, const T& a)
  743. {
  744. typedef typename boost::multiprecision::detail::canonical<A, T>::type canonical_type;
  745. typedef typename mpl::if_<is_same<A, canonical_type>, T, canonical_type>::type cast_type;
  746. cast_type c;
  747. c = x;
  748. eval_atan2(result, c, a);
  749. }
  750. #ifdef BOOST_MSVC
  751. #pragma warning(pop)
  752. #endif