private List <SmoothPair> Sieve(SievePolynomial sievePolynomial, BigInteger n) { var result = new List <SmoothPair>(); var sieveArray = new BigInteger[2 * _sieveBound]; for (int j = 0; j < sieveArray.Length; j++) { var x = j > _sieveBound ? _sieveBound - j : j; var t = sievePolynomial.A * x * x + 2 * sievePolynomial.B * x + sievePolynomial.C; sieveArray[j] = t; } var i = 0; foreach (var p in _factorBase) { //Need skip small primes if (p == 7621) { i++; i--; } if (sievePolynomial.A % p == 0) { continue; } var logp = _logp[i]; var root1 = sievePolynomial.FirstRoot[p]; var root2 = sievePolynomial.SecondRoot[p]; if (root1 < 0) { root1 += p; } if (root2 < 0) { root2 += p; } long x = 0; while (x < _sieveBound) { if (x + root1 < _sieveBound) { if (sieveArray[x + root1] % p != 0) { throw new Exception(); } while (sieveArray[x + root1] % p == 0) { sieveArray[x + root1] /= p; } } if (x + root2 < _sieveBound && root1 != root2) { if (sieveArray[x + root2] % p != 0) { throw new Exception(); } while (sieveArray[x + root2] % p == 0) { sieveArray[x + root2] /= p; } } if (x != 0) { if (sieveArray[x - root1 + _sieveBound] % p != 0 || sieveArray[x - root2 + _sieveBound] % p != 0) { throw new Exception(); } while (sieveArray[x - root1 + _sieveBound] % p == 0) { sieveArray[x - root1 + _sieveBound] /= p; } while (sieveArray[x - root2 + _sieveBound] % p == 0 && root1 != root2) { sieveArray[x - root2 + _sieveBound] /= p; } } x += p; } i += 1; } i = 0; foreach (var value in sieveArray) { if (value == 1 || value == -1) { var x = i > _sieveBound ? _sieveBound - i : i; var vector = new Dictionary <long, int>(); var t = sievePolynomial.A * x + sievePolynomial.B; var polyValue = t * t - n; if (polyValue < 0) { vector.Add(-1, 1); polyValue = -polyValue; } else { vector.Add(-1, 0); } foreach (var p in _factorBase) { while (polyValue % p == 0) { if (vector.ContainsKey(p)) { vector[p]++; } else { vector.Add(p, 1); } polyValue = (polyValue / p); } } if (polyValue == 1) { var xVal = sievePolynomial.A * x + sievePolynomial.B; result.Add(new SmoothPair(xVal, vector)); } } i++; } return(result); }
private List <SmoothPair> LogSieve(SievePolynomial sievePolynomial, BigInteger n) { var result = new List <SmoothPair>(); double[] sieveArray = new double[2 * _sieveBound]; var i = 0; for (; i < _factorBase.Length; i++) { var p = _factorBase[i]; if (sievePolynomial.A % p == 0) { continue; } var logp = _logp[i]; var root1 = sievePolynomial.FirstRoot[p]; var root2 = sievePolynomial.SecondRoot[p]; if (root1 < 0) { root1 += p; } if (root2 < 0) { root2 += p; } long x = 0; while (x < _sieveBound) { if (x + root1 < _sieveBound) { sieveArray[x + root1] += logp; } if (x + root2 < _sieveBound) { sieveArray[x + root2] += logp; } if (x != 0) { sieveArray[x - root1 + _sieveBound] += logp; sieveArray[x - root2 + _sieveBound] += logp; } x += p; } } i = 0; foreach (var value in sieveArray) { if (value > _thresh) { BigInteger x = i > _sieveBound ? _sieveBound - i : i; var vector = new Dictionary <long, int>(); var t = sievePolynomial.A * x + sievePolynomial.B; var polyValue = t * t - n; if (polyValue < 0) { vector.Add(-1, 1); polyValue = -polyValue; } else { vector.Add(-1, 0); } foreach (var p in _factorBase) { while (polyValue % p == 0) { if (vector.ContainsKey(p)) { vector[p]++; } else { vector.Add(p, 1); } polyValue = (polyValue / p); } } var xVal = sievePolynomial.A * x + sievePolynomial.B; if (polyValue == 1) { result.Add(new SmoothPair(xVal, vector)); } } i++; } return(result); }