public Tuple <BigInteger, BigInteger> CalculateAlgebraicSide(CancellationToken cancelToken) { bool solutionFound = false; RootsOfS.AddRange(RelationsSet.Select(rel => new Tuple <BigInteger, BigInteger>(rel.A, rel.B))); PolynomialRing = new List <IPolynomial>(); foreach (Relation rel in RelationsSet) { // poly(x) = A + (B * x) IPolynomial newPoly = new Polynomial( new Term[] { new Term(rel.B, 1), new Term(rel.A, 0) } ); PolynomialRing.Add(newPoly); } if (cancelToken.IsCancellationRequested) { return(new Tuple <BigInteger, BigInteger>(1, 1)); } BigInteger m = polyBase; IPolynomial f = (Polynomial)monicPoly.Clone(); int degree = f.Degree; IPolynomial fd = Polynomial.GetDerivativePolynomial(f); IPolynomial d3 = Polynomial.Product(PolynomialRing); IPolynomial derivativeSquared = Polynomial.Square(fd); IPolynomial d2 = Polynomial.Multiply(d3, derivativeSquared); IPolynomial dd = Polynomial.Field.Modulus(d2, f); // Set the result to S S = dd; SRingSquare = dd; TotalS = d2; algebraicNormCollection = RelationsSet.Select(rel => rel.AlgebraicNorm); AlgebraicProduct = d2.Evaluate(m); AlgebraicSquare = dd.Evaluate(m); AlgebraicProductModF = dd.Evaluate(m).Mod(N); AlgebraicSquareResidue = AlgebraicSquare.Mod(N); IsAlgebraicIrreducible = IsPrimitive(algebraicNormCollection); // Irreducible check IsAlgebraicSquare = AlgebraicSquareResidue.IsSquare(); List <BigInteger> primes = new List <BigInteger>(); List <Tuple <BigInteger, BigInteger> > resultTuples = new List <Tuple <BigInteger, BigInteger> >(); BigInteger primeProduct = 1; BigInteger lastP = N / N.ToString().Length; //((N * 3) + 1).NthRoot(3); //gnfs.QFB.Select(fp => fp.P).Max(); while (!solutionFound) { if (primes.Count > 0 && resultTuples.Count > 0) { primes.Remove(primes.First()); resultTuples.Remove(resultTuples.First()); } do { if (cancelToken.IsCancellationRequested) { return(new Tuple <BigInteger, BigInteger>(1, 1)); } lastP = PrimeFactory.GetNextPrime(lastP + 1); Tuple <BigInteger, BigInteger> lastResult = AlgebraicSquareRoot(f, m, degree, dd, lastP); if (lastResult.Item1 != 0) { primes.Add(lastP); resultTuples.Add(lastResult); } }while (primes.Count < degree); if (primes.Count > degree) { primes.Remove(primes.First()); resultTuples.Remove(resultTuples.First()); } primeProduct = (resultTuples.Select(tup => BigInteger.Min(tup.Item1, tup.Item2)).Product()); if (primeProduct < N) { continue; } AlgebraicPrimes = primes; if (cancelToken.IsCancellationRequested) { return(new Tuple <BigInteger, BigInteger>(1, 1));; } IEnumerable <IEnumerable <BigInteger> > permutations = Combinatorics.CartesianProduct(resultTuples.Select(tup => new List <BigInteger>() { tup.Item1, tup.Item2 })); BigInteger rationalSquareRoot = RationalSquareRootResidue; BigInteger algebraicSquareRoot = 1; foreach (List <BigInteger> X in permutations) { if (cancelToken.IsCancellationRequested) { return(new Tuple <BigInteger, BigInteger>(1, 1));; } algebraicSquareRoot = FiniteFieldArithmetic.ChineseRemainder(N, X, primes); BigInteger min = BigInteger.Min(rationalSquareRoot, algebraicSquareRoot); BigInteger max = BigInteger.Max(rationalSquareRoot, algebraicSquareRoot); BigInteger A = max + min; BigInteger B = max - min; BigInteger U = GCD.FindGCD(N, A); BigInteger V = GCD.FindGCD(N, B); if (U > 1 && U != N) { BigInteger rem = 1; BigInteger other = BigInteger.DivRem(N, U, out rem); if (rem == 0) { solutionFound = true; V = other; AlgebraicResults = X; AlgebraicSquareRootResidue = algebraicSquareRoot; return(new Tuple <BigInteger, BigInteger>(U, V)); } } if (V > 1 && V != N) { BigInteger rem = 1; BigInteger other = BigInteger.DivRem(N, V, out rem); if (rem == 0) { solutionFound = true; U = other; AlgebraicResults = X; AlgebraicSquareRootResidue = algebraicSquareRoot; return(new Tuple <BigInteger, BigInteger>(U, V)); } } } if (!solutionFound) { gnfs.LogFunction($"No solution found amongst the algebraic square roots {{ {string.Join(", ", resultTuples.Select(tup => $"({ tup.Item1}, { tup.Item2})"))} }} mod primes {{ {string.Join(", ", primes.Select(p => p.ToString()))} }}"); } } return(new Tuple <BigInteger, BigInteger>(1, 1)); }
public override string ToString() { StringBuilder result = new StringBuilder(); result.AppendLine($"IsRationalIrreducible ? {IsRationalIrreducible}"); result.AppendLine($"IsAlgebraicIrreducible ? {IsAlgebraicIrreducible}"); result.AppendLine("Square finder, Rational:"); result.AppendLine($"γ² = √( Sᵣ(m) * ƒ'(m)² )"); result.AppendLine($"γ² = √( {RationalProduct} * {PolynomialDerivativeSquared} )"); result.AppendLine($"γ² = √( {RationalSquare} )"); result.AppendLine($"γ = {RationalSquareRoot} mod N"); result.AppendLine($"γ = {RationalSquareRootResidue}"); // δ mod N result.AppendLine(); result.AppendLine(); result.AppendLine("Square finder, Algebraic:"); result.AppendLine($" Sₐ(m) * ƒ'(m) = {AlgebraicProduct} * {PolynomialDerivative}"); result.AppendLine($" Sₐ(m) * ƒ'(m) = {AlgebraicSquare}"); result.AppendLine($"χ = Sₐ(m) * ƒ'(m) mod N = {AlgebraicSquareRootResidue}"); result.AppendLine($"γ = {RationalSquareRootResidue}"); result.AppendLine($"χ = {AlgebraicSquareRootResidue}"); result.AppendLine($"IsRationalSquare ? {IsRationalSquare}"); result.AppendLine($"IsAlgebraicSquare ? {IsAlgebraicSquare}"); BigInteger min = BigInteger.Min(RationalSquareRoot, AlgebraicSquareRootResidue); BigInteger max = BigInteger.Max(RationalSquareRoot, AlgebraicSquareRootResidue); BigInteger add = max + min; BigInteger sub = max - min; BigInteger gcdAdd = GCD.FindGCD(N, add); BigInteger gcdSub = GCD.FindGCD(N, sub); BigInteger answer = BigInteger.Max(gcdAdd, gcdSub); result.AppendLine(); result.AppendLine($"GCD(N, γ+χ) = {gcdAdd}"); result.AppendLine($"GCD(N, γ-χ) = {gcdSub}"); result.AppendLine(); result.AppendLine($"Solution? {(answer != 1).ToString().ToUpper()}"); if (answer != 1) { result.AppendLine(); result.AppendLine(); result.AppendLine("*********************"); result.AppendLine(); result.AppendLine($" SOLUTION = {answer} "); result.AppendLine(); result.AppendLine("*********************"); result.AppendLine(); result.AppendLine(); } result.AppendLine(); return(result.ToString()); }
private static bool IsPrimitive(IEnumerable <BigInteger> coefficients) { return(GCD.FindGCD(coefficients) == 1); }