2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
21 * Static library that provides all the <b>bit level</b> operations for
22 * {@link BigInteger}. The operations are:
24 * <li>Left Shifting</li>
25 * <li>Right Shifting</li>
26 * <li>Bit clearing</li>
27 * <li>Bit setting</li>
28 * <li>Bit counting</li>
29 * <li>Bit testing</li>
30 * <li>Getting of the lowest bit set</li>
32 * All operations are provided in immutable way, and some in both mutable and
37 /** Just to denote that this class can't be instantiated. */
40 /** @see BigInteger#bitLength() */
41 static int bitLength(BigInteger val) {
42 // BEGIN android-added
43 val.establishOldRepresentation("BitLevel.bitLength");
48 int bLength = (val.numberLength << 5);
49 int highDigit = val.digits[val.numberLength - 1];
52 int i = val.getFirstNonzeroDigit();
53 // We reduce the problem to the positive case.
54 if (i == val.numberLength - 1) {
58 // Subtracting all sign bits
59 bLength -= Integer.numberOfLeadingZeros(highDigit);
63 /** @see BigInteger#bitCount() */
64 static int bitCount(BigInteger val) {
65 // BEGIN android-added
66 val.establishOldRepresentation("BitLevel.bitCount");
74 int i = val.getFirstNonzeroDigit();;
76 for ( ; i < val.numberLength; i++) {
77 bCount += Integer.bitCount(val.digits[i]);
80 // this digit absorbs the carry
81 bCount += Integer.bitCount(-val.digits[i]);
82 for (i++; i < val.numberLength; i++) {
83 bCount += Integer.bitCount(~val.digits[i]);
85 // We take the complement sum:
86 bCount = (val.numberLength << 5) - bCount;
92 * Performs a fast bit testing for positive numbers. The bit to to be tested
93 * must be in the range {@code [0, val.bitLength()-1]}
95 static boolean testBit(BigInteger val, int n) {
96 // BEGIN android-added
97 val.establishOldRepresentation("BitLevel.testBit");
99 // PRE: 0 <= n < val.bitLength()
100 return ((val.digits[n >> 5] & (1 << (n & 31))) != 0);
104 * Check if there are 1s in the lowest bits of this BigInteger
106 * @param numberOfBits the number of the lowest bits to check
107 * @return false if all bits are 0s, true otherwise
109 static boolean nonZeroDroppedBits(int numberOfBits, int digits[]) {
110 int intCount = numberOfBits >> 5;
111 int bitCount = numberOfBits & 31;
114 for (i = 0; (i < intCount) && (digits[i] == 0); i++) {
117 return ((i != intCount) || (digits[i] << (32 - bitCount) != 0));
120 // BEGIN android-removed
121 // /** @see BigInteger#shiftLeft(int) */
122 // static BigInteger shiftLeft(BigInteger source, int count) {
123 // int intCount = count >> 5;
124 // count &= 31; // %= 32
125 // int resLength = source.numberLength + intCount
126 // + ( ( count == 0 ) ? 0 : 1 );
127 // int resDigits[] = new int[resLength];
129 // shiftLeft(resDigits, source.digits, intCount, count);
130 // BigInteger result = new BigInteger(source.sign, resLength, resDigits);
131 // result.cutOffLeadingZeroes();
136 // * Performs {@code val <<= count}.
138 // // val should have enough place (and one digit more)
139 // static void inplaceShiftLeft(BigInteger val, int count) {
140 // int intCount = count >> 5; // count of integers
141 // val.numberLength += intCount
143 // .numberOfLeadingZeros(val.digits[val.numberLength - 1])
144 // - ( count & 31 ) >= 0 ? 0 : 1 );
145 // shiftLeft(val.digits, val.digits, intCount, count & 31);
146 // val.cutOffLeadingZeroes();
151 // * Abstractly shifts left an array of integers in little endian (i.e. shift
152 // * it right). Total shift distance in bits is intCount * 32 + count
154 // * @param result the destination array
155 // * @param source the source array
156 // * @param intCount the shift distance in integers
157 // * @param count an additional shift distance in bits
159 // static void shiftLeft(int result[], int source[], int intCount, int count) {
161 // System.arraycopy(source, 0, result, intCount, result.length
164 // int rightShiftCount = 32 - count;
166 // result[result.length - 1] = 0;
167 // for (int i = result.length - 1; i > intCount; i--) {
168 // result[i] |= source[i - intCount - 1] >>> rightShiftCount;
169 // result[i - 1] = source[i - intCount - 1] << count;
173 // for (int i = 0; i < intCount; i++) {
177 // END android-removed
179 static void shiftLeftOneBit(int result[], int source[], int srcLen) {
181 for(int i = 0; i < srcLen; i++) {
183 result[i] = (val << 1) | carry;
187 result[srcLen] = carry;
191 static BigInteger shiftLeftOneBit(BigInteger source) {
192 int srcLen = source.numberLength;
193 int resLen = srcLen + 1;
194 int resDigits[] = new int[resLen];
195 shiftLeftOneBit(resDigits, source.digits, srcLen);
196 BigInteger result = new BigInteger(source.sign, resLen, resDigits);
197 result.cutOffLeadingZeroes();
201 /** @see BigInteger#shiftRight(int) */
202 static BigInteger shiftRight(BigInteger source, int count) {
203 // BEGIN android-added
204 source.establishOldRepresentation("BitLevel.shiftRight");
206 int intCount = count >> 5; // count of integers
207 count &= 31; // count of remaining bits
208 if (intCount >= source.numberLength) {
209 return ((source.sign < 0) ? BigInteger.MINUS_ONE : BigInteger.ZERO);
212 int resLength = source.numberLength - intCount;
213 int resDigits[] = new int[resLength + 1];
215 shiftRight(resDigits, resLength, source.digits, intCount, count);
216 if (source.sign < 0) {
217 // Checking if the dropped bits are zeros (the remainder equals to
219 for (i = 0; (i < intCount) && (source.digits[i] == 0); i++) {
222 // If the remainder is not zero, add 1 to the result
224 || ((count > 0) && ((source.digits[i] << (32 - count)) != 0))) {
225 for (i = 0; (i < resLength) && (resDigits[i] == -1); i++) {
228 if (i == resLength) {
234 BigInteger result = new BigInteger(source.sign, resLength, resDigits);
235 result.cutOffLeadingZeroes();
240 * Performs {@code val >>= count} where {@code val} is a positive number.
242 static void inplaceShiftRight(BigInteger val, int count) {
243 // BEGIN android-added
244 val.establishOldRepresentation("BitLevel.inplaceShiftRight");
246 int sign = val.signum();
247 if (count == 0 || val.signum() == 0)
249 int intCount = count >> 5; // count of integers
250 val.numberLength -= intCount;
251 if (!shiftRight(val.digits, val.numberLength, val.digits, intCount,
254 // remainder not zero: add one to the result
256 for (i = 0; ( i < val.numberLength ) && ( val.digits[i] == -1 ); i++) {
259 if (i == val.numberLength) {
264 val.cutOffLeadingZeroes();
269 * Shifts right an array of integers. Total shift distance in bits is
270 * intCount * 32 + count.
273 * the destination array
275 * the destination array's length
279 * the number of elements to be shifted
281 * the number of bits to be shifted
282 * @return dropped bit's are all zero (i.e. remaider is zero)
284 static boolean shiftRight(int result[], int resultLen, int source[],
285 int intCount, int count) {
287 boolean allZero = true;
288 for (i = 0; i < intCount; i++)
289 allZero &= source[i] == 0;
291 System.arraycopy(source, intCount, result, 0, resultLen);
294 int leftShiftCount = 32 - count;
296 allZero &= ( source[i] << leftShiftCount ) == 0;
297 for (i = 0; i < resultLen - 1; i++) {
298 result[i] = ( source[i + intCount] >>> count )
299 | ( source[i + intCount + 1] << leftShiftCount );
301 result[i] = ( source[i + intCount] >>> count );
310 * Performs a flipBit on the BigInteger, returning a BigInteger with the the
311 * specified bit flipped.
312 * @param intCount: the index of the element of the digits array where the operation will be performed
313 * @param bitNumber: the bit's position in the intCount element
315 static BigInteger flipBit(BigInteger val, int n){
316 // BEGIN android-added
317 val.establishOldRepresentation("BitLevel.flipBit");
319 int resSign = (val.sign == 0) ? 1 : val.sign;
320 int intCount = n >> 5;
322 int resLength = Math.max(intCount + 1, val.numberLength) + 1;
323 int resDigits[] = new int[resLength];
326 int bitNumber = 1 << bitN;
327 System.arraycopy(val.digits, 0, resDigits, 0, val.numberLength);
330 if (intCount >= val.numberLength) {
331 resDigits[intCount] = bitNumber;
333 //val.sign<0 y intCount < val.numberLength
334 int firstNonZeroDigit = val.getFirstNonzeroDigit();
335 if (intCount > firstNonZeroDigit) {
336 resDigits[intCount] ^= bitNumber;
337 } else if (intCount < firstNonZeroDigit) {
338 resDigits[intCount] = -bitNumber;
339 for (i=intCount + 1; i < firstNonZeroDigit; i++) {
342 resDigits[i] = resDigits[i]--;
345 resDigits[i] = -((-resDigits[intCount]) ^ bitNumber);
346 if (resDigits[i] == 0) {
347 for (i++; resDigits[i] == -1 ; i++) {
354 } else {//case where val is positive
355 resDigits[intCount] ^= bitNumber;
357 BigInteger result = new BigInteger(resSign, resLength, resDigits);
358 result.cutOffLeadingZeroes();