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())); }
static BigInteger() { TWO_POWS = new BigInteger[32]; for (int i = 0; i < TWO_POWS.Length; i++) { TWO_POWS[i] = BigInteger.valueOf(1L << i); } }
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 } }; }
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); } }
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 }); }
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); }
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); }
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)); }