public XInt Factorial(int n) { if (n < 0) { throw new ArithmeticException( this.Name + ": " + nameof(n) + " >= 0 required, but was " + n); } this.oddFactNdiv4 = this.oddFactNdiv2 = XInt.One; return(this.OddFactorial(n) << (n - XMath.BitCount(n))); }
public XInt Factorial(int n) { if (n < 20) { return(XMath.Factorial(n)); } this.sieve = new PrimeSieve(n); var pLen = (int)(2.0 * (XMath.FloorSqrt(n) + (double)n / (XMath.Log2(n) - 1))); this.primeList = new int[pLen]; var exp2 = n - XMath.BitCount(n); return(this.RecFactorial(n) << exp2); }
public XInt Factorial(int n) { if (n < 20) { return(XMath.Factorial(n)); } var sieve = new PrimeSieve(n); var task2 = Task.Factory.StartNew <XInt>(() => { this.results2 = new IAsyncResult[XMath.FloorLog2(n)]; this.swingDelegate2 = Swing2; this.taskCounter2 = 0; var N = n; // -- It is more efficient to add the big swings // -- first and the small ones later! while (N >= Smallswing) { this.results2[this.taskCounter2++] = this.swingDelegate2.BeginInvoke(sieve, N, null, null); N >>= 1; } return(this.RecFactorial2(n)); }); this.results3 = new IAsyncResult[XMath.FloorLog2(n)]; this.swingDelegate3 = Swing3; this.taskCounter3 = 0; var m = n; // -- It is more efficient to add the big swings // -- first and the small ones later! while (m >= Smallswing) { this.results3[this.taskCounter3++] = this.swingDelegate3.BeginInvoke(sieve, m, null, null); m >>= 1; } var task3Result = this.RecFactorial3(n); return((task2.Result * task3Result) << (n - XMath.BitCount(n))); }
private static XInt Swing3(PrimeSieve sieve, int n) { var primorial = Task.Factory.StartNew <XInt>(() => { var start = sieve.NextPrime(n / 2); start = sieve.NextPrime(start); return(sieve.GetPrimorial(start, n, 2)); }); var count = 0; var rootN = XMath.FloorSqrt(n); var startPrime = sieve.NextPrime(rootN); startPrime = sieve.NextPrime(startPrime); var aPrimes = sieve.GetPrimeCollectionEveryOther(5, rootN); var bPrimes = sieve.GetPrimeCollectionEveryOther(startPrime, n / 3); var primeList = new int[aPrimes.NumberOfPrimes + bPrimes.NumberOfPrimes]; foreach (var prime in aPrimes) { int q = n, p = 1; while ((q /= prime) > 0) { if ((q & 1) == 1) { p *= prime; } } if (p > 1) { primeList[count++] = p; } } foreach (var prime in bPrimes.Where(prime => ((n / prime) & 1) == 1)) { primeList[count++] = prime; } var primeProduct = XMath.Product(primeList, 0, count); return(primeProduct * primorial.Result); }
public XInt Factorial(int n) { if (n < 20) { return(XMath.Factorial(n)); } var lgN = XMath.FloorLog2(n); var piN = 2 + (15 * n) / (8 * (lgN - 1)); this.primeList = new int[piN]; this.multiList = new int[piN]; var len = this.PrimeFactors(n); var exp2 = n - XMath.BitCount(n); return(this.NestedSquare(len) << exp2); }
XInt Swing(int n) { if (n < 33) { return(SmallOddSwing[n]); } var primorial = Task.Factory.StartNew <XInt>(() => this.sieve.GetPrimorial(n / 2 + 1, n)); var count = 0; var rootN = XMath.FloorSqrt(n); var aPrimes = this.sieve.GetPrimeCollection(3, rootN); var bPrimes = this.sieve.GetPrimeCollection(rootN + 1, n / 3); var piN = aPrimes.NumberOfPrimes + bPrimes.NumberOfPrimes; var primeList = new int[piN]; foreach (var prime in aPrimes) { int q = n, p = 1; while ((q /= prime) > 0) { if ((q & 1) == 1) { p *= prime; } } if (p > 1) { primeList[count++] = p; } } foreach (var prime in bPrimes.Where(prime => ((n / prime) & 1) == 1)) { primeList[count++] = prime; } var primeProduct = XMath.Product(primeList, 0, count); return(primeProduct * primorial.Result); }
public XInt Factorial(int n) { if (n < 20) { return(XMath.Factorial(n)); } this.sieve = new PrimeSieve(n); var log2N = XMath.FloorLog2(n); var source = new int[log2N]; int h = 0, shift = 0, length = 0; // -- It is more efficient to add the big intervals // -- first and the small ones later! Is it? while (h != n) { shift += h; h = n >> log2N--; if (h > 2) { source[length++] = h; } } var results = new XInt[length]; Parallel.For(0, length, currentIndex => results[currentIndex] = this.Swing(source[currentIndex]) ); XInt p = XInt.One, r = XInt.One, rl = XInt.One; for (var i = 0; i < length; i++) { var t = rl * results[i]; p = p * t; rl = r; r = r * p; } return(r << shift); }
private XInt Swing(int n) { if (n < 33) { return(SmallOddSwing[n]); } int count = 0, rootN = XMath.FloorSqrt(n); var aPrimes = this.sieve.GetPrimeCollection(3, rootN); var bPrimes = this.sieve.GetPrimeCollection(rootN + 1, n / 3); foreach (var prime in aPrimes) { int q = n, p = 1; while ((q /= prime) > 0) { if ((q & 1) == 1) { p *= prime; } } if (p > 1) { this.primeList[count++] = p; } } foreach (var prime in bPrimes.Where(prime => ((n / prime) & 1) == 1)) { this.primeList[count++] = prime; } var primorial = this.sieve.GetPrimorial(n / 2 + 1, n); return(primorial * XMath.Product(this.primeList, 0, count)); }
private XInt NestedSquare(int len) { if (len == 0) { return(XInt.One); } var i = 0; var mult = this.multiList[0]; while (mult > 1) { if ((mult & 1) == 1) // is mult odd ? { this.primeList[len++] = this.primeList[i]; } this.multiList[i++] = mult >> 1; mult = this.multiList[i]; } return(XMath.Product(this.primeList, i, len - i) * XInt.Pow(this.NestedSquare(i), 2)); }
public XInt Factorial(int n) { if (n < 20) { return(XMath.Factorial(n)); } var rootN = XMath.FloorSqrt(n); var log2N = XMath.FloorLog2(n); var section = new XInt[log2N + 1]; for (var i = 0; i < section.Length; i++) { section[i] = XInt.One; } var sieve = new PrimeSieve(n); var primes = sieve.GetPrimeCollection(3, rootN); foreach (var prime in primes) { int k = 0, m = 0, q = n; do { m += q /= prime; } while (q >= 1); while (m > 0) { if ((m & 1) == 1) { section[k] *= prime; } m = m / 2; k++; } } var j = 2; var low = n; while (low != rootN) { var high = low; low = n / j++; if (low < rootN) { low = rootN; } var primorial = sieve.GetPrimorial(low + 1, high); if (primorial != XInt.One) { int k = 0, m = j - 2; while (m > 0) { if ((m & 1) == 1) { section[k] *= primorial; } m = m / 2; k++; } } } var factorial = section[log2N]; for (var i = log2N - 1; i >= 0; --i) { factorial = XInt.Pow(factorial, 2) * section[i]; } var exp2N = n - XMath.BitCount(n); return(factorial << exp2N); }