digamma.hpp 22 KB

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