Пример #1
0
        public BigInteger gcd(BigInteger val)
        {
            BigInteger val1 = this.abs();
            BigInteger val2 = val.abs();

            // To avoid a possible division by zero
            if (val1.signum() == 0)
            {
                return(val2);
            }
            else if (val2.signum() == 0)
            {
                return(val1);
            }

            // Optimization for small operands
            // (op2.bitLength() < 64) and (op1.bitLength() < 64)
            if (((val1.numberLength == 1) || ((val1.numberLength == 2) && (val1.digits[1] > 0))) &&
                (val2.numberLength == 1 || (val2.numberLength == 2 && val2.digits[1] > 0)))
            {
                return(BigInteger.valueOf(Division.gcdBinary(val1.longValue(), val2
                                                             .longValue())));
            }

            return(Division.gcdBinary(val1.copy(), val2.copy()));
        }
Пример #2
0
        internal static BigInteger pow2ModPow(BigInteger _base, BigInteger exponent, int j)
        {
            // PRE: (base > 0), (exponent > 0) and (j > 0)
            BigInteger res         = BigInteger.ONE;
            BigInteger e           = exponent.copy();
            BigInteger baseMod2toN = _base.copy();
            BigInteger res2;

            /*
             * If 'base' is odd then it's coprime with 2^j and phi(2^j) = 2^(j-1);
             * so we can reduce reduce the exponent (mod 2^(j-1)).
             */
            if (_base.testBit(0))
            {
                inplaceModPow2(e, j - 1);
            }
            inplaceModPow2(baseMod2toN, j);

            for (int i = e.bitLength() - 1; i >= 0; i--)
            {
                res2 = res.copy();
                inplaceModPow2(res2, j);
                res = res.multiply(res2);
                if (BitLevel.testBit(e, i))
                {
                    res = res.multiply(baseMod2toN);
                    inplaceModPow2(res, j);
                }
            }
            inplaceModPow2(res, j);
            return(res);
        }
Пример #3
0
        internal static BigInteger nextProbablePrime(BigInteger n)
        {
            // PRE: n >= 0
            int i, j;
            int certainty;
            int gapSize = 1024; // for searching of the next probable prime number
            int[] modules = new int[primes.Length];
            bool[] isDivisible = new bool[gapSize];
            BigInteger startPoint;
            BigInteger probPrime;
            // If n < "last prime of table" searches next prime in the table
            if ((n.numberLength == 1) && (n.digits[0] >= 0)
                && (n.digits[0] < primes[primes.Length - 1])) {
                for (i = 0; n.digits[0] >= primes[i]; i++) {
                    ;
                }
                return BIprimes[i];
            }
            /*
             * Creates a "N" enough big to hold the next probable prime Note that: N <
             * "next prime" < 2*N
             */
            startPoint = new BigInteger(1, n.numberLength,
                                        new int[n.numberLength + 1]);
            Array.Copy(n.digits, startPoint.digits, n.numberLength);
            // To fix N to the "next odd number"
            if (n.testBit(0)) {
                Elementary.inplaceAdd(startPoint, 2);
            } else {
                startPoint.digits[0] |= 1;
            }
            // To set the improved certainly of Miller-Rabin
            j = startPoint.bitLength();
            for (certainty = 2; j < BITS[certainty]; certainty++) {
                ;
            }
            // To calculate modules: N mod p1, N mod p2, ... for first primes.
            for (i = 0; i < primes.Length; i++) {
                modules[i] = Division.remainder(startPoint, primes[i]) - gapSize;
            }
            while (true) {
                // At this point, all numbers in the gap are initialized as
                // probably primes
                Array.Clear(isDivisible, 0, isDivisible.Length);
                // To discard multiples of first primes
                for (i = 0; i < primes.Length; i++) {
                    modules[i] = (modules[i] + gapSize) % primes[i];
                    j = (modules[i] == 0) ? 0 : (primes[i] - modules[i]);
                    for (; j < gapSize; j += primes[i]) {
                        isDivisible[j] = true;
                    }
                }
                // To execute Miller-Rabin for non-divisible numbers by all first
                // primes
                for (j = 0; j < gapSize; j++) {
                    if (!isDivisible[j]) {
                        probPrime = startPoint.copy();
                        Elementary.inplaceAdd(probPrime, j);

                        if (millerRabin(probPrime, certainty)) {
                            return probPrime;
                        }
                    }
                }
                Elementary.inplaceAdd(startPoint, gapSize);
            }
        }
Пример #4
0
        internal static BigInteger nextProbablePrime(BigInteger n)
        {
            // PRE: n >= 0
            int i, j;
            int certainty;
            int gapSize = 1024; // for searching of the next probable prime number

            int[]      modules     = new int[primes.Length];
            bool[]     isDivisible = new bool[gapSize];
            BigInteger startPoint;
            BigInteger probPrime;

            // If n < "last prime of table" searches next prime in the table
            if ((n.numberLength == 1) && (n.digits[0] >= 0) &&
                (n.digits[0] < primes[primes.Length - 1]))
            {
                for (i = 0; n.digits[0] >= primes[i]; i++)
                {
                    ;
                }
                return(BIprimes[i]);
            }

            /*
             * Creates a "N" enough big to hold the next probable prime Note that: N <
             * "next prime" < 2*N
             */
            startPoint = new BigInteger(1, n.numberLength,
                                        new int[n.numberLength + 1]);
            Array.Copy(n.digits, startPoint.digits, n.numberLength);
            // To fix N to the "next odd number"
            if (n.testBit(0))
            {
                Elementary.inplaceAdd(startPoint, 2);
            }
            else
            {
                startPoint.digits[0] |= 1;
            }
            // To set the improved certainly of Miller-Rabin
            j = startPoint.bitLength();
            for (certainty = 2; j < BITS[certainty]; certainty++)
            {
                ;
            }
            // To calculate modules: N mod p1, N mod p2, ... for first primes.
            for (i = 0; i < primes.Length; i++)
            {
                modules[i] = Division.remainder(startPoint, primes[i]) - gapSize;
            }
            while (true)
            {
                // At this point, all numbers in the gap are initialized as
                // probably primes
                Array.Clear(isDivisible, 0, isDivisible.Length);
                // To discard multiples of first primes
                for (i = 0; i < primes.Length; i++)
                {
                    modules[i] = (modules[i] + gapSize) % primes[i];
                    j          = (modules[i] == 0) ? 0 : (primes[i] - modules[i]);
                    for (; j < gapSize; j += primes[i])
                    {
                        isDivisible[j] = true;
                    }
                }
                // To execute Miller-Rabin for non-divisible numbers by all first
                // primes
                for (j = 0; j < gapSize; j++)
                {
                    if (!isDivisible[j])
                    {
                        probPrime = startPoint.copy();
                        Elementary.inplaceAdd(probPrime, j);

                        if (millerRabin(probPrime, certainty))
                        {
                            return(probPrime);
                        }
                    }
                }
                Elementary.inplaceAdd(startPoint, gapSize);
            }
        }
Пример #5
0
        internal static BigInteger pow2ModPow(BigInteger _base, BigInteger exponent, int j)
        {
            // PRE: (base > 0), (exponent > 0) and (j > 0)
            BigInteger res = BigInteger.ONE;
            BigInteger e = exponent.copy();
            BigInteger baseMod2toN = _base.copy();
            BigInteger res2;
            /*
             * If 'base' is odd then it's coprime with 2^j and phi(2^j) = 2^(j-1);
             * so we can reduce reduce the exponent (mod 2^(j-1)).
             */
            if (_base.testBit(0)) {
                inplaceModPow2(e, j - 1);
            }
            inplaceModPow2(baseMod2toN, j);

            for (int i = e.bitLength() - 1; i >= 0; i--) {
                res2 = res.copy();
                inplaceModPow2(res2, j);
                res = res.multiply(res2);
                if (BitLevel.testBit(e, i)) {
                    res = res.multiply(baseMod2toN);
                    inplaceModPow2(res, j);
                }
            }
            inplaceModPow2(res, j);
            return res;
        }
Пример #6
0
        internal static BigInteger modInverseMontgomery(BigInteger a, BigInteger p)
        {
            if (a.sign == 0){
                // ZERO hasn't inverse
                throw new ArithmeticException("BigInteger not invertible");
            }

            if (!p.testBit(0)){
                // montgomery inverse require even modulo
                return modInverseLorencz(a, p);
            }

            int m = p.numberLength * 32;
            // PRE: a \in [1, p - 1]
            BigInteger u, v, r, s;
            u = p.copy();  // make copy to use inplace method
            v = a.copy();
            int max = Math.Max(v.numberLength, u.numberLength);
            r = new BigInteger(1, 1, new int[max + 1]);
            s = new BigInteger(1, 1, new int[max + 1]);
            s.digits[0] = 1;
            // s == 1 && v == 0

            int k = 0;

            int lsbu = u.getLowestSetBit();
            int lsbv = v.getLowestSetBit();
            int toShift;

            if (lsbu > lsbv) {
                BitLevel.inplaceShiftRight(u, lsbu);
                BitLevel.inplaceShiftRight(v, lsbv);
                BitLevel.inplaceShiftLeft(r, lsbv);
                k += lsbu - lsbv;
            } else {
                BitLevel.inplaceShiftRight(u, lsbu);
                BitLevel.inplaceShiftRight(v, lsbv);
                BitLevel.inplaceShiftLeft(s, lsbu);
                k += lsbv - lsbu;
            }

            r.sign = 1;
            while (v.signum() > 0) {
                // INV v >= 0, u >= 0, v odd, u odd (except last iteration when v is even (0))

                while (u.compareTo(v) > BigInteger.EQUALS) {
                    Elementary.inplaceSubtract(u, v);
                    toShift = u.getLowestSetBit();
                    BitLevel.inplaceShiftRight(u, toShift);
                    Elementary.inplaceAdd(r, s);
                    BitLevel.inplaceShiftLeft(s, toShift);
                    k += toShift;
                }

                while (u.compareTo(v) <= BigInteger.EQUALS) {
                    Elementary.inplaceSubtract(v, u);
                    if (v.signum() == 0)
                        break;
                    toShift = v.getLowestSetBit();
                    BitLevel.inplaceShiftRight(v, toShift);
                    Elementary.inplaceAdd(s, r);
                    BitLevel.inplaceShiftLeft(r, toShift);
                    k += toShift;
                }
            }
            if (!u.isOne()){
                // in u is stored the gcd
                throw new ArithmeticException("BigInteger not invertible.");
            }
            if (r.compareTo(p) >= BigInteger.EQUALS) {
                Elementary.inplaceSubtract(r, p);
            }

            r = p.subtract(r);

            // Have pair: ((BigInteger)r, (Integer)k) where r == a^(-1) * 2^k mod (module)
            int n1 = calcN(p);
            if (k > m) {
                r = monPro(r, BigInteger.ONE, p, n1);
                k = k - m;
            }

            r = monPro(r, BigInteger.getPowerOfTwo(m - k), p, n1);
            return r;
        }
Пример #7
0
        internal static BigInteger modInverseMontgomery(BigInteger a, BigInteger p)
        {
            if (a.sign == 0)
            {
                // ZERO hasn't inverse
                throw new ArithmeticException("BigInteger not invertible");
            }


            if (!p.testBit(0))
            {
                // montgomery inverse require even modulo
                return(modInverseLorencz(a, p));
            }

            int m = p.numberLength * 32;
            // PRE: a \in [1, p - 1]
            BigInteger u, v, r, s;

            u = p.copy();  // make copy to use inplace method
            v = a.copy();
            int max = Math.Max(v.numberLength, u.numberLength);

            r           = new BigInteger(1, 1, new int[max + 1]);
            s           = new BigInteger(1, 1, new int[max + 1]);
            s.digits[0] = 1;
            // s == 1 && v == 0

            int k = 0;

            int lsbu = u.getLowestSetBit();
            int lsbv = v.getLowestSetBit();
            int toShift;

            if (lsbu > lsbv)
            {
                BitLevel.inplaceShiftRight(u, lsbu);
                BitLevel.inplaceShiftRight(v, lsbv);
                BitLevel.inplaceShiftLeft(r, lsbv);
                k += lsbu - lsbv;
            }
            else
            {
                BitLevel.inplaceShiftRight(u, lsbu);
                BitLevel.inplaceShiftRight(v, lsbv);
                BitLevel.inplaceShiftLeft(s, lsbu);
                k += lsbv - lsbu;
            }

            r.sign = 1;
            while (v.signum() > 0)
            {
                // INV v >= 0, u >= 0, v odd, u odd (except last iteration when v is even (0))

                while (u.compareTo(v) > BigInteger.EQUALS)
                {
                    Elementary.inplaceSubtract(u, v);
                    toShift = u.getLowestSetBit();
                    BitLevel.inplaceShiftRight(u, toShift);
                    Elementary.inplaceAdd(r, s);
                    BitLevel.inplaceShiftLeft(s, toShift);
                    k += toShift;
                }

                while (u.compareTo(v) <= BigInteger.EQUALS)
                {
                    Elementary.inplaceSubtract(v, u);
                    if (v.signum() == 0)
                    {
                        break;
                    }
                    toShift = v.getLowestSetBit();
                    BitLevel.inplaceShiftRight(v, toShift);
                    Elementary.inplaceAdd(s, r);
                    BitLevel.inplaceShiftLeft(r, toShift);
                    k += toShift;
                }
            }
            if (!u.isOne())
            {
                // in u is stored the gcd
                throw new ArithmeticException("BigInteger not invertible.");
            }
            if (r.compareTo(p) >= BigInteger.EQUALS)
            {
                Elementary.inplaceSubtract(r, p);
            }

            r = p.subtract(r);

            // Have pair: ((BigInteger)r, (Integer)k) where r == a^(-1) * 2^k mod (module)
            int n1 = calcN(p);

            if (k > m)
            {
                r = monPro(r, BigInteger.ONE, p, n1);
                k = k - m;
            }

            r = monPro(r, BigInteger.getPowerOfTwo(m - k), p, n1);
            return(r);
        }