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