blob: d6427832c266c8b9e3d93b6b526d76c585cffe98 [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;
/**
* 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 {
/**
* Divides an array by an integer value. Implements the Knuth's division
* algorithm. See D. Knuth, The Art of Computer Programming, vol. 2.
*
* @return remainder
*/
static int divideArrayByInt(int[] quotient, int[] dividend, final int dividendLength,
final int divisor) {
long rem = 0;
long bLong = divisor & 0xffffffffL;
for (int i = dividendLength - 1; i >= 0; i--) {
long temp = (rem << 32) | (dividend[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;
}
}
}
}
quotient[i] = (int) (quot & 0xffffffffL);
}
return (int) rem;
}
}