digamma.hpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609
  1. // (C) Copyright John Maddock 2006.
  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_SF_DIGAMMA_HPP
  6. #define BOOST_MATH_SF_DIGAMMA_HPP
  7. #ifdef _MSC_VER
  8. #pragma once
  9. #pragma warning(push)
  10. #pragma warning(disable:4702) // Unreachable code (release mode only warning)
  11. #endif
  12. #include <boost/math/special_functions/math_fwd.hpp>
  13. #include <boost/math/tools/rational.hpp>
  14. #include <boost/math/tools/series.hpp>
  15. #include <boost/math/tools/promotion.hpp>
  16. #include <boost/math/policies/error_handling.hpp>
  17. #include <boost/math/constants/constants.hpp>
  18. #include <boost/math/tools/big_constant.hpp>
  19. #if defined(__GNUC__) && defined(BOOST_MATH_USE_FLOAT128)
  20. //
  21. // This is the only way we can avoid
  22. // warning: non-standard suffix on floating constant [-Wpedantic]
  23. // when building with -Wall -pedantic. Neither __extension__
  24. // nor #pragma diagnostic ignored work :(
  25. //
  26. #pragma GCC system_header
  27. #endif
  28. namespace boost{
  29. namespace math{
  30. namespace detail{
  31. //
  32. // Begin by defining the smallest value for which it is safe to
  33. // use the asymptotic expansion for digamma:
  34. //
  35. inline unsigned digamma_large_lim(const std::integral_constant<int, 0>*)
  36. { return 20; }
  37. inline unsigned digamma_large_lim(const std::integral_constant<int, 113>*)
  38. { return 20; }
  39. inline unsigned digamma_large_lim(const void*)
  40. { return 10; }
  41. //
  42. // Implementations of the asymptotic expansion come next,
  43. // the coefficients of the series have been evaluated
  44. // in advance at high precision, and the series truncated
  45. // at the first term that's too small to effect the result.
  46. // Note that the series becomes divergent after a while
  47. // so truncation is very important.
  48. //
  49. // This first one gives 34-digit precision for x >= 20:
  50. //
  51. template <class T>
  52. inline T digamma_imp_large(T x, const std::integral_constant<int, 113>*)
  53. {
  54. BOOST_MATH_STD_USING // ADL of std functions.
  55. static const T P[] = {
  56. BOOST_MATH_BIG_CONSTANT(T, 113, 0.083333333333333333333333333333333333333333333333333),
  57. BOOST_MATH_BIG_CONSTANT(T, 113, -0.0083333333333333333333333333333333333333333333333333),
  58. BOOST_MATH_BIG_CONSTANT(T, 113, 0.003968253968253968253968253968253968253968253968254),
  59. BOOST_MATH_BIG_CONSTANT(T, 113, -0.0041666666666666666666666666666666666666666666666667),
  60. BOOST_MATH_BIG_CONSTANT(T, 113, 0.0075757575757575757575757575757575757575757575757576),
  61. BOOST_MATH_BIG_CONSTANT(T, 113, -0.021092796092796092796092796092796092796092796092796),
  62. BOOST_MATH_BIG_CONSTANT(T, 113, 0.083333333333333333333333333333333333333333333333333),
  63. BOOST_MATH_BIG_CONSTANT(T, 113, -0.44325980392156862745098039215686274509803921568627),
  64. BOOST_MATH_BIG_CONSTANT(T, 113, 3.0539543302701197438039543302701197438039543302701),
  65. BOOST_MATH_BIG_CONSTANT(T, 113, -26.456212121212121212121212121212121212121212121212),
  66. BOOST_MATH_BIG_CONSTANT(T, 113, 281.4601449275362318840579710144927536231884057971),
  67. BOOST_MATH_BIG_CONSTANT(T, 113, -3607.510546398046398046398046398046398046398046398),
  68. BOOST_MATH_BIG_CONSTANT(T, 113, 54827.583333333333333333333333333333333333333333333),
  69. BOOST_MATH_BIG_CONSTANT(T, 113, -974936.82385057471264367816091954022988505747126437),
  70. BOOST_MATH_BIG_CONSTANT(T, 113, 20052695.796688078946143462272494530559046688078946),
  71. BOOST_MATH_BIG_CONSTANT(T, 113, -472384867.72162990196078431372549019607843137254902),
  72. BOOST_MATH_BIG_CONSTANT(T, 113, 12635724795.916666666666666666666666666666666666667)
  73. };
  74. x -= 1;
  75. T result = log(x);
  76. result += 1 / (2 * x);
  77. T z = 1 / (x*x);
  78. result -= z * tools::evaluate_polynomial(P, z);
  79. return result;
  80. }
  81. //
  82. // 19-digit precision for x >= 10:
  83. //
  84. template <class T>
  85. inline T digamma_imp_large(T x, const std::integral_constant<int, 64>*)
  86. {
  87. BOOST_MATH_STD_USING // ADL of std functions.
  88. static const T P[] = {
  89. BOOST_MATH_BIG_CONSTANT(T, 64, 0.083333333333333333333333333333333333333333333333333),
  90. BOOST_MATH_BIG_CONSTANT(T, 64, -0.0083333333333333333333333333333333333333333333333333),
  91. BOOST_MATH_BIG_CONSTANT(T, 64, 0.003968253968253968253968253968253968253968253968254),
  92. BOOST_MATH_BIG_CONSTANT(T, 64, -0.0041666666666666666666666666666666666666666666666667),
  93. BOOST_MATH_BIG_CONSTANT(T, 64, 0.0075757575757575757575757575757575757575757575757576),
  94. BOOST_MATH_BIG_CONSTANT(T, 64, -0.021092796092796092796092796092796092796092796092796),
  95. BOOST_MATH_BIG_CONSTANT(T, 64, 0.083333333333333333333333333333333333333333333333333),
  96. BOOST_MATH_BIG_CONSTANT(T, 64, -0.44325980392156862745098039215686274509803921568627),
  97. BOOST_MATH_BIG_CONSTANT(T, 64, 3.0539543302701197438039543302701197438039543302701),
  98. BOOST_MATH_BIG_CONSTANT(T, 64, -26.456212121212121212121212121212121212121212121212),
  99. BOOST_MATH_BIG_CONSTANT(T, 64, 281.4601449275362318840579710144927536231884057971),
  100. };
  101. x -= 1;
  102. T result = log(x);
  103. result += 1 / (2 * x);
  104. T z = 1 / (x*x);
  105. result -= z * tools::evaluate_polynomial(P, z);
  106. return result;
  107. }
  108. //
  109. // 17-digit precision for x >= 10:
  110. //
  111. template <class T>
  112. inline T digamma_imp_large(T x, const std::integral_constant<int, 53>*)
  113. {
  114. BOOST_MATH_STD_USING // ADL of std functions.
  115. static const T P[] = {
  116. 0.083333333333333333333333333333333333333333333333333,
  117. -0.0083333333333333333333333333333333333333333333333333,
  118. 0.003968253968253968253968253968253968253968253968254,
  119. -0.0041666666666666666666666666666666666666666666666667,
  120. 0.0075757575757575757575757575757575757575757575757576,
  121. -0.021092796092796092796092796092796092796092796092796,
  122. 0.083333333333333333333333333333333333333333333333333,
  123. -0.44325980392156862745098039215686274509803921568627
  124. };
  125. x -= 1;
  126. T result = log(x);
  127. result += 1 / (2 * x);
  128. T z = 1 / (x*x);
  129. result -= z * tools::evaluate_polynomial(P, z);
  130. return result;
  131. }
  132. //
  133. // 9-digit precision for x >= 10:
  134. //
  135. template <class T>
  136. inline T digamma_imp_large(T x, const std::integral_constant<int, 24>*)
  137. {
  138. BOOST_MATH_STD_USING // ADL of std functions.
  139. static const T P[] = {
  140. 0.083333333333333333333333333333333333333333333333333f,
  141. -0.0083333333333333333333333333333333333333333333333333f,
  142. 0.003968253968253968253968253968253968253968253968254f
  143. };
  144. x -= 1;
  145. T result = log(x);
  146. result += 1 / (2 * x);
  147. T z = 1 / (x*x);
  148. result -= z * tools::evaluate_polynomial(P, z);
  149. return result;
  150. }
  151. //
  152. // Fully generic asymptotic expansion in terms of Bernoulli numbers, see:
  153. // http://functions.wolfram.com/06.14.06.0012.01
  154. //
  155. template <class T>
  156. struct digamma_series_func
  157. {
  158. private:
  159. int k;
  160. T xx;
  161. T term;
  162. public:
  163. digamma_series_func(T x) : k(1), xx(x * x), term(1 / (x * x)) {}
  164. T operator()()
  165. {
  166. T result = term * boost::math::bernoulli_b2n<T>(k) / (2 * k);
  167. term /= xx;
  168. ++k;
  169. return result;
  170. }
  171. typedef T result_type;
  172. };
  173. template <class T, class Policy>
  174. inline T digamma_imp_large(T x, const Policy& pol, const std::integral_constant<int, 0>*)
  175. {
  176. BOOST_MATH_STD_USING
  177. digamma_series_func<T> s(x);
  178. T result = log(x) - 1 / (2 * x);
  179. std::uintmax_t max_iter = policies::get_max_series_iterations<Policy>();
  180. result = boost::math::tools::sum_series(s, boost::math::policies::get_epsilon<T, Policy>(), max_iter, -result);
  181. result = -result;
  182. policies::check_series_iterations<T>("boost::math::digamma<%1%>(%1%)", max_iter, pol);
  183. return result;
  184. }
  185. //
  186. // Now follow rational approximations over the range [1,2].
  187. //
  188. // 35-digit precision:
  189. //
  190. template <class T>
  191. T digamma_imp_1_2(T x, const std::integral_constant<int, 113>*)
  192. {
  193. //
  194. // Now the approximation, we use the form:
  195. //
  196. // digamma(x) = (x - root) * (Y + R(x-1))
  197. //
  198. // Where root is the location of the positive root of digamma,
  199. // Y is a constant, and R is optimised for low absolute error
  200. // compared to Y.
  201. //
  202. // Max error found at 128-bit long double precision: 5.541e-35
  203. // Maximum Deviation Found (approximation error): 1.965e-35
  204. //
  205. // LCOV_EXCL_START
  206. static const float Y = 0.99558162689208984375F;
  207. static const T root1 = T(1569415565) / 1073741824uL;
  208. static const T root2 = (T(381566830) / 1073741824uL) / 1073741824uL;
  209. static const T root3 = ((T(111616537) / 1073741824uL) / 1073741824uL) / 1073741824uL;
  210. static const T root4 = (((T(503992070) / 1073741824uL) / 1073741824uL) / 1073741824uL) / 1073741824uL;
  211. static const T root5 = BOOST_MATH_BIG_CONSTANT(T, 113, 0.52112228569249997894452490385577338504019838794544e-36);
  212. static const T P[] = {
  213. BOOST_MATH_BIG_CONSTANT(T, 113, 0.25479851061131551526977464225335883769),
  214. BOOST_MATH_BIG_CONSTANT(T, 113, -0.18684290534374944114622235683619897417),
  215. BOOST_MATH_BIG_CONSTANT(T, 113, -0.80360876047931768958995775910991929922),
  216. BOOST_MATH_BIG_CONSTANT(T, 113, -0.67227342794829064330498117008564270136),
  217. BOOST_MATH_BIG_CONSTANT(T, 113, -0.26569010991230617151285010695543858005),
  218. BOOST_MATH_BIG_CONSTANT(T, 113, -0.05775672694575986971640757748003553385),
  219. BOOST_MATH_BIG_CONSTANT(T, 113, -0.0071432147823164975485922555833274240665),
  220. BOOST_MATH_BIG_CONSTANT(T, 113, -0.00048740753910766168912364555706064993274),
  221. BOOST_MATH_BIG_CONSTANT(T, 113, -0.16454996865214115723416538844975174761e-4),
  222. BOOST_MATH_BIG_CONSTANT(T, 113, -0.20327832297631728077731148515093164955e-6)
  223. };
  224. static const T Q[] = {
  225. BOOST_MATH_BIG_CONSTANT(T, 113, 1.0),
  226. BOOST_MATH_BIG_CONSTANT(T, 113, 2.6210924610812025425088411043163287646),
  227. BOOST_MATH_BIG_CONSTANT(T, 113, 2.6850757078559596612621337395886392594),
  228. BOOST_MATH_BIG_CONSTANT(T, 113, 1.4320913706209965531250495490639289418),
  229. BOOST_MATH_BIG_CONSTANT(T, 113, 0.4410872083455009362557012239501953402),
  230. BOOST_MATH_BIG_CONSTANT(T, 113, 0.081385727399251729505165509278152487225),
  231. BOOST_MATH_BIG_CONSTANT(T, 113, 0.0089478633066857163432104815183858149496),
  232. BOOST_MATH_BIG_CONSTANT(T, 113, 0.00055861622855066424871506755481997374154),
  233. BOOST_MATH_BIG_CONSTANT(T, 113, 0.1760168552357342401304462967950178554e-4),
  234. BOOST_MATH_BIG_CONSTANT(T, 113, 0.20585454493572473724556649516040874384e-6),
  235. BOOST_MATH_BIG_CONSTANT(T, 113, -0.90745971844439990284514121823069162795e-11),
  236. BOOST_MATH_BIG_CONSTANT(T, 113, 0.48857673606545846774761343500033283272e-13),
  237. };
  238. // LCOV_EXCL_STOP
  239. T g = x - root1;
  240. g -= root2;
  241. g -= root3;
  242. g -= root4;
  243. g -= root5;
  244. T r = tools::evaluate_polynomial(P, T(x-1)) / tools::evaluate_polynomial(Q, T(x-1));
  245. T result = g * Y + g * r;
  246. return result;
  247. }
  248. //
  249. // 19-digit precision:
  250. //
  251. template <class T>
  252. T digamma_imp_1_2(T x, const std::integral_constant<int, 64>*)
  253. {
  254. //
  255. // Now the approximation, we use the form:
  256. //
  257. // digamma(x) = (x - root) * (Y + R(x-1))
  258. //
  259. // Where root is the location of the positive root of digamma,
  260. // Y is a constant, and R is optimised for low absolute error
  261. // compared to Y.
  262. //
  263. // Max error found at 80-bit long double precision: 5.016e-20
  264. // Maximum Deviation Found (approximation error): 3.575e-20
  265. //
  266. // LCOV_EXCL_START
  267. static const float Y = 0.99558162689208984375F;
  268. static const T root1 = T(1569415565) / 1073741824uL;
  269. static const T root2 = (T(381566830) / 1073741824uL) / 1073741824uL;
  270. static const T root3 = BOOST_MATH_BIG_CONSTANT(T, 64, 0.9016312093258695918615325266959189453125e-19);
  271. static const T P[] = {
  272. BOOST_MATH_BIG_CONSTANT(T, 64, 0.254798510611315515235),
  273. BOOST_MATH_BIG_CONSTANT(T, 64, -0.314628554532916496608),
  274. BOOST_MATH_BIG_CONSTANT(T, 64, -0.665836341559876230295),
  275. BOOST_MATH_BIG_CONSTANT(T, 64, -0.314767657147375752913),
  276. BOOST_MATH_BIG_CONSTANT(T, 64, -0.0541156266153505273939),
  277. BOOST_MATH_BIG_CONSTANT(T, 64, -0.00289268368333918761452)
  278. };
  279. static const T Q[] = {
  280. BOOST_MATH_BIG_CONSTANT(T, 64, 1.0),
  281. BOOST_MATH_BIG_CONSTANT(T, 64, 2.1195759927055347547),
  282. BOOST_MATH_BIG_CONSTANT(T, 64, 1.54350554664961128724),
  283. BOOST_MATH_BIG_CONSTANT(T, 64, 0.486986018231042975162),
  284. BOOST_MATH_BIG_CONSTANT(T, 64, 0.0660481487173569812846),
  285. BOOST_MATH_BIG_CONSTANT(T, 64, 0.00298999662592323990972),
  286. BOOST_MATH_BIG_CONSTANT(T, 64, -0.165079794012604905639e-5),
  287. BOOST_MATH_BIG_CONSTANT(T, 64, 0.317940243105952177571e-7)
  288. };
  289. // LCOV_EXCL_STOP
  290. T g = x - root1;
  291. g -= root2;
  292. g -= root3;
  293. T r = tools::evaluate_polynomial(P, T(x-1)) / tools::evaluate_polynomial(Q, T(x-1));
  294. T result = g * Y + g * r;
  295. return result;
  296. }
  297. //
  298. // 18-digit precision:
  299. //
  300. template <class T>
  301. T digamma_imp_1_2(T x, const std::integral_constant<int, 53>*)
  302. {
  303. //
  304. // Now the approximation, we use the form:
  305. //
  306. // digamma(x) = (x - root) * (Y + R(x-1))
  307. //
  308. // Where root is the location of the positive root of digamma,
  309. // Y is a constant, and R is optimised for low absolute error
  310. // compared to Y.
  311. //
  312. // Maximum Deviation Found: 1.466e-18
  313. // At double precision, max error found: 2.452e-17
  314. //
  315. // LCOV_EXCL_START
  316. static const float Y = 0.99558162689208984F;
  317. static const T root1 = T(1569415565) / 1073741824uL;
  318. static const T root2 = (T(381566830) / 1073741824uL) / 1073741824uL;
  319. static const T root3 = BOOST_MATH_BIG_CONSTANT(T, 53, 0.9016312093258695918615325266959189453125e-19);
  320. static const T P[] = {
  321. BOOST_MATH_BIG_CONSTANT(T, 53, 0.25479851061131551),
  322. BOOST_MATH_BIG_CONSTANT(T, 53, -0.32555031186804491),
  323. BOOST_MATH_BIG_CONSTANT(T, 53, -0.65031853770896507),
  324. BOOST_MATH_BIG_CONSTANT(T, 53, -0.28919126444774784),
  325. BOOST_MATH_BIG_CONSTANT(T, 53, -0.045251321448739056),
  326. BOOST_MATH_BIG_CONSTANT(T, 53, -0.0020713321167745952)
  327. };
  328. static const T Q[] = {
  329. BOOST_MATH_BIG_CONSTANT(T, 53, 1.0),
  330. BOOST_MATH_BIG_CONSTANT(T, 53, 2.0767117023730469),
  331. BOOST_MATH_BIG_CONSTANT(T, 53, 1.4606242909763515),
  332. BOOST_MATH_BIG_CONSTANT(T, 53, 0.43593529692665969),
  333. BOOST_MATH_BIG_CONSTANT(T, 53, 0.054151797245674225),
  334. BOOST_MATH_BIG_CONSTANT(T, 53, 0.0021284987017821144),
  335. BOOST_MATH_BIG_CONSTANT(T, 53, -0.55789841321675513e-6)
  336. };
  337. // LCOV_EXCL_STOP
  338. T g = x - root1;
  339. g -= root2;
  340. g -= root3;
  341. T r = tools::evaluate_polynomial(P, T(x-1)) / tools::evaluate_polynomial(Q, T(x-1));
  342. T result = g * Y + g * r;
  343. return result;
  344. }
  345. //
  346. // 9-digit precision:
  347. //
  348. template <class T>
  349. inline T digamma_imp_1_2(T x, const std::integral_constant<int, 24>*)
  350. {
  351. //
  352. // Now the approximation, we use the form:
  353. //
  354. // digamma(x) = (x - root) * (Y + R(x-1))
  355. //
  356. // Where root is the location of the positive root of digamma,
  357. // Y is a constant, and R is optimised for low absolute error
  358. // compared to Y.
  359. //
  360. // Maximum Deviation Found: 3.388e-010
  361. // At float precision, max error found: 2.008725e-008
  362. //
  363. // LCOV_EXCL_START
  364. static const float Y = 0.99558162689208984f;
  365. static const T root = 1532632.0f / 1048576;
  366. static const T root_minor = static_cast<T>(0.3700660185912626595423257213284682051735604e-6L);
  367. static const T P[] = {
  368. 0.25479851023250261e0f,
  369. -0.44981331915268368e0f,
  370. -0.43916936919946835e0f,
  371. -0.61041765350579073e-1f
  372. };
  373. static const T Q[] = {
  374. 0.1e1f,
  375. 0.15890202430554952e1f,
  376. 0.65341249856146947e0f,
  377. 0.63851690523355715e-1f
  378. };
  379. // LCOV_EXCL_STOP
  380. T g = x - root;
  381. g -= root_minor;
  382. T r = tools::evaluate_polynomial(P, T(x-1)) / tools::evaluate_polynomial(Q, T(x-1));
  383. T result = g * Y + g * r;
  384. return result;
  385. }
  386. template <class T, class Tag, class Policy>
  387. T digamma_imp(T x, const Tag* t, const Policy& pol)
  388. {
  389. //
  390. // This handles reflection of negative arguments, and all our
  391. // error handling, then forwards to the T-specific approximation.
  392. //
  393. BOOST_MATH_STD_USING // ADL of std functions.
  394. T result = 0;
  395. //
  396. // Check for negative arguments and use reflection:
  397. //
  398. if(x <= -1)
  399. {
  400. // Reflect:
  401. x = 1 - x;
  402. // Argument reduction for tan:
  403. T remainder = x - floor(x);
  404. // Shift to negative if > 0.5:
  405. if(remainder > T(0.5))
  406. {
  407. remainder -= 1;
  408. }
  409. //
  410. // check for evaluation at a negative pole:
  411. //
  412. if(remainder == 0)
  413. {
  414. return policies::raise_pole_error<T>("boost::math::digamma<%1%>(%1%)", nullptr, (1-x), pol);
  415. }
  416. result = constants::pi<T>() / tan(constants::pi<T>() * remainder);
  417. }
  418. if(x == 0)
  419. return policies::raise_pole_error<T>("boost::math::digamma<%1%>(%1%)", nullptr, x, pol);
  420. //
  421. // If we're above the lower-limit for the
  422. // asymptotic expansion then use it:
  423. //
  424. if(x >= digamma_large_lim(t))
  425. {
  426. result += digamma_imp_large(x, t);
  427. }
  428. else
  429. {
  430. //
  431. // If x > 2 reduce to the interval [1,2]:
  432. //
  433. while(x > 2)
  434. {
  435. x -= 1;
  436. result += 1/x;
  437. }
  438. //
  439. // If x < 1 use recurrence to shift to > 1:
  440. //
  441. while(x < 1)
  442. {
  443. result -= 1/x;
  444. x += 1;
  445. }
  446. result += digamma_imp_1_2(x, t);
  447. }
  448. return result;
  449. }
  450. template <class T, class Policy>
  451. T digamma_imp(T x, const std::integral_constant<int, 0>* t, const Policy& pol)
  452. {
  453. //
  454. // This handles reflection of negative arguments, and all our
  455. // error handling, then forwards to the T-specific approximation.
  456. //
  457. // This is covered by our real_concept tests, but these are disabled for
  458. // code coverage runs for performance reasons.
  459. // LCOV_EXCL_START
  460. //
  461. BOOST_MATH_STD_USING // ADL of std functions.
  462. T result = 0;
  463. //
  464. // Check for negative arguments and use reflection:
  465. //
  466. if(x <= -1)
  467. {
  468. // Reflect:
  469. x = 1 - x;
  470. // Argument reduction for tan:
  471. T remainder = x - floor(x);
  472. // Shift to negative if > 0.5:
  473. if(remainder > T(0.5))
  474. {
  475. remainder -= 1;
  476. }
  477. //
  478. // check for evaluation at a negative pole:
  479. //
  480. if(remainder == 0)
  481. {
  482. return policies::raise_pole_error<T>("boost::math::digamma<%1%>(%1%)", nullptr, (1 - x), pol);
  483. }
  484. result = constants::pi<T>() / tan(constants::pi<T>() * remainder);
  485. }
  486. if(x == 0)
  487. return policies::raise_pole_error<T>("boost::math::digamma<%1%>(%1%)", nullptr, x, pol);
  488. //
  489. // If we're above the lower-limit for the
  490. // asymptotic expansion then use it, the
  491. // limit is a linear interpolation with
  492. // limit = 10 at 50 bit precision and
  493. // limit = 250 at 1000 bit precision.
  494. //
  495. int lim = 10 + ((tools::digits<T>() - 50) * 240L) / 950;
  496. T two_x = ldexp(x, 1);
  497. if(x >= lim)
  498. {
  499. result += digamma_imp_large(x, pol, t);
  500. }
  501. else if(floor(x) == x)
  502. {
  503. //
  504. // Special case for integer arguments, see
  505. // http://functions.wolfram.com/06.14.03.0001.01
  506. //
  507. result = -constants::euler<T, Policy>();
  508. T val = 1;
  509. while(val < x)
  510. {
  511. result += 1 / val;
  512. val += 1;
  513. }
  514. }
  515. else if(floor(two_x) == two_x)
  516. {
  517. //
  518. // Special case for half integer arguments, see:
  519. // http://functions.wolfram.com/06.14.03.0007.01
  520. //
  521. result = -2 * constants::ln_two<T, Policy>() - constants::euler<T, Policy>();
  522. int n = itrunc(x);
  523. if(n)
  524. {
  525. for(int k = 1; k < n; ++k)
  526. result += 1 / T(k);
  527. for(int k = n; k <= 2 * n - 1; ++k)
  528. result += 2 / T(k);
  529. }
  530. }
  531. else
  532. {
  533. //
  534. // Rescale so we can use the asymptotic expansion:
  535. //
  536. while(x < lim)
  537. {
  538. result -= 1 / x;
  539. x += 1;
  540. }
  541. result += digamma_imp_large(x, pol, t);
  542. }
  543. return result;
  544. // LCOV_EXCL_STOP
  545. }
  546. } // namespace detail
  547. template <class T, class Policy>
  548. inline typename tools::promote_args<T>::type
  549. digamma(T x, const Policy&)
  550. {
  551. typedef typename tools::promote_args<T>::type result_type;
  552. typedef typename policies::evaluation<result_type, Policy>::type value_type;
  553. typedef typename policies::precision<T, Policy>::type precision_type;
  554. typedef std::integral_constant<int,
  555. (precision_type::value <= 0) || (precision_type::value > 113) ? 0 :
  556. precision_type::value <= 24 ? 24 :
  557. precision_type::value <= 53 ? 53 :
  558. precision_type::value <= 64 ? 64 :
  559. precision_type::value <= 113 ? 113 : 0 > tag_type;
  560. typedef typename policies::normalise<
  561. Policy,
  562. policies::promote_float<false>,
  563. policies::promote_double<false>,
  564. policies::discrete_quantile<>,
  565. policies::assert_undefined<> >::type forwarding_policy;
  566. return policies::checked_narrowing_cast<result_type, Policy>(detail::digamma_imp(
  567. static_cast<value_type>(x),
  568. static_cast<const tag_type*>(nullptr), forwarding_policy()), "boost::math::digamma<%1%>(%1%)");
  569. }
  570. template <class T>
  571. inline typename tools::promote_args<T>::type
  572. digamma(T x)
  573. {
  574. return digamma(x, policies::policy<>());
  575. }
  576. } // namespace math
  577. } // namespace boost
  578. #ifdef _MSC_VER
  579. #pragma warning(pop)
  580. #endif
  581. #endif