Ejemplo n.º 1
0
        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));
        }