blob: ce2519d0203d1680a4a59fa14f85cecf4f5614dc [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package java.math;
// BEGIN android-removed
// import org.apache.harmony.math.internal.nls.Messages;
// END android-removed
/**
* Static library that provides all operations related with division and modular
* arithmetic to {@link BigInteger}. Some methods are provided in both mutable
* and immutable way. There are several variants provided listed below:
*
* <ul type="circle">
* <li> <b>Division</b>
* <ul type="circle">
* <li>{@link BigInteger} division and remainder by {@link BigInteger}.</li>
* <li>{@link BigInteger} division and remainder by {@code int}.</li>
* <li><i>gcd</i> between {@link BigInteger} numbers.</li>
* </ul>
* </li>
* <li> <b>Modular arithmetic </b>
* <ul type="circle">
* <li>Modular exponentiation between {@link BigInteger} numbers.</li>
* <li>Modular inverse of a {@link BigInteger} numbers.</li>
* </ul>
* </li>
*</ul>
*/
class Division {
// BEGIN android-note
// The divide method has been dropped since this functionality
// is now available from OpenSSL BIGNUM.
// END android-note
/**
* Divides an array by an integer value. Implements the Knuth's division
* algorithm. See D. Knuth, The Art of Computer Programming, vol. 2.
*
* @param dest the quotient
* @param src the dividend
* @param srcLength the length of the dividend
* @param divisor the divisor
* @return remainder
*/
static int divideArrayByInt(int dest[], int src[], final int srcLength,
final int divisor) {
long rem = 0;
long bLong = divisor & 0xffffffffL;
for (int i = srcLength - 1; i >= 0; i--) {
long temp = (rem << 32) | (src[i] & 0xffffffffL);
long quot;
if (temp >= 0) {
quot = (temp / bLong);
rem = (temp % bLong);
} else {
/*
* make the dividend positive shifting it right by 1 bit then
* get the quotient an remainder and correct them properly
*/
long aPos = temp >>> 1;
long bPos = divisor >>> 1;
quot = aPos / bPos;
rem = aPos % bPos;
// double the remainder and add 1 if a is odd
rem = (rem << 1) + (temp & 1);
if ((divisor & 1) != 0) {
// the divisor is odd
if (quot <= rem) {
rem -= quot;
} else {
if (quot - rem <= bLong) {
rem += bLong - quot;
quot -= 1;
} else {
rem += (bLong << 1) - quot;
quot -= 2;
}
}
}
}
dest[i] = (int) (quot & 0xffffffffL);
}
return (int) rem;
}
/**
* Divides an array by an integer value. Implements the Knuth's division
* algorithm. See D. Knuth, The Art of Computer Programming, vol. 2.
*
* @param src the dividend
* @param srcLength the length of the dividend
* @param divisor the divisor
* @return remainder
*/
static int remainderArrayByInt(int src[], final int srcLength,
final int divisor) {
long result = 0;
for (int i = srcLength - 1; i >= 0; i--) {
long temp = (result << 32) + (src[i] & 0xffffffffL);
long res = divideLongByInt(temp, divisor);
result = (int) (res >> 32);
}
return (int) result;
}
/**
* Divides a <code>BigInteger</code> by a signed <code>int</code> and
* returns the remainder.
*
* @param dividend the BigInteger to be divided. Must be non-negative.
* @param divisor a signed int
* @return divide % divisor
*/
static int remainder(BigInteger dividend, int divisor) {
// BEGIN android-added
dividend.establishOldRepresentation("Division.remainder");
// END android-added
return remainderArrayByInt(dividend.digits, dividend.numberLength,
divisor);
}
/**
* Divides an unsigned long a by an unsigned int b. It is supposed that the
* most significant bit of b is set to 1, i.e. b < 0
*
* @param a the dividend
* @param b the divisor
* @return the long value containing the unsigned integer remainder in the
* left half and the unsigned integer quotient in the right half
*/
static long divideLongByInt(long a, int b) {
long quot;
long rem;
long bLong = b & 0xffffffffL;
if (a >= 0) {
quot = (a / bLong);
rem = (a % bLong);
} else {
/*
* Make the dividend positive shifting it right by 1 bit then get
* the quotient an remainder and correct them properly
*/
long aPos = a >>> 1;
long bPos = b >>> 1;
quot = aPos / bPos;
rem = aPos % bPos;
// double the remainder and add 1 if a is odd
rem = (rem << 1) + (a & 1);
if ((b & 1) != 0) { // the divisor is odd
if (quot <= rem) {
rem -= quot;
} else {
if (quot - rem <= bLong) {
rem += bLong - quot;
quot -= 1;
} else {
rem += (bLong << 1) - quot;
quot -= 2;
}
}
}
}
return (rem << 32) | (quot & 0xffffffffL);
}
/**
* Computes the quotient and the remainder after a division by an {@code int}
* number.
*
* @return an array of the form {@code [quotient, remainder]}.
*/
static BigInteger[] divideAndRemainderByInteger(BigInteger val,
int divisor, int divisorSign) {
// BEGIN android-added
val.establishOldRepresentation("Division.divideAndRemainderByInteger");
// END android-added
// 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 };
}
// BEGIN android-note
// A big part of this class that only has been used by the divide method
// has been dropped in favor of using the BIGNUM impl.
// END android-note
}