1 /* 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 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 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. 16 */ 17 18 package java.math; 19 20 /** 21 * Static library that provides all the <b>bit level</b> operations for 22 * {@link BigInteger}. The operations are: 23 * <ul type="circle"> 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> 31 * </ul> 32 * All operations are provided in immutable way, and some in both mutable and 33 * immutable. 34 */ 35 class BitLevel { 36 37 /** Just to denote that this class can't be instantiated. */ 38 private BitLevel() {} 39 40 /** @see BigInteger#bitLength() */ 41 static int bitLength(BigInteger val) { 42 // BEGIN android-added 43 val.establishOldRepresentation("BitLevel.bitLength"); 44 // END android-added 45 if (val.sign == 0) { 46 return 0; 47 } 48 int bLength = (val.numberLength << 5); 49 int highDigit = val.digits[val.numberLength - 1]; 50 51 if (val.sign < 0) { 52 int i = val.getFirstNonzeroDigit(); 53 // We reduce the problem to the positive case. 54 if (i == val.numberLength - 1) { 55 highDigit--; 56 } 57 } 58 // Subtracting all sign bits 59 bLength -= Integer.numberOfLeadingZeros(highDigit); 60 return bLength; 61 } 62 63 /** @see BigInteger#bitCount() */ 64 static int bitCount(BigInteger val) { 65 // BEGIN android-added 66 val.establishOldRepresentation("BitLevel.bitCount"); 67 // END android-added 68 int bCount = 0; 69 70 if (val.sign == 0) { 71 return 0; 72 } 73 74 int i = val.getFirstNonzeroDigit();; 75 if (val.sign > 0) { 76 for ( ; i < val.numberLength; i++) { 77 bCount += Integer.bitCount(val.digits[i]); 78 } 79 } else {// (sign < 0) 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]); 84 } 85 // We take the complement sum: 86 bCount = (val.numberLength << 5) - bCount; 87 } 88 return bCount; 89 } 90 91 /** 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]} 94 */ 95 static boolean testBit(BigInteger val, int n) { 96 // BEGIN android-added 97 val.establishOldRepresentation("BitLevel.testBit"); 98 // END android-added 99 // PRE: 0 <= n < val.bitLength() 100 return ((val.digits[n >> 5] & (1 << (n & 31))) != 0); 101 } 102 103 /** 104 * Check if there are 1s in the lowest bits of this BigInteger 105 * 106 * @param numberOfBits the number of the lowest bits to check 107 * @return false if all bits are 0s, true otherwise 108 */ 109 static boolean nonZeroDroppedBits(int numberOfBits, int digits[]) { 110 int intCount = numberOfBits >> 5; 111 int bitCount = numberOfBits & 31; 112 int i; 113 114 for (i = 0; (i < intCount) && (digits[i] == 0); i++) { 115 ; 116 } 117 return ((i != intCount) || (digits[i] << (32 - bitCount) != 0)); 118 } 119 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]; 128 // 129 // shiftLeft(resDigits, source.digits, intCount, count); 130 // BigInteger result = new BigInteger(source.sign, resLength, resDigits); 131 // result.cutOffLeadingZeroes(); 132 // return result; 133 // } 134 // 135 // /** 136 // * Performs {@code val <<= count}. 137 // */ 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 142 // + ( Integer 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(); 147 // val.unCache(); 148 // } 149 // 150 // /** 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 153 // * 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 158 // */ 159 // static void shiftLeft(int result[], int source[], int intCount, int count) { 160 // if (count == 0) { 161 // System.arraycopy(source, 0, result, intCount, result.length 162 // - intCount); 163 // } else { 164 // int rightShiftCount = 32 - count; 165 // 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; 170 // } 171 // } 172 // 173 // for (int i = 0; i < intCount; i++) { 174 // result[i] = 0; 175 // } 176 // } 177 // END android-removed 178 179 static void shiftLeftOneBit(int result[], int source[], int srcLen) { 180 int carry = 0; 181 for(int i = 0; i < srcLen; i++) { 182 int val = source[i]; 183 result[i] = (val << 1) | carry; 184 carry = val >>> 31; 185 } 186 if(carry != 0) { 187 result[srcLen] = carry; 188 } 189 } 190 191 static BigInteger shiftLeftOneBit(BigInteger source) { 192 // BEGIN android-added 193 source.establishOldRepresentation("BitLevel.shiftLeftOneBit"); 194 // END android-added 195 int srcLen = source.numberLength; 196 int resLen = srcLen + 1; 197 int resDigits[] = new int[resLen]; 198 shiftLeftOneBit(resDigits, source.digits, srcLen); 199 BigInteger result = new BigInteger(source.sign, resLen, resDigits); 200 result.cutOffLeadingZeroes(); 201 return result; 202 } 203 204 /** @see BigInteger#shiftRight(int) */ 205 static BigInteger shiftRight(BigInteger source, int count) { 206 // BEGIN android-added 207 source.establishOldRepresentation("BitLevel.shiftRight"); 208 // END android-added 209 int intCount = count >> 5; // count of integers 210 count &= 31; // count of remaining bits 211 if (intCount >= source.numberLength) { 212 return ((source.sign < 0) ? BigInteger.MINUS_ONE : BigInteger.ZERO); 213 } 214 int i; 215 int resLength = source.numberLength - intCount; 216 int resDigits[] = new int[resLength + 1]; 217 218 shiftRight(resDigits, resLength, source.digits, intCount, count); 219 if (source.sign < 0) { 220 // Checking if the dropped bits are zeros (the remainder equals to 221 // 0) 222 for (i = 0; (i < intCount) && (source.digits[i] == 0); i++) { 223 ; 224 } 225 // If the remainder is not zero, add 1 to the result 226 if ((i < intCount) 227 || ((count > 0) && ((source.digits[i] << (32 - count)) != 0))) { 228 for (i = 0; (i < resLength) && (resDigits[i] == -1); i++) { 229 resDigits[i] = 0; 230 } 231 if (i == resLength) { 232 resLength++; 233 } 234 resDigits[i]++; 235 } 236 } 237 BigInteger result = new BigInteger(source.sign, resLength, resDigits); 238 result.cutOffLeadingZeroes(); 239 return result; 240 } 241 242 /** 243 * Performs {@code val >>= count} where {@code val} is a positive number. 244 */ 245 static void inplaceShiftRight(BigInteger val, int count) { 246 // BEGIN android-added 247 val.establishOldRepresentation("BitLevel.inplaceShiftRight"); 248 // END android-added 249 int sign = val.signum(); 250 if (count == 0 || val.signum() == 0) 251 return; 252 int intCount = count >> 5; // count of integers 253 val.numberLength -= intCount; 254 if (!shiftRight(val.digits, val.numberLength, val.digits, intCount, 255 count & 31) 256 && sign < 0) { 257 // remainder not zero: add one to the result 258 int i; 259 for (i = 0; ( i < val.numberLength ) && ( val.digits[i] == -1 ); i++) { 260 val.digits[i] = 0; 261 } 262 if (i == val.numberLength) { 263 val.numberLength++; 264 } 265 val.digits[i]++; 266 } 267 val.cutOffLeadingZeroes(); 268 val.unCache(); 269 } 270 271 /** 272 * Shifts right an array of integers. Total shift distance in bits is 273 * intCount * 32 + count. 274 * 275 * @param result 276 * the destination array 277 * @param resultLen 278 * the destination array's length 279 * @param source 280 * the source array 281 * @param intCount 282 * the number of elements to be shifted 283 * @param count 284 * the number of bits to be shifted 285 * @return dropped bit's are all zero (i.e. remaider is zero) 286 */ 287 static boolean shiftRight(int result[], int resultLen, int source[], 288 int intCount, int count) { 289 int i; 290 boolean allZero = true; 291 for (i = 0; i < intCount; i++) 292 allZero &= source[i] == 0; 293 if (count == 0) { 294 System.arraycopy(source, intCount, result, 0, resultLen); 295 i = resultLen; 296 } else { 297 int leftShiftCount = 32 - count; 298 299 allZero &= ( source[i] << leftShiftCount ) == 0; 300 for (i = 0; i < resultLen - 1; i++) { 301 result[i] = ( source[i + intCount] >>> count ) 302 | ( source[i + intCount + 1] << leftShiftCount ); 303 } 304 result[i] = ( source[i + intCount] >>> count ); 305 i++; 306 } 307 308 return allZero; 309 } 310 311 312 /** 313 * Performs a flipBit on the BigInteger, returning a BigInteger with the the 314 * specified bit flipped. 315 * @param intCount: the index of the element of the digits array where the operation will be performed 316 * @param bitNumber: the bit's position in the intCount element 317 */ 318 static BigInteger flipBit(BigInteger val, int n){ 319 // BEGIN android-added 320 val.establishOldRepresentation("BitLevel.flipBit"); 321 // END android-added 322 int resSign = (val.sign == 0) ? 1 : val.sign; 323 int intCount = n >> 5; 324 int bitN = n & 31; 325 int resLength = Math.max(intCount + 1, val.numberLength) + 1; 326 int resDigits[] = new int[resLength]; 327 int i; 328 329 int bitNumber = 1 << bitN; 330 System.arraycopy(val.digits, 0, resDigits, 0, val.numberLength); 331 332 if (val.sign < 0) { 333 if (intCount >= val.numberLength) { 334 resDigits[intCount] = bitNumber; 335 } else { 336 //val.sign<0 y intCount < val.numberLength 337 int firstNonZeroDigit = val.getFirstNonzeroDigit(); 338 if (intCount > firstNonZeroDigit) { 339 resDigits[intCount] ^= bitNumber; 340 } else if (intCount < firstNonZeroDigit) { 341 resDigits[intCount] = -bitNumber; 342 for (i=intCount + 1; i < firstNonZeroDigit; i++) { 343 resDigits[i]=-1; 344 } 345 resDigits[i] = resDigits[i]--; 346 } else { 347 i = intCount; 348 resDigits[i] = -((-resDigits[intCount]) ^ bitNumber); 349 if (resDigits[i] == 0) { 350 for (i++; resDigits[i] == -1 ; i++) { 351 resDigits[i] = 0; 352 } 353 resDigits[i]++; 354 } 355 } 356 } 357 } else {//case where val is positive 358 resDigits[intCount] ^= bitNumber; 359 } 360 BigInteger result = new BigInteger(resSign, resLength, resDigits); 361 result.cutOffLeadingZeroes(); 362 return result; 363 } 364 } 365