trig.hpp 21 KB

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