示例#1
0
文件: BitLevel.cs 项目: tspring/ioke
        internal static void inplaceShiftRight(BigInteger val, int count)
        {
            int sign = val.signum();

            if (count == 0 || val.signum() == 0)
            {
                return;
            }
            int intCount = count >> 5; // count of integers

            val.numberLength -= intCount;
            if (!shiftRight(val.digits, val.numberLength, val.digits, intCount,
                            count & 31) &&
                sign < 0)
            {
                // remainder not zero: add one to the result
                int i;
                for (i = 0; (i < val.numberLength) && (val.digits[i] == -1); i++)
                {
                    val.digits[i] = 0;
                }
                if (i == val.numberLength)
                {
                    val.numberLength++;
                }
                val.digits[i]++;
            }
            val.cutOffLeadingZeroes();
            val.unCache();
        }
示例#2
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()));
        }
示例#3
0
文件: BitLevel.cs 项目: vic/ioke
 internal static void inplaceShiftRight(BigInteger val, int count)
 {
     int sign = val.signum();
     if (count == 0 || val.signum() == 0)
         return;
     int intCount = count >> 5; // count of integers
     val.numberLength -= intCount;
     if (!shiftRight(val.digits, val.numberLength, val.digits, intCount,
                     count & 31)
         && sign < 0) {
         // remainder not zero: add one to the result
         int i;
         for (i = 0; ( i < val.numberLength ) && ( val.digits[i] == -1 ); i++) {
             val.digits[i] = 0;
         }
         if (i == val.numberLength) {
             val.numberLength++;
         }
         val.digits[i]++;
     }
     val.cutOffLeadingZeroes();
     val.unCache();
 }
示例#4
0
文件: Division.cs 项目: 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;
        }
示例#5
0
文件: Division.cs 项目: vic/ioke
        internal static BigInteger gcdBinary(BigInteger op1, BigInteger op2)
        {
            // PRE: (op1 > 0) and (op2 > 0)

            /*
             * Divide both number the maximal possible times by 2 without rounding
             * gcd(2*a, 2*b) = 2 * gcd(a,b)
             */
            int lsb1 = op1.getLowestSetBit();
            int lsb2 = op2.getLowestSetBit();
            int pow2Count = Math.Min(lsb1, lsb2);

            BitLevel.inplaceShiftRight(op1, lsb1);
            BitLevel.inplaceShiftRight(op2, lsb2);

            BigInteger swap;
            // I want op2 > op1
            if (op1.compareTo(op2) == BigInteger.GREATER) {
                swap = op1;
                op1 = op2;
                op2 = swap;
            }

            do { // INV: op2 >= op1 && both are odd unless op1 = 0

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

                // Implements one step of the Euclidean algorithm
                // To reduce one operand if it's much smaller than the other one
                if (op2.numberLength > op1.numberLength * 1.2) {
                    op2 = op2.remainder(op1);
                    if (op2.signum() != 0) {
                        BitLevel.inplaceShiftRight(op2, op2.getLowestSetBit());
                    }
                } else {

                    // Use Knuth's algorithm of successive subtract and shifting
                    do {
                        Elementary.inplaceSubtract(op2, op1); // both are odd
                        BitLevel.inplaceShiftRight(op2, op2.getLowestSetBit()); // op2 is even
                    } while (op2.compareTo(op1) >= BigInteger.EQUALS);
                }
                // now op1 >= op2
                swap = op2;
                op2 = op1;
                op1 = swap;
            } while (op1.sign != 0);
            return op2.shiftLeft(pow2Count);
        }
示例#6
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);
        }
示例#7
0
        internal static BigInteger gcdBinary(BigInteger op1, BigInteger op2)
        {
            // PRE: (op1 > 0) and (op2 > 0)

            /*
             * Divide both number the maximal possible times by 2 without rounding
             * gcd(2*a, 2*b) = 2 * gcd(a,b)
             */
            int lsb1      = op1.getLowestSetBit();
            int lsb2      = op2.getLowestSetBit();
            int pow2Count = Math.Min(lsb1, lsb2);

            BitLevel.inplaceShiftRight(op1, lsb1);
            BitLevel.inplaceShiftRight(op2, lsb2);

            BigInteger swap;

            // I want op2 > op1
            if (op1.compareTo(op2) == BigInteger.GREATER)
            {
                swap = op1;
                op1  = op2;
                op2  = swap;
            }

            do   // INV: op2 >= op1 && both are odd unless op1 = 0

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

                // Implements one step of the Euclidean algorithm
                // To reduce one operand if it's much smaller than the other one
                if (op2.numberLength > op1.numberLength * 1.2)
                {
                    op2 = op2.remainder(op1);
                    if (op2.signum() != 0)
                    {
                        BitLevel.inplaceShiftRight(op2, op2.getLowestSetBit());
                    }
                }
                else
                {
                    // Use Knuth's algorithm of successive subtract and shifting
                    do
                    {
                        Elementary.inplaceSubtract(op2, op1);                   // both are odd
                        BitLevel.inplaceShiftRight(op2, op2.getLowestSetBit()); // op2 is even
                    } while (op2.compareTo(op1) >= BigInteger.EQUALS);
                }
                // now op1 >= op2
                swap = op2;
                op2  = op1;
                op1  = swap;
            } while (op1.sign != 0);
            return(op2.shiftLeft(pow2Count));
        }
示例#8
0
文件: BigDecimal.cs 项目: vic/ioke
        private static BigDecimal divideBigIntegers(BigInteger scaledDividend, BigInteger scaledDivisor, int scale, RoundingMode roundingMode)
        {
            BigInteger[] quotAndRem = scaledDividend.divideAndRemainder(scaledDivisor);  // quotient and remainder

            // If after division there is a remainder...
            BigInteger quotient = quotAndRem[0];
            BigInteger remainder = quotAndRem[1];
            if (remainder.signum() == 0) {
                return new BigDecimal(quotient, scale);
            }
            int sign = scaledDividend.signum() * scaledDivisor.signum();
            int compRem;                                      // 'compare to remainder'
            if(scaledDivisor.bitLength() < 63) { // 63 in order to avoid out of long after <<1
                long rem = remainder.longValue();
                long divisor = scaledDivisor.longValue();
                compRem = longCompareTo(Math.Abs(rem) << 1,Math.Abs(divisor));
                // To look if there is a carry
                compRem = roundingBehavior(quotient.testBit(0) ? 1 : 0,
                                           sign * (5 + compRem), roundingMode);

            } else {
                // Checking if:  remainder * 2 >= scaledDivisor
                compRem = remainder.abs().shiftLeftOneBit().compareTo(scaledDivisor.abs());
                compRem = roundingBehavior(quotient.testBit(0) ? 1 : 0,
                                           sign * (5 + compRem), roundingMode);
            }
            if (compRem != 0) {
                if(quotient.bitLength() < 63) {
                    return valueOf(quotient.longValue() + compRem,scale);
                }
                quotient = quotient.add(BigInteger.valueOf(compRem));
                return new BigDecimal(quotient, scale);
            }
            // Constructing the result with the appropriate unscaled value
            return new BigDecimal(quotient, scale);
        }