factorials.qbk 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370
  1. [section:factorials Factorials and Binomial Coefficients]
  2. [section:sf_factorial Factorial]
  3. [h4 Synopsis]
  4. ``
  5. #include <boost/math/special_functions/factorials.hpp>
  6. ``
  7. namespace boost{ namespace math{
  8. template <class T>
  9. T factorial(unsigned i);
  10. template <class T, class ``__Policy``>
  11. T factorial(unsigned i, const ``__Policy``&);
  12. template <class T>
  13. constexpr T unchecked_factorial(unsigned i);
  14. template <class T>
  15. struct max_factorial;
  16. }} // namespaces
  17. [h4 Description]
  18. [important
  19. The functions described below are templates where the template argument T CANNOT be deduced from the
  20. arguments passed to the function. Therefore if you write something like:
  21. `boost::math::factorial(2);`
  22. You will get a (perhaps perplexing) compiler error, ususally indicating that there is no such function to be found.
  23. Instead you need to specify the return type explicity and write:
  24. `boost::math::factorial<double>(2);`
  25. So that the return type is known.
  26. Furthermore, the template argument must be a real-valued type such as `float` or `double`
  27. and not an integer type - that would overflow far too easily for quite small values of parameter `i`!
  28. The source code `static_assert` and comment just after the will be:
  29. ``
  30. BOOST_STATIC_ASSERT(!boost::is_integral<T>::value);
  31. // factorial<unsigned int>(n) is not implemented
  32. // because it would overflow integral type T for too small n
  33. // to be useful. Use instead a floating-point type,
  34. // and convert to an unsigned type if essential, for example:
  35. // unsigned int nfac = static_cast<unsigned int>(factorial<double>(n));
  36. // See factorial documentation for more detail.
  37. ``
  38. ]
  39. template <class T>
  40. T factorial(unsigned i);
  41. template <class T, class ``__Policy``>
  42. T factorial(unsigned i, const ``__Policy``&);
  43. Returns [^i!].
  44. [optional_policy]
  45. For [^i <= max_factorial<T>::value] this is implemented by table lookup,
  46. for larger values of [^i], this function is implemented in terms of __tgamma.
  47. If [^i] is so large that the result can not be represented in type T, then
  48. calls __overflow_error.
  49. template <class T>
  50. constexpr T unchecked_factorial(unsigned i);
  51. Returns [^i!].
  52. Internally this function performs table lookup of the result. Further it performs
  53. no range checking on the value of i: it is up to the caller to ensure
  54. that [^i <= max_factorial<T>::value]. This function is intended to be used
  55. inside inner loops that require fast table lookup of factorials, but requires
  56. care to ensure that argument [^i] never grows too large.
  57. template <class T>
  58. struct max_factorial
  59. {
  60. static const unsigned value = X;
  61. };
  62. This traits class defines the largest value that can be passed to
  63. [^unchecked_factorial]. The member `value` can be used where integral
  64. constant expressions are required: for example to define the size of
  65. further tables that depend on the factorials.
  66. This function is `constexpr` only if the compiler supports C++14 constexpr functions.
  67. [h4 Accuracy]
  68. For arguments smaller than `max_factorial<T>::value`
  69. the result should be
  70. correctly rounded. For larger arguments the accuracy will be the same
  71. as for __tgamma.
  72. [h4 Testing]
  73. Basic sanity checks and spot values to verify the data tables:
  74. the main tests for the __tgamma function handle those cases already.
  75. [h4 Implementation]
  76. The factorial function is table driven for small arguments, and is
  77. implemented in terms of __tgamma for larger arguments.
  78. [endsect] [/section:sf_factorial Factorial]
  79. [section:sf_double_factorial Double Factorial]
  80. ``
  81. #include <boost/math/special_functions/factorials.hpp>
  82. ``
  83. namespace boost{ namespace math{
  84. template <class T>
  85. T double_factorial(unsigned i);
  86. template <class T, class ``__Policy``>
  87. T double_factorial(unsigned i, const ``__Policy``&);
  88. }} // namespaces
  89. Returns [^i!!].
  90. [optional_policy]
  91. May return the result of __overflow_error if the result is too large
  92. to represent in type T. The implementation is designed to be optimised
  93. for small /i/ where table lookup of i! is possible.
  94. [important
  95. The functions described above are templates where the template argument T can not be deduced from the
  96. arguments passed to the function. Therefore if you write something like:
  97. `boost::math::double_factorial(2);`
  98. You will get a (possibly perplexing) compiler error, ususally indicating that there is no such function to be found. Instead you need to specifiy
  99. the return type explicity and write:
  100. `boost::math::double_factorial<double>(2);`
  101. So that the return type is known. Further, the template argument must be a real-valued type such as `float` or `double`
  102. and not an integer type - that would overflow far too easily!
  103. The source code `static_assert` and comment just after the will be:
  104. ``
  105. BOOST_STATIC_ASSERT(!boost::is_integral<T>::value);
  106. // factorial<unsigned int>(n) is not implemented
  107. // because it would overflow integral type T for too small n
  108. // to be useful. Use instead a floating-point type,
  109. // and convert to an unsigned type if essential, for example:
  110. // unsigned int nfac = static_cast<unsigned int>(factorial<double>(n));
  111. // See factorial documentation for more detail.
  112. ``
  113. ]
  114. [note The argument to `double_factorial` is type `unsigned` even though technically -1!! is defined.]
  115. [h4 Accuracy]
  116. The implementation uses a trivial adaptation of
  117. the factorial function, so error rates should be no more than a couple
  118. of epsilon higher.
  119. [h4 Testing]
  120. The spot tests for the double factorial use data generated by __WolframAlpha.
  121. [h4 Implementation]
  122. The double factorial is implemented in terms of the factorial and gamma
  123. functions using the relations:
  124. [expression ['(2n)!! = 2[super n ] * n!]]
  125. [expression ['(2n+1)!! = (2n+1)! / (2[super n ] n!)]]
  126. and
  127. [expression ['(2n-1)!! = [Gamma]((2n+1)/2) * 2[super n ] / sqrt(pi)]]
  128. [endsect] [/section:sf_double_factorial Double Factorial]
  129. [section:sf_rising_factorial Rising Factorial]
  130. ``
  131. #include <boost/math/special_functions/factorials.hpp>
  132. ``
  133. namespace boost{ namespace math{
  134. template <class T>
  135. ``__sf_result`` rising_factorial(T x, int i);
  136. template <class T, class ``__Policy``>
  137. ``__sf_result`` rising_factorial(T x, int i, const ``__Policy``&);
  138. }} // namespaces
  139. Returns the rising factorial of /x/ and /i/:
  140. [expression ['rising_factorial(x, i) = [Gamma](x + i) / [Gamma](x)]]
  141. or
  142. [expression ['rising_factorial(x, i) = x(x+1)(x+2)(x+3)...(x+i-1)]]
  143. Note that both /x/ and /i/ can be negative as well as positive.
  144. [optional_policy]
  145. May return the result of __overflow_error if the result is too large
  146. to represent in type T.
  147. The return type of these functions is computed using the __arg_promotion_rules:
  148. the type of the result is `double` if T is an integer type, otherwise the type
  149. of the result is T.
  150. [h4 Accuracy]
  151. The accuracy will be the same as
  152. the __tgamma_delta_ratio function.
  153. [h4 Testing]
  154. The spot tests for the rising factorials use data generated by __Wolfram_functions.
  155. [h4 Implementation]
  156. Rising and factorials are implemented as ratios of gamma functions using __tgamma_delta_ratio.
  157. Optimisations for small integer arguments are handled internally by that function.
  158. [endsect] [/section:sf_rising_factorial Rising Factorial]
  159. [section:sf_falling_factorial Falling Factorial]
  160. ``
  161. #include <boost/math/special_functions/factorials.hpp>
  162. ``
  163. namespace boost{ namespace math{
  164. template <class T>
  165. ``__sf_result`` falling_factorial(T x, unsigned i);
  166. template <class T, class ``__Policy``>
  167. ``__sf_result`` falling_factorial(T x, unsigned i, const ``__Policy``&);
  168. }} // namespaces
  169. Returns the falling factorial of /x/ and /i/:
  170. [expression ['falling_factorial(x, i) = x(x-1)(x-2)(x-3)...(x-i+1)]]
  171. Note that this function is only defined for positive /i/, hence the
  172. `unsigned` second argument. Argument /x/ can be either positive or
  173. negative however.
  174. [optional_policy]
  175. May return the result of __overflow_error if the result is too large
  176. to represent in type T.
  177. The return type of these functions is computed using the __arg_promotion_rules:
  178. the type of the result is `double` if T is an integer type, otherwise the type
  179. of the result is T.
  180. [h4 Accuracy]
  181. The accuracy will be the same as
  182. the __tgamma_delta_ratio function.
  183. [h4 Testing]
  184. The spot tests for the falling factorials use data generated by __Wolfram_functions.
  185. [h4 Implementation]
  186. Rising and falling factorials are implemented as ratios of gamma functions
  187. using __tgamma_delta_ratio. Optimisations for
  188. small integer arguments are handled internally by that function.
  189. [endsect] [/section:sf_falling_factorial Falling Factorial]
  190. [section:sf_binomial Binomial Coefficients]
  191. ``
  192. #include <boost/math/special_functions/binomial.hpp>
  193. ``
  194. namespace boost{ namespace math{
  195. template <class T>
  196. T binomial_coefficient(unsigned n, unsigned k);
  197. template <class T, class ``__Policy``>
  198. T binomial_coefficient(unsigned n, unsigned k, const ``__Policy``&);
  199. }} // namespaces
  200. Returns the binomial coefficient: [sub n]C[sub k].
  201. Requires k <= n.
  202. [optional_policy]
  203. May return the result of __overflow_error if the result is too large
  204. to represent in type T.
  205. [important
  206. The functions described above are templates where the template argument `T` can not be deduced from the
  207. arguments passed to the function. Therefore if you write something like:
  208. `boost::math::binomial_coefficient(10, 2);`
  209. You will get a compiler error, ususally indicating that there is no such function to be found. Instead you need to specifiy
  210. the return type explicity and write:
  211. `boost::math::binomial_coefficient<double>(10, 2);`
  212. So that the return type is known. Further, the template argument must be a real-valued type such as `float` or `double`
  213. and not an integer type - that would overflow far too easily!
  214. ]
  215. [h4 Accuracy]
  216. The accuracy will be the same as for the
  217. factorials for small arguments (i.e. no more than one or two epsilon),
  218. and the __beta function for larger arguments.
  219. [h4 Testing]
  220. The spot tests for the binomial coefficients use data generated by __WolframAlpha.
  221. [h4 Implementation]
  222. Binomial coefficients are calculated using table lookup of factorials
  223. where possible using:
  224. [expression ['[sub n]C[sub k] = n! / (k!(n-k)!)]]
  225. Otherwise it is implemented in terms of the beta function using the relations:
  226. [expression ['[sub n]C[sub k] = 1 / (k * __beta(k, n-k+1))]]
  227. and
  228. [expression ['[sub n]C[sub k] = 1 / ((n-k) * __beta(k+1, n-k))]]
  229. [endsect] [/section:sf_binomial Binomial Coefficients]
  230. [endsect] [/section:factorials Factorials]
  231. [/
  232. Copyright 2006, 2010 John Maddock and Paul A. Bristow.
  233. Distributed under the Boost Software License, Version 1.0.
  234. (See accompanying file LICENSE_1_0.txt or copy at
  235. http://www.boost.org/LICENSE_1_0.txt).
  236. ]