Beispiel #1
0
        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);
        }
Beispiel #2
0
        public BigInteger Calculate(Curve curve, ulong b1, ulong b2, ulong b3)
        {
            var        arithmetic   = new MontgomeryArithmetic();
            var        sieve        = new EratosthenesSieve();
            var        primeManager = new PrimeManager();
            var        point        = curve.Point;
            ulong      prime        = 2;
            var        mod          = curve.Mod;
            BigInteger product      = 1;

            while (prime < b1)
            {
                point   = arithmetic.Double(point, curve);
                prime   = prime * 2;
                product = (point.Z * product) % mod;
            }


            var gcd = BigInteger.GreatestCommonDivisor(product, mod);

            if (gcd > 1)
            {
                return(gcd);
            }



            ulong[] primes;
            ulong   upPrimeLimit  = 1000000;
            ulong   lowPrimeLimit = 3;
            ulong   sievestep     = 10000000;

            if (b1 < upPrimeLimit)
            {
                upPrimeLimit = b1;
            }
            ulong partCount = b1 / sievestep;



            for (ulong j = 0; j <= partCount; j++)
            {
                primes = sieve.GetPrimes(lowPrimeLimit, upPrimeLimit);
                for (int i = 0; i < primes.Length; i++)
                {
                    var p = primes[i];
                    prime = p;
                    while (prime < b1)
                    {
                        point   = arithmetic.MontgomeryMul(point, p, curve);
                        prime   = prime * p;
                        product = (point.Z * product) % mod;
                    }
                    gcd = BigInteger.GreatestCommonDivisor(product, mod);
                    if (gcd > 1)
                    {
                        return(gcd);
                    }
                }
                lowPrimeLimit = upPrimeLimit;
                upPrimeLimit += sievestep;
            }


            if (b2 % 2 == 0)
            {
                b2--;
            }


            ulong precomputedDataSize = 1000;
            var   precomputedData     = new ProjectivePoint[precomputedDataSize];

            precomputedData[0] = arithmetic.Double(point, curve);
            precomputedData[1] = arithmetic.Double(precomputedData[0], curve);
            for (ulong i = 2; i < precomputedDataSize; i++)
            {
                precomputedData[i] = arithmetic.Add(precomputedData[i - 1], precomputedData[0], precomputedData[i - 2], curve);
            }

            if (b2 <= 2 * precomputedDataSize)
            {
                b2 = precomputedDataSize + 2;
            }

            product = 1;
            var R = arithmetic.MontgomeryMul(point, b2, curve);
            var T = arithmetic.MontgomeryMul(point, b2 - 2 * precomputedDataSize, curve);

            primeManager.Init(b2 + 1);
            for (ulong i = b2; i < b3; i = i + 2 * precomputedDataSize)
            {
                for (ulong j = 0; j < precomputedDataSize; j++)
                {
                    prime = primeManager.NextPrime();
                    var delta = (prime - i) / 2;
                    if (delta >= (ulong)precomputedData.Length)
                    {
                        break;
                    }
                    product = (product * (R.X * precomputedData[delta - 1].Z - R.Z * precomputedData[delta
                                                                                                     - 1].X)) % curve.Mod;
                }



                gcd = BigInteger.GreatestCommonDivisor(curve.Mod, product);
                if (gcd > 1)
                {
                    return(gcd);
                }
                var temp = T;
                T = R;
                R = arithmetic.Add(R, precomputedData[precomputedDataSize - 1], temp, curve);
            }
            return(1);
        }