Пример #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
 static BigInteger()
 {
     TWO_POWS = new BigInteger[32];
     for (int i = 0; i < TWO_POWS.Length; i++)
     {
         TWO_POWS[i] = BigInteger.valueOf(1L << i);
     }
 }
Пример #3
0
        static Primality()  // To initialize the dual table of BigInteger primes
        {
            for (int i = 0; i < primes.Length; i++)
            {
                BIprimes[i] = BigInteger.valueOf(primes[i]);
            }

            offsetPrimes = new int[][] { null, null, new int[] { 0, 2 },
                                         new int[] { 2, 2 }, new int[] { 4, 2 }, new int[] { 6, 5 }, new int[] { 11, 7 }, new int[] { 18, 13 }, new int[] { 31, 23 },
                                         new int[] { 54, 43 }, new int[] { 97, 75 } };
        }
Пример #4
0
        static Multiplication()
        {
            int  i;
            long fivePow = 1L;

            for (i = 0; i <= 18; i++)
            {
                bigFivePows[i] = BigInteger.valueOf(fivePow);
                bigTenPows[i]  = BigInteger.valueOf(fivePow << i);
                fivePow       *= 5;
            }
            for (; i < bigTenPows.Length; i++)
            {
                bigFivePows[i] = bigFivePows[i - 1].multiply(bigFivePows[1]);
                bigTenPows[i]  = bigTenPows[i - 1].multiply(BigInteger.TEN);
            }
        }
Пример #5
0
        internal static BigInteger[] divideAndRemainderByInteger(BigInteger val,
                                                                 int divisor, int divisorSign)
        {
            // res[0] is a quotient and res[1] is a remainder:
            int[] valDigits = val.digits;
            int   valLen    = val.numberLength;
            int   valSign   = val.sign;

            if (valLen == 1)
            {
                long a   = (valDigits[0] & 0xffffffffL);
                long b   = (divisor & 0xffffffffL);
                long quo = a / b;
                long rem = a % b;
                if (valSign != divisorSign)
                {
                    quo = -quo;
                }
                if (valSign < 0)
                {
                    rem = -rem;
                }
                return(new BigInteger[] { BigInteger.valueOf(quo),
                                          BigInteger.valueOf(rem) });
            }
            int quotientLength = valLen;
            int quotientSign   = ((valSign == divisorSign) ? 1 : -1);

            int[] quotientDigits = new int[quotientLength];
            int[] remainderDigits;
            remainderDigits = new int[] { Division.divideArrayByInt(
                                              quotientDigits, valDigits, valLen, divisor) };
            BigInteger result0 = new BigInteger(quotientSign, quotientLength,
                                                quotientDigits);
            BigInteger result1 = new BigInteger(valSign, 1, remainderDigits);

            result0.cutOffLeadingZeroes();
            result1.cutOffLeadingZeroes();
            return(new BigInteger[] { result0, result1 });
        }
Пример #6
0
        internal static BigInteger add(BigInteger op1, BigInteger op2)
        {
            int[] resDigits;
            int   resSign;
            int   op1Sign = op1.sign;
            int   op2Sign = op2.sign;

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

            if (op1Len + op2Len == 2)
            {
                long a = (op1.digits[0] & 0xFFFFFFFFL);
                long b = (op2.digits[0] & 0xFFFFFFFFL);
                long ress;
                int  valueLo;
                int  valueHi;

                if (op1Sign == op2Sign)
                {
                    ress    = a + b;
                    valueLo = (int)ress;
                    valueHi = (int)((long)(((ulong)ress) >> 32));
                    return((valueHi == 0) ? new BigInteger(op1Sign, valueLo)
                            : new BigInteger(op1Sign, 2, new int[] { valueLo,
                                                                     valueHi }));
                }
                return(BigInteger.valueOf((op1Sign < 0) ? (b - a) : (a - b)));
            }
            else if (op1Sign == op2Sign)
            {
                resSign = op1Sign;
                // an augend should not be shorter than addend
                resDigits = (op1Len >= op2Len) ? add(op1.digits, op1Len,
                                                     op2.digits, op2Len) : add(op2.digits, op2Len, op1.digits,
                                                                               op1Len);
            }
            else     // signs are different
            {
                int cmp = ((op1Len != op2Len) ? ((op1Len > op2Len) ? 1 : -1)
                           : compareArrays(op1.digits, op2.digits, op1Len));

                if (cmp == BigInteger.EQUALS)
                {
                    return(BigInteger.ZERO);
                }
                // a minuend should not be shorter than subtrahend
                if (cmp == BigInteger.GREATER)
                {
                    resSign   = op1Sign;
                    resDigits = subtract(op1.digits, op1Len, op2.digits, op2Len);
                }
                else
                {
                    resSign   = op2Sign;
                    resDigits = subtract(op2.digits, op2Len, op1.digits, op1Len);
                }
            }
            BigInteger res = new BigInteger(resSign, resDigits.Length, resDigits);

            res.cutOffLeadingZeroes();
            return(res);
        }
Пример #7
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);
        }
Пример #8
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));
        }