public void MulTest() { foreach (var prime in _primes) { var firstPoly = GeneratePoly(20, prime); var secondPoly = GeneratePoly(30, prime); while (firstPoly.Deg == -1) { firstPoly = GeneratePoly(20, prime); } while (secondPoly.Deg == -1) { secondPoly = GeneratePoly(30, prime); } var polyMath = new PolynomialMath(prime); Polynomial res; res = polyMath.Mul(firstPoly, secondPoly); var checkPoly = polyMath.Div(res, secondPoly); for (int i = 0; i <= firstPoly.Deg; i++) { if ((firstPoly[i] + prime * prime) % prime != (checkPoly[i] + prime * prime) % prime) { throw new Exception(); } } } }
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 Polynomial Sqrt(Polynomial sqr, Polynomial mod, Polynomial modDerivative, BigInteger sqrtNorm) { BigInteger max = 0; for (int i = 0; i <= sqr.Deg; i++) { if (BigInteger.Abs(sqr[i]) > max) { max = BigInteger.Abs(sqr[i]); } } var nextPrime = new NextPrime(); var bound = max * 10; var primes = new List <BigInteger>(); var sieve = new EratosthenesSieve(); var primesToCheck = sieve.GetPrimes(100000000, 110000000); BigInteger bigMod = 1; foreach (var primeToCheck in primesToCheck) { var irreducibilityTest = new IrreducibilityTest(); if (!irreducibilityTest.IsIrreducible(mod, primeToCheck)) { continue; } bigMod *= primeToCheck; primes.Add(primeToCheck); if (bigMod > bound) { break; } } var prime = 2 * primes[primes.Count - 1]; while (bigMod < bound) { prime = nextPrime.GetNext(prime); var irreducibilityTest = new IrreducibilityTest(); while (!irreducibilityTest.IsIrreducible(mod, prime)) { prime = nextPrime.GetNext(prime + 1); } bigMod *= prime; primes.Add(prime); } var sqrts = new List <Polynomial>(); foreach (var fieldChar in primes) { var polyMath = new PolynomialMath(fieldChar); var four = new Polynomial(new BigInteger[] { 4 }); Polynomial b; var isSqr = false; for (int i = 0; true; i++) { b = new Polynomial(new BigInteger[] { i }); var tmp = polyMath.ModPow(polyMath.Sub(polyMath.Mul(b, b), polyMath.Mul(four, sqr)), (BigInteger.Pow(fieldChar, mod.Deg) - 1) / 2, mod); isSqr = (tmp[0] == 1 || tmp[0] == -(fieldChar - 1)) && (tmp.Deg == 0); if (!isSqr) { break; } } var gfMath = new FiniteFieldMath(mod, fieldChar); var modPoly = new PolynomialOverFiniteField(new Polynomial[] { sqr, b, new Polynomial(new BigInteger[] { 1 }) }); var y = new PolynomialOverFiniteField(new Polynomial[] { new Polynomial(new BigInteger[] { 0 }), new Polynomial(new BigInteger[] { 1 }) }); var sqrt = gfMath.ModPow(y, (BigInteger.Pow(fieldChar, mod.Deg) + 1) / 2, modPoly)[0]; var sqrtNormMod = sqrtNorm * polyMath.ModPow(modDerivative, (BigInteger.Pow(fieldChar, mod.Deg) - 1) / (fieldChar - 1), mod)[0]; var norm = polyMath.ModPow(sqrt, (BigInteger.Pow(fieldChar, mod.Deg) - 1) / (fieldChar - 1), mod)[0]; sqrtNormMod %= fieldChar; if (sqrtNormMod < 0) { sqrtNormMod = sqrtNormMod + fieldChar; } if (norm < 0) { norm = norm + fieldChar; } if (norm != sqrtNormMod) { sqrt = polyMath.ConstMul(-1, sqrt); } sqrts.Add(sqrt); } BigInteger[] result = new BigInteger[mod.Deg]; var crt = new GarnerCrt(); for (int i = 0; i < mod.Deg; i++) { var coefficients = new List <BigInteger>(); for (int j = 0; j < primes.Count; j++) { coefficients.Add(sqrts[j][i]); } result[i] = crt.Calculate(coefficients, primes); } var resultPoly = new Polynomial(result); for (int i = 0; i <= resultPoly.Deg; i++) { var coeff = BigInteger.Abs(resultPoly[i]); if (coeff > max) { if (resultPoly[i] < 0) { resultPoly[i] += bigMod; } else { resultPoly[i] -= bigMod; } } } return(resultPoly); }