// 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 namespace boost{ namespace math{ template T binomial_coefficient(unsigned n, unsigned k, const Policy& pol) { BOOST_STATIC_ASSERT(!boost::is_integral::value); 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; 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 = k * beta(static_cast(k), static_cast(n-k+1), pol); else result = (n - k) * beta(static_cast(k+1), static_cast(n-k), pol); if(result == 0) return policies::raise_overflow_error(function, 0, 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<>& pol) { return policies::checked_narrowing_cast >(binomial_coefficient(n, k, pol), "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