public static Tuple <BigInteger, BigInteger> AlgebraicSquareRoot(IPolynomial f, BigInteger m, int degree, IPolynomial dd, BigInteger p) { IPolynomial startPolynomial = Polynomial.Field.Modulus(dd, p); IPolynomial startInversePolynomial = ModularInverse(startPolynomial, p); IPolynomial resultPoly1 = FiniteFieldArithmetic.SquareRoot(startPolynomial, f, p, degree, m); IPolynomial resultPoly2 = ModularInverse(resultPoly1, p); BigInteger result1 = resultPoly1.Evaluate(m).Mod(p); BigInteger result2 = resultPoly2.Evaluate(m).Mod(p); IPolynomial resultSquared1 = Polynomial.Field.ModMod(Polynomial.Square(resultPoly1), f, p); IPolynomial resultSquared2 = Polynomial.Field.ModMod(Polynomial.Square(resultPoly2), f, p); bool bothResultsAgree = (resultSquared1.CompareTo(resultSquared2) == 0); if (bothResultsAgree) { bool resultSquaredEqualsInput1 = (startPolynomial.CompareTo(resultSquared1) == 0); bool resultSquaredEqualsInput2 = (startInversePolynomial.CompareTo(resultSquared1) == 0); if (resultSquaredEqualsInput1) { return(new Tuple <BigInteger, BigInteger>(result1, result2)); } else if (resultSquaredEqualsInput2) { return(new Tuple <BigInteger, BigInteger>(result2, result1)); } } return(new Tuple <BigInteger, BigInteger>(BigInteger.Zero, BigInteger.Zero)); }
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)); }