rr.hpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876
  1. // Copyright John Maddock 2007.
  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. #ifndef BOOST_MATH_NTL_RR_HPP
  6. #define BOOST_MATH_NTL_RR_HPP
  7. #include <boost/math/tools/real_cast.hpp>
  8. #include <boost/math/tools/precision.hpp>
  9. #include <boost/math/tools/config.hpp>
  10. #include <boost/math/constants/constants.hpp>
  11. #include <boost/math/tools/roots.hpp>
  12. #include <boost/math/special_functions/fpclassify.hpp>
  13. #include <boost/math/bindings/detail/big_digamma.hpp>
  14. #include <boost/math/bindings/detail/big_lanczos.hpp>
  15. #include <stdexcept>
  16. #include <ostream>
  17. #include <istream>
  18. #include <cmath>
  19. #include <limits>
  20. #include <NTL/RR.h>
  21. namespace boost{ namespace math{
  22. namespace ntl
  23. {
  24. class RR;
  25. RR ldexp(RR r, int exp);
  26. RR frexp(RR r, int* exp);
  27. class RR
  28. {
  29. public:
  30. // Constructors:
  31. RR() {}
  32. RR(const ::NTL::RR& c) : m_value(c){}
  33. RR(char c)
  34. {
  35. m_value = c;
  36. }
  37. RR(wchar_t c)
  38. {
  39. m_value = c;
  40. }
  41. RR(unsigned char c)
  42. {
  43. m_value = c;
  44. }
  45. RR(signed char c)
  46. {
  47. m_value = c;
  48. }
  49. RR(unsigned short c)
  50. {
  51. m_value = c;
  52. }
  53. RR(short c)
  54. {
  55. m_value = c;
  56. }
  57. RR(unsigned int c)
  58. {
  59. assign_large_int(c);
  60. }
  61. RR(int c)
  62. {
  63. assign_large_int(c);
  64. }
  65. RR(unsigned long c)
  66. {
  67. assign_large_int(c);
  68. }
  69. RR(long c)
  70. {
  71. assign_large_int(c);
  72. }
  73. RR(unsigned long long c)
  74. {
  75. assign_large_int(c);
  76. }
  77. RR(long long c)
  78. {
  79. assign_large_int(c);
  80. }
  81. RR(float c)
  82. {
  83. m_value = c;
  84. }
  85. RR(double c)
  86. {
  87. m_value = c;
  88. }
  89. RR(long double c)
  90. {
  91. assign_large_real(c);
  92. }
  93. // Assignment:
  94. RR& operator=(char c) { m_value = c; return *this; }
  95. RR& operator=(unsigned char c) { m_value = c; return *this; }
  96. RR& operator=(signed char c) { m_value = c; return *this; }
  97. RR& operator=(wchar_t c) { m_value = c; return *this; }
  98. RR& operator=(short c) { m_value = c; return *this; }
  99. RR& operator=(unsigned short c) { m_value = c; return *this; }
  100. RR& operator=(int c) { assign_large_int(c); return *this; }
  101. RR& operator=(unsigned int c) { assign_large_int(c); return *this; }
  102. RR& operator=(long c) { assign_large_int(c); return *this; }
  103. RR& operator=(unsigned long c) { assign_large_int(c); return *this; }
  104. RR& operator=(long long c) { assign_large_int(c); return *this; }
  105. RR& operator=(unsigned long long c) { assign_large_int(c); return *this; }
  106. RR& operator=(float c) { m_value = c; return *this; }
  107. RR& operator=(double c) { m_value = c; return *this; }
  108. RR& operator=(long double c) { assign_large_real(c); return *this; }
  109. // Access:
  110. NTL::RR& value(){ return m_value; }
  111. NTL::RR const& value()const{ return m_value; }
  112. // Member arithmetic:
  113. RR& operator+=(const RR& other)
  114. { m_value += other.value(); return *this; }
  115. RR& operator-=(const RR& other)
  116. { m_value -= other.value(); return *this; }
  117. RR& operator*=(const RR& other)
  118. { m_value *= other.value(); return *this; }
  119. RR& operator/=(const RR& other)
  120. { m_value /= other.value(); return *this; }
  121. RR operator-()const
  122. { return -m_value; }
  123. RR const& operator+()const
  124. { return *this; }
  125. // RR compatibility:
  126. const ::NTL::ZZ& mantissa() const
  127. { return m_value.mantissa(); }
  128. long exponent() const
  129. { return m_value.exponent(); }
  130. static void SetPrecision(long p)
  131. { ::NTL::RR::SetPrecision(p); }
  132. static long precision()
  133. { return ::NTL::RR::precision(); }
  134. static void SetOutputPrecision(long p)
  135. { ::NTL::RR::SetOutputPrecision(p); }
  136. static long OutputPrecision()
  137. { return ::NTL::RR::OutputPrecision(); }
  138. private:
  139. ::NTL::RR m_value;
  140. template <class V>
  141. void assign_large_real(const V& a)
  142. {
  143. using std::frexp;
  144. using std::ldexp;
  145. using std::floor;
  146. if (a == 0) {
  147. clear(m_value);
  148. return;
  149. }
  150. if (a == 1) {
  151. NTL::set(m_value);
  152. return;
  153. }
  154. if (!(boost::math::isfinite)(a))
  155. {
  156. throw std::overflow_error("Cannot construct an instance of NTL::RR with an infinite value.");
  157. }
  158. int e;
  159. long double f, term;
  160. ::NTL::RR t;
  161. clear(m_value);
  162. f = frexp(a, &e);
  163. while(f)
  164. {
  165. // extract 30 bits from f:
  166. f = ldexp(f, 30);
  167. term = floor(f);
  168. e -= 30;
  169. conv(t.x, (int)term);
  170. t.e = e;
  171. m_value += t;
  172. f -= term;
  173. }
  174. }
  175. template <class V>
  176. void assign_large_int(V a)
  177. {
  178. #ifdef _MSC_VER
  179. #pragma warning(push)
  180. #pragma warning(disable:4146)
  181. #endif
  182. clear(m_value);
  183. int exp = 0;
  184. NTL::RR t;
  185. bool neg = a < V(0) ? true : false;
  186. if(neg)
  187. a = -a;
  188. while(a)
  189. {
  190. t = static_cast<double>(a & 0xffff);
  191. m_value += ldexp(RR(t), exp).value();
  192. a >>= 16;
  193. exp += 16;
  194. }
  195. if(neg)
  196. m_value = -m_value;
  197. #ifdef _MSC_VER
  198. #pragma warning(pop)
  199. #endif
  200. }
  201. };
  202. // Non-member arithmetic:
  203. inline RR operator+(const RR& a, const RR& b)
  204. {
  205. RR result(a);
  206. result += b;
  207. return result;
  208. }
  209. inline RR operator-(const RR& a, const RR& b)
  210. {
  211. RR result(a);
  212. result -= b;
  213. return result;
  214. }
  215. inline RR operator*(const RR& a, const RR& b)
  216. {
  217. RR result(a);
  218. result *= b;
  219. return result;
  220. }
  221. inline RR operator/(const RR& a, const RR& b)
  222. {
  223. RR result(a);
  224. result /= b;
  225. return result;
  226. }
  227. // Comparison:
  228. inline bool operator == (const RR& a, const RR& b)
  229. { return a.value() == b.value() ? true : false; }
  230. inline bool operator != (const RR& a, const RR& b)
  231. { return a.value() != b.value() ? true : false;}
  232. inline bool operator < (const RR& a, const RR& b)
  233. { return a.value() < b.value() ? true : false; }
  234. inline bool operator <= (const RR& a, const RR& b)
  235. { return a.value() <= b.value() ? true : false; }
  236. inline bool operator > (const RR& a, const RR& b)
  237. { return a.value() > b.value() ? true : false; }
  238. inline bool operator >= (const RR& a, const RR& b)
  239. { return a.value() >= b.value() ? true : false; }
  240. #if 0
  241. // Non-member mixed compare:
  242. template <class T>
  243. inline bool operator == (const T& a, const RR& b)
  244. {
  245. return a == b.value();
  246. }
  247. template <class T>
  248. inline bool operator != (const T& a, const RR& b)
  249. {
  250. return a != b.value();
  251. }
  252. template <class T>
  253. inline bool operator < (const T& a, const RR& b)
  254. {
  255. return a < b.value();
  256. }
  257. template <class T>
  258. inline bool operator > (const T& a, const RR& b)
  259. {
  260. return a > b.value();
  261. }
  262. template <class T>
  263. inline bool operator <= (const T& a, const RR& b)
  264. {
  265. return a <= b.value();
  266. }
  267. template <class T>
  268. inline bool operator >= (const T& a, const RR& b)
  269. {
  270. return a >= b.value();
  271. }
  272. #endif // Non-member mixed compare:
  273. // Non-member functions:
  274. /*
  275. inline RR acos(RR a)
  276. { return ::NTL::acos(a.value()); }
  277. */
  278. inline RR cos(RR a)
  279. { return ::NTL::cos(a.value()); }
  280. /*
  281. inline RR asin(RR a)
  282. { return ::NTL::asin(a.value()); }
  283. inline RR atan(RR a)
  284. { return ::NTL::atan(a.value()); }
  285. inline RR atan2(RR a, RR b)
  286. { return ::NTL::atan2(a.value(), b.value()); }
  287. */
  288. inline RR ceil(RR a)
  289. { return ::NTL::ceil(a.value()); }
  290. /*
  291. inline RR fmod(RR a, RR b)
  292. { return ::NTL::fmod(a.value(), b.value()); }
  293. inline RR cosh(RR a)
  294. { return ::NTL::cosh(a.value()); }
  295. */
  296. inline RR exp(RR a)
  297. { return ::NTL::exp(a.value()); }
  298. inline RR fabs(RR a)
  299. { return ::NTL::fabs(a.value()); }
  300. inline RR abs(RR a)
  301. { return ::NTL::abs(a.value()); }
  302. inline RR floor(RR a)
  303. { return ::NTL::floor(a.value()); }
  304. /*
  305. inline RR modf(RR a, RR* ipart)
  306. {
  307. ::NTL::RR ip;
  308. RR result = modf(a.value(), &ip);
  309. *ipart = ip;
  310. return result;
  311. }
  312. inline RR frexp(RR a, int* expon)
  313. { return ::NTL::frexp(a.value(), expon); }
  314. inline RR ldexp(RR a, int expon)
  315. { return ::NTL::ldexp(a.value(), expon); }
  316. */
  317. inline RR log(RR a)
  318. { return ::NTL::log(a.value()); }
  319. inline RR log10(RR a)
  320. { return ::NTL::log10(a.value()); }
  321. /*
  322. inline RR tan(RR a)
  323. { return ::NTL::tan(a.value()); }
  324. */
  325. inline RR pow(RR a, RR b)
  326. { return ::NTL::pow(a.value(), b.value()); }
  327. inline RR pow(RR a, int b)
  328. { return ::NTL::power(a.value(), b); }
  329. inline RR sin(RR a)
  330. { return ::NTL::sin(a.value()); }
  331. /*
  332. inline RR sinh(RR a)
  333. { return ::NTL::sinh(a.value()); }
  334. */
  335. inline RR sqrt(RR a)
  336. { return ::NTL::sqrt(a.value()); }
  337. /*
  338. inline RR tanh(RR a)
  339. { return ::NTL::tanh(a.value()); }
  340. */
  341. inline RR pow(const RR& r, long l)
  342. {
  343. return ::NTL::power(r.value(), l);
  344. }
  345. inline RR tan(const RR& a)
  346. {
  347. return sin(a)/cos(a);
  348. }
  349. inline RR frexp(RR r, int* exp)
  350. {
  351. *exp = r.value().e;
  352. r.value().e = 0;
  353. while(r >= 1)
  354. {
  355. *exp += 1;
  356. r.value().e -= 1;
  357. }
  358. while(r < 0.5)
  359. {
  360. *exp -= 1;
  361. r.value().e += 1;
  362. }
  363. BOOST_MATH_ASSERT(r < 1);
  364. BOOST_MATH_ASSERT(r >= 0.5);
  365. return r;
  366. }
  367. inline RR ldexp(RR r, int exp)
  368. {
  369. r.value().e += exp;
  370. return r;
  371. }
  372. // Streaming:
  373. template <class charT, class traits>
  374. inline std::basic_ostream<charT, traits>& operator<<(std::basic_ostream<charT, traits>& os, const RR& a)
  375. {
  376. return os << a.value();
  377. }
  378. template <class charT, class traits>
  379. inline std::basic_istream<charT, traits>& operator>>(std::basic_istream<charT, traits>& is, RR& a)
  380. {
  381. ::NTL::RR v;
  382. is >> v;
  383. a = v;
  384. return is;
  385. }
  386. } // namespace ntl
  387. namespace lanczos{
  388. struct ntl_lanczos
  389. {
  390. static ntl::RR lanczos_sum(const ntl::RR& z)
  391. {
  392. unsigned long p = ntl::RR::precision();
  393. if(p <= 72)
  394. return lanczos13UDT::lanczos_sum(z);
  395. else if(p <= 120)
  396. return lanczos22UDT::lanczos_sum(z);
  397. else if(p <= 170)
  398. return lanczos31UDT::lanczos_sum(z);
  399. else //if(p <= 370) approx 100 digit precision:
  400. return lanczos61UDT::lanczos_sum(z);
  401. }
  402. static ntl::RR lanczos_sum_expG_scaled(const ntl::RR& z)
  403. {
  404. unsigned long p = ntl::RR::precision();
  405. if(p <= 72)
  406. return lanczos13UDT::lanczos_sum_expG_scaled(z);
  407. else if(p <= 120)
  408. return lanczos22UDT::lanczos_sum_expG_scaled(z);
  409. else if(p <= 170)
  410. return lanczos31UDT::lanczos_sum_expG_scaled(z);
  411. else //if(p <= 370) approx 100 digit precision:
  412. return lanczos61UDT::lanczos_sum_expG_scaled(z);
  413. }
  414. static ntl::RR lanczos_sum_near_1(const ntl::RR& z)
  415. {
  416. unsigned long p = ntl::RR::precision();
  417. if(p <= 72)
  418. return lanczos13UDT::lanczos_sum_near_1(z);
  419. else if(p <= 120)
  420. return lanczos22UDT::lanczos_sum_near_1(z);
  421. else if(p <= 170)
  422. return lanczos31UDT::lanczos_sum_near_1(z);
  423. else //if(p <= 370) approx 100 digit precision:
  424. return lanczos61UDT::lanczos_sum_near_1(z);
  425. }
  426. static ntl::RR lanczos_sum_near_2(const ntl::RR& z)
  427. {
  428. unsigned long p = ntl::RR::precision();
  429. if(p <= 72)
  430. return lanczos13UDT::lanczos_sum_near_2(z);
  431. else if(p <= 120)
  432. return lanczos22UDT::lanczos_sum_near_2(z);
  433. else if(p <= 170)
  434. return lanczos31UDT::lanczos_sum_near_2(z);
  435. else //if(p <= 370) approx 100 digit precision:
  436. return lanczos61UDT::lanczos_sum_near_2(z);
  437. }
  438. static ntl::RR g()
  439. {
  440. unsigned long p = ntl::RR::precision();
  441. if(p <= 72)
  442. return lanczos13UDT::g();
  443. else if(p <= 120)
  444. return lanczos22UDT::g();
  445. else if(p <= 170)
  446. return lanczos31UDT::g();
  447. else //if(p <= 370) approx 100 digit precision:
  448. return lanczos61UDT::g();
  449. }
  450. };
  451. template<class Policy>
  452. struct lanczos<ntl::RR, Policy>
  453. {
  454. typedef ntl_lanczos type;
  455. };
  456. } // namespace lanczos
  457. namespace tools
  458. {
  459. template<>
  460. inline int digits<boost::math::ntl::RR>(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(boost::math::ntl::RR))
  461. {
  462. return ::NTL::RR::precision();
  463. }
  464. template <>
  465. inline float real_cast<float, boost::math::ntl::RR>(boost::math::ntl::RR t)
  466. {
  467. double r;
  468. conv(r, t.value());
  469. return static_cast<float>(r);
  470. }
  471. template <>
  472. inline double real_cast<double, boost::math::ntl::RR>(boost::math::ntl::RR t)
  473. {
  474. double r;
  475. conv(r, t.value());
  476. return r;
  477. }
  478. namespace detail{
  479. template<class Integer>
  480. void convert_to_long_result(NTL::RR const& r, Integer& result)
  481. {
  482. result = 0;
  483. I last_result(0);
  484. NTL::RR t(r);
  485. double term;
  486. do
  487. {
  488. conv(term, t);
  489. last_result = result;
  490. result += static_cast<I>(term);
  491. t -= term;
  492. }while(result != last_result);
  493. }
  494. }
  495. template <>
  496. inline long double real_cast<long double, boost::math::ntl::RR>(boost::math::ntl::RR t)
  497. {
  498. long double result(0);
  499. detail::convert_to_long_result(t.value(), result);
  500. return result;
  501. }
  502. template <>
  503. inline boost::math::ntl::RR real_cast<boost::math::ntl::RR, boost::math::ntl::RR>(boost::math::ntl::RR t)
  504. {
  505. return t;
  506. }
  507. template <>
  508. inline unsigned real_cast<unsigned, boost::math::ntl::RR>(boost::math::ntl::RR t)
  509. {
  510. unsigned result;
  511. detail::convert_to_long_result(t.value(), result);
  512. return result;
  513. }
  514. template <>
  515. inline int real_cast<int, boost::math::ntl::RR>(boost::math::ntl::RR t)
  516. {
  517. int result;
  518. detail::convert_to_long_result(t.value(), result);
  519. return result;
  520. }
  521. template <>
  522. inline long real_cast<long, boost::math::ntl::RR>(boost::math::ntl::RR t)
  523. {
  524. long result;
  525. detail::convert_to_long_result(t.value(), result);
  526. return result;
  527. }
  528. template <>
  529. inline long long real_cast<long long, boost::math::ntl::RR>(boost::math::ntl::RR t)
  530. {
  531. long long result;
  532. detail::convert_to_long_result(t.value(), result);
  533. return result;
  534. }
  535. template <>
  536. inline boost::math::ntl::RR max_value<boost::math::ntl::RR>(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(boost::math::ntl::RR))
  537. {
  538. static bool has_init = false;
  539. static NTL::RR val;
  540. if(!has_init)
  541. {
  542. val = 1;
  543. val.e = NTL_OVFBND-20;
  544. has_init = true;
  545. }
  546. return val;
  547. }
  548. template <>
  549. inline boost::math::ntl::RR min_value<boost::math::ntl::RR>(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(boost::math::ntl::RR))
  550. {
  551. static bool has_init = false;
  552. static NTL::RR val;
  553. if(!has_init)
  554. {
  555. val = 1;
  556. val.e = -NTL_OVFBND+20;
  557. has_init = true;
  558. }
  559. return val;
  560. }
  561. template <>
  562. inline boost::math::ntl::RR log_max_value<boost::math::ntl::RR>(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(boost::math::ntl::RR))
  563. {
  564. static bool has_init = false;
  565. static NTL::RR val;
  566. if(!has_init)
  567. {
  568. val = 1;
  569. val.e = NTL_OVFBND-20;
  570. val = log(val);
  571. has_init = true;
  572. }
  573. return val;
  574. }
  575. template <>
  576. inline boost::math::ntl::RR log_min_value<boost::math::ntl::RR>(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(boost::math::ntl::RR))
  577. {
  578. static bool has_init = false;
  579. static NTL::RR val;
  580. if(!has_init)
  581. {
  582. val = 1;
  583. val.e = -NTL_OVFBND+20;
  584. val = log(val);
  585. has_init = true;
  586. }
  587. return val;
  588. }
  589. template <>
  590. inline boost::math::ntl::RR epsilon<boost::math::ntl::RR>(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(boost::math::ntl::RR))
  591. {
  592. return ldexp(boost::math::ntl::RR(1), 1-boost::math::policies::digits<boost::math::ntl::RR, boost::math::policies::policy<> >());
  593. }
  594. } // namespace tools
  595. //
  596. // The number of digits precision in RR can vary with each call
  597. // so we need to recalculate these with each call:
  598. //
  599. namespace constants{
  600. template<> inline boost::math::ntl::RR pi<boost::math::ntl::RR>(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(boost::math::ntl::RR))
  601. {
  602. NTL::RR result;
  603. ComputePi(result);
  604. return result;
  605. }
  606. template<> inline boost::math::ntl::RR e<boost::math::ntl::RR>(BOOST_MATH_EXPLICIT_TEMPLATE_TYPE_SPEC(boost::math::ntl::RR))
  607. {
  608. NTL::RR result;
  609. result = 1;
  610. return exp(result);
  611. }
  612. } // namespace constants
  613. namespace ntl{
  614. //
  615. // These are some fairly brain-dead versions of the math
  616. // functions that NTL fails to provide.
  617. //
  618. //
  619. // Inverse trig functions:
  620. //
  621. struct asin_root
  622. {
  623. asin_root(RR const& target) : t(target){}
  624. boost::math::tuple<RR, RR, RR> operator()(RR const& p)
  625. {
  626. RR f0 = sin(p);
  627. RR f1 = cos(p);
  628. RR f2 = -f0;
  629. f0 -= t;
  630. return boost::math::make_tuple(f0, f1, f2);
  631. }
  632. private:
  633. RR t;
  634. };
  635. inline RR asin(RR z)
  636. {
  637. double r;
  638. conv(r, z.value());
  639. return boost::math::tools::halley_iterate(
  640. asin_root(z),
  641. RR(std::asin(r)),
  642. RR(-boost::math::constants::pi<RR>()/2),
  643. RR(boost::math::constants::pi<RR>()/2),
  644. NTL::RR::precision());
  645. }
  646. struct acos_root
  647. {
  648. acos_root(RR const& target) : t(target){}
  649. boost::math::tuple<RR, RR, RR> operator()(RR const& p)
  650. {
  651. RR f0 = cos(p);
  652. RR f1 = -sin(p);
  653. RR f2 = -f0;
  654. f0 -= t;
  655. return boost::math::make_tuple(f0, f1, f2);
  656. }
  657. private:
  658. RR t;
  659. };
  660. inline RR acos(RR z)
  661. {
  662. double r;
  663. conv(r, z.value());
  664. return boost::math::tools::halley_iterate(
  665. acos_root(z),
  666. RR(std::acos(r)),
  667. RR(-boost::math::constants::pi<RR>()/2),
  668. RR(boost::math::constants::pi<RR>()/2),
  669. NTL::RR::precision());
  670. }
  671. struct atan_root
  672. {
  673. atan_root(RR const& target) : t(target){}
  674. boost::math::tuple<RR, RR, RR> operator()(RR const& p)
  675. {
  676. RR c = cos(p);
  677. RR ta = tan(p);
  678. RR f0 = ta - t;
  679. RR f1 = 1 / (c * c);
  680. RR f2 = 2 * ta / (c * c);
  681. return boost::math::make_tuple(f0, f1, f2);
  682. }
  683. private:
  684. RR t;
  685. };
  686. inline RR atan(RR z)
  687. {
  688. double r;
  689. conv(r, z.value());
  690. return boost::math::tools::halley_iterate(
  691. atan_root(z),
  692. RR(std::atan(r)),
  693. -boost::math::constants::pi<RR>()/2,
  694. boost::math::constants::pi<RR>()/2,
  695. NTL::RR::precision());
  696. }
  697. inline RR atan2(RR y, RR x)
  698. {
  699. if(x > 0)
  700. return atan(y / x);
  701. if(x < 0)
  702. {
  703. return y < 0 ? atan(y / x) - boost::math::constants::pi<RR>() : atan(y / x) + boost::math::constants::pi<RR>();
  704. }
  705. return y < 0 ? -boost::math::constants::half_pi<RR>() : boost::math::constants::half_pi<RR>() ;
  706. }
  707. inline RR sinh(RR z)
  708. {
  709. return (expm1(z.value()) - expm1(-z.value())) / 2;
  710. }
  711. inline RR cosh(RR z)
  712. {
  713. return (exp(z) + exp(-z)) / 2;
  714. }
  715. inline RR tanh(RR z)
  716. {
  717. return sinh(z) / cosh(z);
  718. }
  719. inline RR fmod(RR x, RR y)
  720. {
  721. // This is a really crummy version of fmod, we rely on lots
  722. // of digits to get us out of trouble...
  723. RR factor = floor(x/y);
  724. return x - factor * y;
  725. }
  726. template <class Policy>
  727. inline int iround(RR const& x, const Policy& pol)
  728. {
  729. return tools::real_cast<int>(round(x, pol));
  730. }
  731. template <class Policy>
  732. inline long lround(RR const& x, const Policy& pol)
  733. {
  734. return tools::real_cast<long>(round(x, pol));
  735. }
  736. template <class Policy>
  737. inline long long llround(RR const& x, const Policy& pol)
  738. {
  739. return tools::real_cast<long long>(round(x, pol));
  740. }
  741. template <class Policy>
  742. inline int itrunc(RR const& x, const Policy& pol)
  743. {
  744. return tools::real_cast<int>(trunc(x, pol));
  745. }
  746. template <class Policy>
  747. inline long ltrunc(RR const& x, const Policy& pol)
  748. {
  749. return tools::real_cast<long>(trunc(x, pol));
  750. }
  751. template <class Policy>
  752. inline long long lltrunc(RR const& x, const Policy& pol)
  753. {
  754. return tools::real_cast<long long>(trunc(x, pol));
  755. }
  756. } // namespace ntl
  757. namespace detail{
  758. template <class Policy>
  759. ntl::RR digamma_imp(ntl::RR x, const std::integral_constant<int, 0>* , const Policy& pol)
  760. {
  761. //
  762. // This handles reflection of negative arguments, and all our
  763. // error handling, then forwards to the T-specific approximation.
  764. //
  765. BOOST_MATH_STD_USING // ADL of std functions.
  766. ntl::RR result = 0;
  767. //
  768. // Check for negative arguments and use reflection:
  769. //
  770. if(x < 0)
  771. {
  772. // Reflect:
  773. x = 1 - x;
  774. // Argument reduction for tan:
  775. ntl::RR remainder = x - floor(x);
  776. // Shift to negative if > 0.5:
  777. if(remainder > 0.5)
  778. {
  779. remainder -= 1;
  780. }
  781. //
  782. // check for evaluation at a negative pole:
  783. //
  784. if(remainder == 0)
  785. {
  786. return policies::raise_pole_error<ntl::RR>("boost::math::digamma<%1%>(%1%)", nullptr, (1-x), pol);
  787. }
  788. result = constants::pi<ntl::RR>() / tan(constants::pi<ntl::RR>() * remainder);
  789. }
  790. result += big_digamma(x);
  791. return result;
  792. }
  793. } // namespace detail
  794. } // namespace math
  795. } // namespace boost
  796. #endif // BOOST_MATH_REAL_CONCEPT_HPP