Esempio n. 1
0
        public BigInteger modPow(BigInteger exponent, BigInteger m)
        {
            if (m.sign <= 0)
            {
                throw new ArithmeticException("BigInteger: modulus not positive");
            }
            BigInteger _base = this;

            if (m.isOne() | (exponent.sign > 0 & _base.sign == 0))
            {
                return(BigInteger.ZERO);
            }
            if (_base.sign == 0 && exponent.sign == 0)
            {
                return(BigInteger.ONE);
            }
            if (exponent.sign < 0)
            {
                _base    = modInverse(m);
                exponent = exponent.negate();
            }
            // From now on: (m > 0) and (exponent >= 0)
            BigInteger res = (m.testBit(0)) ? Division.oddModPow(_base.abs(),
                                                                 exponent, m) : Division.evenModPow(_base.abs(), exponent, m);

            if ((_base.sign < 0) && exponent.testBit(0))
            {
                // -b^e mod m == ((-1 mod m) * (b^e mod m)) mod m
                res = m.subtract(BigInteger.ONE).multiply(res).mod(m);
            }
            // else exponent is even, so base^exp is positive
            return(res);
        }
Esempio n. 2
0
        internal static BigInteger subtract(BigInteger op1, BigInteger op2)
        {
            int resSign;

            int[] resDigits;
            int   op1Sign = op1.sign;
            int   op2Sign = op2.sign;

            if (op2Sign == 0)
            {
                return(op1);
            }
            if (op1Sign == 0)
            {
                return(op2.negate());
            }
            int op1Len = op1.numberLength;
            int op2Len = op2.numberLength;

            if (op1Len + op2Len == 2)
            {
                long a = (op1.digits[0] & 0xFFFFFFFFL);
                long b = (op2.digits[0] & 0xFFFFFFFFL);
                if (op1Sign < 0)
                {
                    a = -a;
                }
                if (op2Sign < 0)
                {
                    b = -b;
                }
                return(BigInteger.valueOf(a - b));
            }
            int cmp = ((op1Len != op2Len) ? ((op1Len > op2Len) ? 1 : -1)
                        : Elementary.compareArrays(op1.digits, op2.digits, op1Len));

            if (cmp == BigInteger.LESS)
            {
                resSign   = -op2Sign;
                resDigits = (op1Sign == op2Sign) ? subtract(op2.digits, op2Len,
                                                            op1.digits, op1Len) : add(op2.digits, op2Len, op1.digits,
                                                                                      op1Len);
            }
            else
            {
                resSign = op1Sign;
                if (op1Sign == op2Sign)
                {
                    if (cmp == BigInteger.EQUALS)
                    {
                        return(BigInteger.ZERO);
                    }
                    resDigits = subtract(op1.digits, op1Len, op2.digits, op2Len);
                }
                else
                {
                    resDigits = add(op1.digits, op1Len, op2.digits, op2Len);
                }
            }
            BigInteger res = new BigInteger(resSign, resDigits.Length, resDigits);

            res.cutOffLeadingZeroes();
            return(res);
        }
Esempio n. 3
0
        public BigInteger modPow(BigInteger exponent, BigInteger m)
        {
            if (m.sign <= 0) {
                throw new ArithmeticException("BigInteger: modulus not positive");
            }
            BigInteger _base = this;

            if (m.isOne() | (exponent.sign > 0 & _base.sign == 0)) {
                return BigInteger.ZERO;
            }
            if (_base.sign == 0 && exponent.sign == 0) {
                return BigInteger.ONE;
            }
            if (exponent.sign < 0) {
                _base = modInverse(m);
                exponent = exponent.negate();
            }
            // From now on: (m > 0) and (exponent >= 0)
            BigInteger res = (m.testBit(0)) ? Division.oddModPow(_base.abs(),
                                                                 exponent, m) : Division.evenModPow(_base.abs(), exponent, m);
            if ((_base.sign < 0) && exponent.testBit(0)) {
                // -b^e mod m == ((-1 mod m) * (b^e mod m)) mod m
                res = m.subtract(BigInteger.ONE).multiply(res).mod(m);
            }
            // else exponent is even, so base^exp is positive
            return res;
        }
Esempio n. 4
0
File: Division.cs Progetto: vic/ioke
        internal static BigInteger modInverseLorencz(BigInteger a, BigInteger modulo)
        {
            int max = Math.Max(a.numberLength, modulo.numberLength);
            int[] uDigits = new int[max + 1]; // enough place to make all the inplace operation
            int[] vDigits = new int[max + 1];
            Array.Copy(modulo.digits, uDigits, modulo.numberLength);
            Array.Copy(a.digits, vDigits, a.numberLength);
            BigInteger u = new BigInteger(modulo.sign, modulo.numberLength,
                                          uDigits);
            BigInteger v = new BigInteger(a.sign, a.numberLength, vDigits);

            BigInteger r = new BigInteger(0, 1, new int[max + 1]); // BigInteger.ZERO;
            BigInteger s = new BigInteger(1, 1, new int[max + 1]);
            s.digits[0] = 1;
            // r == 0 && s == 1, but with enough place

            int coefU = 0, coefV = 0;
            int n = modulo.bitLength();
            int k;
            while (!isPowerOfTwo(u, coefU) && !isPowerOfTwo(v, coefV)) {

                // modification of original algorithm: I calculate how many times the algorithm will enter in the same branch of if
                k = howManyIterations(u, n);

                if (k != 0) {
                    BitLevel.inplaceShiftLeft(u, k);
                    if (coefU >= coefV) {
                        BitLevel.inplaceShiftLeft(r, k);
                    } else {
                        BitLevel.inplaceShiftRight(s, Math.Min(coefV - coefU, k));
                        if (k - ( coefV - coefU ) > 0) {
                            BitLevel.inplaceShiftLeft(r, k - coefV + coefU);
                        }
                    }
                    coefU += k;
                }

                k = howManyIterations(v, n);
                if (k != 0) {
                    BitLevel.inplaceShiftLeft(v, k);
                    if (coefV >= coefU) {
                        BitLevel.inplaceShiftLeft(s, k);
                    } else {
                        BitLevel.inplaceShiftRight(r, Math.Min(coefU - coefV, k));
                        if (k - ( coefU - coefV ) > 0) {
                            BitLevel.inplaceShiftLeft(s, k - coefU + coefV);
                        }
                    }
                    coefV += k;

                }

                if (u.signum() == v.signum()) {
                    if (coefU <= coefV) {
                        Elementary.completeInPlaceSubtract(u, v);
                        Elementary.completeInPlaceSubtract(r, s);
                    } else {
                        Elementary.completeInPlaceSubtract(v, u);
                        Elementary.completeInPlaceSubtract(s, r);
                    }
                } else {
                    if (coefU <= coefV) {
                        Elementary.completeInPlaceAdd(u, v);
                        Elementary.completeInPlaceAdd(r, s);
                    } else {
                        Elementary.completeInPlaceAdd(v, u);
                        Elementary.completeInPlaceAdd(s, r);
                    }
                }
                if (v.signum() == 0 || u.signum() == 0){
                    throw new ArithmeticException("BigInteger not invertible");
                }
            }

            if (isPowerOfTwo(v, coefV)) {
                r = s;
                if (v.signum() != u.signum())
                    u = u.negate();
            }
            if (u.testBit(n)) {
                if (r.signum() < 0) {
                    r = r.negate();
                } else {
                    r = modulo.subtract(r);
                }
            }
            if (r.signum() < 0) {
                r = r.add(modulo);
            }

            return r;
        }
Esempio n. 5
0
        internal static BigInteger modInverseLorencz(BigInteger a, BigInteger modulo)
        {
            int max = Math.Max(a.numberLength, modulo.numberLength);

            int[] uDigits = new int[max + 1]; // enough place to make all the inplace operation
            int[] vDigits = new int[max + 1];
            Array.Copy(modulo.digits, uDigits, modulo.numberLength);
            Array.Copy(a.digits, vDigits, a.numberLength);
            BigInteger u = new BigInteger(modulo.sign, modulo.numberLength,
                                          uDigits);
            BigInteger v = new BigInteger(a.sign, a.numberLength, vDigits);

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

            s.digits[0] = 1;
            // r == 0 && s == 1, but with enough place

            int coefU = 0, coefV = 0;
            int n = modulo.bitLength();
            int k;

            while (!isPowerOfTwo(u, coefU) && !isPowerOfTwo(v, coefV))
            {
                // modification of original algorithm: I calculate how many times the algorithm will enter in the same branch of if
                k = howManyIterations(u, n);

                if (k != 0)
                {
                    BitLevel.inplaceShiftLeft(u, k);
                    if (coefU >= coefV)
                    {
                        BitLevel.inplaceShiftLeft(r, k);
                    }
                    else
                    {
                        BitLevel.inplaceShiftRight(s, Math.Min(coefV - coefU, k));
                        if (k - (coefV - coefU) > 0)
                        {
                            BitLevel.inplaceShiftLeft(r, k - coefV + coefU);
                        }
                    }
                    coefU += k;
                }

                k = howManyIterations(v, n);
                if (k != 0)
                {
                    BitLevel.inplaceShiftLeft(v, k);
                    if (coefV >= coefU)
                    {
                        BitLevel.inplaceShiftLeft(s, k);
                    }
                    else
                    {
                        BitLevel.inplaceShiftRight(r, Math.Min(coefU - coefV, k));
                        if (k - (coefU - coefV) > 0)
                        {
                            BitLevel.inplaceShiftLeft(s, k - coefU + coefV);
                        }
                    }
                    coefV += k;
                }

                if (u.signum() == v.signum())
                {
                    if (coefU <= coefV)
                    {
                        Elementary.completeInPlaceSubtract(u, v);
                        Elementary.completeInPlaceSubtract(r, s);
                    }
                    else
                    {
                        Elementary.completeInPlaceSubtract(v, u);
                        Elementary.completeInPlaceSubtract(s, r);
                    }
                }
                else
                {
                    if (coefU <= coefV)
                    {
                        Elementary.completeInPlaceAdd(u, v);
                        Elementary.completeInPlaceAdd(r, s);
                    }
                    else
                    {
                        Elementary.completeInPlaceAdd(v, u);
                        Elementary.completeInPlaceAdd(s, r);
                    }
                }
                if (v.signum() == 0 || u.signum() == 0)
                {
                    throw new ArithmeticException("BigInteger not invertible");
                }
            }

            if (isPowerOfTwo(v, coefV))
            {
                r = s;
                if (v.signum() != u.signum())
                {
                    u = u.negate();
                }
            }
            if (u.testBit(n))
            {
                if (r.signum() < 0)
                {
                    r = r.negate();
                }
                else
                {
                    r = modulo.subtract(r);
                }
            }
            if (r.signum() < 0)
            {
                r = r.add(modulo);
            }

            return(r);
        }
Esempio n. 6
0
        internal static BigInteger subtract(BigInteger op1, BigInteger op2)
        {
            int resSign;
            int[] resDigits;
            int op1Sign = op1.sign;
            int op2Sign = op2.sign;

            if (op2Sign == 0) {
                return op1;
            }
            if (op1Sign == 0) {
                return op2.negate ();
            }
            int op1Len = op1.numberLength;
            int op2Len = op2.numberLength;
            if (op1Len + op2Len == 2) {
                long a = ( op1.digits[0] & 0xFFFFFFFFL );
                long b = ( op2.digits[0] & 0xFFFFFFFFL );
                if (op1Sign < 0) {
                    a = -a;
                }
                if (op2Sign < 0) {
                    b = -b;
                }
                return BigInteger.valueOf (a - b);
            }
            int cmp = ( ( op1Len != op2Len ) ? ( ( op1Len > op2Len ) ? 1 : -1 )
                        : Elementary.compareArrays (op1.digits, op2.digits, op1Len) );

            if (cmp == BigInteger.LESS) {
                resSign = -op2Sign;
                resDigits = ( op1Sign == op2Sign ) ? subtract (op2.digits, op2Len,
                                                               op1.digits, op1Len) : add (op2.digits, op2Len, op1.digits,
                                                                                          op1Len);
            } else {
                resSign = op1Sign;
                if (op1Sign == op2Sign) {
                    if (cmp == BigInteger.EQUALS) {
                        return BigInteger.ZERO;
                    }
                    resDigits = subtract (op1.digits, op1Len, op2.digits, op2Len);
                } else {
                    resDigits = add (op1.digits, op1Len, op2.digits, op2Len);
                }
            }
            BigInteger res = new BigInteger (resSign, resDigits.Length, resDigits);
            res.cutOffLeadingZeroes();
            return res;
        }