// Copyright John Maddock 2006. // Use, modification and distribution are subject to the // Boost Software License, Version 1.0. (See accompanying file // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_MATH_SF_BINOMIAL_HPP #define BOOST_MATH_SF_BINOMIAL_HPP #ifdef _MSC_VER #pragma once #endif #include #include #include #include #include namespace boost{ namespace math{ template T binomial_coefficient(unsigned n, unsigned k, const Policy& pol) { static_assert(!std::is_integral::value, "Type T must not be an integral type"); BOOST_MATH_STD_USING static const char* function = "boost::math::binomial_coefficient<%1%>(unsigned, unsigned)"; if(k > n) return policies::raise_domain_error(function, "The binomial coefficient is undefined for k > n, but got k = %1%.", static_cast(k), pol); T result; // LCOV_EXCL_LINE if((k == 0) || (k == n)) return static_cast(1); if((k == 1) || (k == n-1)) return static_cast(n); if(n <= max_factorial::value) { // Use fast table lookup: result = unchecked_factorial(n); result /= unchecked_factorial(n-k); result /= unchecked_factorial(k); } else { // Use the beta function: if(k < n - k) result = static_cast(k * beta(static_cast(k), static_cast(n-k+1), pol)); else result = static_cast((n - k) * beta(static_cast(k+1), static_cast(n-k), pol)); if(result == 0) return policies::raise_overflow_error(function, nullptr, pol); result = 1 / result; } // convert to nearest integer: return ceil(result - 0.5f); } // // Type float can only store the first 35 factorials, in order to // increase the chance that we can use a table driven implementation // we'll promote to double: // template <> inline float binomial_coefficient >(unsigned n, unsigned k, const policies::policy<>&) { typedef policies::normalise< policies::policy<>, policies::promote_float, policies::promote_double, policies::discrete_quantile<>, policies::assert_undefined<> >::type forwarding_policy; return policies::checked_narrowing_cast(binomial_coefficient(n, k, forwarding_policy()), "boost::math::binomial_coefficient<%1%>(unsigned,unsigned)"); } template inline T binomial_coefficient(unsigned n, unsigned k) { return binomial_coefficient(n, k, policies::policy<>()); } } // namespace math } // namespace boost #endif // BOOST_MATH_SF_BINOMIAL_HPP