annotate DEPENDENCIES/generic/include/boost/math/special_functions/digamma.hpp @ 133:4acb5d8d80b6 tip

Don't fail environmental check if README.md exists (but .txt and no-suffix don't)
author Chris Cannam
date Tue, 30 Jul 2019 12:25:44 +0100
parents c530137014c0
children
rev   line source
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