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 {@link BigInteger} base conversion from/to any 22 * integer represented in an {@link java.lang.String} Object. 23 */ 24 class Conversion { 25 26 /** Just to denote that this class can't be instantiated */ 27 private Conversion() {} 28 29 /** 30 * Holds the maximal exponent for each radix, so that radix<sup>digitFitInInt[radix]</sup> 31 * fit in an {@code int} (32 bits). 32 */ 33 static final int[] digitFitInInt = { -1, -1, 31, 19, 15, 13, 11, 34 11, 10, 9, 9, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 35 6, 6, 6, 6, 6, 6, 6, 5 }; 36 37 /** 38 * bigRadices values are precomputed maximal powers of radices (integer 39 * numbers from 2 to 36) that fit into unsigned int (32 bits). bigRadices[0] = 40 * 2 ^ 31, bigRadices[8] = 10 ^ 9, etc. 41 */ 42 43 static final int bigRadices[] = { -2147483648, 1162261467, 44 1073741824, 1220703125, 362797056, 1977326743, 1073741824, 45 387420489, 1000000000, 214358881, 429981696, 815730721, 1475789056, 46 170859375, 268435456, 410338673, 612220032, 893871739, 1280000000, 47 1801088541, 113379904, 148035889, 191102976, 244140625, 308915776, 48 387420489, 481890304, 594823321, 729000000, 887503681, 1073741824, 49 1291467969, 1544804416, 1838265625, 60466176 }; 50 51 52 /** @see BigInteger#toString(int) */ 53 static String bigInteger2String(BigInteger val, int radix) { 54 // BEGIN android-added 55 val.establishOldRepresentation("Conversion.bigInteger2String"); 56 // END android-added 57 int sign = val.sign; 58 int numberLength = val.numberLength; 59 int digits[] = val.digits; 60 61 if (sign == 0) { 62 return "0"; //$NON-NLS-1$ 63 } 64 if (numberLength == 1) { 65 int highDigit = digits[numberLength - 1]; 66 long v = highDigit & 0xFFFFFFFFL; 67 if (sign < 0) { 68 v = -v; 69 } 70 return Long.toString(v, radix); 71 } 72 if ((radix == 10) || (radix < Character.MIN_RADIX) 73 || (radix > Character.MAX_RADIX)) { 74 return val.toString(); 75 } 76 double bitsForRadixDigit; 77 bitsForRadixDigit = Math.log(radix) / Math.log(2); 78 int resLengthInChars = (int) (val.abs().bitLength() / bitsForRadixDigit + ((sign < 0) ? 1 79 : 0)) + 1; 80 81 char result[] = new char[resLengthInChars]; 82 int currentChar = resLengthInChars; 83 int resDigit; 84 if (radix != 16) { 85 int temp[] = new int[numberLength]; 86 System.arraycopy(digits, 0, temp, 0, numberLength); 87 int tempLen = numberLength; 88 int charsPerInt = digitFitInInt[radix]; 89 int i; 90 // get the maximal power of radix that fits in int 91 int bigRadix = bigRadices[radix - 2]; 92 while (true) { 93 // divide the array of digits by bigRadix and convert remainders 94 // to characters collecting them in the char array 95 resDigit = Division.divideArrayByInt(temp, temp, tempLen, 96 bigRadix); 97 int previous = currentChar; 98 do { 99 result[--currentChar] = Character.forDigit( 100 resDigit % radix, radix); 101 } while (((resDigit /= radix) != 0) && (currentChar != 0)); 102 int delta = charsPerInt - previous + currentChar; 103 for (i = 0; i < delta && currentChar > 0; i++) { 104 result[--currentChar] = '0'; 105 } 106 for (i = tempLen - 1; (i > 0) && (temp[i] == 0); i--) { 107 ; 108 } 109 tempLen = i + 1; 110 if ((tempLen == 1) && (temp[0] == 0)) { // the quotient is 0 111 break; 112 } 113 } 114 } else { 115 // radix == 16 116 for (int i = 0; i < numberLength; i++) { 117 for (int j = 0; (j < 8) && (currentChar > 0); j++) { 118 resDigit = digits[i] >> (j << 2) & 0xf; 119 result[--currentChar] = Character.forDigit(resDigit, 16); 120 } 121 } 122 } 123 while (result[currentChar] == '0') { 124 currentChar++; 125 } 126 if (sign == -1) { 127 result[--currentChar] = '-'; 128 } 129 return new String(result, currentChar, resLengthInChars - currentChar); 130 } 131 132 /** 133 * Builds the correspondent {@code String} representation of {@code val} 134 * being scaled by {@code scale}. 135 * 136 * @see BigInteger#toString() 137 * @see BigDecimal#toString() 138 */ 139 static String toDecimalScaledString(BigInteger val, int scale) { 140 // BEGIN android-added 141 val.establishOldRepresentation("Conversion.toDecimalScaledString"); 142 // END android-added 143 int sign = val.sign; 144 int numberLength = val.numberLength; 145 int digits[] = val.digits; 146 int resLengthInChars; 147 int currentChar; 148 char result[]; 149 150 if (sign == 0) { 151 switch (scale) { 152 case 0: 153 return "0"; //$NON-NLS-1$ 154 case 1: 155 return "0.0"; //$NON-NLS-1$ 156 case 2: 157 return "0.00"; //$NON-NLS-1$ 158 case 3: 159 return "0.000"; //$NON-NLS-1$ 160 case 4: 161 return "0.0000"; //$NON-NLS-1$ 162 case 5: 163 return "0.00000"; //$NON-NLS-1$ 164 case 6: 165 return "0.000000"; //$NON-NLS-1$ 166 default: 167 StringBuffer result1 = new StringBuffer(); 168 if (scale < 0) { 169 result1.append("0E+"); //$NON-NLS-1$ 170 } else { 171 result1.append("0E"); //$NON-NLS-1$ 172 } 173 result1.append(-scale); 174 return result1.toString(); 175 } 176 } 177 // one 32-bit unsigned value may contains 10 decimal digits 178 resLengthInChars = numberLength * 10 + 1 + 7; 179 // Explanation why +1+7: 180 // +1 - one char for sign if needed. 181 // +7 - For "special case 2" (see below) we have 7 free chars for 182 // inserting necessary scaled digits. 183 result = new char[resLengthInChars + 1]; 184 // allocated [resLengthInChars+1] characters. 185 // a free latest character may be used for "special case 1" (see 186 // below) 187 currentChar = resLengthInChars; 188 if (numberLength == 1) { 189 int highDigit = digits[0]; 190 if (highDigit < 0) { 191 long v = highDigit & 0xFFFFFFFFL; 192 do { 193 long prev = v; 194 v /= 10; 195 result[--currentChar] = (char) (0x0030 + ((int) (prev - v * 10))); 196 } while (v != 0); 197 } else { 198 int v = highDigit; 199 do { 200 int prev = v; 201 v /= 10; 202 result[--currentChar] = (char) (0x0030 + (prev - v * 10)); 203 } while (v != 0); 204 } 205 } else { 206 int temp[] = new int[numberLength]; 207 int tempLen = numberLength; 208 System.arraycopy(digits, 0, temp, 0, tempLen); 209 BIG_LOOP: while (true) { 210 // divide the array of digits by bigRadix and convert 211 // remainders 212 // to characters collecting them in the char array 213 long result11 = 0; 214 for (int i1 = tempLen - 1; i1 >= 0; i1--) { 215 long temp1 = (result11 << 32) 216 + (temp[i1] & 0xFFFFFFFFL); 217 long res = divideLongByBillion(temp1); 218 temp[i1] = (int) res; 219 result11 = (int) (res >> 32); 220 } 221 int resDigit = (int) result11; 222 int previous = currentChar; 223 do { 224 result[--currentChar] = (char) (0x0030 + (resDigit % 10)); 225 } while (((resDigit /= 10) != 0) && (currentChar != 0)); 226 int delta = 9 - previous + currentChar; 227 for (int i = 0; (i < delta) && (currentChar > 0); i++) { 228 result[--currentChar] = '0'; 229 } 230 int j = tempLen - 1; 231 for (; temp[j] == 0; j--) { 232 if (j == 0) { // means temp[0] == 0 233 break BIG_LOOP; 234 } 235 } 236 tempLen = j + 1; 237 } 238 while (result[currentChar] == '0') { 239 currentChar++; 240 } 241 } 242 boolean negNumber = (sign < 0); 243 int exponent = resLengthInChars - currentChar - scale - 1; 244 if (scale == 0) { 245 if (negNumber) { 246 result[--currentChar] = '-'; 247 } 248 return new String(result, currentChar, resLengthInChars 249 - currentChar); 250 } 251 if ((scale > 0) && (exponent >= -6)) { 252 if (exponent >= 0) { 253 // special case 1 254 int insertPoint = currentChar + exponent; 255 for (int j = resLengthInChars - 1; j >= insertPoint; j--) { 256 result[j + 1] = result[j]; 257 } 258 result[++insertPoint] = '.'; 259 if (negNumber) { 260 result[--currentChar] = '-'; 261 } 262 return new String(result, currentChar, resLengthInChars 263 - currentChar + 1); 264 } 265 // special case 2 266 for (int j = 2; j < -exponent + 1; j++) { 267 result[--currentChar] = '0'; 268 } 269 result[--currentChar] = '.'; 270 result[--currentChar] = '0'; 271 if (negNumber) { 272 result[--currentChar] = '-'; 273 } 274 return new String(result, currentChar, resLengthInChars 275 - currentChar); 276 } 277 int startPoint = currentChar + 1; 278 int endPoint = resLengthInChars; 279 StringBuffer result1 = new StringBuffer(16 + endPoint - startPoint); 280 if (negNumber) { 281 result1.append('-'); 282 } 283 if (endPoint - startPoint >= 1) { 284 result1.append(result[currentChar]); 285 result1.append('.'); 286 result1.append(result, currentChar + 1, resLengthInChars 287 - currentChar - 1); 288 } else { 289 result1.append(result, currentChar, resLengthInChars 290 - currentChar); 291 } 292 result1.append('E'); 293 if (exponent > 0) { 294 result1.append('+'); 295 } 296 result1.append(Integer.toString(exponent)); 297 return result1.toString(); 298 } 299 300 /* can process only 32-bit numbers */ 301 static String toDecimalScaledString(long value, int scale) { 302 int resLengthInChars; 303 int currentChar; 304 char result[]; 305 boolean negNumber = value < 0; 306 if(negNumber) { 307 value = -value; 308 } 309 if (value == 0) { 310 switch (scale) { 311 case 0: return "0"; //$NON-NLS-1$ 312 case 1: return "0.0"; //$NON-NLS-1$ 313 case 2: return "0.00"; //$NON-NLS-1$ 314 case 3: return "0.000"; //$NON-NLS-1$ 315 case 4: return "0.0000"; //$NON-NLS-1$ 316 case 5: return "0.00000"; //$NON-NLS-1$ 317 case 6: return "0.000000"; //$NON-NLS-1$ 318 default: 319 StringBuffer result1 = new StringBuffer(); 320 if (scale < 0) { 321 result1.append("0E+"); //$NON-NLS-1$ 322 } else { 323 result1.append("0E"); //$NON-NLS-1$ 324 } 325 result1.append( (scale == Integer.MIN_VALUE) ? "2147483648" : Integer.toString(-scale)); //$NON-NLS-1$ 326 return result1.toString(); 327 } 328 } 329 // one 32-bit unsigned value may contains 10 decimal digits 330 resLengthInChars = 18; 331 // Explanation why +1+7: 332 // +1 - one char for sign if needed. 333 // +7 - For "special case 2" (see below) we have 7 free chars for 334 // inserting necessary scaled digits. 335 result = new char[resLengthInChars+1]; 336 // Allocated [resLengthInChars+1] characters. 337 // a free latest character may be used for "special case 1" (see below) 338 currentChar = resLengthInChars; 339 long v = value; 340 do { 341 long prev = v; 342 v /= 10; 343 result[--currentChar] = (char) (0x0030 + (prev - v * 10)); 344 } while (v != 0); 345 346 long exponent = (long)resLengthInChars - (long)currentChar - scale - 1L; 347 if (scale == 0) { 348 if (negNumber) { 349 result[--currentChar] = '-'; 350 } 351 return new String(result, currentChar, resLengthInChars - currentChar); 352 } 353 if (scale > 0 && exponent >= -6) { 354 if (exponent >= 0) { 355 // special case 1 356 int insertPoint = currentChar + (int) exponent ; 357 for(int j=resLengthInChars-1; j>=insertPoint; j--) { 358 result[j+1] = result[j]; 359 } 360 result[++insertPoint]='.'; 361 if (negNumber) { 362 result[--currentChar] = '-'; 363 } 364 return new String(result, currentChar, resLengthInChars - currentChar + 1); 365 } 366 // special case 2 367 for (int j = 2; j < -exponent + 1; j++) { 368 result[--currentChar] = '0'; 369 } 370 result[--currentChar] = '.'; 371 result[--currentChar] = '0'; 372 if (negNumber) { 373 result[--currentChar] = '-'; 374 } 375 return new String(result, currentChar, resLengthInChars - currentChar); 376 } 377 int startPoint = currentChar + 1; 378 int endPoint = resLengthInChars; 379 StringBuffer result1 = new StringBuffer(16+endPoint-startPoint); 380 if (negNumber) { 381 result1.append('-'); 382 } 383 if (endPoint - startPoint >= 1) { 384 result1.append(result[currentChar]); 385 result1.append('.'); 386 result1.append(result,currentChar+1,resLengthInChars - currentChar-1); 387 } else { 388 result1.append(result,currentChar,resLengthInChars - currentChar); 389 } 390 result1.append('E'); 391 if (exponent > 0) { 392 result1.append('+'); 393 } 394 result1.append(Long.toString(exponent)); 395 return result1.toString(); 396 } 397 398 static long divideLongByBillion(long a) { 399 long quot; 400 long rem; 401 402 if (a >= 0) { 403 long bLong = 1000000000L; 404 quot = (a / bLong); 405 rem = (a % bLong); 406 } else { 407 /* 408 * Make the dividend positive shifting it right by 1 bit then get 409 * the quotient an remainder and correct them properly 410 */ 411 long aPos = a >>> 1; 412 long bPos = 1000000000L >>> 1; 413 quot = aPos / bPos; 414 rem = aPos % bPos; 415 // double the remainder and add 1 if 'a' is odd 416 rem = (rem << 1) + (a & 1); 417 } 418 return ((rem << 32) | (quot & 0xFFFFFFFFL)); 419 } 420 421 /** @see BigInteger#doubleValue() */ 422 static double bigInteger2Double(BigInteger val) { 423 // BEGIN android-added 424 val.establishOldRepresentation("Conversion.bigInteger2Double"); 425 // END android-added 426 // val.bitLength() < 64 427 if ((val.numberLength < 2) 428 || ((val.numberLength == 2) && (val.digits[1] > 0))) { 429 return val.longValue(); 430 } 431 // val.bitLength() >= 33 * 32 > 1024 432 if (val.numberLength > 32) { 433 return ((val.sign > 0) ? Double.POSITIVE_INFINITY 434 : Double.NEGATIVE_INFINITY); 435 } 436 int bitLen = val.abs().bitLength(); 437 long exponent = bitLen - 1; 438 int delta = bitLen - 54; 439 // We need 54 top bits from this, the 53th bit is always 1 in lVal. 440 long lVal = val.abs().shiftRight(delta).longValue(); 441 /* 442 * Take 53 bits from lVal to mantissa. The least significant bit is 443 * needed for rounding. 444 */ 445 long mantissa = lVal & 0x1FFFFFFFFFFFFFL; 446 if (exponent == 1023) { 447 if (mantissa == 0X1FFFFFFFFFFFFFL) { 448 return ((val.sign > 0) ? Double.POSITIVE_INFINITY 449 : Double.NEGATIVE_INFINITY); 450 } 451 if (mantissa == 0x1FFFFFFFFFFFFEL) { 452 return ((val.sign > 0) ? Double.MAX_VALUE : -Double.MAX_VALUE); 453 } 454 } 455 // Round the mantissa 456 if (((mantissa & 1) == 1) 457 && (((mantissa & 2) == 2) || BitLevel.nonZeroDroppedBits(delta, 458 val.digits))) { 459 mantissa += 2; 460 } 461 mantissa >>= 1; // drop the rounding bit 462 long resSign = (val.sign < 0) ? 0x8000000000000000L : 0; 463 exponent = ((1023 + exponent) << 52) & 0x7FF0000000000000L; 464 long result = resSign | exponent | mantissa; 465 return Double.longBitsToDouble(result); 466 } 467 } 468