Index: src/main/java/java/math/BigInteger.java =================================================================== --- src/main/java/java/math/BigInteger.java (revision 501416) +++ src/main/java/java/math/BigInteger.java (working copy) @@ -141,10 +141,7 @@ // math.12=Zero length BigInteger throw new NumberFormatException(Messages.getString("math.12")); //$NON-NLS-1$ } - BigInteger me = Conversion.string2BigInteger(val, radix); - sign = me.sign; - numberLength = me.numberLength; - digits = me.digits; + setFromString(this, val, radix); } /** @ar.org.fitc.spec_ref */ @@ -272,6 +269,7 @@ return new BigInteger(1, val); } } + /** @ar.org.fitc.spec_ref */ public byte[] toByteArray() { @@ -337,7 +335,65 @@ } return bytes; } + + /** @see BigInteger#BigInteger(String, int) */ + private static void setFromString(BigInteger bi, String val, int radix) { + int sign; + int[] digits; + int numberLength; + int stringLength = val.length(); + int startChar; + int endChar = stringLength; + if (val.charAt(0) == '-') { + sign = -1; + startChar = 1; + stringLength--; + } else { + sign = 1; + startChar = 0; + } + /* + * We use the following algorithm: split a string into portions of n + * characters and convert each portion to an integer according to the + * radix. Then convert an exp(radix, n) based number to binary using the + * multiplication method. See D. Knuth, The Art of Computer Programming, + * vol. 2. + */ + + int charsPerInt = Conversion.digitFitInInt[radix]; + int bigRadixDigitsLength = stringLength / charsPerInt; + int topChars = stringLength % charsPerInt; + + if (topChars != 0) { + bigRadixDigitsLength++; + } + digits = new int[bigRadixDigitsLength]; + // Get the maximal power of radix that fits in int + int bigRadix = Conversion.bigRadices[radix - 2]; + // Parse an input string and accumulate the BigInteger's magnitude + int digitIndex = 0; // index of digits array + int substrEnd = startChar + ((topChars == 0) ? charsPerInt : topChars); + int newDigit; + + for (int substrStart = startChar; substrStart < endChar; substrStart = substrEnd, substrEnd = substrStart + + charsPerInt) { + int bigRadixDigit = Integer.parseInt(val.substring(substrStart, + substrEnd), radix); + newDigit = Multiplication.multiplyByInt(digits, digitIndex, + bigRadix); + newDigit += Elementary + .inplaceAdd(digits, digitIndex, bigRadixDigit); + digits[digitIndex++] = newDigit; + } + numberLength = digitIndex; + bi.sign = sign; + bi.numberLength = numberLength; + bi.digits = digits; + bi.cutOffLeadingZeroes(); + } + + /** @ar.org.fitc.spec_ref */ public BigInteger abs() { return ((sign < 0) ? new BigInteger(1, numberLength, digits) : this); Index: src/main/java/java/math/BigDecimal.java =================================================================== --- src/main/java/java/math/BigDecimal.java (revision 501416) +++ src/main/java/java/math/BigDecimal.java (working copy) @@ -232,7 +232,7 @@ int begin = offset; // first index to be copied int last = offset + (len - 1); // last index to be copied String scaleString = null; // buffer for scale - StringBuffer unscaledBuffer; // buffer for unscaled value + StringBuilder unscaledBuffer; // buffer for unscaled value long newScale; // the new scale if (in == null) { @@ -241,18 +241,29 @@ if ((last >= in.length) || (offset < 0) || (len <= 0) || (last < 0)) { throw new NumberFormatException(); } - unscaledBuffer = new StringBuffer(len); + unscaledBuffer = new StringBuilder(len); + int bufLength = 0; // To skip a possible '+' symbol if ((offset <= last) && (in[offset] == '+')) { offset++; begin++; } + int counter = 0; + boolean wasNonZero = false; // Accumulating all digits until a possible decimal point for (; (offset <= last) && (in[offset] != '.') && (in[offset] != 'e') && (in[offset] != 'E'); offset++) { - ; + if (!wasNonZero) { + if (in[offset] == '0') { + counter++; + } else { + wasNonZero = true; + } + }; + } unscaledBuffer.append(in, begin, offset - begin); + bufLength += offset - begin; // A decimal point was found if ((offset <= last) && (in[offset] == '.')) { offset++; @@ -260,9 +271,16 @@ begin = offset; for (; (offset <= last) && (in[offset] != 'e') && (in[offset] != 'E'); offset++) { - ; + if (!wasNonZero) { + if (in[offset] == '0') { + counter++; + } else { + wasNonZero = true; + } + }; } scale = offset - begin; + bufLength +=scale; unscaledBuffer.append(in, begin, scale); } else { scale = 0; @@ -289,7 +307,16 @@ } } // Parsing the unscaled value - setUnscaledValue(new BigInteger(unscaledBuffer.toString())); + if (bufLength < 19) { + smallValue = Long.parseLong(unscaledBuffer.toString()); + bitLength = bitLength(smallValue); + } else { + setUnscaledValue(new BigInteger(unscaledBuffer.toString())); + } + precision = unscaledBuffer.length() - counter; + if (unscaledBuffer.charAt(0) == '-') { + precision --; + } } /** @ar.org.fitc.spec_ref */ @@ -1722,10 +1749,13 @@ * @see #round(MathContext). */ private void inplaceRound(MathContext mc) { - int mcPrecision = mc.getPrecision(); + int mcPrecision = mc.getPrecision(); + if (aproxPrecision() - mcPrecision <= 0 || mcPrecision == 0) { + return; + } int discardedPrecision = precision() - mcPrecision; // If no rounding is necessary it returns immediately - if ((discardedPrecision <= 0) || (mcPrecision == 0)) { + if ((discardedPrecision <= 0)) { return; } // When the number is small perform an efficient rounding Index: src/main/java/java/math/Conversion.java =================================================================== --- src/main/java/java/math/Conversion.java (revision 501416) +++ src/main/java/java/math/Conversion.java (working copy) @@ -33,7 +33,7 @@ * Holds the maximal exponent for each radix, so that radixdigitFitInInt[radix] * fit in an {@code int} (32 bits). */ - private static final int[] digitFitInInt = { -1, -1, 31, 19, 15, 13, 11, + static final int[] digitFitInInt = { -1, -1, 31, 19, 15, 13, 11, 11, 10, 9, 9, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5 }; @@ -43,7 +43,7 @@ * 2 ^ 31, bigRadices[8] = 10 ^ 9, etc. */ - private static final int bigRadices[] = { -2147483648, 1162261467, + static final int bigRadices[] = { -2147483648, 1162261467, 1073741824, 1220703125, 362797056, 1977326743, 1073741824, 387420489, 1000000000, 214358881, 429981696, 815730721, 1475789056, 170859375, 268435456, 410338673, 612220032, 893871739, 1280000000, @@ -51,63 +51,7 @@ 387420489, 481890304, 594823321, 729000000, 887503681, 1073741824, 1291467969, 1544804416, 1838265625, 60466176 }; - /** @see BigInteger#BigInteger(String, int) */ - static BigInteger string2BigInteger(String val, int radix) { - int sign; - int[] digits; - int numberLength; - int stringLength = val.length(); - int startChar; - int endChar = stringLength; - - if (val.charAt(0) == '-') { - sign = -1; - startChar = 1; - stringLength--; - } else { - sign = 1; - startChar = 0; - } - /* - * We use the following algorithm: split a string into portions of n - * characters and convert each portion to an integer according to the - * radix. Then convert an exp(radix, n) based number to binary using the - * multiplication method. See D. Knuth, The Art of Computer Programming, - * vol. 2. - */ - - int charsPerInt = digitFitInInt[radix]; - int bigRadixDigitsLength = stringLength / charsPerInt; - int topChars = stringLength % charsPerInt; - - if (topChars != 0) { - bigRadixDigitsLength++; - } - digits = new int[bigRadixDigitsLength]; - // Get the maximal power of radix that fits in int - int bigRadix = bigRadices[radix - 2]; - // Parse an input string and accumulate the BigInteger's magnitude - int digitIndex = 0; // index of digits array - int substrEnd = startChar + ((topChars == 0) ? charsPerInt : topChars); - int newDigit; - BigInteger result; - - for (int substrStart = startChar; substrStart < endChar; substrStart = substrEnd, substrEnd = substrStart - + charsPerInt) { - int bigRadixDigit = Integer.parseInt(val.substring(substrStart, - substrEnd), radix); - newDigit = Multiplication.multiplyByInt(digits, digitIndex, - bigRadix); - newDigit += Elementary - .inplaceAdd(digits, digitIndex, bigRadixDigit); - digits[digitIndex++] = newDigit; - } - numberLength = digitIndex; - result = new BigInteger(sign, numberLength, digits); - result.cutOffLeadingZeroes(); - return result; - } - + /** @see BigInteger#toString(int) */ static String bigInteger2String(BigInteger val, int radix) { int sign = val.sign;