public static BigInteger multiplyByPositiveInt(BigInteger val, int factor) { int resSign = val.sign; if (resSign == 0) { return(BigInteger.ZERO); } int aNumberLength = val.numberLength; int[] aDigits = val.digits; if (aNumberLength == 1) { long res = unsignedMultAddAdd(aDigits[0], factor, 0, 0); int resLo = (int)res; int resHi = (int)((long)(((ulong)res) >> 32)); return((resHi == 0) ? new BigInteger(resSign, resLo) : new BigInteger(resSign, 2, new int[] { resLo, resHi })); } // Common case int resLength = aNumberLength + 1; int[] resDigits = new int[resLength]; resDigits[aNumberLength] = multiplyByInt(resDigits, aDigits, aNumberLength, factor); BigInteger result = new BigInteger(resSign, resLength, resDigits); result.cutOffLeadingZeroes(); return(result); }
internal static BigInteger finalSubtraction(int[] res, BigInteger modulus) { // skipping leading zeros int modulusLen = modulus.numberLength; bool doSub = res[modulusLen] != 0; if (!doSub) { int[] modulusDigits = modulus.digits; doSub = true; for (int i = modulusLen - 1; i >= 0; i--) { if (res[i] != modulusDigits[i]) { doSub = (res[i] != 0) && ((res[i] & 0xFFFFFFFFL) > (modulusDigits[i] & 0xFFFFFFFFL)); break; } } } BigInteger result = new BigInteger(1, modulusLen + 1, res); // if (res >= modulusDigits) compute (res - modulusDigits) if (doSub) { Elementary.inplaceSubtract(result, modulus); } result.cutOffLeadingZeroes(); return(result); }
public BigInteger remainder(BigInteger divisor) { if (divisor.sign == 0) { throw new ArithmeticException("BigInteger divide by zero"); } int thisLen = numberLength; int divisorLen = divisor.numberLength; if (((thisLen != divisorLen) ? ((thisLen > divisorLen) ? 1 : -1) : Elementary.compareArrays(digits, divisor.digits, thisLen)) == LESS) { return(this); } int resLength = divisorLen; int[] resDigits = new int[resLength]; if (resLength == 1) { resDigits[0] = Division.remainderArrayByInt(digits, thisLen, divisor.digits[0]); } else { int qLen = thisLen - divisorLen + 1; resDigits = Division.divide(null, qLen, digits, thisLen, divisor.digits, divisorLen); } BigInteger result = new BigInteger(sign, resLength, resDigits); result.cutOffLeadingZeroes(); return(result); }
internal static void inplaceSubtract(BigInteger op1, BigInteger op2) { subtract(op1.digits, op1.digits, op1.numberLength, op2.digits, op2.numberLength); op1.cutOffLeadingZeroes(); op1.unCache(); }
public static BigInteger multiplyPAP(BigInteger a, BigInteger b) { // PRE: a >= b int aLen = a.numberLength; int bLen = b.numberLength; int resLength = aLen + bLen; int resSign = (a.sign != b.sign) ? -1 : 1; // A special case when both numbers don't exceed int if (resLength == 2) { long val = unsignedMultAddAdd(a.digits[0], b.digits[0], 0, 0); int valueLo = (int)val; int valueHi = (int)((long)(((ulong)val) >> 32)); return((valueHi == 0) ? new BigInteger(resSign, valueLo) : new BigInteger(resSign, 2, new int[] { valueLo, valueHi })); } int[] aDigits = a.digits; int[] bDigits = b.digits; int[] resDigits = new int[resLength]; // Common case multArraysPAP(aDigits, aLen, bDigits, bLen, resDigits); BigInteger result = new BigInteger(resSign, resLength, resDigits); result.cutOffLeadingZeroes(); return(result); }
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(); }
internal static BigInteger andDiffSigns(BigInteger positive, BigInteger negative) { int iPos = positive.getFirstNonzeroDigit(); int iNeg = negative.getFirstNonzeroDigit(); // Look if the trailing zeros of the negative will "blank" all // the positive digits if (iNeg >= positive.numberLength) { return BigInteger.ZERO; } int resLength = positive.numberLength; int[] resDigits = new int[resLength]; // Must start from max(iPos, iNeg) int i = Math.Max(iPos, iNeg); if (i == iNeg) { resDigits[i] = -negative.digits[i] & positive.digits[i]; i++; } int limit = Math.Min(negative.numberLength, positive.numberLength); for ( ; i < limit; i++) { resDigits[i] = ~negative.digits[i] & positive.digits[i]; } // if the negative was shorter must copy the remaining digits // from positive if (i >= negative.numberLength) { for ( ; i < positive.numberLength; i++) { resDigits[i] = positive.digits[i]; } } // else positive ended and must "copy" virtual 0's, do nothing then BigInteger result = new BigInteger(1, resLength, resDigits); result.cutOffLeadingZeroes(); return result; }
internal static void completeInPlaceAdd(BigInteger op1, BigInteger op2) { if (op1.sign == 0) { Array.Copy(op2.digits, op1.digits, op2.numberLength); } else if (op2.sign == 0) { return; } else if (op1.sign == op2.sign) { add(op1.digits, op1.digits, op1.numberLength, op2.digits, op2.numberLength); } else { int sign = unsignedArraysCompare(op1.digits, op2.digits, op1.numberLength, op2.numberLength); if (sign > 0) { subtract(op1.digits, op1.digits, op1.numberLength, op2.digits, op2.numberLength); } else { inverseSubtract(op1.digits, op1.digits, op1.numberLength, op2.digits, op2.numberLength); op1.sign = -op1.sign; } } op1.numberLength = Math.Max(op1.numberLength, op2.numberLength) + 1; op1.cutOffLeadingZeroes(); op1.unCache(); }
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; }
public BigInteger divide(BigInteger divisor) { if (divisor.sign == 0) { throw new ArithmeticException("BigInteger divide by zero"); } int divisorSign = divisor.sign; if (divisor.isOne()) { return((divisor.sign > 0) ? this : this.negate()); } int thisSign = sign; int thisLen = numberLength; int divisorLen = divisor.numberLength; if (thisLen + divisorLen == 2) { long val = (digits[0] & 0xFFFFFFFFL) / (divisor.digits[0] & 0xFFFFFFFFL); if (thisSign != divisorSign) { val = -val; } return(valueOf(val)); } int cmp = ((thisLen != divisorLen) ? ((thisLen > divisorLen) ? 1 : -1) : Elementary.compareArrays(digits, divisor.digits, thisLen)); if (cmp == EQUALS) { return((thisSign == divisorSign) ? ONE : MINUS_ONE); } if (cmp == LESS) { return(ZERO); } int resLength = thisLen - divisorLen + 1; int[] resDigits = new int[resLength]; int resSign = ((thisSign == divisorSign) ? 1 : -1); if (divisorLen == 1) { Division.divideArrayByInt(resDigits, digits, thisLen, divisor.digits[0]); } else { Division.divide(resDigits, resLength, digits, thisLen, divisor.digits, divisorLen); } BigInteger result = new BigInteger(resSign, resLength, resDigits); result.cutOffLeadingZeroes(); return(result); }
internal static void inplaceAdd(BigInteger op1, BigInteger op2) { // PRE: op1 >= op2 > 0 add(op1.digits, op1.digits, op1.numberLength, op2.digits, op2.numberLength); op1.numberLength = Math.Min(Math.Max(op1.numberLength, op2.numberLength) + 1, op1.digits.Length); op1.cutOffLeadingZeroes(); op1.unCache(); }
internal static void inplaceShiftLeft(BigInteger val, int count) { int intCount = count >> 5; // count of integers val.numberLength += intCount + (BigDecimal .numberOfLeadingZeros(val.digits[val.numberLength - 1]) - (count & 31) >= 0 ? 0 : 1); shiftLeft(val.digits, val.digits, intCount, count & 31); val.cutOffLeadingZeroes(); val.unCache(); }
internal static BigInteger shiftLeftOneBit(BigInteger source) { int srcLen = source.numberLength; int resLen = srcLen + 1; int[] resDigits = new int[resLen]; shiftLeftOneBit(resDigits, source.digits, srcLen); BigInteger result = new BigInteger(source.sign, resLen, resDigits); result.cutOffLeadingZeroes(); return(result); }
internal static BigInteger shiftLeft(BigInteger source, int count) { int intCount = count >> 5; count &= 31; // %= 32 int resLength = source.numberLength + intCount + ((count == 0) ? 0 : 1); int[] resDigits = new int[resLength]; shiftLeft(resDigits, source.digits, intCount, count); BigInteger result = new BigInteger(source.sign, resLength, resDigits); result.cutOffLeadingZeroes(); return(result); }
internal static void inplaceModPow2(BigInteger x, int n) { // PRE: (x > 0) and (n >= 0) int fd = n >> 5; int leadingZeros; if ((x.numberLength < fd) || (x.bitLength() <= n)) { return; } leadingZeros = 32 - (n & 31); x.numberLength = fd + 1; unchecked { x.digits[fd] &= (leadingZeros < 32) ? ((int)(((uint)-1) >> leadingZeros)) : 0; } x.cutOffLeadingZeroes(); }
public BigInteger[] divideAndRemainder(BigInteger divisor) { int divisorSign = divisor.sign; if (divisorSign == 0) { throw new ArithmeticException("BigInteger divide by zero"); } int divisorLen = divisor.numberLength; int[] divisorDigits = divisor.digits; if (divisorLen == 1) { return(Division.divideAndRemainderByInteger(this, divisorDigits[0], divisorSign)); } // res[0] is a quotient and res[1] is a remainder: int[] thisDigits = digits; int thisLen = numberLength; int cmp = (thisLen != divisorLen) ? ((thisLen > divisorLen) ? 1 : -1) : Elementary.compareArrays(thisDigits, divisorDigits, thisLen); if (cmp < 0) { return(new BigInteger[] { ZERO, this }); } int thisSign = sign; int quotientLength = thisLen - divisorLen + 1; int remainderLength = divisorLen; int quotientSign = ((thisSign == divisorSign) ? 1 : -1); int[] quotientDigits = new int[quotientLength]; int[] remainderDigits = Division.divide(quotientDigits, quotientLength, thisDigits, thisLen, divisorDigits, divisorLen); BigInteger result0 = new BigInteger(quotientSign, quotientLength, quotientDigits); BigInteger result1 = new BigInteger(thisSign, remainderLength, remainderDigits); result0.cutOffLeadingZeroes(); result1.cutOffLeadingZeroes(); return(new BigInteger[] { result0, result1 }); }
internal static BigInteger orNegative(BigInteger val, BigInteger that) { int iThat = that.getFirstNonzeroDigit(); int iVal = val.getFirstNonzeroDigit(); int i; if (iVal >= that.numberLength) { return(that); } else if (iThat >= val.numberLength) { return(val); } int resLength = Math.Min(val.numberLength, that.numberLength); int[] resDigits = new int[resLength]; //Looking for the first non-zero digit of the result if (iThat == iVal) { resDigits[iVal] = -(-val.digits[iVal] | -that.digits[iVal]); i = iVal; } else { for (i = iThat; i < iVal; i++) { resDigits[i] = that.digits[i]; } resDigits[i] = that.digits[i] & (val.digits[i] - 1); } for (i++; i < resLength; i++) { resDigits[i] = val.digits[i] & that.digits[i]; } BigInteger result = new BigInteger(-1, resLength, resDigits); result.cutOffLeadingZeroes(); return(result); }
internal static BigInteger andDiffSigns(BigInteger positive, BigInteger negative) { int iPos = positive.getFirstNonzeroDigit(); int iNeg = negative.getFirstNonzeroDigit(); // Look if the trailing zeros of the negative will "blank" all // the positive digits if (iNeg >= positive.numberLength) { return(BigInteger.ZERO); } int resLength = positive.numberLength; int[] resDigits = new int[resLength]; // Must start from max(iPos, iNeg) int i = Math.Max(iPos, iNeg); if (i == iNeg) { resDigits[i] = -negative.digits[i] & positive.digits[i]; i++; } int limit = Math.Min(negative.numberLength, positive.numberLength); for ( ; i < limit; i++) { resDigits[i] = ~negative.digits[i] & positive.digits[i]; } // if the negative was shorter must copy the remaining digits // from positive if (i >= negative.numberLength) { for ( ; i < positive.numberLength; i++) { resDigits[i] = positive.digits[i]; } } // else positive ended and must "copy" virtual 0's, do nothing then BigInteger result = new BigInteger(1, resLength, resDigits); result.cutOffLeadingZeroes(); return(result); }
internal static BigInteger shiftRight(BigInteger source, int count) { int intCount = count >> 5; // count of integers count &= 31; // count of remaining bits if (intCount >= source.numberLength) { return((source.sign < 0) ? BigInteger.MINUS_ONE : BigInteger.ZERO); } int i; int resLength = source.numberLength - intCount; int[] resDigits = new int[resLength + 1]; shiftRight(resDigits, resLength, source.digits, intCount, count); if (source.sign < 0) { // Checking if the dropped bits are zeros (the remainder equals to // 0) for (i = 0; (i < intCount) && (source.digits[i] == 0); i++) { ; } // If the remainder is not zero, add 1 to the result if ((i < intCount) || ((count > 0) && ((source.digits[i] << (32 - count)) != 0))) { for (i = 0; (i < resLength) && (resDigits[i] == -1); i++) { resDigits[i] = 0; } if (i == resLength) { resLength++; } resDigits[i]++; } } BigInteger result = new BigInteger(source.sign, resLength, resDigits); result.cutOffLeadingZeroes(); return(result); }
internal static BigInteger xorPositive(BigInteger longer, BigInteger shorter) { int resLength = longer.numberLength; int[] resDigits = new int[resLength]; int i = Math.Min(longer.getFirstNonzeroDigit(), shorter.getFirstNonzeroDigit()); for ( ; i < shorter.numberLength; i++) { resDigits[i] = longer.digits[i] ^ shorter.digits[i]; } for ( ; i < longer.numberLength; i++) { resDigits[i] = longer.digits[i]; } BigInteger result = new BigInteger(1, resLength, resDigits); result.cutOffLeadingZeroes(); return(result); }
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 andNotPositiveNegative(BigInteger positive, BigInteger negative) { // PRE: positive > 0 && negative < 0 int iNeg = negative.getFirstNonzeroDigit(); int iPos = positive.getFirstNonzeroDigit(); if (iNeg >= positive.numberLength) { return(positive); } int resLength = Math.Min(positive.numberLength, negative.numberLength); int[] resDigits = new int[resLength]; // Always start from first non zero of positive int i = iPos; for ( ; i < iNeg; i++) { // resDigits[i] = positive.digits[i] & -1 (~0) resDigits[i] = positive.digits[i]; } if (i == iNeg) { resDigits[i] = positive.digits[i] & (negative.digits[i] - 1); i++; } for ( ; i < resLength; i++) { // resDigits[i] = positive.digits[i] & ~(~negative.digits[i]); resDigits[i] = positive.digits[i] & negative.digits[i]; } BigInteger result = new BigInteger(1, resLength, resDigits); result.cutOffLeadingZeroes(); return(result); }
internal static BigInteger andNotPositive(BigInteger val, BigInteger that) { // PRE: both arguments are positive int[] resDigits = new int[val.numberLength]; int limit = Math.Min(val.numberLength, that.numberLength); int i; for (i = val.getFirstNonzeroDigit(); i < limit; i++) { resDigits[i] = val.digits[i] & ~that.digits[i]; } for ( ; i < val.numberLength; i++) { resDigits[i] = val.digits[i]; } BigInteger result = new BigInteger(1, val.numberLength, resDigits); result.cutOffLeadingZeroes(); return(result); }
internal static BigInteger andPositive(BigInteger val, BigInteger that) { // PRE: both arguments are positive int resLength = Math.Min(val.numberLength, that.numberLength); int i = Math.Max(val.getFirstNonzeroDigit(), that.getFirstNonzeroDigit()); if (i >= resLength) { return(BigInteger.ZERO); } int[] resDigits = new int[resLength]; for ( ; i < resLength; i++) { resDigits[i] = val.digits[i] & that.digits[i]; } BigInteger result = new BigInteger(1, resLength, resDigits); result.cutOffLeadingZeroes(); return(result); }
internal static void completeInPlaceSubtract(BigInteger op1, BigInteger op2) { int resultSign = op1.compareTo(op2); if (op1.sign == 0) { Array.Copy(op2.digits, op1.digits, op2.numberLength); op1.sign = -op2.sign; } else if (op1.sign != op2.sign) { add(op1.digits, op1.digits, op1.numberLength, op2.digits, op2.numberLength); op1.sign = resultSign; } else { int sign = unsignedArraysCompare(op1.digits, op2.digits, op1.numberLength, op2.numberLength); if (sign > 0) { subtract(op1.digits, op1.digits, op1.numberLength, op2.digits, op2.numberLength); // op1 = op1 - op2 // op1.sign remains equal } else { inverseSubtract(op1.digits, op1.digits, op1.numberLength, op2.digits, op2.numberLength); // op1 = op2 - op1 op1.sign = -op1.sign; } } op1.numberLength = Math.Max(op1.numberLength, op2.numberLength) + 1; op1.cutOffLeadingZeroes(); op1.unCache(); }
public BigInteger remainder(BigInteger divisor) { if (divisor.sign == 0) { throw new ArithmeticException("BigInteger divide by zero"); } int thisLen = numberLength; int divisorLen = divisor.numberLength; if (((thisLen != divisorLen) ? ((thisLen > divisorLen) ? 1 : -1) : Elementary.compareArrays(digits, divisor.digits, thisLen)) == LESS) { return this; } int resLength = divisorLen; int[] resDigits = new int[resLength]; if (resLength == 1) { resDigits[0] = Division.remainderArrayByInt(digits, thisLen, divisor.digits[0]); } else { int qLen = thisLen - divisorLen + 1; resDigits = Division.divide(null, qLen, digits, thisLen, divisor.digits, divisorLen); } BigInteger result = new BigInteger(sign, resLength, resDigits); result.cutOffLeadingZeroes(); return result; }
internal static BigInteger orDiffSigns(BigInteger positive, BigInteger negative) { // Jumping over the least significant zero bits int iNeg = negative.getFirstNonzeroDigit(); int iPos = positive.getFirstNonzeroDigit(); int i; int limit; // Look if the trailing zeros of the positive will "copy" all // the negative digits if (iPos >= negative.numberLength) { return(negative); } int resLength = negative.numberLength; int[] resDigits = new int[resLength]; if (iNeg < iPos) { // We know for sure that this will // be the first non zero digit in the result for (i = iNeg; i < iPos; i++) { resDigits[i] = negative.digits[i]; } } else if (iPos < iNeg) { i = iPos; resDigits[i] = -positive.digits[i]; limit = Math.Min(positive.numberLength, iNeg); for (i++; i < limit; i++) { resDigits[i] = ~positive.digits[i]; } if (i != positive.numberLength) { resDigits[i] = ~(-negative.digits[i] | positive.digits[i]); } else { for (; i < iNeg; i++) { resDigits[i] = -1; } // resDigits[i] = ~(-negative.digits[i] | 0); resDigits[i] = negative.digits[i] - 1; } i++; } else // iNeg == iPos // Applying two complement to negative and to result { i = iPos; resDigits[i] = -(-negative.digits[i] | positive.digits[i]); i++; } limit = Math.Min(negative.numberLength, positive.numberLength); for (; i < limit; i++) { // Applying two complement to negative and to result // resDigits[i] = ~(~negative.digits[i] | positive.digits[i] ); resDigits[i] = negative.digits[i] & ~positive.digits[i]; } for ( ; i < negative.numberLength; i++) { resDigits[i] = negative.digits[i]; } BigInteger result = new BigInteger(-1, resLength, resDigits); result.cutOffLeadingZeroes(); return(result); }
internal static BigInteger shiftRight(BigInteger source, int count) { int intCount = count >> 5; // count of integers count &= 31; // count of remaining bits if (intCount >= source.numberLength) { return ((source.sign < 0) ? BigInteger.MINUS_ONE : BigInteger.ZERO); } int i; int resLength = source.numberLength - intCount; int[] resDigits = new int[resLength + 1]; shiftRight(resDigits, resLength, source.digits, intCount, count); if (source.sign < 0) { // Checking if the dropped bits are zeros (the remainder equals to // 0) for (i = 0; (i < intCount) && (source.digits[i] == 0); i++) { ; } // If the remainder is not zero, add 1 to the result if ((i < intCount) || ((count > 0) && ((source.digits[i] << (32 - count)) != 0))) { for (i = 0; (i < resLength) && (resDigits[i] == -1); i++) { resDigits[i] = 0; } if (i == resLength) { resLength++; } resDigits[i]++; } } BigInteger result = new BigInteger(source.sign, resLength, resDigits); result.cutOffLeadingZeroes(); return result; }
public BigInteger divide(BigInteger divisor) { if (divisor.sign == 0) { throw new ArithmeticException("BigInteger divide by zero"); } int divisorSign = divisor.sign; if (divisor.isOne()) { return ((divisor.sign > 0) ? this : this.negate()); } int thisSign = sign; int thisLen = numberLength; int divisorLen = divisor.numberLength; if (thisLen + divisorLen == 2) { long val = (digits[0] & 0xFFFFFFFFL) / (divisor.digits[0] & 0xFFFFFFFFL); if (thisSign != divisorSign) { val = -val; } return valueOf(val); } int cmp = ((thisLen != divisorLen) ? ((thisLen > divisorLen) ? 1 : -1) : Elementary.compareArrays(digits, divisor.digits, thisLen)); if (cmp == EQUALS) { return ((thisSign == divisorSign) ? ONE : MINUS_ONE); } if (cmp == LESS) { return ZERO; } int resLength = thisLen - divisorLen + 1; int[] resDigits = new int[resLength]; int resSign = ((thisSign == divisorSign) ? 1 : -1); if (divisorLen == 1) { Division.divideArrayByInt(resDigits, digits, thisLen, divisor.digits[0]); } else { Division.divide(resDigits, resLength, digits, thisLen, divisor.digits, divisorLen); } BigInteger result = new BigInteger(resSign, resLength, resDigits); result.cutOffLeadingZeroes(); return result; }
internal static void inplaceShiftLeft(BigInteger val, int count) { int intCount = count >> 5; // count of integers val.numberLength += intCount + ( BigDecimal .numberOfLeadingZeros(val.digits[val.numberLength - 1]) - ( count & 31 ) >= 0 ? 0 : 1 ); shiftLeft(val.digits, val.digits, intCount, count & 31); val.cutOffLeadingZeroes(); val.unCache(); }
internal static BigInteger shiftLeft(BigInteger source, int count) { int intCount = count >> 5; count &= 31; // %= 32 int resLength = source.numberLength + intCount + ( ( count == 0 ) ? 0 : 1 ); int[] resDigits = new int[resLength]; shiftLeft(resDigits, source.digits, intCount, count); BigInteger result = new BigInteger(source.sign, resLength, resDigits); result.cutOffLeadingZeroes(); return result; }
internal static BigInteger xorPositive(BigInteger longer, BigInteger shorter) { int resLength = longer.numberLength; int[] resDigits = new int[resLength]; int i = Math.Min(longer.getFirstNonzeroDigit(), shorter.getFirstNonzeroDigit()); for ( ; i < shorter.numberLength; i++) { resDigits[i] = longer.digits[i] ^ shorter.digits[i]; } for( ; i < longer.numberLength; i++ ){ resDigits[i] = longer.digits[i]; } BigInteger result = new BigInteger(1, resLength, resDigits); result.cutOffLeadingZeroes(); return result; }
internal static BigInteger orDiffSigns(BigInteger positive, BigInteger negative) { // Jumping over the least significant zero bits int iNeg = negative.getFirstNonzeroDigit(); int iPos = positive.getFirstNonzeroDigit(); int i; int limit; // Look if the trailing zeros of the positive will "copy" all // the negative digits if (iPos >= negative.numberLength) { return negative; } int resLength = negative.numberLength; int[] resDigits = new int[resLength]; if (iNeg < iPos ) { // We know for sure that this will // be the first non zero digit in the result for (i = iNeg; i < iPos; i++) { resDigits[i] = negative.digits[i]; } } else if (iPos < iNeg) { i = iPos; resDigits[i] = -positive.digits[i]; limit = Math.Min(positive.numberLength, iNeg); for(i++; i < limit; i++ ) { resDigits[i] = ~positive.digits[i]; } if (i != positive.numberLength) { resDigits[i] = ~(-negative.digits[i] | positive.digits[i]); } else{ for (; i<iNeg; i++) { resDigits[i] = -1; } // resDigits[i] = ~(-negative.digits[i] | 0); resDigits[i] = negative.digits[i] - 1; } i++; } else {// iNeg == iPos // Applying two complement to negative and to result i = iPos; resDigits[i] = -(-negative.digits[i] | positive.digits[i]); i++; } limit = Math.Min(negative.numberLength, positive.numberLength); for (; i < limit; i++) { // Applying two complement to negative and to result // resDigits[i] = ~(~negative.digits[i] | positive.digits[i] ); resDigits[i] = negative.digits[i] & ~positive.digits[i]; } for( ; i < negative.numberLength; i++) { resDigits[i] = negative.digits[i]; } BigInteger result = new BigInteger(-1, resLength, resDigits); result.cutOffLeadingZeroes(); return result; }
internal static void completeInPlaceSubtract(BigInteger op1, BigInteger op2) { int resultSign = op1.compareTo (op2); if (op1.sign == 0) { Array.Copy(op2.digits, op1.digits, op2.numberLength); op1.sign = -op2.sign; } else if (op1.sign != op2.sign) { add (op1.digits, op1.digits, op1.numberLength, op2.digits, op2.numberLength); op1.sign = resultSign; } else { int sign = unsignedArraysCompare (op1.digits, op2.digits, op1.numberLength, op2.numberLength); if (sign > 0) { subtract (op1.digits, op1.digits, op1.numberLength, op2.digits, op2.numberLength); // op1 = op1 - op2 // op1.sign remains equal } else { inverseSubtract (op1.digits, op1.digits, op1.numberLength, op2.digits, op2.numberLength); // op1 = op2 - op1 op1.sign = -op1.sign; } } op1.numberLength = Math.Max(op1.numberLength, op2.numberLength) + 1; op1.cutOffLeadingZeroes (); op1.unCache(); }
public static BigInteger multiplyPAP(BigInteger a, BigInteger b) { // PRE: a >= b int aLen = a.numberLength; int bLen = b.numberLength; int resLength = aLen + bLen; int resSign = (a.sign != b.sign) ? -1 : 1; // A special case when both numbers don't exceed int if (resLength == 2) { long val = unsignedMultAddAdd(a.digits[0], b.digits[0], 0, 0); int valueLo = (int)val; int valueHi = (int)((long)(((ulong)val) >> 32)); return ((valueHi == 0) ? new BigInteger(resSign, valueLo) : new BigInteger(resSign, 2, new int[]{valueLo, valueHi})); } int[] aDigits = a.digits; int[] bDigits = b.digits; int[] resDigits = new int[resLength]; // Common case multArraysPAP(aDigits, aLen, bDigits, bLen, resDigits); BigInteger result = new BigInteger(resSign, resLength, resDigits); result.cutOffLeadingZeroes(); return result; }
internal static void completeInPlaceAdd(BigInteger op1, BigInteger op2) { if (op1.sign == 0) Array.Copy(op2.digits, op1.digits, op2.numberLength); else if (op2.sign == 0) return; else if (op1.sign == op2.sign) add (op1.digits, op1.digits, op1.numberLength, op2.digits, op2.numberLength); else { int sign = unsignedArraysCompare(op1.digits, op2.digits, op1.numberLength, op2.numberLength); if (sign > 0) subtract (op1.digits, op1.digits, op1.numberLength, op2.digits, op2.numberLength); else { inverseSubtract (op1.digits, op1.digits, op1.numberLength, op2.digits, op2.numberLength); op1.sign = -op1.sign; } } op1.numberLength = Math.Max(op1.numberLength, op2.numberLength) + 1; op1.cutOffLeadingZeroes (); op1.unCache(); }
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 void inplaceSubtract(BigInteger op1, BigInteger op2) { subtract (op1.digits, op1.digits, op1.numberLength, op2.digits, op2.numberLength); op1.cutOffLeadingZeroes (); op1.unCache(); }
internal static BigInteger andNotNegative(BigInteger val, BigInteger that) { int iVal = val.getFirstNonzeroDigit(); int iThat = that.getFirstNonzeroDigit(); if (iVal >= that.numberLength) { return(BigInteger.ZERO); } int resLength = that.numberLength; int[] resDigits = new int[resLength]; int limit; int i = iVal; if (iVal < iThat) { // resDigits[i] = -val.digits[i] & -1; resDigits[i] = -val.digits[i]; limit = Math.Min(val.numberLength, iThat); for (i++; i < limit; i++) { // resDigits[i] = ~val.digits[i] & -1; resDigits[i] = ~val.digits[i]; } if (i == val.numberLength) { for ( ; i < iThat; i++) { // resDigits[i] = -1 & -1; resDigits[i] = -1; } // resDigits[i] = -1 & ~-that.digits[i]; resDigits[i] = that.digits[i] - 1; } else { // resDigits[i] = ~val.digits[i] & ~-that.digits[i]; resDigits[i] = ~val.digits[i] & (that.digits[i] - 1); } } else if (iThat < iVal) { // resDigits[i] = -val.digits[i] & ~~that.digits[i]; resDigits[i] = -val.digits[i] & that.digits[i]; } else { // resDigits[i] = -val.digits[i] & ~-that.digits[i]; resDigits[i] = -val.digits[i] & (that.digits[i] - 1); } limit = Math.Min(val.numberLength, that.numberLength); for (i++; i < limit; i++) { // resDigits[i] = ~val.digits[i] & ~~that.digits[i]; resDigits[i] = ~val.digits[i] & that.digits[i]; } for ( ; i < that.numberLength; i++) { // resDigits[i] = -1 & ~~that.digits[i]; resDigits[i] = that.digits[i]; } BigInteger result = new BigInteger(1, resLength, resDigits); result.cutOffLeadingZeroes(); return(result); }
internal static BigInteger xorNegative(BigInteger val, BigInteger that) { int resLength = Math.Max(val.numberLength, that.numberLength); int[] resDigits = new int[resLength]; int iVal = val.getFirstNonzeroDigit(); int iThat = that.getFirstNonzeroDigit(); int i = iThat; int limit; if (iVal == iThat) { resDigits[i] = -val.digits[i] ^ -that.digits[i]; } else { resDigits[i] = -that.digits[i]; limit = Math.Min(that.numberLength, iVal); for (i++; i < limit; i++) { resDigits[i] = ~that.digits[i]; } // Remains digits in that? if (i == that.numberLength) { //Jumping over the remaining zero to the first non one for ( ;i < iVal; i++) { //resDigits[i] = 0 ^ -1; resDigits[i] = -1; } //resDigits[i] = -val.digits[i] ^ -1; resDigits[i] = val.digits[i] - 1; } else { resDigits[i] = -val.digits[i] ^ ~that.digits[i]; } } limit = Math.Min(val.numberLength, that.numberLength); //Perform ^ between that al val until that ends for (i++; i < limit; i++) { //resDigits[i] = ~val.digits[i] ^ ~that.digits[i]; resDigits[i] = val.digits[i] ^ that.digits[i]; } //Perform ^ between val digits and -1 until val ends for ( ; i < val.numberLength; i++) { //resDigits[i] = ~val.digits[i] ^ -1 ; resDigits[i] = val.digits[i] ; } for ( ; i < that.numberLength; i++) { //resDigits[i] = -1 ^ ~that.digits[i] ; resDigits[i] = that.digits[i]; } BigInteger result = new BigInteger(1, resLength, resDigits); result.cutOffLeadingZeroes(); return result; }
internal static BigInteger orNegative(BigInteger val, BigInteger that) { int iThat = that.getFirstNonzeroDigit(); int iVal = val.getFirstNonzeroDigit(); int i; if (iVal >= that.numberLength) { return that; }else if (iThat >= val.numberLength) { return val; } int resLength = Math.Min(val.numberLength, that.numberLength); int[] resDigits = new int[resLength]; //Looking for the first non-zero digit of the result if (iThat == iVal) { resDigits[iVal] = -(-val.digits[iVal] | -that.digits[iVal]); i = iVal; } else { for (i = iThat; i < iVal; i++) { resDigits[i] = that.digits[i]; } resDigits[i] = that.digits[i] & (val.digits[i] - 1); } for (i++; i < resLength; i++) { resDigits[i] = val.digits[i] & that.digits[i]; } BigInteger result = new BigInteger(-1, resLength, resDigits); result.cutOffLeadingZeroes(); return result; }
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 andPositive(BigInteger val, BigInteger that) { // PRE: both arguments are positive int resLength = Math.Min(val.numberLength, that.numberLength); int i = Math.Max(val.getFirstNonzeroDigit(), that.getFirstNonzeroDigit()); if (i >= resLength) { return BigInteger.ZERO; } int[] resDigits = new int[resLength]; for ( ; i < resLength; i++) { resDigits[i] = val.digits[i] & that.digits[i]; } BigInteger result = new BigInteger(1, resLength, resDigits); result.cutOffLeadingZeroes(); return result; }
internal static BigInteger andNotPositiveNegative(BigInteger positive, BigInteger negative) { // PRE: positive > 0 && negative < 0 int iNeg = negative.getFirstNonzeroDigit(); int iPos = positive.getFirstNonzeroDigit(); if (iNeg >= positive.numberLength) { return positive; } int resLength = Math.Min(positive.numberLength, negative.numberLength); int[] resDigits = new int[resLength]; // Always start from first non zero of positive int i = iPos; for ( ; i < iNeg; i++) { // resDigits[i] = positive.digits[i] & -1 (~0) resDigits[i] = positive.digits[i]; } if (i == iNeg) { resDigits[i] = positive.digits[i] & (negative.digits[i] - 1); i++; } for ( ; i < resLength; i++) { // resDigits[i] = positive.digits[i] & ~(~negative.digits[i]); resDigits[i] = positive.digits[i] & negative.digits[i]; } BigInteger result = new BigInteger(1, resLength, resDigits); result.cutOffLeadingZeroes(); return result; }
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(); }
internal static BigInteger xorDiffSigns(BigInteger positive, BigInteger negative) { int resLength = Math.Max(negative.numberLength, positive.numberLength); int[] resDigits; int iNeg = negative.getFirstNonzeroDigit(); int iPos = positive.getFirstNonzeroDigit(); int i; int limit; //The first if (iNeg < iPos) { resDigits = new int[resLength]; i = iNeg; //resDigits[i] = -(-negative.digits[i]); resDigits[i] = negative.digits[i]; limit = Math.Min(negative.numberLength, iPos); //Skip the positive digits while they are zeros for (i++; i < limit; i++) { //resDigits[i] = ~(~negative.digits[i]); resDigits[i] = negative.digits[i]; } //if the negative has no more elements, must fill the //result with the remaining digits of the positive if (i == negative.numberLength) { for ( ; i < positive.numberLength; i++) { //resDigits[i] = ~(positive.digits[i] ^ -1) -> ~(~positive.digits[i]) resDigits[i] = positive.digits[i]; } } } else if (iPos < iNeg) { resDigits = new int[resLength]; i = iPos; //Applying two complement to the first non-zero digit of the result resDigits[i] = -positive.digits[i]; limit = Math.Min(positive.numberLength, iNeg); for (i++; i < limit; i++) { //Continue applying two complement the result resDigits[i] = ~positive.digits[i]; } //When the first non-zero digit of the negative is reached, must apply //two complement (arithmetic negation) to it, and then operate if (i == iNeg) { resDigits[i] = ~(positive.digits[i] ^ -negative.digits[i]); i++; } else { //if the positive has no more elements must fill the remaining digits with //the negative ones for ( ; i < iNeg; i++) { // resDigits[i] = ~(0 ^ 0) resDigits[i] = -1; } for ( ; i < negative.numberLength; i++) { //resDigits[i] = ~(~negative.digits[i] ^ 0) resDigits[i] = negative.digits[i]; } } } else { int digit; //The first non-zero digit of the positive and negative are the same i = iNeg; digit = positive.digits[i] ^ -negative.digits[i]; if (digit == 0) { limit = Math.Min(positive.numberLength, negative.numberLength); for (i++; i < limit && (digit = positive.digits[i] ^ ~negative.digits[i]) == 0; i++) { ; } if (digit == 0) { // shorter has only the remaining virtual sign bits for ( ; i < positive.numberLength && (digit = ~positive.digits[i]) == 0; i++) { ; } for ( ; i < negative.numberLength && (digit = ~negative.digits[i]) == 0; i++) { ; } if (digit == 0) { resLength = resLength + 1; resDigits = new int[resLength]; resDigits[resLength - 1] = 1; return(new BigInteger(-1, resLength, resDigits)); } } } resDigits = new int[resLength]; resDigits[i] = -digit; i++; } limit = Math.Min(negative.numberLength, positive.numberLength); for ( ; i < limit; i++) { resDigits[i] = ~(~negative.digits[i] ^ positive.digits[i]); } for ( ; i < positive.numberLength; i++) { // resDigits[i] = ~(positive.digits[i] ^ -1) resDigits[i] = positive.digits[i]; } for ( ; i < negative.numberLength; i++) { // resDigits[i] = ~(0 ^ ~negative.digits[i]) resDigits[i] = negative.digits[i]; } BigInteger result = new BigInteger(-1, resLength, resDigits); result.cutOffLeadingZeroes(); return(result); }
internal static BigInteger shiftLeftOneBit(BigInteger source) { int srcLen = source.numberLength; int resLen = srcLen + 1; int[] resDigits = new int[resLen]; shiftLeftOneBit(resDigits, source.digits, srcLen); BigInteger result = new BigInteger(source.sign, resLen, resDigits); result.cutOffLeadingZeroes(); return result; }
internal static void inplaceModPow2(BigInteger x, int n) { // PRE: (x > 0) and (n >= 0) int fd = n >> 5; int leadingZeros; if ((x.numberLength < fd) || (x.bitLength() <= n)) { return; } leadingZeros = 32 - (n & 31); x.numberLength = fd + 1; unchecked { x.digits[fd] &= (leadingZeros < 32) ? ((int)(((uint)-1) >> leadingZeros)) : 0; } x.cutOffLeadingZeroes(); }
internal static BigInteger flipBit(BigInteger val, int n) { int resSign = (val.sign == 0) ? 1 : val.sign; int intCount = n >> 5; int bitN = n & 31; int resLength = Math.Max(intCount + 1, val.numberLength) + 1; int[] resDigits = new int[resLength]; int i; int bitNumber = 1 << bitN; Array.Copy(val.digits, 0, resDigits, 0, val.numberLength); if (val.sign < 0) { if (intCount >= val.numberLength) { resDigits[intCount] = bitNumber; } else { //val.sign<0 y intCount < val.numberLength int firstNonZeroDigit = val.getFirstNonzeroDigit(); if (intCount > firstNonZeroDigit) { resDigits[intCount] ^= bitNumber; } else if (intCount < firstNonZeroDigit) { resDigits[intCount] = -bitNumber; for (i=intCount + 1; i < firstNonZeroDigit; i++) { resDigits[i]=-1; } resDigits[i] = resDigits[i]--; } else { i = intCount; resDigits[i] = -((-resDigits[intCount]) ^ bitNumber); if (resDigits[i] == 0) { for (i++; resDigits[i] == -1 ; i++) { resDigits[i] = 0; } resDigits[i]++; } } } } else {//case where val is positive resDigits[intCount] ^= bitNumber; } BigInteger result = new BigInteger(resSign, resLength, resDigits); result.cutOffLeadingZeroes(); return result; }
private static void setFromString(BigInteger bi, String val, int radix) { int sign; int[] digits; int numberLength; int stringLength = val.Length; int startChar; int endChar = stringLength; if (val[0] == '-') { sign = -1; startChar = 1; stringLength--; } else { sign = 1; startChar = 0; } /* * We use the following algorithm: split a string into portions of n * characters and convert each portion to an integer according to the * radix. Then convert an exp(radix, n) based number to binary using the * multiplication method. See D. Knuth, The Art of Computer Programming, * vol. 2. */ int charsPerInt = Conversion.digitFitInInt[radix]; int bigRadixDigitsLength = stringLength / charsPerInt; int topChars = stringLength % charsPerInt; if (topChars != 0) { bigRadixDigitsLength++; } digits = new int[bigRadixDigitsLength]; // Get the maximal power of radix that fits in int int bigRadix = Conversion.bigRadices[radix - 2]; // Parse an input string and accumulate the BigInteger's magnitude int digitIndex = 0; // index of digits array int substrEnd = startChar + ((topChars == 0) ? charsPerInt : topChars); int newDigit; for (int substrStart = startChar; substrStart < endChar; substrStart = substrEnd, substrEnd = substrStart + charsPerInt) { int bigRadixDigit = Convert.ToInt32(val.Substring(substrStart, substrEnd - substrStart), radix); newDigit = Multiplication.multiplyByInt(digits, digitIndex, bigRadix); newDigit += Elementary .inplaceAdd(digits, digitIndex, bigRadixDigit); digits[digitIndex++] = newDigit; } numberLength = digitIndex; bi.sign = sign; bi.numberLength = numberLength; bi.digits = digits; bi.cutOffLeadingZeroes(); }
public BigInteger[] divideAndRemainder(BigInteger divisor) { int divisorSign = divisor.sign; if (divisorSign == 0) { throw new ArithmeticException("BigInteger divide by zero"); } int divisorLen = divisor.numberLength; int[] divisorDigits = divisor.digits; if (divisorLen == 1) { return Division.divideAndRemainderByInteger(this, divisorDigits[0], divisorSign); } // res[0] is a quotient and res[1] is a remainder: int[] thisDigits = digits; int thisLen = numberLength; int cmp = (thisLen != divisorLen) ? ((thisLen > divisorLen) ? 1 : -1) : Elementary.compareArrays(thisDigits, divisorDigits, thisLen); if (cmp < 0) { return new BigInteger[] { ZERO, this }; } int thisSign = sign; int quotientLength = thisLen - divisorLen + 1; int remainderLength = divisorLen; int quotientSign = ((thisSign == divisorSign) ? 1 : -1); int[] quotientDigits = new int[quotientLength]; int[] remainderDigits = Division.divide(quotientDigits, quotientLength, thisDigits, thisLen, divisorDigits, divisorLen); BigInteger result0 = new BigInteger(quotientSign, quotientLength, quotientDigits); BigInteger result1 = new BigInteger(thisSign, remainderLength, remainderDigits); result0.cutOffLeadingZeroes(); result1.cutOffLeadingZeroes(); return new BigInteger[] { result0, result1 }; }
internal static BigInteger xorDiffSigns(BigInteger positive, BigInteger negative) { int resLength = Math.Max(negative.numberLength, positive.numberLength); int[] resDigits; int iNeg = negative.getFirstNonzeroDigit(); int iPos = positive.getFirstNonzeroDigit(); int i; int limit; //The first if (iNeg < iPos) { resDigits = new int[resLength]; i = iNeg; //resDigits[i] = -(-negative.digits[i]); resDigits[i] = negative.digits[i]; limit = Math.Min(negative.numberLength, iPos); //Skip the positive digits while they are zeros for (i++; i < limit; i++) { //resDigits[i] = ~(~negative.digits[i]); resDigits[i] = negative.digits[i]; } //if the negative has no more elements, must fill the //result with the remaining digits of the positive if (i == negative.numberLength) { for ( ; i < positive.numberLength; i++) { //resDigits[i] = ~(positive.digits[i] ^ -1) -> ~(~positive.digits[i]) resDigits[i] = positive.digits[i]; } } } else if (iPos < iNeg) { resDigits = new int[resLength]; i = iPos; //Applying two complement to the first non-zero digit of the result resDigits[i] = -positive.digits[i]; limit = Math.Min(positive.numberLength, iNeg); for (i++; i < limit; i++) { //Continue applying two complement the result resDigits[i] = ~positive.digits[i]; } //When the first non-zero digit of the negative is reached, must apply //two complement (arithmetic negation) to it, and then operate if (i == iNeg) { resDigits[i] = ~(positive.digits[i] ^ -negative.digits[i]); i++; } else { //if the positive has no more elements must fill the remaining digits with //the negative ones for ( ; i < iNeg; i++) { // resDigits[i] = ~(0 ^ 0) resDigits[i] = -1; } for ( ; i < negative.numberLength; i++) { //resDigits[i] = ~(~negative.digits[i] ^ 0) resDigits[i] = negative.digits[i]; } } } else { int digit; //The first non-zero digit of the positive and negative are the same i = iNeg; digit = positive.digits[i] ^ -negative.digits[i]; if (digit == 0) { limit = Math.Min(positive.numberLength, negative.numberLength); for (i++; i < limit && (digit = positive.digits[i] ^ ~negative.digits[i]) == 0; i++) ; if (digit == 0) { // shorter has only the remaining virtual sign bits for ( ; i < positive.numberLength && (digit = ~positive.digits[i]) == 0; i++) ; for ( ; i < negative.numberLength && (digit = ~negative.digits[i]) == 0; i++) ; if (digit == 0) { resLength = resLength + 1; resDigits = new int[resLength]; resDigits[resLength - 1] = 1; return new BigInteger(-1, resLength, resDigits); } } } resDigits = new int[resLength]; resDigits[i] = -digit; i++; } limit = Math.Min(negative.numberLength, positive.numberLength); for ( ; i < limit; i++) { resDigits[i] = ~(~negative.digits[i] ^ positive.digits[i]); } for ( ; i < positive.numberLength; i++) { // resDigits[i] = ~(positive.digits[i] ^ -1) resDigits[i] = positive.digits[i]; } for ( ; i < negative.numberLength; i++) { // resDigits[i] = ~(0 ^ ~negative.digits[i]) resDigits[i] = negative.digits[i]; } BigInteger result = new BigInteger(-1, resLength, resDigits); result.cutOffLeadingZeroes(); return result; }
private static void setFromString(BigInteger bi, String val, int radix) { int sign; int[] digits; int numberLength; int stringLength = val.Length; int startChar; int endChar = stringLength; if (val[0] == '-') { sign = -1; startChar = 1; stringLength--; } else { sign = 1; startChar = 0; } /* * We use the following algorithm: split a string into portions of n * characters and convert each portion to an integer according to the * radix. Then convert an exp(radix, n) based number to binary using the * multiplication method. See D. Knuth, The Art of Computer Programming, * vol. 2. */ int charsPerInt = Conversion.digitFitInInt[radix]; int bigRadixDigitsLength = stringLength / charsPerInt; int topChars = stringLength % charsPerInt; if (topChars != 0) { bigRadixDigitsLength++; } digits = new int[bigRadixDigitsLength]; // Get the maximal power of radix that fits in int int bigRadix = Conversion.bigRadices[radix - 2]; // Parse an input string and accumulate the BigInteger's magnitude int digitIndex = 0; // index of digits array int substrEnd = startChar + ((topChars == 0) ? charsPerInt : topChars); int newDigit; for (int substrStart = startChar; substrStart < endChar; substrStart = substrEnd, substrEnd = substrStart + charsPerInt) { int bigRadixDigit = Convert.ToInt32(val.Substring(substrStart, substrEnd - substrStart), radix); newDigit = Multiplication.multiplyByInt(digits, digitIndex, bigRadix); newDigit += Elementary .inplaceAdd(digits, digitIndex, bigRadixDigit); digits[digitIndex++] = newDigit; } numberLength = digitIndex; bi.sign = sign; bi.numberLength = numberLength; bi.digits = digits; bi.cutOffLeadingZeroes(); }
internal static void inplaceAdd(BigInteger op1, BigInteger op2) { // PRE: op1 >= op2 > 0 add (op1.digits, op1.digits, op1.numberLength, op2.digits, op2.numberLength); op1.numberLength = Math.Min(Math.Max(op1.numberLength, op2.numberLength) + 1, op1.digits.Length); op1.cutOffLeadingZeroes (); op1.unCache(); }
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 andNotPositive(BigInteger val, BigInteger that) { // PRE: both arguments are positive int[] resDigits = new int[val.numberLength]; int limit = Math.Min(val.numberLength, that.numberLength); int i; for (i = val.getFirstNonzeroDigit(); i < limit; i++) { resDigits[i] = val.digits[i] & ~that.digits[i]; } for ( ; i < val.numberLength; i++) { resDigits[i] = val.digits[i]; } BigInteger result = new BigInteger(1, val.numberLength, resDigits); result.cutOffLeadingZeroes(); return result; }
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 finalSubtraction(int[] res, BigInteger modulus) { // skipping leading zeros int modulusLen = modulus.numberLength; bool doSub = res[modulusLen]!=0; if(!doSub) { int[] modulusDigits = modulus.digits; doSub = true; for(int i = modulusLen - 1; i >= 0; i--) { if(res[i] != modulusDigits[i]) { doSub = (res[i] != 0) && ((res[i] & 0xFFFFFFFFL) > (modulusDigits[i] & 0xFFFFFFFFL)); break; } } } BigInteger result = new BigInteger(1, modulusLen+1, res); // if (res >= modulusDigits) compute (res - modulusDigits) if (doSub) { Elementary.inplaceSubtract(result, modulus); } result.cutOffLeadingZeroes(); return result; }
public static BigInteger multiplyByPositiveInt(BigInteger val, int factor) { int resSign = val.sign; if (resSign == 0) { return BigInteger.ZERO; } int aNumberLength = val.numberLength; int[] aDigits = val.digits; if (aNumberLength == 1) { long res = unsignedMultAddAdd(aDigits[0], factor, 0, 0); int resLo = (int)res; int resHi = (int)((long)(((ulong)res) >> 32)); return ((resHi == 0) ? new BigInteger(resSign, resLo) : new BigInteger(resSign, 2, new int[]{resLo, resHi})); } // Common case int resLength = aNumberLength + 1; int[] resDigits = new int[resLength]; resDigits[aNumberLength] = multiplyByInt(resDigits, aDigits, aNumberLength, factor); BigInteger result = new BigInteger(resSign, resLength, resDigits); result.cutOffLeadingZeroes(); return result; }
internal static BigInteger xorNegative(BigInteger val, BigInteger that) { int resLength = Math.Max(val.numberLength, that.numberLength); int[] resDigits = new int[resLength]; int iVal = val.getFirstNonzeroDigit(); int iThat = that.getFirstNonzeroDigit(); int i = iThat; int limit; if (iVal == iThat) { resDigits[i] = -val.digits[i] ^ -that.digits[i]; } else { resDigits[i] = -that.digits[i]; limit = Math.Min(that.numberLength, iVal); for (i++; i < limit; i++) { resDigits[i] = ~that.digits[i]; } // Remains digits in that? if (i == that.numberLength) { //Jumping over the remaining zero to the first non one for ( ; i < iVal; i++) { //resDigits[i] = 0 ^ -1; resDigits[i] = -1; } //resDigits[i] = -val.digits[i] ^ -1; resDigits[i] = val.digits[i] - 1; } else { resDigits[i] = -val.digits[i] ^ ~that.digits[i]; } } limit = Math.Min(val.numberLength, that.numberLength); //Perform ^ between that al val until that ends for (i++; i < limit; i++) { //resDigits[i] = ~val.digits[i] ^ ~that.digits[i]; resDigits[i] = val.digits[i] ^ that.digits[i]; } //Perform ^ between val digits and -1 until val ends for ( ; i < val.numberLength; i++) { //resDigits[i] = ~val.digits[i] ^ -1 ; resDigits[i] = val.digits[i]; } for ( ; i < that.numberLength; i++) { //resDigits[i] = -1 ^ ~that.digits[i] ; resDigits[i] = that.digits[i]; } BigInteger result = new BigInteger(1, resLength, resDigits); result.cutOffLeadingZeroes(); return(result); }