rr.hpp 20 KB

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