• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1[section:factorials Factorials and Binomial Coefficients]
2
3[section:sf_factorial Factorial]
4
5[h4 Synopsis]
6
7``
8#include <boost/math/special_functions/factorials.hpp>
9``
10
11   namespace boost{ namespace math{
12
13   template <class T>
14   T factorial(unsigned i);
15
16   template <class T, class ``__Policy``>
17   T factorial(unsigned i, const ``__Policy``&);
18
19   template <class T>
20   constexpr T unchecked_factorial(unsigned i);
21
22   template <class T>
23   struct max_factorial;
24
25   }} // namespaces
26
27[h4 Description]
28
29[important
30The functions described below are templates where the template argument T CANNOT be deduced from the
31arguments passed to the function.  Therefore if you write something like:
32
33   `boost::math::factorial(2);`
34
35You will get a (perhaps perplexing) compiler error, usually indicating that there is no such function to be found.
36Instead you need to specify the return type explicitly and write:
37
38   `boost::math::factorial<double>(2);`
39
40So that the return type is known.
41
42Furthermore, the template argument must be a real-valued type such as `float` or `double`
43and not an integer type - that would overflow far too easily for quite small values of parameter `i`!
44
45The source code `static_assert` and comment just after the  will be:
46
47``
48   BOOST_STATIC_ASSERT(!boost::is_integral<T>::value);
49   // factorial<unsigned int>(n) is not implemented
50   // because it would overflow integral type T for too small n
51   // to be useful. Use instead a floating-point type,
52   // and convert to an unsigned type if essential, for example:
53   // unsigned int nfac = static_cast<unsigned int>(factorial<double>(n));
54   // See factorial documentation for more detail.
55``
56]
57
58   template <class T>
59   T factorial(unsigned i);
60
61   template <class T, class ``__Policy``>
62   T factorial(unsigned i, const ``__Policy``&);
63
64Returns [^i!].
65
66[optional_policy]
67
68For [^i <= max_factorial<T>::value] this is implemented by table lookup,
69for larger values of [^i], this function is implemented in terms of __tgamma.
70
71If [^i] is so large that the result can not be represented in type T, then
72calls __overflow_error.
73
74   template <class T>
75   constexpr T unchecked_factorial(unsigned i);
76
77Returns [^i!].
78
79Internally this function performs table lookup of the result.  Further it performs
80no range checking on the value of i: it is up to the caller to ensure
81that [^i <= max_factorial<T>::value].  This function is intended to be used
82inside inner loops that require fast table lookup of factorials, but requires
83care to ensure that argument [^i] never grows too large.
84
85   template <class T>
86   struct max_factorial
87   {
88      static const unsigned value = X;
89   };
90
91This traits class defines the largest value that can be passed to
92[^unchecked_factorial].  The member `value` can be used where integral
93constant expressions are required: for example to define the size of
94further tables that depend on the factorials.
95
96This function is `constexpr` only if the compiler supports C++14 constexpr functions.
97
98[h4 Accuracy]
99
100For arguments smaller than `max_factorial<T>::value`
101the result should be
102correctly rounded.  For larger arguments the accuracy will be the same
103as for __tgamma.
104
105[h4 Testing]
106
107Basic sanity checks and spot values to verify the data tables:
108the main tests for the __tgamma function handle those cases already.
109
110[h4 Implementation]
111
112The factorial function is table driven for small arguments, and is
113implemented in terms of __tgamma for larger arguments.
114
115[endsect] [/section:sf_factorial Factorial]
116
117[section:sf_double_factorial Double Factorial]
118
119``
120#include <boost/math/special_functions/factorials.hpp>
121``
122
123   namespace boost{ namespace math{
124
125   template <class T>
126   T double_factorial(unsigned i);
127
128   template <class T, class ``__Policy``>
129   T double_factorial(unsigned i, const ``__Policy``&);
130
131   }} // namespaces
132
133Returns [^i!!].
134
135[optional_policy]
136
137May return the result of __overflow_error if the result is too large
138to represent in type T.  The implementation is designed to be optimised
139for small /i/ where table lookup of i! is possible.
140
141[important
142The functions described above are templates where the template argument T can not be deduced from the
143arguments passed to the function.  Therefore if you write something like:
144
145   `boost::math::double_factorial(2);`
146
147You will get a (possibly perplexing) compiler error, usually indicating that there is no such function to be found.  Instead you need to specify
148the return type explicitly and write:
149
150   `boost::math::double_factorial<double>(2);`
151
152So that the return type is known.  Further, the template argument must be a real-valued type such as `float` or `double`
153and not an integer type - that would overflow far too easily!
154
155The source code `static_assert` and comment just after the  will be:
156
157``
158   BOOST_STATIC_ASSERT(!boost::is_integral<T>::value);
159   // factorial<unsigned int>(n) is not implemented
160   // because it would overflow integral type T for too small n
161   // to be useful. Use instead a floating-point type,
162   // and convert to an unsigned type if essential, for example:
163   // unsigned int nfac = static_cast<unsigned int>(factorial<double>(n));
164   // See factorial documentation for more detail.
165``
166]
167
168[note The argument to `double_factorial` is type `unsigned` even though technically -1!! is defined.]
169
170[h4 Accuracy]
171
172The implementation uses a trivial adaptation of
173the factorial function, so error rates should be no more than a couple
174of epsilon higher.
175
176[h4 Testing]
177
178The spot tests for the double factorial use data generated by __WolframAlpha.
179
180[h4 Implementation]
181
182The double factorial is implemented in terms of the factorial and gamma
183functions using the relations:
184
185[expression ['(2n)!! = 2[super n ] * n!]]
186
187[expression ['(2n+1)!! = (2n+1)! / (2[super n ] n!)]]
188
189and
190
191[expression ['(2n-1)!! = [Gamma]((2n+1)/2) * 2[super n ] / sqrt(pi)]]
192
193[endsect] [/section:sf_double_factorial Double Factorial]
194
195[section:sf_rising_factorial Rising Factorial]
196
197``
198#include <boost/math/special_functions/factorials.hpp>
199``
200
201   namespace boost{ namespace math{
202
203   template <class T>
204   ``__sf_result`` rising_factorial(T x, int i);
205
206   template <class T, class ``__Policy``>
207   ``__sf_result`` rising_factorial(T x, int i, const ``__Policy``&);
208
209   }} // namespaces
210
211Returns the rising factorial of /x/ and /i/:
212
213[expression ['rising_factorial(x, i) = [Gamma](x + i) / [Gamma](x)]]
214
215or
216
217[expression ['rising_factorial(x, i) = x(x+1)(x+2)(x+3)...(x+i-1)]]
218
219Note that both /x/ and /i/ can be negative as well as positive.
220
221[optional_policy]
222
223May return the result of __overflow_error if the result is too large
224to represent in type T.
225
226The return type of these functions is computed using the __arg_promotion_rules:
227the type of the result is `double` if T is an integer type, otherwise the type
228of the result is T.
229
230[h4 Accuracy]
231
232The accuracy will be the same as
233the __tgamma_delta_ratio function.
234
235[h4 Testing]
236
237The spot tests for the rising factorials use data generated by __Wolfram_functions.
238
239[h4 Implementation]
240
241Rising and factorials are implemented as ratios of gamma functions using __tgamma_delta_ratio.
242Optimisations for small integer arguments are handled internally by that function.
243
244[endsect] [/section:sf_rising_factorial Rising Factorial]
245
246[section:sf_falling_factorial Falling Factorial]
247
248``
249#include <boost/math/special_functions/factorials.hpp>
250``
251
252   namespace boost{ namespace math{
253
254   template <class T>
255   ``__sf_result`` falling_factorial(T x, unsigned i);
256
257   template <class T, class ``__Policy``>
258   ``__sf_result`` falling_factorial(T x, unsigned i, const ``__Policy``&);
259
260   }} // namespaces
261
262Returns the falling factorial of /x/ and /i/:
263
264[expression ['falling_factorial(x, i) = x(x-1)(x-2)(x-3)...(x-i+1)]]
265
266Note that this function is only defined for positive /i/, hence the
267`unsigned` second argument.  Argument /x/ can be either positive or
268negative however.
269
270[optional_policy]
271
272May return the result of __overflow_error if the result is too large
273to represent in type T.
274
275The return type of these functions is computed using the __arg_promotion_rules:
276the type of the result is `double` if T is an integer type, otherwise the type
277of the result is T.
278
279[h4 Accuracy]
280
281The accuracy will be the same as
282the __tgamma_delta_ratio function.
283
284[h4 Testing]
285
286The spot tests for the falling factorials use data generated by __Wolfram_functions.
287
288[h4 Implementation]
289
290Rising and falling factorials are implemented as ratios of gamma functions
291using __tgamma_delta_ratio.  Optimisations for
292small integer arguments are handled internally by that function.
293
294[endsect] [/section:sf_falling_factorial Falling Factorial]
295
296[section:sf_binomial Binomial Coefficients]
297
298``
299#include <boost/math/special_functions/binomial.hpp>
300``
301
302   namespace boost{ namespace math{
303
304   template <class T>
305   T binomial_coefficient(unsigned n, unsigned k);
306
307   template <class T, class ``__Policy``>
308   T binomial_coefficient(unsigned n, unsigned k, const ``__Policy``&);
309
310   }} // namespaces
311
312Returns the binomial coefficient: [sub n]C[sub k].
313
314Requires k <= n.
315
316[optional_policy]
317
318May return the result of __overflow_error if the result is too large
319to represent in type T.
320
321[important
322The functions described above are templates where the template argument `T` can not be deduced from the
323arguments passed to the function.  Therefore if you write something like:
324
325   `boost::math::binomial_coefficient(10, 2);`
326
327You will get a compiler error, usually indicating that there is no such function to be found.  Instead you need to specify
328the return type explicitly and write:
329
330   `boost::math::binomial_coefficient<double>(10, 2);`
331
332So that the return type is known.  Further, the template argument must be a real-valued type such as `float` or `double`
333and not an integer type - that would overflow far too easily!
334]
335
336[h4 Accuracy]
337
338The accuracy will be the same as for the
339factorials for small arguments (i.e. no more than one or two epsilon),
340and the __beta function for larger arguments.
341
342[h4 Testing]
343
344The spot tests for the binomial coefficients use data generated by __WolframAlpha.
345
346[h4 Implementation]
347
348Binomial coefficients are calculated using table lookup of factorials
349where possible using:
350
351[expression ['[sub n]C[sub k] = n! / (k!(n-k)!)]]
352
353Otherwise it is implemented in terms of the beta function using the relations:
354
355[expression ['[sub n]C[sub k] = 1 / (k * __beta(k, n-k+1))]]
356
357and
358
359[expression ['[sub n]C[sub k] = 1 / ((n-k) * __beta(k+1, n-k))]]
360
361[endsect] [/section:sf_binomial Binomial Coefficients]
362
363[endsect] [/section:factorials Factorials]
364
365[/
366  Copyright 2006, 2010 John Maddock and Paul A. Bristow.
367  Distributed under the Boost Software License, Version 1.0.
368  (See accompanying file LICENSE_1_0.txt or copy at
369  http://www.boost.org/LICENSE_1_0.txt).
370]
371