malachite_base/num/arithmetic/
factorial.rs

1// Copyright © 2025 Mikhail Hogrefe
2//
3// This file is part of Malachite.
4//
5// Malachite is free software: you can redistribute it and/or modify it under the terms of the GNU
6// Lesser General Public License (LGPL) as published by the Free Software Foundation; either version
7// 3 of the License, or (at your option) any later version. See <https://www.gnu.org/licenses/>.
8
9use crate::num::arithmetic::traits::{
10    CheckedDoubleFactorial, CheckedFactorial, CheckedMultifactorial, CheckedSubfactorial,
11    DoubleFactorial, Factorial, Multifactorial, Parity, Subfactorial,
12};
13use crate::num::basic::integers::USIZE_IS_U32;
14use crate::num::basic::unsigneds::PrimitiveUnsigned;
15use crate::num::conversion::traits::WrappingFrom;
16
17pub_test! {checked_multifactorial_naive<T: PrimitiveUnsigned>(n: u64, m: u64) -> Option<T> {
18    assert_ne!(m, 0);
19    let mut f = T::ONE;
20    let mut n = T::try_from(n).ok()?;
21    let m = T::saturating_from(m);
22    while n != T::ZERO {
23        f = f.checked_mul(n)?;
24        n.saturating_sub_assign(m);
25    }
26    Some(f)
27}}
28
29const FACTORIALS_U8: [u8; 6] = [1, 1, 2, 6, 24, 120];
30const FACTORIALS_U16: [u16; 9] = [1, 1, 2, 6, 24, 120, 720, 5040, 40320];
31const FACTORIALS_U32: [u32; 13] =
32    [1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800, 39916800, 479001600];
33const FACTORIALS_U64: [u64; 21] = [
34    1,
35    1,
36    2,
37    6,
38    24,
39    120,
40    720,
41    5040,
42    40320,
43    362880,
44    3628800,
45    39916800,
46    479001600,
47    6227020800,
48    87178291200,
49    1307674368000,
50    20922789888000,
51    355687428096000,
52    6402373705728000,
53    121645100408832000,
54    2432902008176640000,
55];
56const FACTORIALS_U128: [u128; 35] = [
57    1,
58    1,
59    2,
60    6,
61    24,
62    120,
63    720,
64    5040,
65    40320,
66    362880,
67    3628800,
68    39916800,
69    479001600,
70    6227020800,
71    87178291200,
72    1307674368000,
73    20922789888000,
74    355687428096000,
75    6402373705728000,
76    121645100408832000,
77    2432902008176640000,
78    51090942171709440000,
79    1124000727777607680000,
80    25852016738884976640000,
81    620448401733239439360000,
82    15511210043330985984000000,
83    403291461126605635584000000,
84    10888869450418352160768000000,
85    304888344611713860501504000000,
86    8841761993739701954543616000000,
87    265252859812191058636308480000000,
88    8222838654177922817725562880000000,
89    263130836933693530167218012160000000,
90    8683317618811886495518194401280000000,
91    295232799039604140847618609643520000000,
92];
93
94const ODD_DOUBLE_FACTORIALS_U8: [u8; 4] = [1, 3, 15, 105];
95const ODD_DOUBLE_FACTORIALS_U16: [u16; 6] = [1, 3, 15, 105, 945, 10395];
96const ODD_DOUBLE_FACTORIALS_U32: [u32; 10] =
97    [1, 3, 15, 105, 945, 10395, 135135, 2027025, 34459425, 654729075];
98const ODD_DOUBLE_FACTORIALS_U64: [u64; 17] = [
99    1,
100    3,
101    15,
102    105,
103    945,
104    10395,
105    135135,
106    2027025,
107    34459425,
108    654729075,
109    13749310575,
110    316234143225,
111    7905853580625,
112    213458046676875,
113    6190283353629375,
114    191898783962510625,
115    6332659870762850625,
116];
117const ODD_DOUBLE_FACTORIALS_U128: [u128; 28] = [
118    1,
119    3,
120    15,
121    105,
122    945,
123    10395,
124    135135,
125    2027025,
126    34459425,
127    654729075,
128    13749310575,
129    316234143225,
130    7905853580625,
131    213458046676875,
132    6190283353629375,
133    191898783962510625,
134    6332659870762850625,
135    221643095476699771875,
136    8200794532637891559375,
137    319830986772877770815625,
138    13113070457687988603440625,
139    563862029680583509947946875,
140    25373791335626257947657609375,
141    1192568192774434123539907640625,
142    58435841445947272053455474390625,
143    2980227913743310874726229193921875,
144    157952079428395476360490147277859375,
145    8687364368561751199826958100282265625,
146];
147
148const SUBFACTORIALS_U8: [u8; 6] = [1, 0, 1, 2, 9, 44];
149const SUBFACTORIALS_U16: [u16; 9] = [1, 0, 1, 2, 9, 44, 265, 1854, 14833];
150const SUBFACTORIALS_U32: [u32; 14] =
151    [1, 0, 1, 2, 9, 44, 265, 1854, 14833, 133496, 1334961, 14684570, 176214841, 2290792932];
152const SUBFACTORIALS_U64: [u64; 21] = [
153    1,
154    0,
155    1,
156    2,
157    9,
158    44,
159    265,
160    1854,
161    14833,
162    133496,
163    1334961,
164    14684570,
165    176214841,
166    2290792932,
167    32071101049,
168    481066515734,
169    7697064251745,
170    130850092279664,
171    2355301661033953,
172    44750731559645106,
173    895014631192902121,
174];
175const SUBFACTORIALS_U128: [u128; 35] = [
176    1,
177    0,
178    1,
179    2,
180    9,
181    44,
182    265,
183    1854,
184    14833,
185    133496,
186    1334961,
187    14684570,
188    176214841,
189    2290792932,
190    32071101049,
191    481066515734,
192    7697064251745,
193    130850092279664,
194    2355301661033953,
195    44750731559645106,
196    895014631192902121,
197    18795307255050944540,
198    413496759611120779881,
199    9510425471055777937262,
200    228250211305338670494289,
201    5706255282633466762357224,
202    148362637348470135821287825,
203    4005791208408693667174771274,
204    112162153835443422680893595673,
205    3252702461227859257745914274516,
206    97581073836835777732377428235481,
207    3025013288941909109703700275299910,
208    96800425246141091510518408809597121,
209    3194414033122656019847107490716704992,
210    108610077126170304674801654684367969729,
211];
212
213macro_rules! impl_factorials_a {
214    ($t:ident, $fs:ident, $odfs:ident, $sfs:ident, $df_limit:expr) => {
215        impl CheckedFactorial for $t {
216            /// Computes the factorial of a number.
217            ///
218            /// If the input is too large, the function returns `None`.
219            ///
220            /// $$
221            /// f(n) = \\begin{cases}
222            ///     \operatorname{Some}(n!) & \text{if} \\quad n! < 2^W, \\\\
223            ///     \operatorname{None} & \text{if} \\quad n! \geq 2^W,
224            /// \\end{cases}
225            /// $$
226            /// where $W$ is `Self::WIDTH`.
227            ///
228            /// $n! = O(\sqrt{n}(n/e)^n)$.
229            ///
230            /// # Worst-case complexity
231            /// Constant time and additional memory.
232            ///
233            /// # Examples
234            /// See [here](super::factorial#checked_factorial).
235            #[inline]
236            fn checked_factorial(n: u64) -> Option<$t> {
237                $fs.get(usize::try_from(n).ok()?).copied()
238            }
239        }
240
241        impl CheckedDoubleFactorial for $t {
242            /// Computes the double factorial of a number.
243            ///
244            /// If the input is too large, the function returns `None`.
245            ///
246            /// $$
247            /// f(n) = \\begin{cases}
248            ///     \operatorname{Some}(n!!) & \text{if} \\quad n!! < 2^W, \\\\
249            ///     \operatorname{None} & \text{if} \\quad n!! \geq 2^W,
250            /// \\end{cases}
251            /// $$
252            /// where $W$ is `Self::WIDTH`.
253            ///
254            /// $n!! = O(\sqrt{n}(n/e)^{n/2})$.
255            ///
256            /// # Worst-case complexity
257            /// Constant time and additional memory.
258            ///
259            /// # Examples
260            /// See [here](super::factorial#checked_double_factorial).
261            #[inline]
262            fn checked_double_factorial(n: u64) -> Option<$t> {
263                if n > $df_limit {
264                    None
265                } else if n.odd() {
266                    $odfs.get(usize::try_from(n >> 1).ok()?).copied()
267                } else {
268                    let half = n >> 1;
269                    $fs.get(usize::try_from(half).ok()?).map(|&f| f << half)
270                }
271            }
272        }
273
274        impl CheckedSubfactorial for $t {
275            /// Computes the subfactorial of a number.
276            ///
277            /// The subfactorial of $n$ counts the number of derangements of a set of size $n$; a
278            /// derangement is a permutation with no fixed points.
279            ///
280            /// If the input is too large, the function returns `None`.
281            ///
282            /// $$
283            /// f(n) = \\begin{cases}
284            ///     \operatorname{Some}(!n) & \text{if} \\quad !n < 2^W, \\\\
285            ///     \operatorname{None} & \text{if} \\quad !n \geq 2^W,
286            /// \\end{cases}
287            /// $$
288            /// where $W$ is `Self::WIDTH`.
289            ///
290            /// $!n = O(n!) = O(\sqrt{n}(n/e)^n)$.
291            ///
292            /// # Worst-case complexity
293            /// Constant time and additional memory.
294            ///
295            /// # Examples
296            /// See [here](super::factorial#checked_subfactorial).
297            #[inline]
298            fn checked_subfactorial(n: u64) -> Option<$t> {
299                $sfs.get(usize::try_from(n).ok()?).copied()
300            }
301        }
302    };
303}
304impl_factorials_a!(
305    u8,
306    FACTORIALS_U8,
307    ODD_DOUBLE_FACTORIALS_U8,
308    SUBFACTORIALS_U8,
309    7
310);
311impl_factorials_a!(
312    u16,
313    FACTORIALS_U16,
314    ODD_DOUBLE_FACTORIALS_U16,
315    SUBFACTORIALS_U16,
316    12
317);
318impl_factorials_a!(
319    u32,
320    FACTORIALS_U32,
321    ODD_DOUBLE_FACTORIALS_U32,
322    SUBFACTORIALS_U32,
323    20
324);
325impl_factorials_a!(
326    u64,
327    FACTORIALS_U64,
328    ODD_DOUBLE_FACTORIALS_U64,
329    SUBFACTORIALS_U64,
330    33
331);
332impl_factorials_a!(
333    u128,
334    FACTORIALS_U128,
335    ODD_DOUBLE_FACTORIALS_U128,
336    SUBFACTORIALS_U128,
337    56
338);
339
340impl CheckedFactorial for usize {
341    /// Computes the factorial of a [`usize`].
342    ///
343    /// If the input is too large, the function returns `None`.
344    ///
345    /// $$
346    /// f(n) = \\begin{cases}
347    ///     \operatorname{Some}(n!) & \text{if} \\quad n! < 2^W, \\\\
348    ///     \operatorname{None} & \text{if} \\quad n! \geq 2^W,
349    /// \\end{cases}
350    /// $$
351    /// where $W$ is `usize::WIDTH`.
352    ///
353    /// $n! = O(\sqrt{n}(n/e)^n)$.
354    ///
355    /// # Worst-case complexity
356    /// Constant time and additional memory.
357    ///
358    /// # Examples
359    /// See [here](super::factorial#checked_factorial).
360    #[inline]
361    fn checked_factorial(n: u64) -> Option<usize> {
362        FACTORIALS_U64
363            .get(usize::try_from(n).ok()?)
364            .and_then(|&f| usize::try_from(f).ok())
365    }
366}
367
368impl CheckedSubfactorial for usize {
369    /// Computes the subfactorial of a [`usize`].
370    ///
371    /// The subfactorial of $n$ counts the number of derangements of a set of size $n$; a
372    /// derangement is a permutation with no fixed points.
373    ///
374    /// If the input is too large, the function returns `None`.
375    ///
376    /// $$
377    /// f(n) = \\begin{cases}
378    ///     \operatorname{Some}(!n) & \text{if} \\quad !n < 2^W, \\\\
379    ///     \operatorname{None} & \text{if} \\quad !n \geq 2^W,
380    /// \\end{cases}
381    /// $$
382    /// where $W$ is `usize::WIDTH`.
383    ///
384    /// $!n = O(n!) = O(\sqrt{n}(n/e)^n)$.
385    ///
386    /// # Worst-case complexity
387    /// Constant time and additional memory.
388    ///
389    /// # Examples
390    /// See [here](super::factorial#checked_subfactorial).
391    #[inline]
392    fn checked_subfactorial(n: u64) -> Option<usize> {
393        SUBFACTORIALS_U64
394            .get(usize::try_from(n).ok()?)
395            .and_then(|&f| usize::try_from(f).ok())
396    }
397}
398
399impl CheckedDoubleFactorial for usize {
400    /// Computes the double factorial of a [`usize`].
401    ///
402    /// If the input is too large, the function returns `None`.
403    ///
404    /// $$
405    /// f(n) = \\begin{cases}
406    ///     \operatorname{Some}(n!!) & \text{if} \\quad n!! < 2^W, \\\\
407    ///     \operatorname{None} & \text{if} \\quad n!! \geq 2^W,
408    /// \\end{cases}
409    /// $$
410    /// where $W$ is `usize::WIDTH`.
411    ///
412    /// $n!! = O(\sqrt{n}(n/e)^{n/2})$.
413    ///
414    /// # Worst-case complexity
415    /// Constant time and additional memory.
416    ///
417    /// # Examples
418    /// See [here](super::factorial#checked_double_factorial).
419    #[inline]
420    fn checked_double_factorial(n: u64) -> Option<usize> {
421        if USIZE_IS_U32 {
422            u32::checked_double_factorial(n).map(usize::wrapping_from)
423        } else {
424            u64::checked_double_factorial(n).map(usize::wrapping_from)
425        }
426    }
427}
428
429macro_rules! impl_factorials_b {
430    ($t:ident) => {
431        impl Factorial for $t {
432            /// Computes the factorial of a number.
433            ///
434            /// If the input is too large, the function panics. For a function that returns `None`
435            /// instead, try [`checked_factorial`](CheckedFactorial::checked_factorial).
436            ///
437            /// $$
438            /// f(n) = n! = 1 \times 2 \times 3 \times \cdots \times n.
439            /// $$
440            ///
441            /// $n! = O(\sqrt{n}(n/e)^n)$.
442            ///
443            /// # Worst-case complexity
444            /// Constant time and additional memory.
445            ///
446            /// # Panics
447            /// Panics if the output is too large to be represented.
448            ///
449            /// # Examples
450            /// See [here](super::factorial#factorial).
451            #[inline]
452            fn factorial(n: u64) -> $t {
453                $t::checked_factorial(n).unwrap()
454            }
455        }
456
457        impl DoubleFactorial for $t {
458            /// Computes the double factorial of a number.
459            ///
460            /// If the input is too large, the function panics. For a function that returns `None`
461            /// instead, try
462            /// [`checked_double_factorial`](CheckedDoubleFactorial::checked_double_factorial).
463            ///
464            /// $$
465            /// f(n) = n!! = n \times (n - 2) \times (n - 4) \times \cdots \times i,
466            /// $$
467            /// where $i$ is 1 if $n$ is odd and $2$ if $n$ is even.
468            ///
469            /// $n!! = O(\sqrt{n}(n/e)^{n/2})$.
470            ///
471            /// # Worst-case complexity
472            /// Constant time and additional memory.
473            ///
474            /// # Panics
475            /// Panics if the output is too large to be represented.
476            ///
477            /// # Examples
478            /// See [here](super::factorial#double_factorial).
479            #[inline]
480            fn double_factorial(n: u64) -> $t {
481                $t::checked_double_factorial(n).unwrap()
482            }
483        }
484
485        impl Multifactorial for $t {
486            /// Computes a multifactorial of a number.
487            ///
488            /// If the input is too large, the function panics. For a function that returns `None`
489            /// instead, try
490            /// [`checked_multifactorial`](CheckedMultifactorial::checked_multifactorial).
491            ///
492            /// $$
493            /// f(n, m) = n!^{(m)} = n \times (n - m) \times (n - 2m) \times \cdots \times i.
494            /// $$
495            /// If $n$ is divisible by $m$, then $i$ is $m$; otherwise, $i$ is the remainder when
496            /// $n$ is divided by $m$.
497            ///
498            /// $n!^{(m)} = O(\sqrt{n}(n/e)^{n/m})$.
499            ///
500            /// # Worst-case complexity
501            /// Constant time and additional memory.
502            ///
503            /// # Panics
504            /// Panics if the output is too large to be represented.
505            ///
506            /// # Examples
507            /// See [here](super::factorial#multifactorial).
508            #[inline]
509            fn multifactorial(n: u64, m: u64) -> $t {
510                $t::checked_multifactorial(n, m).unwrap()
511            }
512        }
513
514        impl CheckedMultifactorial for $t {
515            /// Computes a multifactorial of a number.
516            ///
517            /// If the input is too large, the function returns `None`.
518            ///
519            /// $$
520            /// f(n, m) = \\begin{cases}
521            ///     \operatorname{Some}(n!^{(m)}) & \text{if} \\quad n!^{(m)} < 2^W, \\\\
522            ///     \operatorname{None} & \text{if} \\quad n!^{(m)} \geq 2^W,
523            /// \\end{cases}
524            /// $$
525            /// where $W$ is `Self::WIDTH`.
526            ///
527            /// $n!^{(m)} = O(\sqrt{n}(n/e)^{n/m})$.
528            ///
529            /// # Worst-case complexity
530            /// Constant time and additional memory.
531            ///
532            /// # Examples
533            /// See [here](super::factorial#checked_multifactorial).
534            #[inline]
535            fn checked_multifactorial(n: u64, m: u64) -> Option<$t> {
536                assert_ne!(m, 0);
537                if m == 1 {
538                    $t::checked_factorial(n)
539                } else if m == 2 {
540                    $t::checked_double_factorial(n)
541                } else {
542                    checked_multifactorial_naive(n, m)
543                }
544            }
545        }
546
547        impl Subfactorial for $t {
548            /// Computes the subfactorial of a number.
549            ///
550            /// The subfactorial of $n$ counts the number of derangements of a set of size $n$; a
551            /// derangement is a permutation with no fixed points.
552            ///
553            /// If the input is too large, the function panics. For a function that returns `None`
554            /// instead, try [`checked_subfactorial`](CheckedSubfactorial::checked_subfactorial).
555            ///
556            /// $$
557            /// f(n) = \\ !n = \lfloor n!/e \rfloor.
558            /// $$
559            ///
560            /// $!n = O(n!) = O(\sqrt{n}(n/e)^n)$.
561            ///
562            /// # Worst-case complexity
563            /// Constant time and additional memory.
564            ///
565            /// # Panics
566            /// Panics if the output is too large to be represented.
567            ///
568            /// # Examples
569            /// See [here](super::factorial#subfactorial).
570            #[inline]
571            fn subfactorial(n: u64) -> $t {
572                $t::checked_subfactorial(n).unwrap()
573            }
574        }
575    };
576}
577apply_to_unsigneds!(impl_factorials_b);