1: // Author & Copyright : Peter Luschny
2: // Created: 2010-01-15
3: // License: LGPL version 2.1 or (at your option)
4: // Creative Commons Attribution-ShareAlike 3.0
5:
6: // Differs only in a single function call from Schoenhage::Factorial.
7:
8: #include "schoenhage.h"
9: #include "xmath.h"
10:
11: void Schoenhage::ParallelFactorial(Xint result, ulong n)
12: {
13: lmp::SetUi(result, 1);
14:
15: if (n < 2) { return; }
16:
17: slong iterLen = 0, m = n;
18: ulong lim = n / 2, i;
19: while (m > 0) { m >>= 1; iterLen++; }
20:
21: ulong* primes = 0;
22: ulong piN = Xmath::PrimeSieve(&primes, n);
23: ulong* exponents = lmp::MallocUi(piN);
24: ulong* factors = lmp::MallocUi(piN);
25:
26: exponents[0] = n - Xmath::BitCount(n);
27:
28: for (i = 1; i < piN; i++)
29: {
30: ulong p = primes[i];
31: ulong exp = 1;
32: if (p <= lim)
33: {
34: slong N = n / p;
35: exp = N;
36: while (N > 0)
37: {
38: N /= p;
39: exp += N;
40: }
41: }
42: exponents[i] = exp;
43: }
44:
45: Xint prod; lmp::Init(prod);
46:
47: for (; iterLen >= 0; iterLen--)
48: {
49: ulong count = 0;
50: for (ulong m = 1; m < piN ; m++)
51: {
52: if (((exponents[m] >> iterLen) & 1) == 1)
53: {
54: factors[count++] = primes[m];
55: }
56: }
57:
58: lmp::Pow2(result, result);
59: if (count > 0)
60: {
61: Xmath::ParallelProduct(prod, factors, 0, count);
62: lmp::Mul(result, result, prod);
63: }
64: }
65:
66: lmp::Mul2Exp(result, result, exponents[0]);
67:
68: lmp::FreeUi(factors, piN);
69: lmp::FreeUi(primes, piN);
70: lmp::FreeUi(exponents, piN);
71: lmp::Clear(prod);
72: }