private SievePolynomial GetDefaultPolynomial(BigInteger n) { var m = new IntegerSquareRoot().Sqrt(n); var ainv = new Dictionary <long, long>(); foreach (var p in _factorBase) { ainv.Add(p, 1); } var firstSln = new Dictionary <long, long>(); var secondSln = new Dictionary <long, long>(); for (int i = 0; i < _factorBase.Length; i++) { var p = _factorBase[i]; firstSln[p] = (long)(ainv[p] * (_sqrtN[p] - m) % p); secondSln[p] = (long)(ainv[p] * (-_sqrtN[p] - m) % p); } return(new SievePolynomial() { A = 1, B = m, C = (m * m - n), FirstRoot = firstSln, SecondRoot = secondSln, InvA = ainv }); }
static BigInteger TrialDivision(BigInteger n) { var sqrtN = new IntegerSquareRoot().Sqrt(n); if (n % 2 == 0) { return(2); } for (BigInteger i = 3; i < sqrtN; i += 2) { if (n % i == 0) { return(i); } } return(1); }
private void Init(BigInteger n) { if (_autoInit) { _primeBound = (long)(12 * BigInteger.Log10(n) * BigInteger.Log10(n)); _factorBase = BuildFactorBase(n); _sieveBound = (_factorBase.Length) * 60; _kerSize = 10; } else { _factorBase = BuildFactorBase(n); } _logp = _factorBase.Select(x => Math.Log10(x)).ToArray(); var sqrt = new IntegerSquareRoot(); _thresh = BigInteger.Log10((_sieveBound * sqrt.Sqrt(2 * n)) >> 1) * 0.735; _partial = new Dictionary <BigInteger, int>(); Console.WriteLine("Prime bound:" + _primeBound); Console.WriteLine("Sieve size:" + _sieveBound); Console.WriteLine("Factorbase size:" + _factorBase.Length); }
public BigInteger FindFactor() { var timer = new Stopwatch(); timer.Start(); _polyInfo = _generator.GeneratePolynomial(); Console.WriteLine(_number.Value()); Console.WriteLine("f(x)=" + _polyInfo.Polynomial); Console.WriteLine("Root=" + _polyInfo.Root); var rootFinder = new GcdRootFinder(); var algFbBuilder = new AlgebraicFactorbaseBuilder(_polyInfo.Polynomial, rootFinder, _algebraicPrimeBound); var rationalFbBuilder = new RationalFactorbaseBuilder(_polyInfo.Root, _rationalPrimeBound); var quadraticCharFbBuilder = new QuadraticCharactersBuilder(_polyInfo.Polynomial, rootFinder, _algebraicPrimeBound, _quadraticCharFbSize); var rationalFb = rationalFbBuilder.Build(); var quadraticCharFb = quadraticCharFbBuilder.Build(); var algFb = algFbBuilder.Build(); var sieve = new LogSieve(); Console.WriteLine("\nRational factorbase size: " + rationalFb.Elements.Count); Console.WriteLine("Algebraic factorbase size: " + algFb.Elements.Count); Console.WriteLine("Quadratic characters factorbase size: " + quadraticCharFb.Elements.Count); Console.WriteLine("Init time: " + timer.Elapsed); timer.Reset(); timer.Start(); var pairs = sieve.Sieve( (algFb.Elements.Count + rationalFb.Elements.Count + quadraticCharFb.Elements.Count + _kerDim + 1), new SieveOptions(_sieveSize, -_sieveSize, algFb, rationalFb, _polyInfo.Polynomial, _polyInfo.Root)); Console.WriteLine(); Console.WriteLine(pairs.Count + " relations collected."); Console.WriteLine("Sieve time: " + timer.Elapsed); timer.Reset(); timer.Start(); var matrixBuilder = new MatrixBuilder(); var matrix = matrixBuilder.Build(pairs, rationalFb, algFb, quadraticCharFb, _polyInfo.Root, _polyInfo.Polynomial); var matrixSolver = new GaussianEliminationOverGf2(); //Console.WriteLine("{0}x{1} matrix builded. ",matrix.ColumnsCount,matrix.RowsCount); var solutions = matrixSolver.Solve(matrix); // var solutions =matrix.Solve(); Console.WriteLine(); Console.WriteLine("Linear algebra time: " + timer.Elapsed); Console.WriteLine("{0} solution computed. ", solutions.Count); timer.Reset(); timer.Start(); var polyMath = new PolynomialMath(-1); var df = new PolynomialDerivative().Derivative(_polyInfo.Polynomial); var sqrDf = polyMath.Mul(df, df); var solutionsCheked = -1; foreach (var solution in solutions) { timer.Reset(); timer.Start(); var sqr = new Polynomial(new BigInteger[] { 1 }); BigInteger sqrtNorm = 1; BigInteger x = 1; for (int i = 0; i < solution.Length; i++) { if (solution[i] == 1) { var tmp = new Polynomial(new BigInteger[] { pairs[i].Item1, pairs[i].Item2 }); x *= pairs[i].Item1 + _polyInfo.Root * pairs[i].Item2; sqr = polyMath.Rem(polyMath.Mul(tmp, sqr), _polyInfo.Polynomial); var normCalculator = new FirstDegreeElementsNormCalculator(_polyInfo.Polynomial, pairs[i].Item2); sqrtNorm *= normCalculator.CalculateNorm(pairs[i].Item1); } } x *= sqrDf.Value(_polyInfo.Root); if (x < 0) { throw new Exception(); } sqr = polyMath.Rem(polyMath.Mul(sqrDf, sqr), _polyInfo.Polynomial); var integerSqrt = new IntegerSquareRoot(); var sqrtX = integerSqrt.Sqrt(x); if (sqrtX * sqrtX != x) { if (sqrtX * sqrtX != x) { if (sqrtX * sqrtX != x) { throw new Exception(); } } } var algSqrt = new AlgebraicSqrt(); sqrtNorm = BigInteger.Abs(sqrtNorm); var tmpNorm = sqrtNorm; sqrtNorm = integerSqrt.Sqrt(BigInteger.Abs(sqrtNorm)); timer.Stop(); Console.WriteLine(timer.Elapsed + " Умножение"); if (sqrtNorm * sqrtNorm != tmpNorm) { if (sqrtNorm * sqrtNorm != tmpNorm) { if (sqrtNorm * sqrtNorm != tmpNorm) { throw new Exception(); } } } timer.Reset(); timer.Start(); var sqrt = algSqrt.Sqrt(sqr, _polyInfo.Polynomial, df, sqrtNorm); timer.Stop(); Console.WriteLine(timer.Elapsed + " Квадратный корень"); if (algSqrt.DontExist) { Console.Write("\r{0}/{1} solutions cheked. (BAD SQRT) ", ++solutionsCheked, solutions.Count); continue; } var sqrtY = sqrt.Value(_polyInfo.Root); var check = polyMath.Rem(polyMath.Mul(sqrt, sqrt), _polyInfo.Polynomial); if (check != sqr) { var primes = new EratosthenesSieve().GetPrimes(5, 10000); int i; for (i = 0; i < primes.Length; i++) { if (!algSqrt.IsSqr(sqr, _polyInfo.Polynomial, primes[i])) { break; } } if (i == primes.Length) { throw new Exception(); } Console.Write("\r{0}/{1} solutions cheked. (BAD SQRT) ", ++solutionsCheked, solutions.Count); continue; } if ((sqrtY * sqrtY - sqrtX * sqrtX) % _number.Value() != 0) { throw new Exception(); } var factor = BigInteger.GreatestCommonDivisor(sqrtX - sqrtY, _number.Value()); if (factor > 1 && factor < _number.Value()) { Console.Write("\r{0}/{1} solutions cheked ", ++solutionsCheked, solutions.Count); return(factor); } Console.Write("\r{0}/{1} solutions cheked. (BAD SOLUTION)", ++solutionsCheked, solutions.Count); } Console.Write("\r{0}/{1} solutions cheked. ", solutionsCheked, solutions.Count); return(1); }
public void IntegerSqrt_Test(int number, object expected) { Assert.AreEqual(expected, IntegerSquareRoot.SqrtApproximation(number)); }
private List <SievePolynomial> GeneratePolynomials(BigInteger n) { var result = new List <SievePolynomial>(); var sqrt = new IntegerSquareRoot(); var sizeBound = sqrt.Sqrt(2 * n) / _sieveBound; var primes = new List <long>(); BigInteger a = 1; var aFactorsBound = Math.Exp(BigInteger.Log(sizeBound) / 13); var indexes = new HashSet <int>(); while (a < sizeBound && _polyIndex < _factorBase.Length) { if (_factorBase[_polyIndex] < aFactorsBound) { _polyIndex++; continue; } indexes.Add(_polyIndex); var p = _factorBase[_polyIndex++]; a *= p; primes.Add(p); } var inv = new ModularInverse(); var B = new BigInteger[primes.Count]; var Bainv = new Dictionary <long, Dictionary <int, long> >(); for (int i = 0; i < primes.Count; i++) { var q = primes[i]; var aq = a / q; var gamma = _sqrtN[q] * inv.Inverse(aq, q); if (gamma > q / 2) { gamma = q - gamma; } B[i] = aq * gamma; } var ainv = new Dictionary <long, long>(); BigInteger b = 0; for (int i = 0; i < B.Length; i++) { b += B[i]; } var firstSln = new Dictionary <long, long>(); var secondSln = new Dictionary <long, long>(); for (int i = 0; i < _factorBase.Length; i++) { if (indexes.Contains(i)) { continue; } var p = _factorBase[i]; ainv.Add(p, (long)inv.Inverse(a, p)); Bainv[p] = new Dictionary <int, long>(); for (int j = 0; j < primes.Count; j++) { Bainv[p][j] = (long)(2 * B[j] * ainv[p] % p); } firstSln[p] = (long)(ainv[p] * (_sqrtN[p] - b) % p); secondSln[p] = (long)(ainv[p] * (-_sqrtN[p] - b) % p); } if (primes.Count == 0) { return(null); } result.Add(new SievePolynomial() { A = a, B = b, C = (b * b - n) / a, FirstRoot = firstSln, SecondRoot = secondSln, InvA = ainv, MinFactorA = primes[0], MaxFactorA = primes[primes.Count - 1] }); var polyCount = Math.Pow(2, primes.Count - 1) - 1; for (int i = 1; i <= polyCount; i++) { var v = 1; for (; (i & (0x1 << (v - 1))) == 0; v++) { } var tmp = (long)Math.Ceiling(i / Math.Pow(2, v)); if (tmp % 2 == 0) { b = b + 2 * B[v]; } else { b = b - 2 * B[v]; } firstSln = new Dictionary <long, long>(); secondSln = new Dictionary <long, long>(); for (var k = 0; k < _factorBase.Length; k++) { if (indexes.Contains(k)) { continue; } var p = _factorBase[k]; firstSln[p] = (long)(ainv[p] * (_sqrtN[p] - b) % p); secondSln[p] = (long)(ainv[p] * (-_sqrtN[p] - b) % p); } result.Add(new SievePolynomial() { A = a, B = b, C = (b * b - n) / a, FirstRoot = firstSln, SecondRoot = secondSln, InvA = ainv, MinFactorA = primes[0], MaxFactorA = primes[primes.Count - 1] }); } _polyIndex += 3 - primes.Count; return(result); }