mirror of
				https://github.com/saitohirga/WSJT-X.git
				synced 2025-10-30 20:40:28 -04:00 
			
		
		
		
	
		
			
	
	
		
			375 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
		
		
			
		
	
	
			375 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
|  | [section:factorials Factorials and Binomial Coefficients] | ||
|  | 
 | ||
|  | [section:sf_factorial Factorial] | ||
|  | 
 | ||
|  | [h4 Synopsis] | ||
|  | 
 | ||
|  | `` | ||
|  | #include <boost/math/special_functions/factorials.hpp> | ||
|  | `` | ||
|  | 
 | ||
|  |    namespace boost{ namespace math{ | ||
|  |     | ||
|  |    template <class T> | ||
|  |    T factorial(unsigned i); | ||
|  |     | ||
|  |    template <class T, class ``__Policy``> | ||
|  |    T factorial(unsigned i, const ``__Policy``&); | ||
|  |     | ||
|  |    template <class T> | ||
|  |    T unchecked_factorial(unsigned i); | ||
|  |     | ||
|  |    template <class T> | ||
|  |    struct max_factorial; | ||
|  | 
 | ||
|  |    }} // namespaces | ||
|  | 
 | ||
|  | [h4 Description] | ||
|  | 
 | ||
|  | [important | ||
|  | The functions described below are templates where the template argument T CANNOT be deduced from the | ||
|  | arguments passed to the function.  Therefore if you write something like: | ||
|  | 
 | ||
|  |    `boost::math::factorial(2);` | ||
|  | 
 | ||
|  | You will get a (perhaps perplexing) compiler error, ususally indicating that there is no such function to be found. | ||
|  | Instead you need to specify the return type explicity and write: | ||
|  | 
 | ||
|  |    `boost::math::factorial<double>(2);` | ||
|  | 
 | ||
|  | So that the return type is known. | ||
|  | 
 | ||
|  | Furthermore, the template argument must be a real-valued type such as `float` or `double` | ||
|  | and not an integer type - that would overflow far too easily for quite small values of parameter `i`! | ||
|  | 
 | ||
|  | The source code `static_assert` and comment just after the  will be: | ||
|  | 
 | ||
|  | `` | ||
|  |    BOOST_STATIC_ASSERT(!boost::is_integral<T>::value); | ||
|  |    // factorial<unsigned int>(n) is not implemented | ||
|  |    // because it would overflow integral type T for too small n | ||
|  |    // to be useful. Use instead a floating-point type, | ||
|  |    // and convert to an unsigned type if essential, for example: | ||
|  |    // unsigned int nfac = static_cast<unsigned int>(factorial<double>(n)); | ||
|  |    // See factorial documentation for more detail. | ||
|  | `` | ||
|  | ] | ||
|  | 
 | ||
|  |    template <class T> | ||
|  |    T factorial(unsigned i); | ||
|  | 
 | ||
|  |    template <class T, class ``__Policy``> | ||
|  |    T factorial(unsigned i, const ``__Policy``&); | ||
|  | 
 | ||
|  | Returns [^i!]. | ||
|  | 
 | ||
|  | [optional_policy] | ||
|  | 
 | ||
|  | For [^i <= max_factorial<T>::value] this is implemented by table lookup,  | ||
|  | for larger values of [^i], this function is implemented in terms of __tgamma.   | ||
|  | 
 | ||
|  | If [^i] is so large that the result can not be represented in type T, then  | ||
|  | calls __overflow_error. | ||
|  | 
 | ||
|  |    template <class T> | ||
|  |    T unchecked_factorial(unsigned i); | ||
|  | 
 | ||
|  | Returns [^i!]. | ||
|  | 
 | ||
|  | Internally this function performs table lookup of the result.  Further it performs | ||
|  | no range checking on the value of i: it is up to the caller to ensure | ||
|  | that [^i <= max_factorial<T>::value].  This function is intended to be used | ||
|  | inside inner loops that require fast table lookup of factorials, but requires | ||
|  | care to ensure that argument [^i] never grows too large. | ||
|  | 
 | ||
|  |    template <class T> | ||
|  |    struct max_factorial | ||
|  |    { | ||
|  |       static const unsigned value = X; | ||
|  |    }; | ||
|  | 
 | ||
|  | This traits class defines the largest value that can be passed to | ||
|  | [^unchecked_factorial].  The member `value` can be used where integral | ||
|  | constant expressions are required: for example to define the size of | ||
|  | further tables that depend on the factorials. | ||
|  | 
 | ||
|  | [h4 Accuracy] | ||
|  | 
 | ||
|  | For arguments smaller than `max_factorial<T>::value`  | ||
|  | the result should be | ||
|  | correctly rounded.  For larger arguments the accuracy will be the same | ||
|  | as for __tgamma. | ||
|  | 
 | ||
|  | [h4 Testing] | ||
|  | 
 | ||
|  | Basic sanity checks and spot values to verify the data tables:  | ||
|  | the main tests for the __tgamma function handle those cases already. | ||
|  | 
 | ||
|  | [h4 Implementation] | ||
|  | 
 | ||
|  | The factorial function is table driven for small arguments, and is | ||
|  | implemented in terms of __tgamma for larger arguments. | ||
|  | 
 | ||
|  | [endsect] | ||
|  | 
 | ||
|  | [section:sf_double_factorial Double Factorial] | ||
|  | 
 | ||
|  | `` | ||
|  | #include <boost/math/special_functions/factorials.hpp> | ||
|  | `` | ||
|  | 
 | ||
|  |    namespace boost{ namespace math{ | ||
|  |     | ||
|  |    template <class T> | ||
|  |    T double_factorial(unsigned i); | ||
|  |     | ||
|  |    template <class T, class ``__Policy``> | ||
|  |    T double_factorial(unsigned i, const ``__Policy``&); | ||
|  |     | ||
|  |    }} // namespaces | ||
|  | 
 | ||
|  | Returns [^i!!].   | ||
|  | 
 | ||
|  | [optional_policy] | ||
|  | 
 | ||
|  | May return the result of __overflow_error if the result is too large | ||
|  | to represent in type T.  The implementation is designed to be optimised | ||
|  | for small /i/ where table lookup of i! is possible. | ||
|  | 
 | ||
|  | [important | ||
|  | The functions described above are templates where the template argument T can not be deduced from the | ||
|  | arguments passed to the function.  Therefore if you write something like: | ||
|  | 
 | ||
|  |    `boost::math::double_factorial(2);` | ||
|  | 
 | ||
|  | You will get a (possibly perplexing) compiler error, ususally indicating that there is no such function to be found.  Instead you need to specifiy | ||
|  | the return type explicity and write: | ||
|  | 
 | ||
|  |    `boost::math::double_factorial<double>(2);` | ||
|  | 
 | ||
|  | So that the return type is known.  Further, the template argument must be a real-valued type such as `float` or `double` | ||
|  | and not an integer type - that would overflow far too easily! | ||
|  | 
 | ||
|  | The source code `static_assert` and comment just after the  will be: | ||
|  | 
 | ||
|  | `` | ||
|  |    BOOST_STATIC_ASSERT(!boost::is_integral<T>::value); | ||
|  |    // factorial<unsigned int>(n) is not implemented | ||
|  |    // because it would overflow integral type T for too small n | ||
|  |    // to be useful. Use instead a floating-point type, | ||
|  |    // and convert to an unsigned type if essential, for example: | ||
|  |    // unsigned int nfac = static_cast<unsigned int>(factorial<double>(n)); | ||
|  |    // See factorial documentation for more detail. | ||
|  | `` | ||
|  | ] | ||
|  | 
 | ||
|  | [note The argument to `double_factorial` is type `unsigned` even though technically -1!! is defined.] | ||
|  | 
 | ||
|  | [h4 Accuracy] | ||
|  | 
 | ||
|  | The implementation uses a trivial adaptation of | ||
|  | the factorial function, so error rates should be no more than a couple | ||
|  | of epsilon higher. | ||
|  | 
 | ||
|  | [h4 Testing] | ||
|  | 
 | ||
|  | The spot tests for the double factorial use data  | ||
|  | generated by functions.wolfram.com. | ||
|  | 
 | ||
|  | [h4 Implementation] | ||
|  | 
 | ||
|  | The double factorial is implemented in terms of the factorial and gamma | ||
|  | functions using the relations: | ||
|  | 
 | ||
|  | (2n)!! = 2[super n ] * n! | ||
|  | 
 | ||
|  | (2n+1)!! = (2n+1)! / (2[super n ] n!) | ||
|  | 
 | ||
|  | and | ||
|  | 
 | ||
|  | (2n-1)!! = [Gamma]((2n+1)/2) * 2[super n ] / sqrt(pi) | ||
|  | 
 | ||
|  | [endsect] | ||
|  | 
 | ||
|  | [section:sf_rising_factorial Rising Factorial] | ||
|  | 
 | ||
|  | `` | ||
|  | #include <boost/math/special_functions/factorials.hpp> | ||
|  | `` | ||
|  | 
 | ||
|  |    namespace boost{ namespace math{ | ||
|  |     | ||
|  |    template <class T> | ||
|  |    ``__sf_result`` rising_factorial(T x, int i); | ||
|  |     | ||
|  |    template <class T, class ``__Policy``> | ||
|  |    ``__sf_result`` rising_factorial(T x, int i, const ``__Policy``&); | ||
|  |     | ||
|  |    }} // namespaces | ||
|  | 
 | ||
|  | Returns the rising factorial of /x/ and /i/: | ||
|  | 
 | ||
|  | rising_factorial(x, i) = [Gamma](x + i) / [Gamma](x); | ||
|  | 
 | ||
|  | or | ||
|  | 
 | ||
|  | rising_factorial(x, i) = x(x+1)(x+2)(x+3)...(x+i-1) | ||
|  |                            | ||
|  | Note that both /x/ and /i/ can be negative as well as positive. | ||
|  | 
 | ||
|  | [optional_policy] | ||
|  | 
 | ||
|  | May return the result of __overflow_error if the result is too large | ||
|  | to represent in type T. | ||
|  | 
 | ||
|  | The return type of these functions is computed using the __arg_promotion_rules: | ||
|  | the type of the result is `double` if T is an integer type, otherwise the type | ||
|  | of the result is T. | ||
|  | 
 | ||
|  | [h4 Accuracy] | ||
|  | 
 | ||
|  | The accuracy will be the same as | ||
|  | the __tgamma_delta_ratio function. | ||
|  | 
 | ||
|  | [h4 Testing] | ||
|  | 
 | ||
|  | The spot tests for the rising factorials use data generated  | ||
|  | by functions.wolfram.com. | ||
|  | 
 | ||
|  | [h4 Implementation] | ||
|  | 
 | ||
|  | Rising and falling factorials are implemented as ratios of gamma functions | ||
|  | using __tgamma_delta_ratio.  Optimisations for | ||
|  | small integer arguments are handled internally by that function. | ||
|  | 
 | ||
|  | [endsect] | ||
|  | 
 | ||
|  | [section:sf_falling_factorial Falling Factorial] | ||
|  | 
 | ||
|  | `` | ||
|  | #include <boost/math/special_functions/factorials.hpp> | ||
|  | `` | ||
|  | 
 | ||
|  |    namespace boost{ namespace math{ | ||
|  |     | ||
|  |    template <class T> | ||
|  |    ``__sf_result`` falling_factorial(T x, unsigned i); | ||
|  |     | ||
|  |    template <class T, class ``__Policy``> | ||
|  |    ``__sf_result`` falling_factorial(T x, unsigned i, const ``__Policy``&); | ||
|  |     | ||
|  |    }} // namespaces | ||
|  | 
 | ||
|  | Returns the falling factorial of /x/ and /i/: | ||
|  | 
 | ||
|  | falling_factorial(x, i) = x(x-1)(x-2)(x-3)...(x-i+1) | ||
|  |     | ||
|  | Note that this function is only defined for positive /i/, hence the | ||
|  | `unsigned` second argument.  Argument /x/ can be either positive or | ||
|  | negative however. | ||
|  | 
 | ||
|  | [optional_policy] | ||
|  | 
 | ||
|  | May return the result of __overflow_error if the result is too large | ||
|  | to represent in type T. | ||
|  | 
 | ||
|  | The return type of these functions is computed using the __arg_promotion_rules: | ||
|  | the type of the result is `double` if T is an integer type, otherwise the type | ||
|  | of the result is T. | ||
|  | 
 | ||
|  | [h4 Accuracy] | ||
|  | 
 | ||
|  | The accuracy will be the same as | ||
|  | the __tgamma_delta_ratio function. | ||
|  | 
 | ||
|  | [h4 Testing] | ||
|  | 
 | ||
|  | The spot tests for the falling factorials use data generated by  | ||
|  | functions.wolfram.com. | ||
|  | 
 | ||
|  | [h4 Implementation] | ||
|  | 
 | ||
|  | Rising and falling factorials are implemented as ratios of gamma functions | ||
|  | using __tgamma_delta_ratio.  Optimisations for | ||
|  | small integer arguments are handled internally by that function. | ||
|  | 
 | ||
|  | [endsect] | ||
|  | 
 | ||
|  | [section:sf_binomial Binomial Coefficients] | ||
|  | 
 | ||
|  | `` | ||
|  | #include <boost/math/special_functions/binomial.hpp> | ||
|  | `` | ||
|  | 
 | ||
|  |    namespace boost{ namespace math{ | ||
|  |     | ||
|  |    template <class T> | ||
|  |    T binomial_coefficient(unsigned n, unsigned k); | ||
|  | 
 | ||
|  |    template <class T, class ``__Policy``> | ||
|  |    T binomial_coefficient(unsigned n, unsigned k, const ``__Policy``&); | ||
|  | 
 | ||
|  |    }} // namespaces | ||
|  | 
 | ||
|  | Returns the binomial coefficient: [sub n]C[sub k]. | ||
|  | 
 | ||
|  | Requires k <= n. | ||
|  | 
 | ||
|  | [optional_policy] | ||
|  | 
 | ||
|  | May return the result of __overflow_error if the result is too large | ||
|  | to represent in type T. | ||
|  |     | ||
|  | [important | ||
|  | The functions described above are templates where the template argument T can not be deduced from the | ||
|  | arguments passed to the function.  Therefore if you write something like: | ||
|  | 
 | ||
|  |    `boost::math::binomial_coefficient(10, 2);` | ||
|  | 
 | ||
|  | You will get a compiler error, ususally indicating that there is no such function to be found.  Instead you need to specifiy | ||
|  | the return type explicity and write: | ||
|  | 
 | ||
|  |    `boost::math::binomial_coefficient<double>(10, 2);` | ||
|  | 
 | ||
|  | So that the return type is known.  Further, the template argument must be a real-valued type such as `float` or `double` | ||
|  | and not an integer type - that would overflow far too easily! | ||
|  | ] | ||
|  | 
 | ||
|  | [h4 Accuracy] | ||
|  | 
 | ||
|  | The accuracy will be the same as for the | ||
|  | factorials for small arguments (i.e. no more than one or two epsilon),  | ||
|  | and the __beta function for larger arguments. | ||
|  | 
 | ||
|  | [h4 Testing] | ||
|  | 
 | ||
|  | The spot tests for the binomial coefficients use data  | ||
|  | generated by functions.wolfram.com. | ||
|  | 
 | ||
|  | [h4 Implementation] | ||
|  | 
 | ||
|  | Binomial coefficients are calculated using table lookup of factorials | ||
|  | where possible using: | ||
|  | 
 | ||
|  | [sub n]C[sub k] = n! / (k!(n-k)!) | ||
|  | 
 | ||
|  | Otherwise it is implemented in terms of the beta function using the relations: | ||
|  | 
 | ||
|  | [sub n]C[sub k] = 1 / (k * __beta(k, n-k+1)) | ||
|  | 
 | ||
|  | and | ||
|  | 
 | ||
|  | [sub n]C[sub k] = 1 / ((n-k) * __beta(k+1, n-k)) | ||
|  | 
 | ||
|  | [endsect] | ||
|  | 
 | ||
|  | 
 | ||
|  | [endsect][/section:factorials Factorials] | ||
|  | 
 | ||
|  | [/  | ||
|  |   Copyright 2006, 2010 John Maddock and Paul A. Bristow. | ||
|  |   Distributed under 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). | ||
|  | ] |