1 2 /////////////////////////////////////////////////////////////////////////////// 3 // Copyright 2013 Nikhar Agrawal 4 // Copyright 2013 Christopher Kormanyos 5 // Copyright 2014 John Maddock 6 // Copyright 2013 Paul Bristow 7 // Distributed under the Boost 8 // Software License, Version 1.0. (See accompanying file 9 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 10 11 #ifndef _BOOST_POLYGAMMA_2013_07_30_HPP_ 12 #define _BOOST_POLYGAMMA_2013_07_30_HPP_ 13 14 #include <boost/math/special_functions/factorials.hpp> 15 #include <boost/math/special_functions/detail/polygamma.hpp> 16 #include <boost/math/special_functions/trigamma.hpp> 17 18 namespace boost { namespace math { 19 20 21 template<class T, class Policy> polygamma(const int n,T x,const Policy & pol)22 inline typename tools::promote_args<T>::type polygamma(const int n, T x, const Policy& pol) 23 { 24 // 25 // Filter off special cases right at the start: 26 // 27 if(n == 0) 28 return boost::math::digamma(x, pol); 29 if(n == 1) 30 return boost::math::trigamma(x, pol); 31 // 32 // We've found some standard library functions to misbehave if any FPU exception flags 33 // are set prior to their call, this code will clear those flags, then reset them 34 // on exit: 35 // 36 BOOST_FPU_EXCEPTION_GUARD 37 // 38 // The type of the result - the common type of T and U after 39 // any integer types have been promoted to double: 40 // 41 typedef typename tools::promote_args<T>::type result_type; 42 // 43 // The type used for the calculation. This may be a wider type than 44 // the result in order to ensure full precision: 45 // 46 typedef typename policies::evaluation<result_type, Policy>::type value_type; 47 // 48 // The type of the policy to forward to the actual implementation. 49 // We disable promotion of float and double as that's [possibly] 50 // happened already in the line above. Also reset to the default 51 // any policies we don't use (reduces code bloat if we're called 52 // multiple times with differing policies we don't actually use). 53 // Also normalise the type, again to reduce code bloat in case we're 54 // called multiple times with functionally identical policies that happen 55 // to be different types. 56 // 57 typedef typename policies::normalise< 58 Policy, 59 policies::promote_float<false>, 60 policies::promote_double<false>, 61 policies::discrete_quantile<>, 62 policies::assert_undefined<> >::type forwarding_policy; 63 // 64 // Whew. Now we can make the actual call to the implementation. 65 // Arguments are explicitly cast to the evaluation type, and the result 66 // passed through checked_narrowing_cast which handles things like overflow 67 // according to the policy passed: 68 // 69 return policies::checked_narrowing_cast<result_type, forwarding_policy>( 70 detail::polygamma_imp(n, static_cast<value_type>(x), forwarding_policy()), 71 "boost::math::polygamma<%1%>(int, %1%)"); 72 } 73 74 template<class T> polygamma(const int n,T x)75 inline typename tools::promote_args<T>::type polygamma(const int n, T x) 76 { 77 return boost::math::polygamma(n, x, policies::policy<>()); 78 } 79 80 } } // namespace boost::math 81 82 #endif // _BOOST_BERNOULLI_2013_05_30_HPP_ 83 84