--- old/src/share/classes/java/lang/AbstractStringBuilder.java 2013-06-07 13:08:24.000000000 -0700 +++ new/src/share/classes/java/lang/AbstractStringBuilder.java 2013-06-07 13:08:24.000000000 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -689,7 +689,7 @@ * @return a reference to this object. */ public AbstractStringBuilder append(float f) { - new FloatingDecimal(f).appendTo(this); + FloatingDecimal.appendTo(f,this); return this; } @@ -706,7 +706,7 @@ * @return a reference to this object. */ public AbstractStringBuilder append(double d) { - new FloatingDecimal(d).appendTo(this); + FloatingDecimal.appendTo(d,this); return this; } --- old/src/share/classes/java/lang/Double.java 2013-06-07 13:08:26.000000000 -0700 +++ new/src/share/classes/java/lang/Double.java 2013-06-07 13:08:25.000000000 -0700 @@ -201,7 +201,7 @@ * @return a string representation of the argument. */ public static String toString(double d) { - return new FloatingDecimal(d).toJavaFormatString(); + return FloatingDecimal.toJavaFormatString(d); } /** @@ -509,7 +509,7 @@ * parsable number. */ public static Double valueOf(String s) throws NumberFormatException { - return new Double(FloatingDecimal.readJavaFormatString(s).doubleValue()); + return new Double(parseDouble(s)); } /** @@ -545,7 +545,7 @@ * @since 1.2 */ public static double parseDouble(String s) throws NumberFormatException { - return FloatingDecimal.readJavaFormatString(s).doubleValue(); + return FloatingDecimal.parseDouble(s); } /** --- old/src/share/classes/java/lang/Float.java 2013-06-07 13:08:27.000000000 -0700 +++ new/src/share/classes/java/lang/Float.java 2013-06-07 13:08:27.000000000 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -203,7 +203,7 @@ * @return a string representation of the argument. */ public static String toString(float f) { - return new FloatingDecimal(f).toJavaFormatString(); + return FloatingDecimal.toJavaFormatString(f); } /** @@ -421,7 +421,7 @@ * parsable number. */ public static Float valueOf(String s) throws NumberFormatException { - return new Float(FloatingDecimal.readJavaFormatString(s).floatValue()); + return new Float(parseFloat(s)); } /** @@ -456,7 +456,7 @@ * @since 1.2 */ public static float parseFloat(String s) throws NumberFormatException { - return FloatingDecimal.readJavaFormatString(s).floatValue(); + return FloatingDecimal.parseFloat(s); } /** --- old/src/share/classes/java/text/DigitList.java 2013-06-07 13:08:28.000000000 -0700 +++ new/src/share/classes/java/text/DigitList.java 2013-06-07 13:08:28.000000000 -0700 @@ -271,7 +271,7 @@ * @param maximumFractionDigits The most fractional digits which should * be converted. */ - public final void set(boolean isNegative, double source, int maximumFractionDigits) { + final void set(boolean isNegative, double source, int maximumFractionDigits) { set(isNegative, source, maximumFractionDigits, true); } @@ -288,10 +288,11 @@ */ final void set(boolean isNegative, double source, int maximumDigits, boolean fixedPoint) { - FloatingDecimal fd = new FloatingDecimal(source); - boolean hasBeenRoundedUp = fd.digitsRoundedUp(); - boolean allDecimalDigits = fd.decimalDigitsExact(); - String digitsString = fd.toJavaFormatString(); + FloatingDecimal.BinaryToASCIIConverter fdConverter = FloatingDecimal.getBinaryToASCIIConverter(source); + boolean hasBeenRoundedUp = fdConverter.digitsRoundedUp(); + boolean allDecimalDigits = fdConverter.decimalDigitsExact(); + assert !fdConverter.isExceptional(); + String digitsString = fdConverter.toJavaFormatString(); set(isNegative, digitsString, hasBeenRoundedUp, allDecimalDigits, @@ -305,9 +306,9 @@ * @param allDecimalDigits Boolean value indicating if the digits in s are * an exact decimal representation of the double that was passed. */ - final void set(boolean isNegative, String s, - boolean roundedUp, boolean allDecimalDigits, - int maximumDigits, boolean fixedPoint) { + private void set(boolean isNegative, String s, + boolean roundedUp, boolean allDecimalDigits, + int maximumDigits, boolean fixedPoint) { this.isNegative = isNegative; int len = s.length(); char[] source = getDataChars(len); @@ -607,7 +608,7 @@ /** * Utility routine to set the value of the digit list from a long */ - public final void set(boolean isNegative, long source) { + final void set(boolean isNegative, long source) { set(isNegative, source, 0); } @@ -620,7 +621,7 @@ * If maximumDigits is lower than the number of significant digits * in source, the representation will be rounded. Ignored if <= 0. */ - public final void set(boolean isNegative, long source, int maximumDigits) { + final void set(boolean isNegative, long source, int maximumDigits) { this.isNegative = isNegative; // This method does not expect a negative number. However, --- old/src/share/classes/java/util/Formatter.java 2013-06-07 13:08:30.000000000 -0700 +++ new/src/share/classes/java/util/Formatter.java 2013-06-07 13:08:29.000000000 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -2807,10 +2807,10 @@ cal = Calendar.getInstance(l == null ? Locale.US : l); cal.setTime((Date)arg); } else if (arg instanceof Calendar) { - cal = (Calendar) ((Calendar)arg).clone(); + cal = (Calendar) ((Calendar) arg).clone(); cal.setLenient(true); } else if (arg instanceof TemporalAccessor) { - print((TemporalAccessor)arg, c, l); + print((TemporalAccessor) arg, c, l); return; } else { failConversion(c, arg); @@ -3242,13 +3242,10 @@ int prec = (precision == -1 ? 6 : precision); FormattedFloatingDecimal fd - = new FormattedFloatingDecimal(value, prec, - FormattedFloatingDecimal.Form.SCIENTIFIC); + = FormattedFloatingDecimal.valueOf(value, prec, + FormattedFloatingDecimal.Form.SCIENTIFIC); - char[] v = new char[MAX_FD_CHARS]; - int len = fd.getChars(v); - - char[] mant = addZeros(mantissa(v, len), prec); + char[] mant = addZeros(fd.getMantissa(), prec); // If the precision is zero and the '#' flag is set, add the // requested decimal point. @@ -3256,7 +3253,7 @@ mant = addDot(mant); char[] exp = (value == 0.0) - ? new char[] {'+','0','0'} : exponent(v, len); + ? new char[] {'+','0','0'} : fd.getExponent(); int newW = width; if (width != -1) @@ -3279,15 +3276,10 @@ int prec = (precision == -1 ? 6 : precision); FormattedFloatingDecimal fd - = new FormattedFloatingDecimal(value, prec, - FormattedFloatingDecimal.Form.DECIMAL_FLOAT); - - // MAX_FD_CHARS + 1 (round?) - char[] v = new char[MAX_FD_CHARS + 1 - + Math.abs(fd.getExponent())]; - int len = fd.getChars(v); + = FormattedFloatingDecimal.valueOf(value, prec, + FormattedFloatingDecimal.Form.DECIMAL_FLOAT); - char[] mant = addZeros(mantissa(v, len), prec); + char[] mant = addZeros(fd.getMantissa(), prec); // If the precision is zero and the '#' flag is set, add the // requested decimal point. @@ -3306,22 +3298,17 @@ prec = 1; FormattedFloatingDecimal fd - = new FormattedFloatingDecimal(value, prec, - FormattedFloatingDecimal.Form.GENERAL); + = FormattedFloatingDecimal.valueOf(value, prec, + FormattedFloatingDecimal.Form.GENERAL); - // MAX_FD_CHARS + 1 (round?) - char[] v = new char[MAX_FD_CHARS + 1 - + Math.abs(fd.getExponent())]; - int len = fd.getChars(v); - - char[] exp = exponent(v, len); + char[] exp = fd.getExponent(); if (exp != null) { prec -= 1; } else { prec = prec - (value == 0 ? 0 : fd.getExponentRounded()) - 1; } - char[] mant = addZeros(mantissa(v, len), prec); + char[] mant = addZeros(fd.getMantissa(), prec); // If the precision is zero and the '#' flag is set, add the // requested decimal point. if (f.contains(Flags.ALTERNATE) && (prec == 0)) @@ -3380,30 +3367,6 @@ } } - private char[] mantissa(char[] v, int len) { - int i; - for (i = 0; i < len; i++) { - if (v[i] == 'e') - break; - } - char[] tmp = new char[i]; - System.arraycopy(v, 0, tmp, 0, i); - return tmp; - } - - private char[] exponent(char[] v, int len) { - int i; - for (i = len - 1; i >= 0; i--) { - if (v[i] == 'e') - break; - } - if (i == -1) - return null; - char[] tmp = new char[len - i - 1]; - System.arraycopy(v, i + 1, tmp, 0, len - i - 1); - return tmp; - } - // Add zeros to the requested precision. private char[] addZeros(char[] v, int prec) { // Look for the dot. If we don't find one, the we'll need to add --- old/src/share/classes/sun/misc/FloatingDecimal.java 2013-06-07 13:08:31.000000000 -0700 +++ new/src/share/classes/sun/misc/FloatingDecimal.java 2013-06-07 13:08:31.000000000 -0700 @@ -25,768 +25,704 @@ package sun.misc; -import sun.misc.DoubleConsts; -import sun.misc.FloatConsts; +import java.util.Arrays; import java.util.regex.*; +/** + * A class for converting between ASCII and decimal representations of a single + * or double precision floating point number. Most conversions are provided via + * static convenience methods, although a BinaryToASCIIConverter + * instance may be obtained and reused. + */ public class FloatingDecimal{ - boolean isExceptional; - boolean isNegative; - int decExponent; - char digits[]; - int nDigits; - int bigIntExp; - int bigIntNBits; - boolean mustSetRoundDir = false; - boolean fromHex = false; - int roundDir = 0; // set by doubleValue - - /* - * The fields below provides additional information about the result of - * the binary to decimal digits conversion done in dtoa() and roundup() - * methods. They are changed if needed by those two methods. - */ + // + // Constants of the implementation; + // most are IEEE-754 related. + // (There are more really boring constants at the end.) + // + static final int EXP_SHIFT = DoubleConsts.SIGNIFICAND_WIDTH - 1; + static final long FRACT_HOB = ( 1L<String. + * + * @param d The double precision value. + * @return The value converted to a String. */ - private static int - countBits( long v ){ - // - // the strategy is to shift until we get a non-zero sign bit - // then shift until we have no bits left, counting the difference. - // we do byte shifting as a hack. Hope it helps. - // - if ( v == 0L ) return 0; - - while ( ( v & highbyte ) == 0L ){ - v <<= 8; - } - while ( v > 0L ) { // i.e. while ((v&highbit) == 0L ) - v <<= 1; - } - - int n = 0; - while (( v & lowbytes ) != 0L ){ - v <<= 8; - n += 8; - } - while ( v != 0L ){ - v <<= 1; - n += 1; - } - return n; + public static String toJavaFormatString(double d) { + return getBinaryToASCIIConverter(d).toJavaFormatString(); } - /* - * Keep big powers of 5 handy for future reference. + /** + * Converts a single precision floating point value to a String. + * + * @param f The single precision value. + * @return The value converted to a String. */ - private static FDBigInt b5p[]; - - private static synchronized FDBigInt - big5pow( int p ){ - assert p >= 0 : p; // negative power of 5 - if ( b5p == null ){ - b5p = new FDBigInt[ p+1 ]; - }else if (b5p.length <= p ){ - FDBigInt t[] = new FDBigInt[ p+1 ]; - System.arraycopy( b5p, 0, t, 0, b5p.length ); - b5p = t; - } - if ( b5p[p] != null ) - return b5p[p]; - else if ( p < small5pow.length ) - return b5p[p] = new FDBigInt( small5pow[p] ); - else if ( p < long5pow.length ) - return b5p[p] = new FDBigInt( long5pow[p] ); - else { - // construct the value. - // recursively. - int q, r; - // in order to compute 5^p, - // compute its square root, 5^(p/2) and square. - // or, let q = p / 2, r = p -q, then - // 5^p = 5^(q+r) = 5^q * 5^r - q = p >> 1; - r = p - q; - FDBigInt bigq = b5p[q]; - if ( bigq == null ) - bigq = big5pow ( q ); - if ( r < small5pow.length ){ - return (b5p[p] = bigq.mult( small5pow[r] ) ); - }else{ - FDBigInt bigr = b5p[ r ]; - if ( bigr == null ) - bigr = big5pow( r ); - return (b5p[p] = bigq.mult( bigr ) ); - } - } + public static String toJavaFormatString(float f) { + return getBinaryToASCIIConverter(f).toJavaFormatString(); } - // - // a common operation - // - private static FDBigInt - multPow52( FDBigInt v, int p5, int p2 ){ - if ( p5 != 0 ){ - if ( p5 < small5pow.length ){ - v = v.mult( small5pow[p5] ); - } else { - v = v.mult( big5pow( p5 ) ); - } - } - if ( p2 != 0 ){ - v.lshiftMe( p2 ); - } - return v; + /** + * Appends a double precision floating point value to an Appendable. + * @param d The double precision value. + * @param buf The Appendable with the value appended. + */ + public static void appendTo(double d, Appendable buf) { + getBinaryToASCIIConverter(d).appendTo(buf); } - // - // another common operation - // - private static FDBigInt - constructPow52( int p5, int p2 ){ - FDBigInt v = new FDBigInt( big5pow( p5 ) ); - if ( p2 != 0 ){ - v.lshiftMe( p2 ); - } - return v; + /** + * Appends a single precision floating point value to an Appendable. + * @param f The single precision value. + * @param buf The Appendable with the value appended. + */ + public static void appendTo(float f, Appendable buf) { + getBinaryToASCIIConverter(f).appendTo(buf); } - /* - * Make a floating double into a FDBigInt. - * This could also be structured as a FDBigInt - * constructor, but we'd have to build a lot of knowledge - * about floating-point representation into it, and we don't want to. + /** + * Converts a String to a double precision floating point value. * - * AS A SIDE EFFECT, THIS METHOD WILL SET THE INSTANCE VARIABLES - * bigIntExp and bigIntNBits + * @param s The String to convert. + * @return The double precision value. + * @throws NumberFormatException If the String does not + * represent a properly formatted double precision value. + */ + public static double parseDouble(String s) throws NumberFormatException { + return readJavaFormatString(s).doubleValue(); + } + + /** + * Converts a String to a single precision floating point value. * + * @param s The String to convert. + * @return The single precision value. + * @throws NumberFormatException If the String does not + * represent a properly formatted single precision value. */ - private FDBigInt - doubleToBigInt( double dval ){ - long lbits = Double.doubleToLongBits( dval ) & ~signMask; - int binexp = (int)(lbits >>> expShift); - lbits &= fractMask; - if ( binexp > 0 ){ - lbits |= fractHOB; - } else { - assert lbits != 0L : lbits; // doubleToBigInt(0.0) - binexp +=1; - while ( (lbits & fractHOB ) == 0L){ - lbits <<= 1; - binexp -= 1; - } - } - binexp -= expBias; - int nbits = countBits( lbits ); - /* - * We now know where the high-order 1 bit is, - * and we know how many there are. + public static float parseFloat(String s) throws NumberFormatException { + return readJavaFormatString(s).floatValue(); + } + + /** + * A converter which can process single or double precision floating point + * values into an ASCII String representation. + */ + public interface BinaryToASCIIConverter { + /** + * Converts a floating point value into an ASCII String. + * @return The value converted to a String. + */ + public String toJavaFormatString(); + + /** + * Appends a floating point value to an Appendable. + * @param buf The Appendable to receive the value. + */ + public void appendTo(Appendable buf); + + /** + * Retrieves the decimal exponent most closely corresponding to this value. + * @return The decimal exponent. */ - int lowOrderZeros = expShift+1-nbits; - lbits >>>= lowOrderZeros; + public int getDecimalExponent(); - bigIntExp = binexp+1-nbits; - bigIntNBits = nbits; - return new FDBigInt( lbits ); + /** + * Retrieves the value as an array of digits. + * @param digits The digit array. + * @return The number of valid digits copied into the array. + */ + public int getDigits(char[] digits); + + /** + * Indicates the sign of the value. + * @return value < 0.0. + */ + public boolean isNegative(); + + /** + * Indicates whether the value is either infinite or not a number. + * + * @return true if and only if the value is NaN + * or infinite. + */ + public boolean isExceptional(); + + /** + * Indicates whether the value was rounded up during the binary to ASCII + * conversion. + * + * @return true if and only if the value was rounded up. + */ + public boolean digitsRoundedUp(); + + /** + * Indicates whether the binary to ASCII conversion was exact. + * + * @return true if any only if the conversion was exact. + */ + public boolean decimalDigitsExact(); } - /* - * Compute a number that is the ULP of the given value, - * for purposes of addition/subtraction. Generally easy. - * More difficult if subtracting and the argument - * is a normalized a power of 2, as the ULP changes at these points. + /** + * A BinaryToASCIIConverter which represents NaN + * and infinite values. */ - private static double ulp( double dval, boolean subtracting ){ - long lbits = Double.doubleToLongBits( dval ) & ~signMask; - int binexp = (int)(lbits >>> expShift); - double ulpval; - if ( subtracting && ( binexp >= expShift ) && ((lbits&fractMask) == 0L) ){ - // for subtraction from normalized, powers of 2, - // use next-smaller exponent - binexp -= 1; - } - if ( binexp > expShift ){ - ulpval = Double.longBitsToDouble( ((long)(binexp-expShift))< 0L (not zero, nor negative). - * - * The only reason that we develop the digits here, rather than - * calling on Long.toString() is that we can do it a little faster, - * and besides want to treat trailing 0s specially. If Long.toString - * changes, we should re-evaluate this strategy! - */ - private void - developLongDigits( int decExponent, long lvalue, long insignificant ){ - char digits[]; - int ndigits; - int digitno; - int c; - // - // Discard non-significant low-order bits, while rounding, - // up to insignificant value. - int i; - for ( i = 0; insignificant >= 10L; i++ ) - insignificant /= 10L; - if ( i != 0 ){ - long pow10 = long5pow[i] << i; // 10^i == 5^i * 2^i; - long residue = lvalue % pow10; - lvalue /= pow10; - decExponent += i; - if ( residue >= (pow10>>1) ){ - // round up based on the low-order bits we're discarding - lvalue++; - } - } - if ( lvalue <= Integer.MAX_VALUE ){ - assert lvalue > 0L : lvalue; // lvalue <= 0 - // even easier subcase! - // can do int arithmetic rather than long! - int ivalue = (int)lvalue; - ndigits = 10; - digits = perThreadBuffer.get(); - digitno = ndigits-1; - c = ivalue%10; - ivalue /= 10; - while ( c == 0 ){ - decExponent++; - c = ivalue%10; - ivalue /= 10; - } - while ( ivalue != 0){ - digits[digitno--] = (char)(c+'0'); - decExponent++; - c = ivalue%10; - ivalue /= 10; - } - digits[digitno] = (char)(c+'0'); - } else { - // same algorithm as above (same bugs, too ) - // but using long arithmetic. - ndigits = 20; - digits = perThreadBuffer.get(); - digitno = ndigits-1; - c = (int)(lvalue%10L); - lvalue /= 10L; - while ( c == 0 ){ - decExponent++; - c = (int)(lvalue%10L); - lvalue /= 10L; - } - while ( lvalue != 0L ){ - digits[digitno--] = (char)(c+'0'); - decExponent++; - c = (int)(lvalue%10L); - lvalue /= 10; - } - digits[digitno] = (char)(c+'0'); + @Override + public boolean isExceptional() { + return true; } - char result []; - ndigits -= digitno; - result = new char[ ndigits ]; - System.arraycopy( digits, digitno, result, 0, ndigits ); - this.digits = result; - this.decExponent = decExponent+1; - this.nDigits = ndigits; - } - // - // add one to the least significant digit. - // in the unlikely event there is a carry out, - // deal with it. - // assert that this will only happen where there - // is only one digit, e.g. (float)1e-44 seems to do it. - // - private void - roundup(){ - int i; - int q = digits[ i = (nDigits-1)]; - if ( q == '9' ){ - while ( q == '9' && i > 0 ){ - digits[i] = '0'; - q = digits[--i]; - } - if ( q == '9' ){ - // carryout! High-order 1, rest 0s, larger exp. - decExponent += 1; - digits[0] = '1'; - return; - } - // else fall through. + @Override + public boolean digitsRoundedUp() { + throw new IllegalArgumentException("Exceptional value is not rounded"); } - digits[i] = (char)(q+1); - decimalDigitsRoundedUp = true; - } - public boolean digitsRoundedUp() { - return decimalDigitsRoundedUp; + @Override + public boolean decimalDigitsExact() { + throw new IllegalArgumentException("Exceptional value is not exact"); + } } - /* - * FIRST IMPORTANT CONSTRUCTOR: DOUBLE + private static final String INFINITY_REP = "Infinity"; + private static final int INFINITY_LENGTH = INFINITY_REP.length(); + private static final String NAN_REP = "NaN"; + private static final int NAN_LENGTH = NAN_REP.length(); + + private static final BinaryToASCIIConverter B2AC_POSITIVE_INFINITY = new ExceptionalBinaryToASCIIBuffer(INFINITY_REP, false); + private static final BinaryToASCIIConverter B2AC_NEGATIVE_INFINITY = new ExceptionalBinaryToASCIIBuffer("-" + INFINITY_REP, true); + private static final BinaryToASCIIConverter B2AC_NOT_A_NUMBER = new ExceptionalBinaryToASCIIBuffer(NAN_REP, false); + private static final BinaryToASCIIConverter B2AC_POSITIVE_ZERO = new BinaryToASCIIBuffer(false, new char[]{'0'}); + private static final BinaryToASCIIConverter B2AC_NEGATIVE_ZERO = new BinaryToASCIIBuffer(true, new char[]{'0'}); + + /** + * A buffered implementation of BinaryToASCIIConverter. */ - public FloatingDecimal( double d ) - { - long dBits = Double.doubleToLongBits( d ); - long fractBits; - int binExp; - int nSignificantBits; - - // discover and delete sign - if ( (dBits&signMask) != 0 ){ - isNegative = true; - dBits ^= signMask; - } else { - isNegative = false; + static class BinaryToASCIIBuffer implements BinaryToASCIIConverter { + private boolean isNegative; + private int decExponent; + private int firstDigitIndex; + private int nDigits; + private final char[] digits; + private final char[] buffer = new char[26]; + + // + // The fields below provide additional information about the result of + // the binary to decimal digits conversion done in dtoa() and roundup() + // methods. They are changed if needed by those two methods. + // + + // True if the dtoa() binary to decimal conversion was exact. + private boolean exactDecimalConversion = false; + + // True if the result of the binary to decimal conversion was rounded-up + // at the end of the conversion process, i.e. roundUp() method was called. + private boolean decimalDigitsRoundedUp = false; + + /** + * Default constructor; used for non-zero values, + * BinaryToASCIIBuffer may be thread-local and reused + */ + BinaryToASCIIBuffer(){ + this.digits = new char[20]; } - // Begin to unpack - // Discover obvious special cases of NaN and Infinity. - binExp = (int)( (dBits&expMask) >> expShift ); - fractBits = dBits&fractMask; - if ( binExp == (int)(expMask>>expShift) ) { - isExceptional = true; - if ( fractBits == 0L ){ - digits = infinity; + + /** + * Creates a specialized value (positive and negative zeros). + */ + BinaryToASCIIBuffer(boolean isNegative, char[] digits){ + this.isNegative = isNegative; + this.decExponent = 0; + this.digits = digits; + this.firstDigitIndex = 0; + this.nDigits = digits.length; + } + + @Override + public String toJavaFormatString() { + int len = getChars(buffer); + return new String(buffer, 0, len); + } + + @Override + public void appendTo(Appendable buf) { + int len = getChars(buffer); + if (buf instanceof StringBuilder) { + ((StringBuilder) buf).append(buffer, 0, len); + } else if (buf instanceof StringBuffer) { + ((StringBuffer) buf).append(buffer, 0, len); } else { - digits = notANumber; - isNegative = false; // NaN has no sign! + assert false; } - nDigits = digits.length; - return; } - isExceptional = false; - // Finish unpacking - // Normalize denormalized numbers. - // Insert assumed high-order bit for normalized numbers. - // Subtract exponent bias. - if ( binExp == 0 ){ - if ( fractBits == 0L ){ - // not a denorm, just a 0! - decExponent = 0; - digits = zero; - nDigits = 1; - return; - } - while ( (fractBits&fractHOB) == 0L ){ - fractBits <<= 1; - binExp -= 1; - } - nSignificantBits = expShift + binExp +1; // recall binExp is - shift count. - binExp += 1; - } else { - fractBits |= fractHOB; - nSignificantBits = expShift+1; + + @Override + public int getDecimalExponent() { + return decExponent; } - binExp -= expBias; - // call the routine that actually does all the hard work. - dtoa( binExp, fractBits, nSignificantBits ); - } - /* - * SECOND IMPORTANT CONSTRUCTOR: SINGLE - */ - public FloatingDecimal( float f ) - { - int fBits = Float.floatToIntBits( f ); - int fractBits; - int binExp; - int nSignificantBits; - - // discover and delete sign - if ( (fBits&singleSignMask) != 0 ){ - isNegative = true; - fBits ^= singleSignMask; - } else { - isNegative = false; + @Override + public int getDigits(char[] digits) { + System.arraycopy(this.digits,firstDigitIndex,digits,0,this.nDigits); + return this.nDigits; } - // Begin to unpack - // Discover obvious special cases of NaN and Infinity. - binExp = (fBits&singleExpMask) >> singleExpShift; - fractBits = fBits&singleFractMask; - if ( binExp == (singleExpMask>>singleExpShift) ) { - isExceptional = true; - if ( fractBits == 0L ){ - digits = infinity; - } else { - digits = notANumber; - isNegative = false; // NaN has no sign! - } - nDigits = digits.length; - return; + + @Override + public boolean isNegative() { + return isNegative; } - isExceptional = false; - // Finish unpacking - // Normalize denormalized numbers. - // Insert assumed high-order bit for normalized numbers. - // Subtract exponent bias. - if ( binExp == 0 ){ - if ( fractBits == 0 ){ - // not a denorm, just a 0! - decExponent = 0; - digits = zero; - nDigits = 1; - return; - } - while ( (fractBits&singleFractHOB) == 0 ){ - fractBits <<= 1; - binExp -= 1; - } - nSignificantBits = singleExpShift + binExp +1; // recall binExp is - shift count. - binExp += 1; - } else { - fractBits |= singleFractHOB; - nSignificantBits = singleExpShift+1; + + @Override + public boolean isExceptional() { + return false; } - binExp -= singleExpBias; - // call the routine that actually does all the hard work. - dtoa( binExp, ((long)fractBits)<<(expShift-singleExpShift), nSignificantBits ); - } - private void - dtoa( int binExp, long fractBits, int nSignificantBits ) - { - int nFractBits; // number of significant bits of fractBits; - int nTinyBits; // number of these to the right of the point. - int decExp; + @Override + public boolean digitsRoundedUp() { + return decimalDigitsRoundedUp; + } - // Examine number. Determine if it is an easy case, - // which we can do pretty trivially using float/long conversion, - // or whether we must do real work. - nFractBits = countBits( fractBits ); - nTinyBits = Math.max( 0, nFractBits - binExp - 1 ); - if ( binExp <= maxSmallBinExp && binExp >= minSmallBinExp ){ - // Look more closely at the number to decide if, - // with scaling by 10^nTinyBits, the result will fit in - // a long. - if ( (nTinyBits < long5pow.length) && ((nFractBits + n5bits[nTinyBits]) < 64 ) ){ - /* - * We can do this: - * take the fraction bits, which are normalized. - * (a) nTinyBits == 0: Shift left or right appropriately - * to align the binary point at the extreme right, i.e. - * where a long int point is expected to be. The integer - * result is easily converted to a string. - * (b) nTinyBits > 0: Shift right by expShift-nFractBits, - * which effectively converts to long and scales by - * 2^nTinyBits. Then multiply by 5^nTinyBits to - * complete the scaling. We know this won't overflow - * because we just counted the number of bits necessary - * in the result. The integer you get from this can - * then be converted to a string pretty easily. - */ - long halfULP; - if ( nTinyBits == 0 ) { - if ( binExp > nSignificantBits ){ - halfULP = 1L << ( binExp-nSignificantBits-1); - } else { - halfULP = 0L; - } - if ( binExp >= expShift ){ - fractBits <<= (binExp-expShift); - } else { - fractBits >>>= (expShift-binExp) ; - } - developLongDigits( 0, fractBits, halfULP ); - return; - } - /* - * The following causes excess digits to be printed - * out in the single-float case. Our manipulation of - * halfULP here is apparently not correct. If we - * better understand how this works, perhaps we can - * use this special case again. But for the time being, - * we do not. - * else { - * fractBits >>>= expShift+1-nFractBits; - * fractBits *= long5pow[ nTinyBits ]; - * halfULP = long5pow[ nTinyBits ] >> (1+nSignificantBits-nFractBits); - * developLongDigits( -nTinyBits, fractBits, halfULP ); - * return; - * } - */ - } - } - /* - * This is the hard case. We are going to compute large positive - * integers B and S and integer decExp, s.t. - * d = ( B / S ) * 10^decExp - * 1 <= B / S < 10 - * Obvious choices are: - * decExp = floor( log10(d) ) - * B = d * 2^nTinyBits * 10^max( 0, -decExp ) - * S = 10^max( 0, decExp) * 2^nTinyBits - * (noting that nTinyBits has already been forced to non-negative) - * I am also going to compute a large positive integer - * M = (1/2^nSignificantBits) * 2^nTinyBits * 10^max( 0, -decExp ) - * i.e. M is (1/2) of the ULP of d, scaled like B. - * When we iterate through dividing B/S and picking off the - * quotient bits, we will know when to stop when the remainder - * is <= M. - * - * We keep track of powers of 2 and powers of 5. - */ + @Override + public boolean decimalDigitsExact() { + return exactDecimalConversion; + } - /* - * Estimate decimal exponent. (If it is small-ish, - * we could double-check.) - * - * First, scale the mantissa bits such that 1 <= d2 < 2. - * We are then going to estimate - * log10(d2) ~=~ (d2-1.5)/1.5 + log(1.5) - * and so we can estimate - * log10(d) ~=~ log10(d2) + binExp * log10(2) - * take the floor and call it decExp. - * FIXME -- use more precise constants here. It costs no more. - */ - double d2 = Double.longBitsToDouble( - expOne | ( fractBits &~ fractHOB ) ); - decExp = (int)Math.floor( - (d2-1.5D)*0.289529654D + 0.176091259 + (double)binExp * 0.301029995663981 ); - int B2, B5; // powers of 2 and powers of 5, respectively, in B - int S2, S5; // powers of 2 and powers of 5, respectively, in S - int M2, M5; // powers of 2 and powers of 5, respectively, in M - int Bbits; // binary digits needed to represent B, approx. - int tenSbits; // binary digits needed to represent 10*S, approx. - FDBigInt Sval, Bval, Mval; - - B5 = Math.max( 0, -decExp ); - B2 = B5 + nTinyBits + binExp; - - S5 = Math.max( 0, decExp ); - S2 = S5 + nTinyBits; - - M5 = B5; - M2 = B2 - nSignificantBits; - - /* - * the long integer fractBits contains the (nFractBits) interesting - * bits from the mantissa of d ( hidden 1 added if necessary) followed - * by (expShift+1-nFractBits) zeros. In the interest of compactness, - * I will shift out those zeros before turning fractBits into a - * FDBigInt. The resulting whole number will be - * d * 2^(nFractBits-1-binExp). - */ - fractBits >>>= (expShift+1-nFractBits); - B2 -= nFractBits-1; - int common2factor = Math.min( B2, S2 ); - B2 -= common2factor; - S2 -= common2factor; - M2 -= common2factor; - - /* - * HACK!! For exact powers of two, the next smallest number - * is only half as far away as we think (because the meaning of - * ULP changes at power-of-two bounds) for this reason, we - * hack M2. Hope this works. - */ - if ( nFractBits == 1 ) - M2 -= 1; + private void setSign(boolean isNegative) { + this.isNegative = isNegative; + } - if ( M2 < 0 ){ - // oops. - // since we cannot scale M down far enough, - // we must scale the other values up. - B2 -= M2; - S2 -= M2; - M2 = 0; - } - /* - * Construct, Scale, iterate. - * Some day, we'll write a stopping test that takes - * account of the asymmetry of the spacing of floating-point - * numbers below perfect powers of 2 - * 26 Sept 96 is not that day. - * So we use a symmetric test. - */ - char digits[] = this.digits = new char[18]; - int ndigit = 0; - boolean low, high; - long lowDigitDifference; - int q; - - /* - * Detect the special cases where all the numbers we are about - * to compute will fit in int or long integers. - * In these cases, we will avoid doing FDBigInt arithmetic. - * We use the same algorithms, except that we "normalize" - * our FDBigInts before iterating. This is to make division easier, - * as it makes our fist guess (quotient of high-order words) - * more accurate! + /** + * This is the easy subcase -- + * all the significant bits, after scaling, are held in lvalue. + * negSign and decExponent tell us what processing and scaling + * has already been done. Exceptional cases have already been + * stripped out. + * In particular: + * lvalue is a finite number (not Inf, nor NaN) + * lvalue > 0L (not zero, nor negative). * - * Some day, we'll write a stopping test that takes - * account of the asymmetry of the spacing of floating-point - * numbers below perfect powers of 2 - * 26 Sept 96 is not that day. - * So we use a symmetric test. + * The only reason that we develop the digits here, rather than + * calling on Long.toString() is that we can do it a little faster, + * and besides want to treat trailing 0s specially. If Long.toString + * changes, we should re-evaluate this strategy! */ - Bbits = nFractBits + B2 + (( B5 < n5bits.length )? n5bits[B5] : ( B5*3 )); - tenSbits = S2+1 + (( (S5+1) < n5bits.length )? n5bits[(S5+1)] : ( (S5+1)*3 )); - if ( Bbits < 64 && tenSbits < 64){ - if ( Bbits < 32 && tenSbits < 32){ - // wa-hoo! They're all ints! - int b = ((int)fractBits * small5pow[B5] ) << B2; - int s = small5pow[S5] << S2; - int m = small5pow[M5] << M2; - int tens = s * 10; - /* - * Unroll the first iteration. If our decExp estimate - * was too high, our first quotient will be zero. In this - * case, we discard it and decrement decExp. - */ - ndigit = 0; - q = b / s; - b = 10 * ( b % s ); - m *= 10; - low = (b < m ); - high = (b+m > tens ); - assert q < 10 : q; // excessively large digit - if ( (q == 0) && ! high ){ - // oops. Usually ignore leading zero. - decExp--; - } else { - digits[ndigit++] = (char)('0' + q); + private void developLongDigits( int decExponent, long lvalue, int insignificantDigits ){ + if ( insignificantDigits != 0 ){ + // Discard non-significant low-order bits, while rounding, + // up to insignificant value. + long pow10 = FDBigInteger.LONG_5_POW[insignificantDigits] << insignificantDigits; // 10^i == 5^i * 2^i; + long residue = lvalue % pow10; + lvalue /= pow10; + decExponent += insignificantDigits; + if ( residue >= (pow10>>1) ){ + // round up based on the low-order bits we're discarding + lvalue++; + } + } + int digitno = digits.length -1; + int c; + if ( lvalue <= Integer.MAX_VALUE ){ + assert lvalue > 0L : lvalue; // lvalue <= 0 + // even easier subcase! + // can do int arithmetic rather than long! + int ivalue = (int)lvalue; + c = ivalue%10; + ivalue /= 10; + while ( c == 0 ){ + decExponent++; + c = ivalue%10; + ivalue /= 10; + } + while ( ivalue != 0){ + digits[digitno--] = (char)(c+'0'); + decExponent++; + c = ivalue%10; + ivalue /= 10; } - /* - * HACK! Java spec sez that we always have at least - * one digit after the . in either F- or E-form output. - * Thus we will need more than one digit if we're using - * E-form - */ - if ( decExp < -3 || decExp >= 8 ){ - high = low = false; + digits[digitno] = (char)(c+'0'); + } else { + // same algorithm as above (same bugs, too ) + // but using long arithmetic. + c = (int)(lvalue%10L); + lvalue /= 10L; + while ( c == 0 ){ + decExponent++; + c = (int)(lvalue%10L); + lvalue /= 10L; + } + while ( lvalue != 0L ){ + digits[digitno--] = (char)(c+'0'); + decExponent++; + c = (int)(lvalue%10L); + lvalue /= 10; + } + digits[digitno] = (char)(c+'0'); + } + this.decExponent = decExponent+1; + this.firstDigitIndex = digitno; + this.nDigits = this.digits.length - digitno; + } + + private void dtoa( int binExp, long fractBits, int nSignificantBits, boolean isCompatibleFormat) + { + assert fractBits > 0 ; // fractBits here can't be zero or negative + assert (fractBits & FRACT_HOB)!=0 ; // Hi-order bit should be set + // Examine number. Determine if it is an easy case, + // which we can do pretty trivially using float/long conversion, + // or whether we must do real work. + final int tailZeros = Long.numberOfTrailingZeros(fractBits); + + // number of significant bits of fractBits; + final int nFractBits = EXP_SHIFT+1-tailZeros; + + // reset flags to default values as dtoa() does not always set these + // flags and a prior call to dtoa() might have set them to incorrect + // values with respect to the current state. + decimalDigitsRoundedUp = false; + exactDecimalConversion = false; + + // number of significant bits to the right of the point. + int nTinyBits = Math.max( 0, nFractBits - binExp - 1 ); + if ( binExp <= MAX_SMALL_BIN_EXP && binExp >= MIN_SMALL_BIN_EXP ){ + // Look more closely at the number to decide if, + // with scaling by 10^nTinyBits, the result will fit in + // a long. + if ( (nTinyBits < FDBigInteger.LONG_5_POW.length) && ((nFractBits + N_5_BITS[nTinyBits]) < 64 ) ){ + // + // We can do this: + // take the fraction bits, which are normalized. + // (a) nTinyBits == 0: Shift left or right appropriately + // to align the binary point at the extreme right, i.e. + // where a long int point is expected to be. The integer + // result is easily converted to a string. + // (b) nTinyBits > 0: Shift right by EXP_SHIFT-nFractBits, + // which effectively converts to long and scales by + // 2^nTinyBits. Then multiply by 5^nTinyBits to + // complete the scaling. We know this won't overflow + // because we just counted the number of bits necessary + // in the result. The integer you get from this can + // then be converted to a string pretty easily. + // + if ( nTinyBits == 0 ) { + int insignificant; + if ( binExp > nSignificantBits ){ + insignificant = insignificantDigitsForPow2(binExp-nSignificantBits-1); + } else { + insignificant = 0; + } + if ( binExp >= EXP_SHIFT ){ + fractBits <<= (binExp-EXP_SHIFT); + } else { + fractBits >>>= (EXP_SHIFT-binExp) ; + } + developLongDigits( 0, fractBits, insignificant ); + return; + } + // + // The following causes excess digits to be printed + // out in the single-float case. Our manipulation of + // halfULP here is apparently not correct. If we + // better understand how this works, perhaps we can + // use this special case again. But for the time being, + // we do not. + // else { + // fractBits >>>= EXP_SHIFT+1-nFractBits; + // fractBits//= long5pow[ nTinyBits ]; + // halfULP = long5pow[ nTinyBits ] >> (1+nSignificantBits-nFractBits); + // developLongDigits( -nTinyBits, fractBits, insignificantDigits(halfULP) ); + // return; + // } + // } - while( ! low && ! high ){ + } + // + // This is the hard case. We are going to compute large positive + // integers B and S and integer decExp, s.t. + // d = ( B / S )// 10^decExp + // 1 <= B / S < 10 + // Obvious choices are: + // decExp = floor( log10(d) ) + // B = d// 2^nTinyBits// 10^max( 0, -decExp ) + // S = 10^max( 0, decExp)// 2^nTinyBits + // (noting that nTinyBits has already been forced to non-negative) + // I am also going to compute a large positive integer + // M = (1/2^nSignificantBits)// 2^nTinyBits// 10^max( 0, -decExp ) + // i.e. M is (1/2) of the ULP of d, scaled like B. + // When we iterate through dividing B/S and picking off the + // quotient bits, we will know when to stop when the remainder + // is <= M. + // + // We keep track of powers of 2 and powers of 5. + // + int decExp = estimateDecExp(fractBits,binExp); + int B2, B5; // powers of 2 and powers of 5, respectively, in B + int S2, S5; // powers of 2 and powers of 5, respectively, in S + int M2, M5; // powers of 2 and powers of 5, respectively, in M + + B5 = Math.max( 0, -decExp ); + B2 = B5 + nTinyBits + binExp; + + S5 = Math.max( 0, decExp ); + S2 = S5 + nTinyBits; + + M5 = B5; + M2 = B2 - nSignificantBits; + + // + // the long integer fractBits contains the (nFractBits) interesting + // bits from the mantissa of d ( hidden 1 added if necessary) followed + // by (EXP_SHIFT+1-nFractBits) zeros. In the interest of compactness, + // I will shift out those zeros before turning fractBits into a + // FDBigInteger. The resulting whole number will be + // d * 2^(nFractBits-1-binExp). + // + fractBits >>>= tailZeros; + B2 -= nFractBits-1; + int common2factor = Math.min( B2, S2 ); + B2 -= common2factor; + S2 -= common2factor; + M2 -= common2factor; + + // + // HACK!! For exact powers of two, the next smallest number + // is only half as far away as we think (because the meaning of + // ULP changes at power-of-two bounds) for this reason, we + // hack M2. Hope this works. + // + if ( nFractBits == 1 ) { + M2 -= 1; + } + + if ( M2 < 0 ){ + // oops. + // since we cannot scale M down far enough, + // we must scale the other values up. + B2 -= M2; + S2 -= M2; + M2 = 0; + } + // + // Construct, Scale, iterate. + // Some day, we'll write a stopping test that takes + // account of the asymmetry of the spacing of floating-point + // numbers below perfect powers of 2 + // 26 Sept 96 is not that day. + // So we use a symmetric test. + // + int ndigit = 0; + boolean low, high; + long lowDigitDifference; + int q; + + // + // Detect the special cases where all the numbers we are about + // to compute will fit in int or long integers. + // In these cases, we will avoid doing FDBigInteger arithmetic. + // We use the same algorithms, except that we "normalize" + // our FDBigIntegers before iterating. This is to make division easier, + // as it makes our fist guess (quotient of high-order words) + // more accurate! + // + // Some day, we'll write a stopping test that takes + // account of the asymmetry of the spacing of floating-point + // numbers below perfect powers of 2 + // 26 Sept 96 is not that day. + // So we use a symmetric test. + // + // binary digits needed to represent B, approx. + int Bbits = nFractBits + B2 + (( B5 < N_5_BITS.length )? N_5_BITS[B5] : ( B5*3 )); + + // binary digits needed to represent 10*S, approx. + int tenSbits = S2+1 + (( (S5+1) < N_5_BITS.length )? N_5_BITS[(S5+1)] : ( (S5+1)*3 )); + if ( Bbits < 64 && tenSbits < 64){ + if ( Bbits < 32 && tenSbits < 32){ + // wa-hoo! They're all ints! + int b = ((int)fractBits * FDBigInteger.SMALL_5_POW[B5] ) << B2; + int s = FDBigInteger.SMALL_5_POW[S5] << S2; + int m = FDBigInteger.SMALL_5_POW[M5] << M2; + int tens = s * 10; + // + // Unroll the first iteration. If our decExp estimate + // was too high, our first quotient will be zero. In this + // case, we discard it and decrement decExp. + // + ndigit = 0; q = b / s; b = 10 * ( b % s ); m *= 10; + low = (b < m ); + high = (b+m > tens ); assert q < 10 : q; // excessively large digit - if ( m > 0L ){ - low = (b < m ); - high = (b+m > tens ); + if ( (q == 0) && ! high ){ + // oops. Usually ignore leading zero. + decExp--; } else { - // hack -- m might overflow! - // in this case, it is certainly > b, - // which won't - // and b+m > tens, too, since that has overflowed - // either! - low = true; - high = true; + digits[ndigit++] = (char)('0' + q); } - digits[ndigit++] = (char)('0' + q); + // + // HACK! Java spec sez that we always have at least + // one digit after the . in either F- or E-form output. + // Thus we will need more than one digit if we're using + // E-form + // + if ( !isCompatibleFormat ||decExp < -3 || decExp >= 8 ){ + high = low = false; + } + while( ! low && ! high ){ + q = b / s; + b = 10 * ( b % s ); + m *= 10; + assert q < 10 : q; // excessively large digit + if ( m > 0L ){ + low = (b < m ); + high = (b+m > tens ); + } else { + // hack -- m might overflow! + // in this case, it is certainly > b, + // which won't + // and b+m > tens, too, since that has overflowed + // either! + low = true; + high = true; + } + digits[ndigit++] = (char)('0' + q); + } + lowDigitDifference = (b<<1) - tens; + exactDecimalConversion = (b == 0); + } else { + // still good! they're all longs! + long b = (fractBits * FDBigInteger.LONG_5_POW[B5] ) << B2; + long s = FDBigInteger.LONG_5_POW[S5] << S2; + long m = FDBigInteger.LONG_5_POW[M5] << M2; + long tens = s * 10L; + // + // Unroll the first iteration. If our decExp estimate + // was too high, our first quotient will be zero. In this + // case, we discard it and decrement decExp. + // + ndigit = 0; + q = (int) ( b / s ); + b = 10L * ( b % s ); + m *= 10L; + low = (b < m ); + high = (b+m > tens ); + assert q < 10 : q; // excessively large digit + if ( (q == 0) && ! high ){ + // oops. Usually ignore leading zero. + decExp--; + } else { + digits[ndigit++] = (char)('0' + q); + } + // + // HACK! Java spec sez that we always have at least + // one digit after the . in either F- or E-form output. + // Thus we will need more than one digit if we're using + // E-form + // + if ( !isCompatibleFormat || decExp < -3 || decExp >= 8 ){ + high = low = false; + } + while( ! low && ! high ){ + q = (int) ( b / s ); + b = 10 * ( b % s ); + m *= 10; + assert q < 10 : q; // excessively large digit + if ( m > 0L ){ + low = (b < m ); + high = (b+m > tens ); + } else { + // hack -- m might overflow! + // in this case, it is certainly > b, + // which won't + // and b+m > tens, too, since that has overflowed + // either! + low = true; + high = true; + } + digits[ndigit++] = (char)('0' + q); + } + lowDigitDifference = (b<<1) - tens; + exactDecimalConversion = (b == 0); } - lowDigitDifference = (b<<1) - tens; - exactDecimalConversion = (b == 0); } else { - // still good! they're all longs! - long b = (fractBits * long5pow[B5] ) << B2; - long s = long5pow[S5] << S2; - long m = long5pow[M5] << M2; - long tens = s * 10L; - /* - * Unroll the first iteration. If our decExp estimate - * was too high, our first quotient will be zero. In this - * case, we discard it and decrement decExp. - */ + // + // We really must do FDBigInteger arithmetic. + // Fist, construct our FDBigInteger initial values. + // + FDBigInteger Sval = FDBigInteger.valueOfPow52(S5, S2); + int shiftBias = Sval.getNormalizationBias(); + Sval = Sval.leftShift(shiftBias); // normalize so that division works better + + FDBigInteger Bval = FDBigInteger.valueOfMulPow52(fractBits, B5, B2 + shiftBias); + FDBigInteger Mval = FDBigInteger.valueOfPow52(M5 + 1, M2 + shiftBias + 1); + + FDBigInteger tenSval = FDBigInteger.valueOfPow52(S5 + 1, S2 + shiftBias + 1); //Sval.mult( 10 ); + // + // Unroll the first iteration. If our decExp estimate + // was too high, our first quotient will be zero. In this + // case, we discard it and decrement decExp. + // ndigit = 0; - q = (int) ( b / s ); - b = 10L * ( b % s ); - m *= 10L; - low = (b < m ); - high = (b+m > tens ); + q = Bval.quoRemIteration( Sval ); + low = (Bval.cmp( Mval ) < 0); + high = tenSval.addAndCmp(Bval,Mval)<=0; + assert q < 10 : q; // excessively large digit if ( (q == 0) && ! high ){ // oops. Usually ignore leading zero. @@ -794,160 +730,191 @@ } else { digits[ndigit++] = (char)('0' + q); } - /* - * HACK! Java spec sez that we always have at least - * one digit after the . in either F- or E-form output. - * Thus we will need more than one digit if we're using - * E-form - */ - if ( decExp < -3 || decExp >= 8 ){ + // + // HACK! Java spec sez that we always have at least + // one digit after the . in either F- or E-form output. + // Thus we will need more than one digit if we're using + // E-form + // + if (!isCompatibleFormat || decExp < -3 || decExp >= 8 ){ high = low = false; } while( ! low && ! high ){ - q = (int) ( b / s ); - b = 10 * ( b % s ); - m *= 10; + q = Bval.quoRemIteration( Sval ); assert q < 10 : q; // excessively large digit - if ( m > 0L ){ - low = (b < m ); - high = (b+m > tens ); - } else { - // hack -- m might overflow! - // in this case, it is certainly > b, - // which won't - // and b+m > tens, too, since that has overflowed - // either! - low = true; - high = true; - } + Mval = Mval.multBy10(); //Mval = Mval.mult( 10 ); + low = (Bval.cmp( Mval ) < 0); + high = tenSval.addAndCmp(Bval,Mval)<=0; digits[ndigit++] = (char)('0' + q); } - lowDigitDifference = (b<<1) - tens; - exactDecimalConversion = (b == 0); - } - } else { - FDBigInt ZeroVal = new FDBigInt(0); - FDBigInt tenSval; - int shiftBias; - - /* - * We really must do FDBigInt arithmetic. - * Fist, construct our FDBigInt initial values. - */ - Bval = multPow52( new FDBigInt( fractBits ), B5, B2 ); - Sval = constructPow52( S5, S2 ); - Mval = constructPow52( M5, M2 ); - - - // normalize so that division works better - Bval.lshiftMe( shiftBias = Sval.normalizeMe() ); - Mval.lshiftMe( shiftBias ); - tenSval = Sval.mult( 10 ); - /* - * Unroll the first iteration. If our decExp estimate - * was too high, our first quotient will be zero. In this - * case, we discard it and decrement decExp. - */ - ndigit = 0; - q = Bval.quoRemIteration( Sval ); - Mval = Mval.mult( 10 ); - low = (Bval.cmp( Mval ) < 0); - high = (Bval.add( Mval ).cmp( tenSval ) > 0 ); - assert q < 10 : q; // excessively large digit - if ( (q == 0) && ! high ){ - // oops. Usually ignore leading zero. - decExp--; - } else { - digits[ndigit++] = (char)('0' + q); - } - /* - * HACK! Java spec sez that we always have at least - * one digit after the . in either F- or E-form output. - * Thus we will need more than one digit if we're using - * E-form - */ - if ( decExp < -3 || decExp >= 8 ){ - high = low = false; + if ( high && low ){ + Bval = Bval.leftShift(1); + lowDigitDifference = Bval.cmp(tenSval); + } else { + lowDigitDifference = 0L; // this here only for flow analysis! + } + exactDecimalConversion = (Bval.cmp( FDBigInteger.ZERO ) == 0); } - while( ! low && ! high ){ - q = Bval.quoRemIteration( Sval ); - Mval = Mval.mult( 10 ); - assert q < 10 : q; // excessively large digit - low = (Bval.cmp( Mval ) < 0); - high = (Bval.add( Mval ).cmp( tenSval ) > 0 ); - digits[ndigit++] = (char)('0' + q); + this.decExponent = decExp+1; + this.firstDigitIndex = 0; + this.nDigits = ndigit; + // + // Last digit gets rounded based on stopping condition. + // + if ( high ){ + if ( low ){ + if ( lowDigitDifference == 0L ){ + // it's a tie! + // choose based on which digits we like. + if ( (digits[firstDigitIndex+nDigits-1]&1) != 0 ) { + roundup(); + } + } else if ( lowDigitDifference > 0 ){ + roundup(); + } + } else { + roundup(); + } } - if ( high && low ){ - Bval.lshiftMe(1); - lowDigitDifference = Bval.cmp(tenSval); - } else { - lowDigitDifference = 0L; // this here only for flow analysis! + } + + // add one to the least significant digit. + // in the unlikely event there is a carry out, deal with it. + // assert that this will only happen where there + // is only one digit, e.g. (float)1e-44 seems to do it. + // + private void roundup() { + int i = (firstDigitIndex + nDigits - 1); + int q = digits[i]; + if (q == '9') { + while (q == '9' && i > firstDigitIndex) { + digits[i] = '0'; + q = digits[--i]; + } + if (q == '9') { + // carryout! High-order 1, rest 0s, larger exp. + decExponent += 1; + digits[firstDigitIndex] = '1'; + return; + } + // else fall through. } - exactDecimalConversion = (Bval.cmp( ZeroVal ) == 0); + digits[i] = (char) (q + 1); + decimalDigitsRoundedUp = true; } - this.decExponent = decExp+1; - this.digits = digits; - this.nDigits = ndigit; - /* - * Last digit gets rounded based on stopping condition. + + /** + * Estimate decimal exponent. (If it is small-ish, + * we could double-check.) + * + * First, scale the mantissa bits such that 1 <= d2 < 2. + * We are then going to estimate + * log10(d2) ~=~ (d2-1.5)/1.5 + log(1.5) + * and so we can estimate + * log10(d) ~=~ log10(d2) + binExp * log10(2) + * take the floor and call it decExp. */ - if ( high ){ - if ( low ){ - if ( lowDigitDifference == 0L ){ - // it's a tie! - // choose based on which digits we like. - if ( (digits[nDigits-1]&1) != 0 ) roundup(); - } else if ( lowDigitDifference > 0 ){ - roundup(); - } - } else { - roundup(); + static int estimateDecExp(long fractBits, int binExp) { + double d2 = Double.longBitsToDouble( EXP_ONE | ( fractBits & DoubleConsts.SIGNIF_BIT_MASK ) ); + double d = (d2-1.5D)*0.289529654D + 0.176091259 + (double)binExp * 0.301029995663981; + long dBits = Double.doubleToRawLongBits(d); //can't be NaN here so use raw + int exponent = (int)((dBits & DoubleConsts.EXP_BIT_MASK) >> EXP_SHIFT) - DoubleConsts.EXP_BIAS; + boolean isNegative = (dBits & DoubleConsts.SIGN_BIT_MASK) != 0; // discover sign + if(exponent>=0 && exponent<52) { // hot path + long mask = DoubleConsts.SIGNIF_BIT_MASK >> exponent; + int r = (int)(( (dBits&DoubleConsts.SIGNIF_BIT_MASK) | FRACT_HOB )>>(EXP_SHIFT-exponent)); + return isNegative ? (((mask & dBits) == 0L ) ? -r : -r-1 ) : r; + } else if (exponent < 0) { + return (((dBits&~DoubleConsts.SIGN_BIT_MASK) == 0) ? 0 : + ( (isNegative) ? -1 : 0) ); + } else { //if (exponent >= 52) + return (int)d; } } - } - public boolean decimalDigitsExact() { - return exactDecimalConversion; - } + private static int insignificantDigits(int insignificant) { + int i; + for ( i = 0; insignificant >= 10L; i++ ) { + insignificant /= 10L; + } + return i; + } + + /** + * Calculates + *
+         * insignificantDigitsForPow2(v) == insignificantDigits(1L<
+         */
+        private static int insignificantDigitsForPow2(int p2) {
+            if(p2>1 && p2 < insignificantDigitsNumber.length) {
+                return insignificantDigitsNumber[p2];
+            }
+            return 0;
+        }
 
-    public String
-    toString(){
-        // most brain-dead version
-        StringBuffer result = new StringBuffer( nDigits+8 );
-        if ( isNegative ){ result.append( '-' ); }
-        if ( isExceptional ){
-            result.append( digits, 0, nDigits );
-        } else {
-            result.append( "0.");
-            result.append( digits, 0, nDigits );
-            result.append('e');
-            result.append( decExponent );
-        }
-        return new String(result);
-    }
-
-    public String toJavaFormatString() {
-        char result[] = perThreadBuffer.get();
-        int i = getChars(result);
-        return new String(result, 0, i);
-    }
-
-    private int getChars(char[] result) {
-        assert nDigits <= 19 : nDigits; // generous bound on size of nDigits
-        int i = 0;
-        if (isNegative) { result[0] = '-'; i = 1; }
-        if (isExceptional) {
-            System.arraycopy(digits, 0, result, i, nDigits);
-            i += nDigits;
-        } else {
+        /**
+         *  If insignificant==(1L << ixd)
+         *  i = insignificantDigitsNumber[idx] is the same as:
+         *  int i;
+         *  for ( i = 0; insignificant >= 10L; i++ )
+         *         insignificant /= 10L;
+         */
+        private static int[] insignificantDigitsNumber = {
+            0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3,
+            4, 4, 4, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7,
+            8, 8, 8, 9, 9, 9, 9, 10, 10, 10, 11, 11, 11,
+            12, 12, 12, 12, 13, 13, 13, 14, 14, 14,
+            15, 15, 15, 15, 16, 16, 16, 17, 17, 17,
+            18, 18, 18, 19
+        };
+
+        // approximately ceil( log2( long5pow[i] ) )
+        private static final int[] N_5_BITS = {
+                0,
+                3,
+                5,
+                7,
+                10,
+                12,
+                14,
+                17,
+                19,
+                21,
+                24,
+                26,
+                28,
+                31,
+                33,
+                35,
+                38,
+                40,
+                42,
+                45,
+                47,
+                49,
+                52,
+                54,
+                56,
+                59,
+                61,
+        };
+
+        private int getChars(char[] result) {
+            assert nDigits <= 19 : nDigits; // generous bound on size of nDigits
+            int i = 0;
+            if (isNegative) {
+                result[0] = '-';
+                i = 1;
+            }
             if (decExponent > 0 && decExponent < 8) {
                 // print digits.digits.
                 int charLength = Math.min(nDigits, decExponent);
-                System.arraycopy(digits, 0, result, i, charLength);
+                System.arraycopy(digits, firstDigitIndex, result, i, charLength);
                 i += charLength;
                 if (charLength < decExponent) {
-                    charLength = decExponent-charLength;
-                    System.arraycopy(zero, 0, result, i, charLength);
+                    charLength = decExponent - charLength;
+                    Arrays.fill(result,i,i+charLength,'0');
                     i += charLength;
                     result[i++] = '.';
                     result[i++] = '0';
@@ -955,27 +922,27 @@
                     result[i++] = '.';
                     if (charLength < nDigits) {
                         int t = nDigits - charLength;
-                        System.arraycopy(digits, charLength, result, i, t);
+                        System.arraycopy(digits, firstDigitIndex+charLength, result, i, t);
                         i += t;
                     } else {
                         result[i++] = '0';
                     }
                 }
-            } else if (decExponent <=0 && decExponent > -3) {
+            } else if (decExponent <= 0 && decExponent > -3) {
                 result[i++] = '0';
                 result[i++] = '.';
                 if (decExponent != 0) {
-                    System.arraycopy(zero, 0, result, i, -decExponent);
+                    Arrays.fill(result, i, i-decExponent, '0');
                     i -= decExponent;
                 }
-                System.arraycopy(digits, 0, result, i, nDigits);
+                System.arraycopy(digits, firstDigitIndex, result, i, nDigits);
                 i += nDigits;
             } else {
-                result[i++] = digits[0];
+                result[i++] = digits[firstDigitIndex];
                 result[i++] = '.';
                 if (nDigits > 1) {
-                    System.arraycopy(digits, 1, result, i, nDigits-1);
-                    i += nDigits-1;
+                    System.arraycopy(digits, firstDigitIndex+1, result, i, nDigits - 1);
+                    i += nDigits - 1;
                 } else {
                     result[i++] = '0';
                 }
@@ -983,48 +950,776 @@
                 int e;
                 if (decExponent <= 0) {
                     result[i++] = '-';
-                    e = -decExponent+1;
+                    e = -decExponent + 1;
                 } else {
-                    e = decExponent-1;
+                    e = decExponent - 1;
                 }
                 // decExponent has 1, 2, or 3, digits
                 if (e <= 9) {
-                    result[i++] = (char)(e+'0');
+                    result[i++] = (char) (e + '0');
                 } else if (e <= 99) {
-                    result[i++] = (char)(e/10 +'0');
-                    result[i++] = (char)(e%10 + '0');
+                    result[i++] = (char) (e / 10 + '0');
+                    result[i++] = (char) (e % 10 + '0');
                 } else {
-                    result[i++] = (char)(e/100+'0');
+                    result[i++] = (char) (e / 100 + '0');
                     e %= 100;
-                    result[i++] = (char)(e/10+'0');
-                    result[i++] = (char)(e%10 + '0');
+                    result[i++] = (char) (e / 10 + '0');
+                    result[i++] = (char) (e % 10 + '0');
+                }
+            }
+            return i;
+        }
+
+    }
+
+    private static final ThreadLocal threadLocalBinaryToASCIIBuffer =
+            new ThreadLocal() {
+                @Override
+                protected BinaryToASCIIBuffer initialValue() {
+                    return new BinaryToASCIIBuffer();
+                }
+            };
+
+    private static BinaryToASCIIBuffer getBinaryToASCIIBuffer() {
+        return threadLocalBinaryToASCIIBuffer.get();
+    }
+
+    /**
+     * A converter which can process an ASCII String representation
+     * of a single or double precision floating point value into a
+     * float or a double.
+     */
+    interface ASCIIToBinaryConverter {
+
+        double doubleValue();
+
+        float floatValue();
+
+    }
+
+    /**
+     * A ASCIIToBinaryConverter container for a double.
+     */
+    static class PreparedASCIIToBinaryBuffer implements ASCIIToBinaryConverter {
+        final private double doubleVal;
+        private int roundDir = 0;
+
+        public PreparedASCIIToBinaryBuffer(double doubleVal) {
+            this.doubleVal = doubleVal;
+        }
+
+        public PreparedASCIIToBinaryBuffer(double doubleVal, int roundDir) {
+            this.doubleVal = doubleVal;
+            this.roundDir = roundDir;
+        }
+
+        @Override
+        public double doubleValue() {
+            return doubleVal;
+        }
+
+        @Override
+        public float floatValue() {
+            return stickyRound(doubleVal,roundDir);
+        }
+    }
+
+    static final ASCIIToBinaryConverter A2BC_POSITIVE_INFINITY = new PreparedASCIIToBinaryBuffer(Double.POSITIVE_INFINITY);
+    static final ASCIIToBinaryConverter A2BC_NEGATIVE_INFINITY = new PreparedASCIIToBinaryBuffer(Double.NEGATIVE_INFINITY);
+    static final ASCIIToBinaryConverter A2BC_NOT_A_NUMBER  = new PreparedASCIIToBinaryBuffer(Double.NaN);
+    static final ASCIIToBinaryConverter A2BC_POSITIVE_ZERO = new PreparedASCIIToBinaryBuffer(0.0d);
+    static final ASCIIToBinaryConverter A2BC_NEGATIVE_ZERO = new PreparedASCIIToBinaryBuffer(-0.0d);
+
+    /**
+     * A buffered implementation of ASCIIToBinaryConverter.
+     */
+    static class ASCIIToBinaryBuffer implements ASCIIToBinaryConverter {
+        boolean     isNegative;
+        int         decExponent;
+        char        digits[];
+        int         nDigits;
+        int         roundDir = 0; // set by doubleValue
+
+        ASCIIToBinaryBuffer( boolean negSign, int decExponent, char[] digits, int n)
+        {
+            this.isNegative = negSign;
+            this.decExponent = decExponent;
+            this.digits = digits;
+            this.nDigits = n;
+        }
+
+        @Override
+        public double doubleValue() {
+            return doubleValue(false);
+        }
+
+        /**
+         * Computes a number that is the ULP of the given value,
+         * for purposes of addition/subtraction. Generally easy.
+         * More difficult if subtracting and the argument
+         * is a normalized a power of 2, as the ULP changes at these points.
+         */
+        private static double ulp(double dval, boolean subtracting) {
+            long lbits = Double.doubleToLongBits(dval) & ~DoubleConsts.SIGN_BIT_MASK;
+            int binexp = (int) (lbits >>> EXP_SHIFT);
+            double ulpval;
+            if (subtracting && (binexp >= EXP_SHIFT) && ((lbits & DoubleConsts.SIGNIF_BIT_MASK) == 0L)) {
+                // for subtraction from normalized, powers of 2,
+                // use next-smaller exponent
+                binexp -= 1;
+            }
+            if (binexp > EXP_SHIFT) {
+                ulpval = Double.longBitsToDouble(((long) (binexp - EXP_SHIFT)) << EXP_SHIFT);
+            } else if (binexp == 0) {
+                ulpval = Double.MIN_VALUE;
+            } else {
+                ulpval = Double.longBitsToDouble(1L << (binexp - 1));
+            }
+            if (subtracting) {
+                ulpval = -ulpval;
+            }
+
+            return ulpval;
+        }
+
+        /**
+         * Takes a FloatingDecimal, which we presumably just scanned in,
+         * and finds out what its value is, as a double.
+         *
+         * AS A SIDE EFFECT, SET roundDir TO INDICATE PREFERRED
+         * ROUNDING DIRECTION in case the result is really destined
+         * for a single-precision float.
+         */
+        private strictfp double doubleValue(boolean mustSetRoundDir) {
+            int kDigits = Math.min(nDigits, MAX_DECIMAL_DIGITS + 1);
+            long lValue;
+            double dValue;
+            double rValue;
+
+            if (mustSetRoundDir) {
+                roundDir = 0;
+            }
+            //
+            // convert the lead kDigits to a long integer.
+            //
+            // (special performance hack: start to do it using int)
+            int iValue = (int) digits[0] - (int) '0';
+            int iDigits = Math.min(kDigits, INT_DECIMAL_DIGITS);
+            for (int i = 1; i < iDigits; i++) {
+                iValue = iValue * 10 + (int) digits[i] - (int) '0';
+            }
+            lValue = (long) iValue;
+            for (int i = iDigits; i < kDigits; i++) {
+                lValue = lValue * 10L + (long) ((int) digits[i] - (int) '0');
+            }
+            dValue = (double) lValue;
+            int exp = decExponent - kDigits;
+            //
+            // lValue now contains a long integer with the value of
+            // the first kDigits digits of the number.
+            // dValue contains the (double) of the same.
+            //
+
+            if (nDigits <= MAX_DECIMAL_DIGITS) {
+                //
+                // possibly an easy case.
+                // We know that the digits can be represented
+                // exactly. And if the exponent isn't too outrageous,
+                // the whole thing can be done with one operation,
+                // thus one rounding error.
+                // Note that all our constructors trim all leading and
+                // trailing zeros, so simple values (including zero)
+                // will always end up here
+                //
+                if (exp == 0 || dValue == 0.0) {
+                    return (isNegative) ? -dValue : dValue; // small floating integer
+                }
+                else if (exp >= 0) {
+                    if (exp <= MAX_SMALL_TEN) {
+                        //
+                        // Can get the answer with one operation,
+                        // thus one roundoff.
+                        //
+                        rValue = dValue * SMALL_10_POW[exp];
+                        if (mustSetRoundDir) {
+                            double tValue = rValue / SMALL_10_POW[exp];
+                            roundDir = (tValue == dValue) ? 0
+                                    : (tValue < dValue) ? 1
+                                    : -1;
+                        }
+                        return (isNegative) ? -rValue : rValue;
+                    }
+                    int slop = MAX_DECIMAL_DIGITS - kDigits;
+                    if (exp <= MAX_SMALL_TEN + slop) {
+                        //
+                        // We can multiply dValue by 10^(slop)
+                        // and it is still "small" and exact.
+                        // Then we can multiply by 10^(exp-slop)
+                        // with one rounding.
+                        //
+                        dValue *= SMALL_10_POW[slop];
+                        rValue = dValue * SMALL_10_POW[exp - slop];
+
+                        if (mustSetRoundDir) {
+                            double tValue = rValue / SMALL_10_POW[exp - slop];
+                            roundDir = (tValue == dValue) ? 0
+                                    : (tValue < dValue) ? 1
+                                    : -1;
+                        }
+                        return (isNegative) ? -rValue : rValue;
+                    }
+                    //
+                    // Else we have a hard case with a positive exp.
+                    //
+                } else {
+                    if (exp >= -MAX_SMALL_TEN) {
+                        //
+                        // Can get the answer in one division.
+                        //
+                        rValue = dValue / SMALL_10_POW[-exp];
+                        if (mustSetRoundDir) {
+                            double tValue = rValue * SMALL_10_POW[-exp];
+                            roundDir = (tValue == dValue) ? 0
+                                    : (tValue < dValue) ? 1
+                                    : -1;
+                        }
+                        return (isNegative) ? -rValue : rValue;
+                    }
+                    //
+                    // Else we have a hard case with a negative exp.
+                    //
+                }
+            }
+
+            //
+            // Harder cases:
+            // The sum of digits plus exponent is greater than
+            // what we think we can do with one error.
+            //
+            // Start by approximating the right answer by,
+            // naively, scaling by powers of 10.
+            //
+            if (exp > 0) {
+                if (decExponent > MAX_DECIMAL_EXPONENT + 1) {
+                    //
+                    // Lets face it. This is going to be
+                    // Infinity. Cut to the chase.
+                    //
+                    return (isNegative) ? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY;
+                }
+                if ((exp & 15) != 0) {
+                    dValue *= SMALL_10_POW[exp & 15];
+                }
+                if ((exp >>= 4) != 0) {
+                    int j;
+                    for (j = 0; exp > 1; j++, exp >>= 1) {
+                        if ((exp & 1) != 0) {
+                            dValue *= BIG_10_POW[j];
+                        }
+                    }
+                    //
+                    // The reason for the weird exp > 1 condition
+                    // in the above loop was so that the last multiply
+                    // would get unrolled. We handle it here.
+                    // It could overflow.
+                    //
+                    double t = dValue * BIG_10_POW[j];
+                    if (Double.isInfinite(t)) {
+                        //
+                        // It did overflow.
+                        // Look more closely at the result.
+                        // If the exponent is just one too large,
+                        // then use the maximum finite as our estimate
+                        // value. Else call the result infinity
+                        // and punt it.
+                        // ( I presume this could happen because
+                        // rounding forces the result here to be
+                        // an ULP or two larger than
+                        // Double.MAX_VALUE ).
+                        //
+                        t = dValue / 2.0;
+                        t *= BIG_10_POW[j];
+                        if (Double.isInfinite(t)) {
+                            return (isNegative) ? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY;
+                        }
+                        t = Double.MAX_VALUE;
+                    }
+                    dValue = t;
+                }
+            } else if (exp < 0) {
+                exp = -exp;
+                if (decExponent < MIN_DECIMAL_EXPONENT - 1) {
+                    //
+                    // Lets face it. This is going to be
+                    // zero. Cut to the chase.
+                    //
+                    return (isNegative) ? -0.0 : 0.0;
+                }
+                if ((exp & 15) != 0) {
+                    dValue /= SMALL_10_POW[exp & 15];
+                }
+                if ((exp >>= 4) != 0) {
+                    int j;
+                    for (j = 0; exp > 1; j++, exp >>= 1) {
+                        if ((exp & 1) != 0) {
+                            dValue *= TINY_10_POW[j];
+                        }
+                    }
+                    //
+                    // The reason for the weird exp > 1 condition
+                    // in the above loop was so that the last multiply
+                    // would get unrolled. We handle it here.
+                    // It could underflow.
+                    //
+                    double t = dValue * TINY_10_POW[j];
+                    if (t == 0.0) {
+                        //
+                        // It did underflow.
+                        // Look more closely at the result.
+                        // If the exponent is just one too small,
+                        // then use the minimum finite as our estimate
+                        // value. Else call the result 0.0
+                        // and punt it.
+                        // ( I presume this could happen because
+                        // rounding forces the result here to be
+                        // an ULP or two less than
+                        // Double.MIN_VALUE ).
+                        //
+                        t = dValue * 2.0;
+                        t *= TINY_10_POW[j];
+                        if (t == 0.0) {
+                            return (isNegative) ? -0.0 : 0.0;
+                        }
+                        t = Double.MIN_VALUE;
+                    }
+                    dValue = t;
+                }
+            }
+
+            //
+            // dValue is now approximately the result.
+            // The hard part is adjusting it, by comparison
+            // with FDBigInteger arithmetic.
+            // Formulate the EXACT big-number result as
+            // bigD0 * 10^exp
+            //
+            FDBigInteger bigD0 = new FDBigInteger(lValue, digits, kDigits, nDigits);
+            exp = decExponent - nDigits;
+
+            final int B5 = Math.max(0, -exp); // powers of 5 in bigB, value is not modified inside correctionLoop
+            final int D5 = Math.max(0, exp); // powers of 5 in bigD, value is not modified inside correctionLoop
+            bigD0 = bigD0.multByPow52(D5, 0);
+            bigD0.makeImmutable();   // prevent bigD0 modification inside correctionLoop
+            FDBigInteger bigD = null;
+            int prevD2 = 0;
+
+            correctionLoop:
+            while (true) {
+                // here dValue can't be NaN, Infinity or zero
+                long bigBbits = Double.doubleToRawLongBits(dValue) & ~DoubleConsts.SIGN_BIT_MASK;
+                int binexp = (int) (bigBbits >>> EXP_SHIFT);
+                bigBbits &= DoubleConsts.SIGNIF_BIT_MASK;
+                if (binexp > 0) {
+                    bigBbits |= FRACT_HOB;
+                } else { // Normalize denormalized numbers.
+                    assert bigBbits != 0L : bigBbits; // doubleToBigInt(0.0)
+                    int leadingZeros = Long.numberOfLeadingZeros(bigBbits);
+                    int shift = leadingZeros - (63 - EXP_SHIFT);
+                    bigBbits <<= shift;
+                    binexp = 1 - shift;
+                }
+                binexp -= DoubleConsts.EXP_BIAS;
+                int lowOrderZeros = Long.numberOfTrailingZeros(bigBbits);
+                bigBbits >>>= lowOrderZeros;
+                final int bigIntExp = binexp - EXP_SHIFT + lowOrderZeros;
+                final int bigIntNBits = EXP_SHIFT + 1 - lowOrderZeros;
+
+                //
+                // Scale bigD, bigB appropriately for
+                // big-integer operations.
+                // Naively, we multiply by powers of ten
+                // and powers of two. What we actually do
+                // is keep track of the powers of 5 and
+                // powers of 2 we would use, then factor out
+                // common divisors before doing the work.
+                //
+                int B2 = B5; // powers of 2 in bigB
+                int D2 = D5; // powers of 2 in bigD
+                int Ulp2;   // powers of 2 in halfUlp.
+                if (bigIntExp >= 0) {
+                    B2 += bigIntExp;
+                } else {
+                    D2 -= bigIntExp;
+                }
+                Ulp2 = B2;
+                // shift bigB and bigD left by a number s. t.
+                // halfUlp is still an integer.
+                int hulpbias;
+                if (binexp <= -DoubleConsts.EXP_BIAS) {
+                    // This is going to be a denormalized number
+                    // (if not actually zero).
+                    // half an ULP is at 2^-(expBias+EXP_SHIFT+1)
+                    hulpbias = binexp + lowOrderZeros + DoubleConsts.EXP_BIAS;
+                } else {
+                    hulpbias = 1 + lowOrderZeros;
+                }
+                B2 += hulpbias;
+                D2 += hulpbias;
+                // if there are common factors of 2, we might just as well
+                // factor them out, as they add nothing useful.
+                int common2 = Math.min(B2, Math.min(D2, Ulp2));
+                B2 -= common2;
+                D2 -= common2;
+                Ulp2 -= common2;
+                // do multiplications by powers of 5 and 2
+                FDBigInteger bigB = FDBigInteger.valueOfMulPow52(bigBbits, B5, B2);
+                if (bigD == null || prevD2 != D2) {
+                    bigD = bigD0.leftShift(D2);
+                    prevD2 = D2;
                 }
+                //
+                // to recap:
+                // bigB is the scaled-big-int version of our floating-point
+                // candidate.
+                // bigD is the scaled-big-int version of the exact value
+                // as we understand it.
+                // halfUlp is 1/2 an ulp of bigB, except for special cases
+                // of exact powers of 2
+                //
+                // the plan is to compare bigB with bigD, and if the difference
+                // is less than halfUlp, then we're satisfied. Otherwise,
+                // use the ratio of difference to halfUlp to calculate a fudge
+                // factor to add to the floating value, then go 'round again.
+                //
+                FDBigInteger diff;
+                int cmpResult;
+                boolean overvalue;
+                if ((cmpResult = bigB.cmp(bigD)) > 0) {
+                    overvalue = true; // our candidate is too big.
+                    diff = bigB.leftInplaceSub(bigD); // bigB is not user further - reuse
+                    if ((bigIntNBits == 1) && (bigIntExp > -DoubleConsts.EXP_BIAS + 1)) {
+                        // candidate is a normalized exact power of 2 and
+                        // is too big (larger than Double.MIN_NORMAL). We will be subtracting.
+                        // For our purposes, ulp is the ulp of the
+                        // next smaller range.
+                        Ulp2 -= 1;
+                        if (Ulp2 < 0) {
+                            // rats. Cannot de-scale ulp this far.
+                            // must scale diff in other direction.
+                            Ulp2 = 0;
+                            diff = diff.leftShift(1);
+                        }
+                    }
+                } else if (cmpResult < 0) {
+                    overvalue = false; // our candidate is too small.
+                    diff = bigD.rightInplaceSub(bigB); // bigB is not user further - reuse
+                } else {
+                    // the candidate is exactly right!
+                    // this happens with surprising frequency
+                    break correctionLoop;
+                }
+                cmpResult = diff.cmpPow52(B5, Ulp2);
+                if ((cmpResult) < 0) {
+                    // difference is small.
+                    // this is close enough
+                    if (mustSetRoundDir) {
+                        roundDir = overvalue ? -1 : 1;
+                    }
+                    break correctionLoop;
+                } else if (cmpResult == 0) {
+                    // difference is exactly half an ULP
+                    // round to some other value maybe, then finish
+                    dValue += 0.5 * ulp(dValue, overvalue);
+                    // should check for bigIntNBits == 1 here??
+                    if (mustSetRoundDir) {
+                        roundDir = overvalue ? -1 : 1;
+                    }
+                    break correctionLoop;
+                } else {
+                    // difference is non-trivial.
+                    // could scale addend by ratio of difference to
+                    // halfUlp here, if we bothered to compute that difference.
+                    // Most of the time ( I hope ) it is about 1 anyway.
+                    dValue += ulp(dValue, overvalue);
+                    if (dValue == 0.0 || dValue == Double.POSITIVE_INFINITY) {
+                        break correctionLoop; // oops. Fell off end of range.
+                    }
+                    continue; // try again.
+                }
+
+            }
+            return (isNegative) ? -dValue : dValue;
+        }
+
+        /**
+         * Takes a FloatingDecimal, which we presumably just scanned in,
+         * and finds out what its value is, as a float.
+         * This is distinct from doubleValue() to avoid the extremely
+         * unlikely case of a double rounding error, wherein the conversion
+         * to double has one rounding error, and the conversion of that double
+         * to a float has another rounding error, IN THE WRONG DIRECTION,
+         * ( because of the preference to a zero low-order bit ).
+         */
+        @Override
+        public strictfp float floatValue() {
+            int kDigits = Math.min(nDigits, SINGLE_MAX_DECIMAL_DIGITS + 1);
+            int iValue;
+            float fValue;
+            //
+            // convert the lead kDigits to an integer.
+            //
+            iValue = (int) digits[0] - (int) '0';
+            for (int i = 1; i < kDigits; i++) {
+                iValue = iValue * 10 + (int) digits[i] - (int) '0';
+            }
+            fValue = (float) iValue;
+            int exp = decExponent - kDigits;
+            //
+            // iValue now contains an integer with the value of
+            // the first kDigits digits of the number.
+            // fValue contains the (float) of the same.
+            //
+
+            if (nDigits <= SINGLE_MAX_DECIMAL_DIGITS) {
+                //
+                // possibly an easy case.
+                // We know that the digits can be represented
+                // exactly. And if the exponent isn't too outrageous,
+                // the whole thing can be done with one operation,
+                // thus one rounding error.
+                // Note that all our constructors trim all leading and
+                // trailing zeros, so simple values (including zero)
+                // will always end up here.
+                //
+                if (exp == 0 || fValue == 0.0f) {
+                    return (isNegative) ? -fValue : fValue; // small floating integer
+                } else if (exp >= 0) {
+                    if (exp <= SINGLE_MAX_SMALL_TEN) {
+                        //
+                        // Can get the answer with one operation,
+                        // thus one roundoff.
+                        //
+                        fValue *= SINGLE_SMALL_10_POW[exp];
+                        return (isNegative) ? -fValue : fValue;
+                    }
+                    int slop = SINGLE_MAX_DECIMAL_DIGITS - kDigits;
+                    if (exp <= SINGLE_MAX_SMALL_TEN + slop) {
+                        //
+                        // We can multiply dValue by 10^(slop)
+                        // and it is still "small" and exact.
+                        // Then we can multiply by 10^(exp-slop)
+                        // with one rounding.
+                        //
+                        fValue *= SINGLE_SMALL_10_POW[slop];
+                        fValue *= SINGLE_SMALL_10_POW[exp - slop];
+                        return (isNegative) ? -fValue : fValue;
+                    }
+                    //
+                    // Else we have a hard case with a positive exp.
+                    //
+                } else {
+                    if (exp >= -SINGLE_MAX_SMALL_TEN) {
+                        //
+                        // Can get the answer in one division.
+                        //
+                        fValue /= SINGLE_SMALL_10_POW[-exp];
+                        return (isNegative) ? -fValue : fValue;
+                    }
+                    //
+                    // Else we have a hard case with a negative exp.
+                    //
+                }
+            } else if ((decExponent >= nDigits) && (nDigits + decExponent <= MAX_DECIMAL_DIGITS)) {
+                //
+                // In double-precision, this is an exact floating integer.
+                // So we can compute to double, then shorten to float
+                // with one round, and get the right answer.
+                //
+                // First, finish accumulating digits.
+                // Then convert that integer to a double, multiply
+                // by the appropriate power of ten, and convert to float.
+                //
+                long lValue = (long) iValue;
+                for (int i = kDigits; i < nDigits; i++) {
+                    lValue = lValue * 10L + (long) ((int) digits[i] - (int) '0');
+                }
+                double dValue = (double) lValue;
+                exp = decExponent - nDigits;
+                dValue *= SMALL_10_POW[exp];
+                fValue = (float) dValue;
+                return (isNegative) ? -fValue : fValue;
+
+            }
+            //
+            // Harder cases:
+            // The sum of digits plus exponent is greater than
+            // what we think we can do with one error.
+            //
+            // Start by weeding out obviously out-of-range
+            // results, then convert to double and go to
+            // common hard-case code.
+            //
+            if (decExponent > SINGLE_MAX_DECIMAL_EXPONENT + 1) {
+                //
+                // Lets face it. This is going to be
+                // Infinity. Cut to the chase.
+                //
+                return (isNegative) ? Float.NEGATIVE_INFINITY : Float.POSITIVE_INFINITY;
+            } else if (decExponent < SINGLE_MIN_DECIMAL_EXPONENT - 1) {
+                //
+                // Lets face it. This is going to be
+                // zero. Cut to the chase.
+                //
+                return (isNegative) ? -0.0f : 0.0f;
+            }
+
+            //
+            // Here, we do 'way too much work, but throwing away
+            // our partial results, and going and doing the whole
+            // thing as double, then throwing away half the bits that computes
+            // when we convert back to float.
+            //
+            // The alternative is to reproduce the whole multiple-precision
+            // algorithm for float precision, or to try to parameterize it
+            // for common usage. The former will take about 400 lines of code,
+            // and the latter I tried without success. Thus the semi-hack
+            // answer here.
+            //
+            double dValue = doubleValue(true);
+            return stickyRound(dValue, roundDir);
+        }
+
+
+        /**
+         * All the positive powers of 10 that can be
+         * represented exactly in double/float.
+         */
+        private static final double[] SMALL_10_POW = {
+            1.0e0,
+            1.0e1, 1.0e2, 1.0e3, 1.0e4, 1.0e5,
+            1.0e6, 1.0e7, 1.0e8, 1.0e9, 1.0e10,
+            1.0e11, 1.0e12, 1.0e13, 1.0e14, 1.0e15,
+            1.0e16, 1.0e17, 1.0e18, 1.0e19, 1.0e20,
+            1.0e21, 1.0e22
+        };
+
+        private static final float[] SINGLE_SMALL_10_POW = {
+            1.0e0f,
+            1.0e1f, 1.0e2f, 1.0e3f, 1.0e4f, 1.0e5f,
+            1.0e6f, 1.0e7f, 1.0e8f, 1.0e9f, 1.0e10f
+        };
+
+        private static final double[] BIG_10_POW = {
+            1e16, 1e32, 1e64, 1e128, 1e256 };
+        private static final double[] TINY_10_POW = {
+            1e-16, 1e-32, 1e-64, 1e-128, 1e-256 };
+
+        private static final int MAX_SMALL_TEN = SMALL_10_POW.length-1;
+        private static final int SINGLE_MAX_SMALL_TEN = SINGLE_SMALL_10_POW.length-1;
+
+    }
+
+    /**
+     * Returns a BinaryToASCIIConverter for a double.
+     * The returned object is a ThreadLocal variable of this class.
+     *
+     * @param d The double precision value to convert.
+     * @return The converter.
+     */
+    public static BinaryToASCIIConverter getBinaryToASCIIConverter(double d) {
+        return getBinaryToASCIIConverter(d, true);
+    }
+
+    /**
+     * Returns a BinaryToASCIIConverter for a double.
+     * The returned object is a ThreadLocal variable of this class.
+     *
+     * @param d The double precision value to convert.
+     * @param isCompatibleFormat
+     * @return The converter.
+     */
+    static BinaryToASCIIConverter getBinaryToASCIIConverter(double d, boolean isCompatibleFormat) {
+        long dBits = Double.doubleToRawLongBits(d);
+        boolean isNegative = (dBits&DoubleConsts.SIGN_BIT_MASK) != 0; // discover sign
+        long fractBits = dBits & DoubleConsts.SIGNIF_BIT_MASK;
+        int  binExp = (int)( (dBits&DoubleConsts.EXP_BIT_MASK) >> EXP_SHIFT );
+        // Discover obvious special cases of NaN and Infinity.
+        if ( binExp == (int)(DoubleConsts.EXP_BIT_MASK>>EXP_SHIFT) ) {
+            if ( fractBits == 0L ){
+                return isNegative ? B2AC_NEGATIVE_INFINITY : B2AC_POSITIVE_INFINITY;
+            } else {
+                return B2AC_NOT_A_NUMBER;
+            }
+        }
+        // Finish unpacking
+        // Normalize denormalized numbers.
+        // Insert assumed high-order bit for normalized numbers.
+        // Subtract exponent bias.
+        int  nSignificantBits;
+        if ( binExp == 0 ){
+            if ( fractBits == 0L ){
+                // not a denorm, just a 0!
+                return isNegative ? B2AC_NEGATIVE_ZERO : B2AC_POSITIVE_ZERO;
             }
+            int leadingZeros = Long.numberOfLeadingZeros(fractBits);
+            int shift = leadingZeros-(63-EXP_SHIFT);
+            fractBits <<= shift;
+            binExp = 1 - shift;
+            nSignificantBits =  64-leadingZeros; // recall binExp is  - shift count.
+        } else {
+            fractBits |= FRACT_HOB;
+            nSignificantBits = EXP_SHIFT+1;
         }
-        return i;
+        binExp -= DoubleConsts.EXP_BIAS;
+        BinaryToASCIIBuffer buf = getBinaryToASCIIBuffer();
+        buf.setSign(isNegative);
+        // call the routine that actually does all the hard work.
+        buf.dtoa(binExp, fractBits, nSignificantBits, isCompatibleFormat);
+        return buf;
     }
 
-    // Per-thread buffer for string/stringbuffer conversion
-    private static ThreadLocal perThreadBuffer = new ThreadLocal() {
-            protected synchronized char[] initialValue() {
-                return new char[26];
+    private static BinaryToASCIIConverter getBinaryToASCIIConverter(float f) {
+        int fBits = Float.floatToRawIntBits( f );
+        boolean isNegative = (fBits&FloatConsts.SIGN_BIT_MASK) != 0;
+        int fractBits = fBits&FloatConsts.SIGNIF_BIT_MASK;
+        int binExp = (fBits&FloatConsts.EXP_BIT_MASK) >> SINGLE_EXP_SHIFT;
+        // Discover obvious special cases of NaN and Infinity.
+        if ( binExp == (FloatConsts.EXP_BIT_MASK>>SINGLE_EXP_SHIFT) ) {
+            if ( fractBits == 0L ){
+                return isNegative ? B2AC_NEGATIVE_INFINITY : B2AC_POSITIVE_INFINITY;
+            } else {
+                return B2AC_NOT_A_NUMBER;
             }
-        };
-
-    public void appendTo(Appendable buf) {
-          char result[] = perThreadBuffer.get();
-          int i = getChars(result);
-        if (buf instanceof StringBuilder)
-            ((StringBuilder) buf).append(result, 0, i);
-        else if (buf instanceof StringBuffer)
-            ((StringBuffer) buf).append(result, 0, i);
-        else
-            assert false;
+        }
+        // Finish unpacking
+        // Normalize denormalized numbers.
+        // Insert assumed high-order bit for normalized numbers.
+        // Subtract exponent bias.
+        int  nSignificantBits;
+        if ( binExp == 0 ){
+            if ( fractBits == 0 ){
+                // not a denorm, just a 0!
+                return isNegative ? B2AC_NEGATIVE_ZERO : B2AC_POSITIVE_ZERO;
+            }
+            int leadingZeros = Integer.numberOfLeadingZeros(fractBits);
+            int shift = leadingZeros-(31-SINGLE_EXP_SHIFT);
+            fractBits <<= shift;
+            binExp = 1 - shift;
+            nSignificantBits =  32 - leadingZeros; // recall binExp is  - shift count.
+        } else {
+            fractBits |= SINGLE_FRACT_HOB;
+            nSignificantBits = SINGLE_EXP_SHIFT+1;
+        }
+        binExp -= FloatConsts.EXP_BIAS;
+        BinaryToASCIIBuffer buf = getBinaryToASCIIBuffer();
+        buf.setSign(isNegative);
+        // call the routine that actually does all the hard work.
+        buf.dtoa(binExp, ((long)fractBits)<<(EXP_SHIFT-SINGLE_EXP_SHIFT), nSignificantBits, true);
+        return buf;
     }
 
     @SuppressWarnings("fallthrough")
-    public static FloatingDecimal
-    readJavaFormatString( String in ) throws NumberFormatException {
+    static ASCIIToBinaryConverter readJavaFormatString( String in ) throws NumberFormatException {
         boolean isNegative = false;
         boolean signSeen   = false;
         int     decExp;
@@ -1034,10 +1729,12 @@
         try{
             in = in.trim(); // don't fool around with white space.
                             // throws NullPointerException if null
-            int l = in.length();
-            if ( l == 0 ) throw new NumberFormatException("empty String");
+            int len = in.length();
+            if ( len == 0 ) {
+                throw new NumberFormatException("empty String");
+            }
             int i = 0;
-            switch ( c = in.charAt( i ) ){
+            switch (in.charAt(i)){
             case '-':
                 isNegative = true;
                 //FALLTHROUGH
@@ -1045,144 +1742,121 @@
                 i++;
                 signSeen = true;
             }
-
-            // Check for NaN and Infinity strings
             c = in.charAt(i);
-            if(c == 'N' || c == 'I') { // possible NaN or infinity
-                boolean potentialNaN = false;
-                char targetChars[] = null;  // char array of "NaN" or "Infinity"
-
-                if(c == 'N') {
-                    targetChars = notANumber;
-                    potentialNaN = true;
-                } else {
-                    targetChars = infinity;
+            if(c == 'N') { // Check for NaN
+                if((len-i)==NAN_LENGTH && in.indexOf(NAN_REP,i)==i) {
+                    return A2BC_NOT_A_NUMBER;
+                }
+                // something went wrong, throw exception
+                break parseNumber;
+            } else if(c == 'I') { // Check for Infinity strings
+                if((len-i)==INFINITY_LENGTH && in.indexOf(INFINITY_REP,i)==i) {
+                    return isNegative? A2BC_NEGATIVE_INFINITY : A2BC_POSITIVE_INFINITY;
                 }
-
-                // compare Input string to "NaN" or "Infinity"
-                int j = 0;
-                while(i < l && j < targetChars.length) {
-                    if(in.charAt(i) == targetChars[j]) {
-                        i++; j++;
-                    }
-                    else // something is amiss, throw exception
-                        break parseNumber;
-                }
-
-                // For the candidate string to be a NaN or infinity,
-                // all characters in input string and target char[]
-                // must be matched ==> j must equal targetChars.length
-                // and i must equal l
-                if( (j == targetChars.length) && (i == l) ) { // return NaN or infinity
-                    return (potentialNaN ? new FloatingDecimal(Double.NaN) // NaN has no sign
-                            : new FloatingDecimal(isNegative?
-                                                  Double.NEGATIVE_INFINITY:
-                                                  Double.POSITIVE_INFINITY)) ;
-                }
-                else { // something went wrong, throw exception
-                    break parseNumber;
-                }
-
+                // something went wrong, throw exception
+                break parseNumber;
             } else if (c == '0')  { // check for hexadecimal floating-point number
-                if (l > i+1 ) {
+                if (len > i+1 ) {
                     char ch = in.charAt(i+1);
-                    if (ch == 'x' || ch == 'X' ) // possible hex string
+                    if (ch == 'x' || ch == 'X' ) { // possible hex string
                         return parseHexString(in);
+                    }
                 }
             }  // look for and process decimal floating-point string
 
-            char[] digits = new char[ l ];
+            char[] digits = new char[ len ];
             int    nDigits= 0;
             boolean decSeen = false;
             int decPt = 0;
             int nLeadZero = 0;
             int nTrailZero= 0;
-        digitLoop:
-            while ( i < l ){
-                switch ( c = in.charAt( i ) ){
-                case '0':
-                    if ( nDigits > 0 ){
-                        nTrailZero += 1;
-                    } else {
-                        nLeadZero += 1;
+
+        skipLeadingZerosLoop:
+            while (i < len) {
+                c = in.charAt(i);
+                if (c == '0') {
+                    nLeadZero++;
+                } else if (c == '.') {
+                    if (decSeen) {
+                        // already saw one ., this is the 2nd.
+                        throw new NumberFormatException("multiple points");
                     }
-                    break; // out of switch.
-                case '1':
-                case '2':
-                case '3':
-                case '4':
-                case '5':
-                case '6':
-                case '7':
-                case '8':
-                case '9':
-                    while ( nTrailZero > 0 ){
-                        digits[nDigits++] = '0';
-                        nTrailZero -= 1;
+                    decPt = i;
+                    if (signSeen) {
+                        decPt -= 1;
                     }
+                    decSeen = true;
+                } else {
+                    break skipLeadingZerosLoop;
+                }
+                i++;
+            }
+        digitLoop:
+            while (i < len) {
+                c = in.charAt(i);
+                if (c >= '1' && c <= '9') {
                     digits[nDigits++] = c;
-                    break; // out of switch.
-                case '.':
-                    if ( decSeen ){
+                    nTrailZero = 0;
+                } else if (c == '0') {
+                    digits[nDigits++] = c;
+                    nTrailZero++;
+                } else if (c == '.') {
+                    if (decSeen) {
                         // already saw one ., this is the 2nd.
                         throw new NumberFormatException("multiple points");
                     }
                     decPt = i;
-                    if ( signSeen ){
+                    if (signSeen) {
                         decPt -= 1;
                     }
                     decSeen = true;
-                    break; // out of switch.
-                default:
+                } else {
                     break digitLoop;
                 }
                 i++;
             }
-            /*
-             * At this point, we've scanned all the digits and decimal
-             * point we're going to see. Trim off leading and trailing
-             * zeros, which will just confuse us later, and adjust
-             * our initial decimal exponent accordingly.
-             * To review:
-             * we have seen i total characters.
-             * nLeadZero of them were zeros before any other digits.
-             * nTrailZero of them were zeros after any other digits.
-             * if ( decSeen ), then a . was seen after decPt characters
-             * ( including leading zeros which have been discarded )
-             * nDigits characters were neither lead nor trailing
-             * zeros, nor point
-             */
-            /*
-             * special hack: if we saw no non-zero digits, then the
-             * answer is zero!
-             * Unfortunately, we feel honor-bound to keep parsing!
-             */
-            if ( nDigits == 0 ){
-                digits = zero;
-                nDigits = 1;
-                if ( nLeadZero == 0 ){
-                    // we saw NO DIGITS AT ALL,
-                    // not even a crummy 0!
-                    // this is not allowed.
-                    break parseNumber; // go throw exception
-                }
-
+            nDigits -=nTrailZero;
+            //
+            // At this point, we've scanned all the digits and decimal
+            // point we're going to see. Trim off leading and trailing
+            // zeros, which will just confuse us later, and adjust
+            // our initial decimal exponent accordingly.
+            // To review:
+            // we have seen i total characters.
+            // nLeadZero of them were zeros before any other digits.
+            // nTrailZero of them were zeros after any other digits.
+            // if ( decSeen ), then a . was seen after decPt characters
+            // ( including leading zeros which have been discarded )
+            // nDigits characters were neither lead nor trailing
+            // zeros, nor point
+            //
+            //
+            // special hack: if we saw no non-zero digits, then the
+            // answer is zero!
+            // Unfortunately, we feel honor-bound to keep parsing!
+            //
+            boolean isZero = (nDigits == 0);
+            if ( isZero &&  nLeadZero == 0 ){
+                // we saw NO DIGITS AT ALL,
+                // not even a crummy 0!
+                // this is not allowed.
+                break parseNumber; // go throw exception
             }
-
-            /* Our initial exponent is decPt, adjusted by the number of
-             * discarded zeros. Or, if there was no decPt,
-             * then its just nDigits adjusted by discarded trailing zeros.
-             */
+            //
+            // Our initial exponent is decPt, adjusted by the number of
+            // discarded zeros. Or, if there was no decPt,
+            // then its just nDigits adjusted by discarded trailing zeros.
+            //
             if ( decSeen ){
                 decExp = decPt - nLeadZero;
             } else {
-                decExp = nDigits+nTrailZero;
+                decExp = nDigits + nTrailZero;
             }
 
-            /*
-             * Look for 'e' or 'E' and an optionally signed integer.
-             */
-            if ( (i < l) &&  (((c = in.charAt(i) )=='e') || (c == 'E') ) ){
+            //
+            // Look for 'e' or 'E' and an optionally signed integer.
+            //
+            if ( (i < len) &&  (((c = in.charAt(i) )=='e') || (c == 'E') ) ){
                 int expSign = 1;
                 int expVal  = 0;
                 int reallyBig = Integer.MAX_VALUE / 10;
@@ -1196,31 +1870,21 @@
                 }
                 int expAt = i;
             expLoop:
-                while ( i < l  ){
+                while ( i < len  ){
                     if ( expVal >= reallyBig ){
                         // the next character will cause integer
                         // overflow.
                         expOverflow = true;
                     }
-                    switch ( c = in.charAt(i++) ){
-                    case '0':
-                    case '1':
-                    case '2':
-                    case '3':
-                    case '4':
-                    case '5':
-                    case '6':
-                    case '7':
-                    case '8':
-                    case '9':
+                    c = in.charAt(i++);
+                    if(c>='0' && c<='9') {
                         expVal = expVal*10 + ( (int)c - (int)'0' );
-                        continue;
-                    default:
+                    } else {
                         i--;           // back up.
                         break expLoop; // stop parsing exponent.
                     }
                 }
-                int expLimit = bigDecimalExponent+nDigits+nTrailZero;
+                int expLimit = BIG_DECIMAL_EXPONENT+nDigits+nTrailZero;
                 if ( expOverflow || ( expVal > expLimit ) ){
                     //
                     // The intent here is to end up with
@@ -1247,1182 +1911,588 @@
                 // but then some trailing garbage, that might be ok.
                 // so we just fall through in that case.
                 // HUMBUG
-                if ( i == expAt )
+                if ( i == expAt ) {
                     break parseNumber; // certainly bad
+                }
             }
-            /*
-             * We parsed everything we could.
-             * If there are leftovers, then this is not good input!
-             */
-            if ( i < l &&
-                ((i != l - 1) ||
+            //
+            // We parsed everything we could.
+            // If there are leftovers, then this is not good input!
+            //
+            if ( i < len &&
+                ((i != len - 1) ||
                 (in.charAt(i) != 'f' &&
                  in.charAt(i) != 'F' &&
                  in.charAt(i) != 'd' &&
                  in.charAt(i) != 'D'))) {
                 break parseNumber; // go throw exception
             }
-
-            return new FloatingDecimal( isNegative, decExp, digits, nDigits,  false );
+            if(isZero) {
+                return isNegative ? A2BC_NEGATIVE_ZERO : A2BC_POSITIVE_ZERO;
+            }
+            return new ASCIIToBinaryBuffer(isNegative, decExp, digits, nDigits);
         } catch ( StringIndexOutOfBoundsException e ){ }
         throw new NumberFormatException("For input string: \"" + in + "\"");
     }
 
-    /*
-     * Take a FloatingDecimal, which we presumably just scanned in,
-     * and find out what its value is, as a double.
-     *
-     * AS A SIDE EFFECT, SET roundDir TO INDICATE PREFERRED
-     * ROUNDING DIRECTION in case the result is really destined
-     * for a single-precision float.
+    /**
+     * Rounds a double to a float.
+     * In addition to the fraction bits of the double,
+     * look at the class instance variable roundDir,
+     * which should help us avoid double-rounding error.
+     * roundDir was set in hardValueOf if the estimate was
+     * close enough, but not exact. It tells us which direction
+     * of rounding is preferred.
      */
-
-    public strictfp double doubleValue(){
-        int     kDigits = Math.min( nDigits, maxDecimalDigits+1 );
-        long    lValue;
-        double  dValue;
-        double  rValue, tValue;
-
-        // First, check for NaN and Infinity values
-        if(digits == infinity || digits == notANumber) {
-            if(digits == notANumber)
-                return Double.NaN;
-            else
-                return (isNegative?Double.NEGATIVE_INFINITY:Double.POSITIVE_INFINITY);
-        }
-        else {
-            if (mustSetRoundDir) {
-                roundDir = 0;
-            }
-            /*
-             * convert the lead kDigits to a long integer.
-             */
-            // (special performance hack: start to do it using int)
-            int iValue = (int)digits[0]-(int)'0';
-            int iDigits = Math.min( kDigits, intDecimalDigits );
-            for ( int i=1; i < iDigits; i++ ){
-                iValue = iValue*10 + (int)digits[i]-(int)'0';
-            }
-            lValue = (long)iValue;
-            for ( int i=iDigits; i < kDigits; i++ ){
-                lValue = lValue*10L + (long)((int)digits[i]-(int)'0');
-            }
-            dValue = (double)lValue;
-            int exp = decExponent-kDigits;
-            /*
-             * lValue now contains a long integer with the value of
-             * the first kDigits digits of the number.
-             * dValue contains the (double) of the same.
-             */
-
-            if ( nDigits <= maxDecimalDigits ){
-                /*
-                 * possibly an easy case.
-                 * We know that the digits can be represented
-                 * exactly. And if the exponent isn't too outrageous,
-                 * the whole thing can be done with one operation,
-                 * thus one rounding error.
-                 * Note that all our constructors trim all leading and
-                 * trailing zeros, so simple values (including zero)
-                 * will always end up here
-                 */
-                if (exp == 0 || dValue == 0.0)
-                    return (isNegative)? -dValue : dValue; // small floating integer
-                else if ( exp >= 0 ){
-                    if ( exp <= maxSmallTen ){
-                        /*
-                         * Can get the answer with one operation,
-                         * thus one roundoff.
-                         */
-                        rValue = dValue * small10pow[exp];
-                        if ( mustSetRoundDir ){
-                            tValue = rValue / small10pow[exp];
-                            roundDir = ( tValue ==  dValue ) ? 0
-                                :( tValue < dValue ) ? 1
-                                : -1;
-                        }
-                        return (isNegative)? -rValue : rValue;
-                    }
-                    int slop = maxDecimalDigits - kDigits;
-                    if ( exp <= maxSmallTen+slop ){
-                        /*
-                         * We can multiply dValue by 10^(slop)
-                         * and it is still "small" and exact.
-                         * Then we can multiply by 10^(exp-slop)
-                         * with one rounding.
-                         */
-                        dValue *= small10pow[slop];
-                        rValue = dValue * small10pow[exp-slop];
-
-                        if ( mustSetRoundDir ){
-                            tValue = rValue / small10pow[exp-slop];
-                            roundDir = ( tValue ==  dValue ) ? 0
-                                :( tValue < dValue ) ? 1
-                                : -1;
-                        }
-                        return (isNegative)? -rValue : rValue;
-                    }
-                    /*
-                     * Else we have a hard case with a positive exp.
-                     */
-                } else {
-                    if ( exp >= -maxSmallTen ){
-                        /*
-                         * Can get the answer in one division.
-                         */
-                        rValue = dValue / small10pow[-exp];
-                        tValue = rValue * small10pow[-exp];
-                        if ( mustSetRoundDir ){
-                            roundDir = ( tValue ==  dValue ) ? 0
-                                :( tValue < dValue ) ? 1
-                                : -1;
-                        }
-                        return (isNegative)? -rValue : rValue;
-                    }
-                    /*
-                     * Else we have a hard case with a negative exp.
-                     */
-                }
+    static float stickyRound( double dval, int roundDirection ){
+        if(roundDirection!=0) {
+            long lbits = Double.doubleToRawLongBits( dval );
+            long binexp = lbits & DoubleConsts.EXP_BIT_MASK;
+            if ( binexp == 0L || binexp == DoubleConsts.EXP_BIT_MASK ){
+                // what we have here is special.
+                // don't worry, the right thing will happen.
+                return (float) dval;
             }
+            lbits += (long)roundDirection; // hack-o-matic.
+            return (float)Double.longBitsToDouble( lbits );
+        } else {
+            return (float)dval;
+        }
+    }
 
-            /*
-             * Harder cases:
-             * The sum of digits plus exponent is greater than
-             * what we think we can do with one error.
-             *
-             * Start by approximating the right answer by,
-             * naively, scaling by powers of 10.
-             */
-            if ( exp > 0 ){
-                if ( decExponent > maxDecimalExponent+1 ){
-                    /*
-                     * Lets face it. This is going to be
-                     * Infinity. Cut to the chase.
-                     */
-                    return (isNegative)? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY;
-                }
-                if ( (exp&15) != 0 ){
-                    dValue *= small10pow[exp&15];
-                }
-                if ( (exp>>=4) != 0 ){
-                    int j;
-                    for( j = 0; exp > 1; j++, exp>>=1 ){
-                        if ( (exp&1)!=0)
-                            dValue *= big10pow[j];
-                    }
-                    /*
-                     * The reason for the weird exp > 1 condition
-                     * in the above loop was so that the last multiply
-                     * would get unrolled. We handle it here.
-                     * It could overflow.
-                     */
-                    double t = dValue * big10pow[j];
-                    if ( Double.isInfinite( t ) ){
-                        /*
-                         * It did overflow.
-                         * Look more closely at the result.
-                         * If the exponent is just one too large,
-                         * then use the maximum finite as our estimate
-                         * value. Else call the result infinity
-                         * and punt it.
-                         * ( I presume this could happen because
-                         * rounding forces the result here to be
-                         * an ULP or two larger than
-                         * Double.MAX_VALUE ).
-                         */
-                        t = dValue / 2.0;
-                        t *= big10pow[j];
-                        if ( Double.isInfinite( t ) ){
-                            return (isNegative)? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY;
-                        }
-                        t = Double.MAX_VALUE;
-                    }
-                    dValue = t;
-                }
-            } else if ( exp < 0 ){
-                exp = -exp;
-                if ( decExponent < minDecimalExponent-1 ){
-                    /*
-                     * Lets face it. This is going to be
-                     * zero. Cut to the chase.
-                     */
-                    return (isNegative)? -0.0 : 0.0;
-                }
-                if ( (exp&15) != 0 ){
-                    dValue /= small10pow[exp&15];
-                }
-                if ( (exp>>=4) != 0 ){
-                    int j;
-                    for( j = 0; exp > 1; j++, exp>>=1 ){
-                        if ( (exp&1)!=0)
-                            dValue *= tiny10pow[j];
-                    }
-                    /*
-                     * The reason for the weird exp > 1 condition
-                     * in the above loop was so that the last multiply
-                     * would get unrolled. We handle it here.
-                     * It could underflow.
-                     */
-                    double t = dValue * tiny10pow[j];
-                    if ( t == 0.0 ){
-                        /*
-                         * It did underflow.
-                         * Look more closely at the result.
-                         * If the exponent is just one too small,
-                         * then use the minimum finite as our estimate
-                         * value. Else call the result 0.0
-                         * and punt it.
-                         * ( I presume this could happen because
-                         * rounding forces the result here to be
-                         * an ULP or two less than
-                         * Double.MIN_VALUE ).
-                         */
-                        t = dValue * 2.0;
-                        t *= tiny10pow[j];
-                        if ( t == 0.0 ){
-                            return (isNegative)? -0.0 : 0.0;
-                        }
-                        t = Double.MIN_VALUE;
-                    }
-                    dValue = t;
-                }
-            }
 
-            /*
-             * dValue is now approximately the result.
-             * The hard part is adjusting it, by comparison
-             * with FDBigInt arithmetic.
-             * Formulate the EXACT big-number result as
-             * bigD0 * 10^exp
-             */
-            FDBigInt bigD0 = new FDBigInt( lValue, digits, kDigits, nDigits );
-            exp   = decExponent - nDigits;
+    private static class HexFloatPattern {
+        /**
+         * Grammar is compatible with hexadecimal floating-point constants
+         * described in section 6.4.4.2 of the C99 specification.
+         */
+        private static final Pattern VALUE = Pattern.compile(
+                   //1           234                   56                7                   8      9
+                    "([-+])?0[xX](((\\p{XDigit}+)\\.?)|((\\p{XDigit}*)\\.(\\p{XDigit}+)))[pP]([-+])?(\\p{Digit}+)[fFdD]?"
+                    );
+    }
 
-            correctionLoop:
-            while(true){
-                /* AS A SIDE EFFECT, THIS METHOD WILL SET THE INSTANCE VARIABLES
-                 * bigIntExp and bigIntNBits
-                 */
-                FDBigInt bigB = doubleToBigInt( dValue );
-
-                /*
-                 * Scale bigD, bigB appropriately for
-                 * big-integer operations.
-                 * Naively, we multiply by powers of ten
-                 * and powers of two. What we actually do
-                 * is keep track of the powers of 5 and
-                 * powers of 2 we would use, then factor out
-                 * common divisors before doing the work.
-                 */
-                int B2, B5; // powers of 2, 5 in bigB
-                int     D2, D5; // powers of 2, 5 in bigD
-                int Ulp2;   // powers of 2 in halfUlp.
-                if ( exp >= 0 ){
-                    B2 = B5 = 0;
-                    D2 = D5 = exp;
-                } else {
-                    B2 = B5 = -exp;
-                    D2 = D5 = 0;
-                }
-                if ( bigIntExp >= 0 ){
-                    B2 += bigIntExp;
-                } else {
-                    D2 -= bigIntExp;
-                }
-                Ulp2 = B2;
-                // shift bigB and bigD left by a number s. t.
-                // halfUlp is still an integer.
-                int hulpbias;
-                if ( bigIntExp+bigIntNBits <= -expBias+1 ){
-                    // This is going to be a denormalized number
-                    // (if not actually zero).
-                    // half an ULP is at 2^-(expBias+expShift+1)
-                    hulpbias = bigIntExp+ expBias + expShift;
-                } else {
-                    hulpbias = expShift + 2 - bigIntNBits;
-                }
-                B2 += hulpbias;
-                D2 += hulpbias;
-                // if there are common factors of 2, we might just as well
-                // factor them out, as they add nothing useful.
-                int common2 = Math.min( B2, Math.min( D2, Ulp2 ) );
-                B2 -= common2;
-                D2 -= common2;
-                Ulp2 -= common2;
-                // do multiplications by powers of 5 and 2
-                bigB = multPow52( bigB, B5, B2 );
-                FDBigInt bigD = multPow52( new FDBigInt( bigD0 ), D5, D2 );
+    /**
+     * Converts string s to a suitable floating decimal; uses the
+     * double constructor and sets the roundDir variable appropriately
+     * in case the value is later converted to a float.
+     *
+     * @param s The String to parse.
+     */
+   static ASCIIToBinaryConverter parseHexString(String s) {
+            // Verify string is a member of the hexadecimal floating-point
+            // string language.
+            Matcher m = HexFloatPattern.VALUE.matcher(s);
+            boolean validInput = m.matches();
+            if (!validInput) {
+                // Input does not match pattern
+                throw new NumberFormatException("For input string: \"" + s + "\"");
+            } else { // validInput
                 //
-                // to recap:
-                // bigB is the scaled-big-int version of our floating-point
-                // candidate.
-                // bigD is the scaled-big-int version of the exact value
-                // as we understand it.
-                // halfUlp is 1/2 an ulp of bigB, except for special cases
-                // of exact powers of 2
+                // We must isolate the sign, significand, and exponent
+                // fields.  The sign value is straightforward.  Since
+                // floating-point numbers are stored with a normalized
+                // representation, the significand and exponent are
+                // interrelated.
                 //
-                // the plan is to compare bigB with bigD, and if the difference
-                // is less than halfUlp, then we're satisfied. Otherwise,
-                // use the ratio of difference to halfUlp to calculate a fudge
-                // factor to add to the floating value, then go 'round again.
+                // After extracting the sign, we normalized the
+                // significand as a hexadecimal value, calculating an
+                // exponent adjust for any shifts made during
+                // normalization.  If the significand is zero, the
+                // exponent doesn't need to be examined since the output
+                // will be zero.
                 //
-                FDBigInt diff;
-                int cmpResult;
-                boolean overvalue;
-                if ( (cmpResult = bigB.cmp( bigD ) ) > 0 ){
-                    overvalue = true; // our candidate is too big.
-                    diff = bigB.sub( bigD );
-                    if ( (bigIntNBits == 1) && (bigIntExp > -expBias+1) ){
-                        // candidate is a normalized exact power of 2 and
-                        // is too big. We will be subtracting.
-                        // For our purposes, ulp is the ulp of the
-                        // next smaller range.
-                        Ulp2 -= 1;
-                        if ( Ulp2 < 0 ){
-                            // rats. Cannot de-scale ulp this far.
-                            // must scale diff in other direction.
-                            Ulp2 = 0;
-                            diff.lshiftMe( 1 );
-                        }
+                // Next the exponent in the input string is extracted.
+                // Afterwards, the significand is normalized as a *binary*
+                // value and the input value's normalized exponent can be
+                // computed.  The significand bits are copied into a
+                // double significand; if the string has more logical bits
+                // than can fit in a double, the extra bits affect the
+                // round and sticky bits which are used to round the final
+                // value.
+                //
+                //  Extract significand sign
+                String group1 = m.group(1);
+                boolean isNegative = ((group1 != null) && group1.equals("-"));
+
+                //  Extract Significand magnitude
+                //
+                // Based on the form of the significand, calculate how the
+                // binary exponent needs to be adjusted to create a
+                // normalized//hexadecimal* floating-point number; that
+                // is, a number where there is one nonzero hex digit to
+                // the left of the (hexa)decimal point.  Since we are
+                // adjusting a binary, not hexadecimal exponent, the
+                // exponent is adjusted by a multiple of 4.
+                //
+                // There are a number of significand scenarios to consider;
+                // letters are used in indicate nonzero digits:
+                //
+                // 1. 000xxxx       =>      x.xxx   normalized
+                //    increase exponent by (number of x's - 1)*4
+                //
+                // 2. 000xxx.yyyy =>        x.xxyyyy        normalized
+                //    increase exponent by (number of x's - 1)*4
+                //
+                // 3. .000yyy  =>   y.yy    normalized
+                //    decrease exponent by (number of zeros + 1)*4
+                //
+                // 4. 000.00000yyy => y.yy normalized
+                //    decrease exponent by (number of zeros to right of point + 1)*4
+                //
+                // If the significand is exactly zero, return a properly
+                // signed zero.
+                //
+
+                String significandString = null;
+                int signifLength = 0;
+                int exponentAdjust = 0;
+                {
+                    int leftDigits = 0; // number of meaningful digits to
+                    // left of "decimal" point
+                    // (leading zeros stripped)
+                    int rightDigits = 0; // number of digits to right of
+                    // "decimal" point; leading zeros
+                    // must always be accounted for
+                    //
+                    // The significand is made up of either
+                    //
+                    // 1. group 4 entirely (integer portion only)
+                    //
+                    // OR
+                    //
+                    // 2. the fractional portion from group 7 plus any
+                    // (optional) integer portions from group 6.
+                    //
+                    String group4;
+                    if ((group4 = m.group(4)) != null) {  // Integer-only significand
+                        // Leading zeros never matter on the integer portion
+                        significandString = stripLeadingZeros(group4);
+                        leftDigits = significandString.length();
+                    } else {
+                        // Group 6 is the optional integer; leading zeros
+                        // never matter on the integer portion
+                        String group6 = stripLeadingZeros(m.group(6));
+                        leftDigits = group6.length();
+
+                        // fraction
+                        String group7 = m.group(7);
+                        rightDigits = group7.length();
+
+                        // Turn "integer.fraction" into "integer"+"fraction"
+                        significandString =
+                                ((group6 == null) ? "" : group6) + // is the null
+                                        // check necessary?
+                                        group7;
                     }
-                } else if ( cmpResult < 0 ){
-                    overvalue = false; // our candidate is too small.
-                    diff = bigD.sub( bigB );
-                } else {
-                    // the candidate is exactly right!
-                    // this happens with surprising frequency
-                    break correctionLoop;
-                }
-                FDBigInt halfUlp = constructPow52( B5, Ulp2 );
-                if ( (cmpResult = diff.cmp( halfUlp ) ) < 0 ){
-                    // difference is small.
-                    // this is close enough
-                    if (mustSetRoundDir) {
-                        roundDir = overvalue ? -1 : 1;
+
+                    significandString = stripLeadingZeros(significandString);
+                    signifLength = significandString.length();
+
+                    //
+                    // Adjust exponent as described above
+                    //
+                    if (leftDigits >= 1) {  // Cases 1 and 2
+                        exponentAdjust = 4 * (leftDigits - 1);
+                    } else {                // Cases 3 and 4
+                        exponentAdjust = -4 * (rightDigits - signifLength + 1);
                     }
-                    break correctionLoop;
-                } else if ( cmpResult == 0 ){
-                    // difference is exactly half an ULP
-                    // round to some other value maybe, then finish
-                    dValue += 0.5*ulp( dValue, overvalue );
-                    // should check for bigIntNBits == 1 here??
-                    if (mustSetRoundDir) {
-                        roundDir = overvalue ? -1 : 1;
+
+                    // If the significand is zero, the exponent doesn't
+                    // matter; return a properly signed zero.
+
+                    if (signifLength == 0) { // Only zeros in input
+                        return isNegative ? A2BC_NEGATIVE_ZERO : A2BC_POSITIVE_ZERO;
                     }
-                    break correctionLoop;
-                } else {
-                    // difference is non-trivial.
-                    // could scale addend by ratio of difference to
-                    // halfUlp here, if we bothered to compute that difference.
-                    // Most of the time ( I hope ) it is about 1 anyway.
-                    dValue += ulp( dValue, overvalue );
-                    if ( dValue == 0.0 || dValue == Double.POSITIVE_INFINITY )
-                        break correctionLoop; // oops. Fell off end of range.
-                    continue; // try again.
                 }
 
-            }
-            return (isNegative)? -dValue : dValue;
-        }
-    }
+                //  Extract Exponent
+                //
+                // Use an int to read in the exponent value; this should
+                // provide more than sufficient range for non-contrived
+                // inputs.  If reading the exponent in as an int does
+                // overflow, examine the sign of the exponent and
+                // significand to determine what to do.
+                //
+                String group8 = m.group(8);
+                boolean positiveExponent = (group8 == null) || group8.equals("+");
+                long unsignedRawExponent;
+                try {
+                    unsignedRawExponent = Integer.parseInt(m.group(9));
+                }
+                catch (NumberFormatException e) {
+                    // At this point, we know the exponent is
+                    // syntactically well-formed as a sequence of
+                    // digits.  Therefore, if an NumberFormatException
+                    // is thrown, it must be due to overflowing int's
+                    // range.  Also, at this point, we have already
+                    // checked for a zero significand.  Thus the signs
+                    // of the exponent and significand determine the
+                    // final result:
+                    //
+                    //                      significand
+                    //                      +               -
+                    // exponent     +       +infinity       -infinity
+                    //              -       +0.0            -0.0
+                    return isNegative ?
+                              (positiveExponent ? A2BC_NEGATIVE_INFINITY : A2BC_NEGATIVE_ZERO)
+                            : (positiveExponent ? A2BC_POSITIVE_INFINITY : A2BC_POSITIVE_ZERO);
 
-    /*
-     * Take a FloatingDecimal, which we presumably just scanned in,
-     * and find out what its value is, as a float.
-     * This is distinct from doubleValue() to avoid the extremely
-     * unlikely case of a double rounding error, wherein the conversion
-     * to double has one rounding error, and the conversion of that double
-     * to a float has another rounding error, IN THE WRONG DIRECTION,
-     * ( because of the preference to a zero low-order bit ).
-     */
+                }
 
-    public strictfp float floatValue(){
-        int     kDigits = Math.min( nDigits, singleMaxDecimalDigits+1 );
-        int     iValue;
-        float   fValue;
-
-        // First, check for NaN and Infinity values
-        if(digits == infinity || digits == notANumber) {
-            if(digits == notANumber)
-                return Float.NaN;
-            else
-                return (isNegative?Float.NEGATIVE_INFINITY:Float.POSITIVE_INFINITY);
-        }
-        else {
-            /*
-             * convert the lead kDigits to an integer.
-             */
-            iValue = (int)digits[0]-(int)'0';
-            for ( int i=1; i < kDigits; i++ ){
-                iValue = iValue*10 + (int)digits[i]-(int)'0';
-            }
-            fValue = (float)iValue;
-            int exp = decExponent-kDigits;
-            /*
-             * iValue now contains an integer with the value of
-             * the first kDigits digits of the number.
-             * fValue contains the (float) of the same.
-             */
-
-            if ( nDigits <= singleMaxDecimalDigits ){
-                /*
-                 * possibly an easy case.
-                 * We know that the digits can be represented
-                 * exactly. And if the exponent isn't too outrageous,
-                 * the whole thing can be done with one operation,
-                 * thus one rounding error.
-                 * Note that all our constructors trim all leading and
-                 * trailing zeros, so simple values (including zero)
-                 * will always end up here.
-                 */
-                if (exp == 0 || fValue == 0.0f)
-                    return (isNegative)? -fValue : fValue; // small floating integer
-                else if ( exp >= 0 ){
-                    if ( exp <= singleMaxSmallTen ){
-                        /*
-                         * Can get the answer with one operation,
-                         * thus one roundoff.
-                         */
-                        fValue *= singleSmall10pow[exp];
-                        return (isNegative)? -fValue : fValue;
-                    }
-                    int slop = singleMaxDecimalDigits - kDigits;
-                    if ( exp <= singleMaxSmallTen+slop ){
-                        /*
-                         * We can multiply dValue by 10^(slop)
-                         * and it is still "small" and exact.
-                         * Then we can multiply by 10^(exp-slop)
-                         * with one rounding.
-                         */
-                        fValue *= singleSmall10pow[slop];
-                        fValue *= singleSmall10pow[exp-slop];
-                        return (isNegative)? -fValue : fValue;
-                    }
-                    /*
-                     * Else we have a hard case with a positive exp.
-                     */
-                } else {
-                    if ( exp >= -singleMaxSmallTen ){
-                        /*
-                         * Can get the answer in one division.
-                         */
-                        fValue /= singleSmall10pow[-exp];
-                        return (isNegative)? -fValue : fValue;
-                    }
-                    /*
-                     * Else we have a hard case with a negative exp.
-                     */
-                }
-            } else if ( (decExponent >= nDigits) && (nDigits+decExponent <= maxDecimalDigits) ){
-                /*
-                 * In double-precision, this is an exact floating integer.
-                 * So we can compute to double, then shorten to float
-                 * with one round, and get the right answer.
-                 *
-                 * First, finish accumulating digits.
-                 * Then convert that integer to a double, multiply
-                 * by the appropriate power of ten, and convert to float.
-                 */
-                long lValue = (long)iValue;
-                for ( int i=kDigits; i < nDigits; i++ ){
-                    lValue = lValue*10L + (long)((int)digits[i]-(int)'0');
-                }
-                double dValue = (double)lValue;
-                exp = decExponent-nDigits;
-                dValue *= small10pow[exp];
-                fValue = (float)dValue;
-                return (isNegative)? -fValue : fValue;
-
-            }
-            /*
-             * Harder cases:
-             * The sum of digits plus exponent is greater than
-             * what we think we can do with one error.
-             *
-             * Start by weeding out obviously out-of-range
-             * results, then convert to double and go to
-             * common hard-case code.
-             */
-            if ( decExponent > singleMaxDecimalExponent+1 ){
-                /*
-                 * Lets face it. This is going to be
-                 * Infinity. Cut to the chase.
-                 */
-                return (isNegative)? Float.NEGATIVE_INFINITY : Float.POSITIVE_INFINITY;
-            } else if ( decExponent < singleMinDecimalExponent-1 ){
-                /*
-                 * Lets face it. This is going to be
-                 * zero. Cut to the chase.
-                 */
-                return (isNegative)? -0.0f : 0.0f;
-            }
-
-            /*
-             * Here, we do 'way too much work, but throwing away
-             * our partial results, and going and doing the whole
-             * thing as double, then throwing away half the bits that computes
-             * when we convert back to float.
-             *
-             * The alternative is to reproduce the whole multiple-precision
-             * algorithm for float precision, or to try to parameterize it
-             * for common usage. The former will take about 400 lines of code,
-             * and the latter I tried without success. Thus the semi-hack
-             * answer here.
-             */
-            mustSetRoundDir = !fromHex;
-            double dValue = doubleValue();
-            return stickyRound( dValue );
-        }
-    }
-
-
-    /*
-     * All the positive powers of 10 that can be
-     * represented exactly in double/float.
-     */
-    private static final double small10pow[] = {
-        1.0e0,
-        1.0e1, 1.0e2, 1.0e3, 1.0e4, 1.0e5,
-        1.0e6, 1.0e7, 1.0e8, 1.0e9, 1.0e10,
-        1.0e11, 1.0e12, 1.0e13, 1.0e14, 1.0e15,
-        1.0e16, 1.0e17, 1.0e18, 1.0e19, 1.0e20,
-        1.0e21, 1.0e22
-    };
-
-    private static final float singleSmall10pow[] = {
-        1.0e0f,
-        1.0e1f, 1.0e2f, 1.0e3f, 1.0e4f, 1.0e5f,
-        1.0e6f, 1.0e7f, 1.0e8f, 1.0e9f, 1.0e10f
-    };
-
-    private static final double big10pow[] = {
-        1e16, 1e32, 1e64, 1e128, 1e256 };
-    private static final double tiny10pow[] = {
-        1e-16, 1e-32, 1e-64, 1e-128, 1e-256 };
-
-    private static final int maxSmallTen = small10pow.length-1;
-    private static final int singleMaxSmallTen = singleSmall10pow.length-1;
-
-    private static final int small5pow[] = {
-        1,
-        5,
-        5*5,
-        5*5*5,
-        5*5*5*5,
-        5*5*5*5*5,
-        5*5*5*5*5*5,
-        5*5*5*5*5*5*5,
-        5*5*5*5*5*5*5*5,
-        5*5*5*5*5*5*5*5*5,
-        5*5*5*5*5*5*5*5*5*5,
-        5*5*5*5*5*5*5*5*5*5*5,
-        5*5*5*5*5*5*5*5*5*5*5*5,
-        5*5*5*5*5*5*5*5*5*5*5*5*5
-    };
-
-
-    private static final long long5pow[] = {
-        1L,
-        5L,
-        5L*5,
-        5L*5*5,
-        5L*5*5*5,
-        5L*5*5*5*5,
-        5L*5*5*5*5*5,
-        5L*5*5*5*5*5*5,
-        5L*5*5*5*5*5*5*5,
-        5L*5*5*5*5*5*5*5*5,
-        5L*5*5*5*5*5*5*5*5*5,
-        5L*5*5*5*5*5*5*5*5*5*5,
-        5L*5*5*5*5*5*5*5*5*5*5*5,
-        5L*5*5*5*5*5*5*5*5*5*5*5*5,
-        5L*5*5*5*5*5*5*5*5*5*5*5*5*5,
-        5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
-        5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
-        5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
-        5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
-        5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
-        5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
-        5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
-        5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
-        5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
-        5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
-        5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
-        5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
-    };
-
-    // approximately ceil( log2( long5pow[i] ) )
-    private static final int n5bits[] = {
-        0,
-        3,
-        5,
-        7,
-        10,
-        12,
-        14,
-        17,
-        19,
-        21,
-        24,
-        26,
-        28,
-        31,
-        33,
-        35,
-        38,
-        40,
-        42,
-        45,
-        47,
-        49,
-        52,
-        54,
-        56,
-        59,
-        61,
-    };
-
-    private static final char infinity[] = { 'I', 'n', 'f', 'i', 'n', 'i', 't', 'y' };
-    private static final char notANumber[] = { 'N', 'a', 'N' };
-    private static final char zero[] = { '0', '0', '0', '0', '0', '0', '0', '0' };
-
-
-    /*
-     * Grammar is compatible with hexadecimal floating-point constants
-     * described in section 6.4.4.2 of the C99 specification.
-     */
-    private static Pattern hexFloatPattern = null;
-    private static synchronized Pattern getHexFloatPattern() {
-        if (hexFloatPattern == null) {
-           hexFloatPattern = Pattern.compile(
-                   //1           234                   56                7                   8      9
-                    "([-+])?0[xX](((\\p{XDigit}+)\\.?)|((\\p{XDigit}*)\\.(\\p{XDigit}+)))[pP]([-+])?(\\p{Digit}+)[fFdD]?"
-                    );
-        }
-        return hexFloatPattern;
-    }
+                long rawExponent =
+                        (positiveExponent ? 1L : -1L) * // exponent sign
+                                unsignedRawExponent;            // exponent magnitude
+
+                // Calculate partially adjusted exponent
+                long exponent = rawExponent + exponentAdjust;
+
+                // Starting copying non-zero bits into proper position in
+                // a long; copy explicit bit too; this will be masked
+                // later for normal values.
+
+                boolean round = false;
+                boolean sticky = false;
+                int nextShift = 0;
+                long significand = 0L;
+                // First iteration is different, since we only copy
+                // from the leading significand bit; one more exponent
+                // adjust will be needed...
+
+                // IMPORTANT: make leadingDigit a long to avoid
+                // surprising shift semantics!
+                long leadingDigit = getHexDigit(significandString, 0);
 
-    /*
-     * Convert string s to a suitable floating decimal; uses the
-     * double constructor and set the roundDir variable appropriately
-     * in case the value is later converted to a float.
-     */
-   static FloatingDecimal parseHexString(String s) {
-        // Verify string is a member of the hexadecimal floating-point
-        // string language.
-        Matcher m = getHexFloatPattern().matcher(s);
-        boolean validInput = m.matches();
-
-        if (!validInput) {
-            // Input does not match pattern
-            throw new NumberFormatException("For input string: \"" + s + "\"");
-        } else { // validInput
-            /*
-             * We must isolate the sign, significand, and exponent
-             * fields.  The sign value is straightforward.  Since
-             * floating-point numbers are stored with a normalized
-             * representation, the significand and exponent are
-             * interrelated.
-             *
-             * After extracting the sign, we normalized the
-             * significand as a hexadecimal value, calculating an
-             * exponent adjust for any shifts made during
-             * normalization.  If the significand is zero, the
-             * exponent doesn't need to be examined since the output
-             * will be zero.
-             *
-             * Next the exponent in the input string is extracted.
-             * Afterwards, the significand is normalized as a *binary*
-             * value and the input value's normalized exponent can be
-             * computed.  The significand bits are copied into a
-             * double significand; if the string has more logical bits
-             * than can fit in a double, the extra bits affect the
-             * round and sticky bits which are used to round the final
-             * value.
-             */
-
-            //  Extract significand sign
-            String group1 = m.group(1);
-            double sign = (( group1 == null ) || group1.equals("+"))? 1.0 : -1.0;
-
-
-            //  Extract Significand magnitude
-            /*
-             * Based on the form of the significand, calculate how the
-             * binary exponent needs to be adjusted to create a
-             * normalized *hexadecimal* floating-point number; that
-             * is, a number where there is one nonzero hex digit to
-             * the left of the (hexa)decimal point.  Since we are
-             * adjusting a binary, not hexadecimal exponent, the
-             * exponent is adjusted by a multiple of 4.
-             *
-             * There are a number of significand scenarios to consider;
-             * letters are used in indicate nonzero digits:
-             *
-             * 1. 000xxxx       =>      x.xxx   normalized
-             *    increase exponent by (number of x's - 1)*4
-             *
-             * 2. 000xxx.yyyy =>        x.xxyyyy        normalized
-             *    increase exponent by (number of x's - 1)*4
-             *
-             * 3. .000yyy  =>   y.yy    normalized
-             *    decrease exponent by (number of zeros + 1)*4
-             *
-             * 4. 000.00000yyy => y.yy normalized
-             *    decrease exponent by (number of zeros to right of point + 1)*4
-             *
-             * If the significand is exactly zero, return a properly
-             * signed zero.
-             */
-
-            String significandString =null;
-            int signifLength = 0;
-            int exponentAdjust = 0;
-            {
-                int leftDigits  = 0; // number of meaningful digits to
-                                     // left of "decimal" point
-                                     // (leading zeros stripped)
-                int rightDigits = 0; // number of digits to right of
-                                     // "decimal" point; leading zeros
-                                     // must always be accounted for
-                /*
-                 * The significand is made up of either
-                 *
-                 * 1. group 4 entirely (integer portion only)
-                 *
-                 * OR
-                 *
-                 * 2. the fractional portion from group 7 plus any
-                 * (optional) integer portions from group 6.
-                 */
-                String group4;
-                if( (group4 = m.group(4)) != null) {  // Integer-only significand
-                    // Leading zeros never matter on the integer portion
-                    significandString = stripLeadingZeros(group4);
-                    leftDigits = significandString.length();
-                }
-                else {
-                    // Group 6 is the optional integer; leading zeros
-                    // never matter on the integer portion
-                    String group6 = stripLeadingZeros(m.group(6));
-                    leftDigits = group6.length();
-
-                    // fraction
-                    String group7 = m.group(7);
-                    rightDigits = group7.length();
-
-                    // Turn "integer.fraction" into "integer"+"fraction"
-                    significandString =
-                        ((group6 == null)?"":group6) + // is the null
-                        // check necessary?
-                        group7;
-                }
-
-                significandString = stripLeadingZeros(significandString);
-                signifLength  = significandString.length();
-
-                /*
-                 * Adjust exponent as described above
-                 */
-                if (leftDigits >= 1) {  // Cases 1 and 2
-                    exponentAdjust = 4*(leftDigits - 1);
-                } else {                // Cases 3 and 4
-                    exponentAdjust = -4*( rightDigits - signifLength + 1);
-                }
-
-                // If the significand is zero, the exponent doesn't
-                // matter; return a properly signed zero.
-
-                if (signifLength == 0) { // Only zeros in input
-                    return new FloatingDecimal(sign * 0.0);
-                }
-            }
-
-            //  Extract Exponent
-            /*
-             * Use an int to read in the exponent value; this should
-             * provide more than sufficient range for non-contrived
-             * inputs.  If reading the exponent in as an int does
-             * overflow, examine the sign of the exponent and
-             * significand to determine what to do.
-             */
-            String group8 = m.group(8);
-            boolean positiveExponent = ( group8 == null ) || group8.equals("+");
-            long unsignedRawExponent;
-            try {
-                unsignedRawExponent = Integer.parseInt(m.group(9));
-            }
-            catch (NumberFormatException e) {
-                // At this point, we know the exponent is
-                // syntactically well-formed as a sequence of
-                // digits.  Therefore, if an NumberFormatException
-                // is thrown, it must be due to overflowing int's
-                // range.  Also, at this point, we have already
-                // checked for a zero significand.  Thus the signs
-                // of the exponent and significand determine the
-                // final result:
-                //
-                //                      significand
-                //                      +               -
-                // exponent     +       +infinity       -infinity
-                //              -       +0.0            -0.0
-                return new FloatingDecimal(sign * (positiveExponent ?
-                                                   Double.POSITIVE_INFINITY : 0.0));
-            }
-
-            long rawExponent =
-                (positiveExponent ? 1L : -1L) * // exponent sign
-                unsignedRawExponent;            // exponent magnitude
-
-            // Calculate partially adjusted exponent
-            long exponent = rawExponent + exponentAdjust ;
-
-            // Starting copying non-zero bits into proper position in
-            // a long; copy explicit bit too; this will be masked
-            // later for normal values.
-
-            boolean round = false;
-            boolean sticky = false;
-            int bitsCopied=0;
-            int nextShift=0;
-            long significand=0L;
-            // First iteration is different, since we only copy
-            // from the leading significand bit; one more exponent
-            // adjust will be needed...
-
-            // IMPORTANT: make leadingDigit a long to avoid
-            // surprising shift semantics!
-            long leadingDigit = getHexDigit(significandString, 0);
-
-            /*
-             * Left shift the leading digit (53 - (bit position of
-             * leading 1 in digit)); this sets the top bit of the
-             * significand to 1.  The nextShift value is adjusted
-             * to take into account the number of bit positions of
-             * the leadingDigit actually used.  Finally, the
-             * exponent is adjusted to normalize the significand
-             * as a binary value, not just a hex value.
-             */
-            if (leadingDigit == 1) {
-                significand |= leadingDigit << 52;
-                nextShift = 52 - 4;
-                /* exponent += 0 */     }
-            else if (leadingDigit <= 3) { // [2, 3]
-                significand |= leadingDigit << 51;
-                nextShift = 52 - 5;
-                exponent += 1;
-            }
-            else if (leadingDigit <= 7) { // [4, 7]
-                significand |= leadingDigit << 50;
-                nextShift = 52 - 6;
-                exponent += 2;
-            }
-            else if (leadingDigit <= 15) { // [8, f]
-                significand |= leadingDigit << 49;
-                nextShift = 52 - 7;
-                exponent += 3;
-            } else {
-                throw new AssertionError("Result from digit conversion too large!");
-            }
-            // The preceding if-else could be replaced by a single
-            // code block based on the high-order bit set in
-            // leadingDigit.  Given leadingOnePosition,
-
-            // significand |= leadingDigit << (SIGNIFICAND_WIDTH - leadingOnePosition);
-            // nextShift = 52 - (3 + leadingOnePosition);
-            // exponent += (leadingOnePosition-1);
-
-
-            /*
-             * Now the exponent variable is equal to the normalized
-             * binary exponent.  Code below will make representation
-             * adjustments if the exponent is incremented after
-             * rounding (includes overflows to infinity) or if the
-             * result is subnormal.
-             */
-
-            // Copy digit into significand until the significand can't
-            // hold another full hex digit or there are no more input
-            // hex digits.
-            int i = 0;
-            for(i = 1;
-                i < signifLength && nextShift >= 0;
-                i++) {
-                long currentDigit = getHexDigit(significandString, i);
-                significand |= (currentDigit << nextShift);
-                nextShift-=4;
-            }
-
-            // After the above loop, the bulk of the string is copied.
-            // Now, we must copy any partial hex digits into the
-            // significand AND compute the round bit and start computing
-            // sticky bit.
-
-            if ( i < signifLength ) { // at least one hex input digit exists
-                long currentDigit = getHexDigit(significandString, i);
-
-                // from nextShift, figure out how many bits need
-                // to be copied, if any
-                switch(nextShift) { // must be negative
-                case -1:
-                    // three bits need to be copied in; can
-                    // set round bit
-                    significand |= ((currentDigit & 0xEL) >> 1);
-                    round = (currentDigit & 0x1L)  != 0L;
-                    break;
-
-                case -2:
-                    // two bits need to be copied in; can
-                    // set round and start sticky
-                    significand |= ((currentDigit & 0xCL) >> 2);
-                    round = (currentDigit &0x2L)  != 0L;
-                    sticky = (currentDigit & 0x1L) != 0;
-                    break;
-
-                case -3:
-                    // one bit needs to be copied in
-                    significand |= ((currentDigit & 0x8L)>>3);
-                    // Now set round and start sticky, if possible
-                    round = (currentDigit &0x4L)  != 0L;
-                    sticky = (currentDigit & 0x3L) != 0;
-                    break;
-
-                case -4:
-                    // all bits copied into significand; set
-                    // round and start sticky
-                    round = ((currentDigit & 0x8L) != 0);  // is top bit set?
-                    // nonzeros in three low order bits?
-                    sticky = (currentDigit & 0x7L) != 0;
-                    break;
-
-                default:
-                    throw new AssertionError("Unexpected shift distance remainder.");
-                    // break;
-                }
-
-                // Round is set; sticky might be set.
-
-                // For the sticky bit, it suffices to check the
-                // current digit and test for any nonzero digits in
-                // the remaining unprocessed input.
-                i++;
-                while(i < signifLength && !sticky) {
-                    currentDigit =  getHexDigit(significandString,i);
-                    sticky = sticky || (currentDigit != 0);
-                    i++;
+                //
+                // Left shift the leading digit (53 - (bit position of
+                // leading 1 in digit)); this sets the top bit of the
+                // significand to 1.  The nextShift value is adjusted
+                // to take into account the number of bit positions of
+                // the leadingDigit actually used.  Finally, the
+                // exponent is adjusted to normalize the significand
+                // as a binary value, not just a hex value.
+                //
+                if (leadingDigit == 1) {
+                    significand |= leadingDigit << 52;
+                    nextShift = 52 - 4;
+                    // exponent += 0
+                } else if (leadingDigit <= 3) { // [2, 3]
+                    significand |= leadingDigit << 51;
+                    nextShift = 52 - 5;
+                    exponent += 1;
+                } else if (leadingDigit <= 7) { // [4, 7]
+                    significand |= leadingDigit << 50;
+                    nextShift = 52 - 6;
+                    exponent += 2;
+                } else if (leadingDigit <= 15) { // [8, f]
+                    significand |= leadingDigit << 49;
+                    nextShift = 52 - 7;
+                    exponent += 3;
+                } else {
+                    throw new AssertionError("Result from digit conversion too large!");
                 }
+                // The preceding if-else could be replaced by a single
+                // code block based on the high-order bit set in
+                // leadingDigit.  Given leadingOnePosition,
+
+                // significand |= leadingDigit << (SIGNIFICAND_WIDTH - leadingOnePosition);
+                // nextShift = 52 - (3 + leadingOnePosition);
+                // exponent += (leadingOnePosition-1);
 
-            }
-            // else all of string was seen, round and sticky are
-            // correct as false.
+                //
+                // Now the exponent variable is equal to the normalized
+                // binary exponent.  Code below will make representation
+                // adjustments if the exponent is incremented after
+                // rounding (includes overflows to infinity) or if the
+                // result is subnormal.
+                //
 
+                // Copy digit into significand until the significand can't
+                // hold another full hex digit or there are no more input
+                // hex digits.
+                int i = 0;
+                for (i = 1;
+                     i < signifLength && nextShift >= 0;
+                     i++) {
+                    long currentDigit = getHexDigit(significandString, i);
+                    significand |= (currentDigit << nextShift);
+                    nextShift -= 4;
+                }
+
+                // After the above loop, the bulk of the string is copied.
+                // Now, we must copy any partial hex digits into the
+                // significand AND compute the round bit and start computing
+                // sticky bit.
+
+                if (i < signifLength) { // at least one hex input digit exists
+                    long currentDigit = getHexDigit(significandString, i);
+
+                    // from nextShift, figure out how many bits need
+                    // to be copied, if any
+                    switch (nextShift) { // must be negative
+                        case -1:
+                            // three bits need to be copied in; can
+                            // set round bit
+                            significand |= ((currentDigit & 0xEL) >> 1);
+                            round = (currentDigit & 0x1L) != 0L;
+                            break;
+
+                        case -2:
+                            // two bits need to be copied in; can
+                            // set round and start sticky
+                            significand |= ((currentDigit & 0xCL) >> 2);
+                            round = (currentDigit & 0x2L) != 0L;
+                            sticky = (currentDigit & 0x1L) != 0;
+                            break;
+
+                        case -3:
+                            // one bit needs to be copied in
+                            significand |= ((currentDigit & 0x8L) >> 3);
+                            // Now set round and start sticky, if possible
+                            round = (currentDigit & 0x4L) != 0L;
+                            sticky = (currentDigit & 0x3L) != 0;
+                            break;
+
+                        case -4:
+                            // all bits copied into significand; set
+                            // round and start sticky
+                            round = ((currentDigit & 0x8L) != 0);  // is top bit set?
+                            // nonzeros in three low order bits?
+                            sticky = (currentDigit & 0x7L) != 0;
+                            break;
+
+                        default:
+                            throw new AssertionError("Unexpected shift distance remainder.");
+                            // break;
+                    }
+
+                    // Round is set; sticky might be set.
+
+                    // For the sticky bit, it suffices to check the
+                    // current digit and test for any nonzero digits in
+                    // the remaining unprocessed input.
+                    i++;
+                    while (i < signifLength && !sticky) {
+                        currentDigit = getHexDigit(significandString, i);
+                        sticky = sticky || (currentDigit != 0);
+                        i++;
+                    }
+
+                }
+                // else all of string was seen, round and sticky are
+                // correct as false.
+
+                // Check for overflow and update exponent accordingly.
+                if (exponent > DoubleConsts.MAX_EXPONENT) {         // Infinite result
+                    // overflow to properly signed infinity
+                    return isNegative ? A2BC_NEGATIVE_INFINITY : A2BC_POSITIVE_INFINITY;
+                } else {  // Finite return value
+                    if (exponent <= DoubleConsts.MAX_EXPONENT && // (Usually) normal result
+                            exponent >= DoubleConsts.MIN_EXPONENT) {
+
+                        // The result returned in this block cannot be a
+                        // zero or subnormal; however after the
+                        // significand is adjusted from rounding, we could
+                        // still overflow in infinity.
+
+                        // AND exponent bits into significand; if the
+                        // significand is incremented and overflows from
+                        // rounding, this combination will update the
+                        // exponent correctly, even in the case of
+                        // Double.MAX_VALUE overflowing to infinity.
+
+                        significand = ((( exponent +
+                                (long) DoubleConsts.EXP_BIAS) <<
+                                (DoubleConsts.SIGNIFICAND_WIDTH - 1))
+                                & DoubleConsts.EXP_BIT_MASK) |
+                                (DoubleConsts.SIGNIF_BIT_MASK & significand);
+
+                    } else {  // Subnormal or zero
+                        // (exponent < DoubleConsts.MIN_EXPONENT)
+
+                        if (exponent < (DoubleConsts.MIN_SUB_EXPONENT - 1)) {
+                            // No way to round back to nonzero value
+                            // regardless of significand if the exponent is
+                            // less than -1075.
+                            return isNegative ? A2BC_NEGATIVE_ZERO : A2BC_POSITIVE_ZERO;
+                        } else { //  -1075 <= exponent <= MIN_EXPONENT -1 = -1023
+                            //
+                            // Find bit position to round to; recompute
+                            // round and sticky bits, and shift
+                            // significand right appropriately.
+                            //
+
+                            sticky = sticky || round;
+                            round = false;
+
+                            // Number of bits of significand to preserve is
+                            // exponent - abs_min_exp +1
+                            // check:
+                            // -1075 +1074 + 1 = 0
+                            // -1023 +1074 + 1 = 52
+
+                            int bitsDiscarded = 53 -
+                                    ((int) exponent - DoubleConsts.MIN_SUB_EXPONENT + 1);
+                            assert bitsDiscarded >= 1 && bitsDiscarded <= 53;
+
+                            // What to do here:
+                            // First, isolate the new round bit
+                            round = (significand & (1L << (bitsDiscarded - 1))) != 0L;
+                            if (bitsDiscarded > 1) {
+                                // create mask to update sticky bits; low
+                                // order bitsDiscarded bits should be 1
+                                long mask = ~((~0L) << (bitsDiscarded - 1));
+                                sticky = sticky || ((significand & mask) != 0L);
+                            }
 
-            // Check for overflow and update exponent accordingly.
+                            // Now, discard the bits
+                            significand = significand >> bitsDiscarded;
 
-            if (exponent > DoubleConsts.MAX_EXPONENT) {         // Infinite result
-                // overflow to properly signed infinity
-                return new FloatingDecimal(sign * Double.POSITIVE_INFINITY);
-            } else {  // Finite return value
-                if (exponent <= DoubleConsts.MAX_EXPONENT && // (Usually) normal result
-                    exponent >= DoubleConsts.MIN_EXPONENT) {
-
-                    // The result returned in this block cannot be a
-                    // zero or subnormal; however after the
-                    // significand is adjusted from rounding, we could
-                    // still overflow in infinity.
-
-                    // AND exponent bits into significand; if the
-                    // significand is incremented and overflows from
-                    // rounding, this combination will update the
-                    // exponent correctly, even in the case of
-                    // Double.MAX_VALUE overflowing to infinity.
-
-                    significand = (( (exponent +
-                                     (long)DoubleConsts.EXP_BIAS) <<
-                                     (DoubleConsts.SIGNIFICAND_WIDTH-1))
-                                   & DoubleConsts.EXP_BIT_MASK) |
-                        (DoubleConsts.SIGNIF_BIT_MASK & significand);
-
-                }  else  {  // Subnormal or zero
-                    // (exponent < DoubleConsts.MIN_EXPONENT)
-
-                    if (exponent < (DoubleConsts.MIN_SUB_EXPONENT -1 )) {
-                        // No way to round back to nonzero value
-                        // regardless of significand if the exponent is
-                        // less than -1075.
-                        return new FloatingDecimal(sign * 0.0);
-                    } else { //  -1075 <= exponent <= MIN_EXPONENT -1 = -1023
-                        /*
-                         * Find bit position to round to; recompute
-                         * round and sticky bits, and shift
-                         * significand right appropriately.
-                         */
-
-                        sticky = sticky || round;
-                        round = false;
-
-                        // Number of bits of significand to preserve is
-                        // exponent - abs_min_exp +1
-                        // check:
-                        // -1075 +1074 + 1 = 0
-                        // -1023 +1074 + 1 = 52
-
-                        int bitsDiscarded = 53 -
-                            ((int)exponent - DoubleConsts.MIN_SUB_EXPONENT + 1);
-                        assert bitsDiscarded >= 1 && bitsDiscarded <= 53;
-
-                        // What to do here:
-                        // First, isolate the new round bit
-                        round = (significand & (1L << (bitsDiscarded -1))) != 0L;
-                        if (bitsDiscarded > 1) {
-                            // create mask to update sticky bits; low
-                            // order bitsDiscarded bits should be 1
-                            long mask = ~((~0L) << (bitsDiscarded -1));
-                            sticky = sticky || ((significand & mask) != 0L ) ;
+                            significand = ((((long) (DoubleConsts.MIN_EXPONENT - 1) + // subnorm exp.
+                                    (long) DoubleConsts.EXP_BIAS) <<
+                                    (DoubleConsts.SIGNIFICAND_WIDTH - 1))
+                                    & DoubleConsts.EXP_BIT_MASK) |
+                                    (DoubleConsts.SIGNIF_BIT_MASK & significand);
                         }
+                    }
+
+                    // The significand variable now contains the currently
+                    // appropriate exponent bits too.
+
+                    //
+                    // Determine if significand should be incremented;
+                    // making this determination depends on the least
+                    // significant bit and the round and sticky bits.
+                    //
+                    // Round to nearest even rounding table, adapted from
+                    // table 4.7 in "Computer Arithmetic" by IsraelKoren.
+                    // The digit to the left of the "decimal" point is the
+                    // least significant bit, the digits to the right of
+                    // the point are the round and sticky bits
+                    //
+                    // Number       Round(x)
+                    // x0.00        x0.
+                    // x0.01        x0.
+                    // x0.10        x0.
+                    // x0.11        x1. = x0. +1
+                    // x1.00        x1.
+                    // x1.01        x1.
+                    // x1.10        x1. + 1
+                    // x1.11        x1. + 1
+                    //
+                    boolean leastZero = ((significand & 1L) == 0L);
+                    if ((leastZero && round && sticky) ||
+                            ((!leastZero) && round)) {
+                        significand++;
+                    }
 
-                        // Now, discard the bits
-                        significand = significand >> bitsDiscarded;
+                    double value = isNegative ?
+                            Double.longBitsToDouble(significand | DoubleConsts.SIGN_BIT_MASK) :
+                            Double.longBitsToDouble(significand );
 
-                        significand = (( ((long)(DoubleConsts.MIN_EXPONENT -1) + // subnorm exp.
-                                          (long)DoubleConsts.EXP_BIAS) <<
-                                         (DoubleConsts.SIGNIFICAND_WIDTH-1))
-                                       & DoubleConsts.EXP_BIT_MASK) |
-                            (DoubleConsts.SIGNIF_BIT_MASK & significand);
-                    }
-                }
-
-                // The significand variable now contains the currently
-                // appropriate exponent bits too.
-
-                /*
-                 * Determine if significand should be incremented;
-                 * making this determination depends on the least
-                 * significant bit and the round and sticky bits.
-                 *
-                 * Round to nearest even rounding table, adapted from
-                 * table 4.7 in "Computer Arithmetic" by IsraelKoren.
-                 * The digit to the left of the "decimal" point is the
-                 * least significant bit, the digits to the right of
-                 * the point are the round and sticky bits
-                 *
-                 * Number       Round(x)
-                 * x0.00        x0.
-                 * x0.01        x0.
-                 * x0.10        x0.
-                 * x0.11        x1. = x0. +1
-                 * x1.00        x1.
-                 * x1.01        x1.
-                 * x1.10        x1. + 1
-                 * x1.11        x1. + 1
-                 */
-                boolean incremented = false;
-                boolean leastZero  = ((significand & 1L) == 0L);
-                if( (  leastZero  && round && sticky ) ||
-                    ((!leastZero) && round )) {
-                    incremented = true;
-                    significand++;
-                }
-
-                FloatingDecimal fd = new FloatingDecimal(Math.copySign(
-                                                              Double.longBitsToDouble(significand),
-                                                              sign));
-
-                /*
-                 * Set roundingDir variable field of fd properly so
-                 * that the input string can be properly rounded to a
-                 * float value.  There are two cases to consider:
-                 *
-                 * 1. rounding to double discards sticky bit
-                 * information that would change the result of a float
-                 * rounding (near halfway case between two floats)
-                 *
-                 * 2. rounding to double rounds up when rounding up
-                 * would not occur when rounding to float.
-                 *
-                 * For former case only needs to be considered when
-                 * the bits rounded away when casting to float are all
-                 * zero; otherwise, float round bit is properly set
-                 * and sticky will already be true.
-                 *
-                 * The lower exponent bound for the code below is the
-                 * minimum (normalized) subnormal exponent - 1 since a
-                 * value with that exponent can round up to the
-                 * minimum subnormal value and the sticky bit
-                 * information must be preserved (i.e. case 1).
-                 */
-                if ((exponent >= FloatConsts.MIN_SUB_EXPONENT-1) &&
-                    (exponent <= FloatConsts.MAX_EXPONENT ) ){
-                    // Outside above exponent range, the float value
-                    // will be zero or infinity.
-
-                    /*
-                     * If the low-order 28 bits of a rounded double
-                     * significand are 0, the double could be a
-                     * half-way case for a rounding to float.  If the
-                     * double value is a half-way case, the double
-                     * significand may have to be modified to round
-                     * the the right float value (see the stickyRound
-                     * method).  If the rounding to double has lost
-                     * what would be float sticky bit information, the
-                     * double significand must be incremented.  If the
-                     * double value's significand was itself
-                     * incremented, the float value may end up too
-                     * large so the increment should be undone.
-                     */
-                    if ((significand & 0xfffffffL) ==  0x0L) {
-                        // For negative values, the sign of the
-                        // roundDir is the same as for positive values
-                        // since adding 1 increasing the significand's
-                        // magnitude and subtracting 1 decreases the
-                        // significand's magnitude.  If neither round
-                        // nor sticky is true, the double value is
-                        // exact and no adjustment is required for a
-                        // proper float rounding.
-                        if( round || sticky) {
-                            if (leastZero) { // prerounding lsb is 0
-                                // If round and sticky were both true,
-                                // and the least significant
-                                // significand bit were 0, the rounded
-                                // significand would not have its
-                                // low-order bits be zero.  Therefore,
-                                // we only need to adjust the
-                                // significand if round XOR sticky is
-                                // true.
-                                if (round ^ sticky) {
-                                    fd.roundDir =  1;
+                    int roundDir = 0;
+                    //
+                    // Set roundingDir variable field of fd properly so
+                    // that the input string can be properly rounded to a
+                    // float value.  There are two cases to consider:
+                    //
+                    // 1. rounding to double discards sticky bit
+                    // information that would change the result of a float
+                    // rounding (near halfway case between two floats)
+                    //
+                    // 2. rounding to double rounds up when rounding up
+                    // would not occur when rounding to float.
+                    //
+                    // For former case only needs to be considered when
+                    // the bits rounded away when casting to float are all
+                    // zero; otherwise, float round bit is properly set
+                    // and sticky will already be true.
+                    //
+                    // The lower exponent bound for the code below is the
+                    // minimum (normalized) subnormal exponent - 1 since a
+                    // value with that exponent can round up to the
+                    // minimum subnormal value and the sticky bit
+                    // information must be preserved (i.e. case 1).
+                    //
+                    if ((exponent >= FloatConsts.MIN_SUB_EXPONENT - 1) &&
+                            (exponent <= FloatConsts.MAX_EXPONENT)) {
+                        // Outside above exponent range, the float value
+                        // will be zero or infinity.
+
+                        //
+                        // If the low-order 28 bits of a rounded double
+                        // significand are 0, the double could be a
+                        // half-way case for a rounding to float.  If the
+                        // double value is a half-way case, the double
+                        // significand may have to be modified to round
+                        // the the right float value (see the stickyRound
+                        // method).  If the rounding to double has lost
+                        // what would be float sticky bit information, the
+                        // double significand must be incremented.  If the
+                        // double value's significand was itself
+                        // incremented, the float value may end up too
+                        // large so the increment should be undone.
+                        //
+                        if ((significand & 0xfffffffL) == 0x0L) {
+                            // For negative values, the sign of the
+                            // roundDir is the same as for positive values
+                            // since adding 1 increasing the significand's
+                            // magnitude and subtracting 1 decreases the
+                            // significand's magnitude.  If neither round
+                            // nor sticky is true, the double value is
+                            // exact and no adjustment is required for a
+                            // proper float rounding.
+                            if (round || sticky) {
+                                if (leastZero) { // prerounding lsb is 0
+                                    // If round and sticky were both true,
+                                    // and the least significant
+                                    // significand bit were 0, the rounded
+                                    // significand would not have its
+                                    // low-order bits be zero.  Therefore,
+                                    // we only need to adjust the
+                                    // significand if round XOR sticky is
+                                    // true.
+                                    if (round ^ sticky) {
+                                        roundDir = 1;
+                                    }
+                                } else { // prerounding lsb is 1
+                                    // If the prerounding lsb is 1 and the
+                                    // resulting significand has its
+                                    // low-order bits zero, the significand
+                                    // was incremented.  Here, we undo the
+                                    // increment, which will ensure the
+                                    // right guard and sticky bits for the
+                                    // float rounding.
+                                    if (round) {
+                                        roundDir = -1;
+                                    }
                                 }
                             }
-                            else { // prerounding lsb is 1
-                                // If the prerounding lsb is 1 and the
-                                // resulting significand has its
-                                // low-order bits zero, the significand
-                                // was incremented.  Here, we undo the
-                                // increment, which will ensure the
-                                // right guard and sticky bits for the
-                                // float rounding.
-                                if (round)
-                                    fd.roundDir =  -1;
-                            }
                         }
                     }
+                    return new PreparedASCIIToBinaryBuffer(value,roundDir);
                 }
-
-                fd.fromHex = true;
-                return fd;
             }
-        }
     }
 
     /**
-     * Return s with any leading zeros removed.
+     * Returns s with any leading zeros removed.
      */
     static String stripLeadingZeros(String s) {
-        return  s.replaceFirst("^0+", "");
+//        return  s.replaceFirst("^0+", "");
+        if(!s.isEmpty() && s.charAt(0)=='0') {
+            for(int i=1; iposition
+     * Extracts a hexadecimal digit from position position
      * of string s.
      */
     static int getHexDigit(String s, int position) {
@@ -2433,6 +2503,4 @@
         }
         return value;
     }
-
-
 }
--- old/src/share/classes/sun/misc/FormattedFloatingDecimal.java	2013-06-07 13:08:33.000000000 -0700
+++ new/src/share/classes/sun/misc/FormattedFloatingDecimal.java	2013-06-07 13:08:32.000000000 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,422 +25,118 @@
 
 package sun.misc;
 
-import sun.misc.DoubleConsts;
-import sun.misc.FloatConsts;
-import java.util.regex.*;
+import java.util.Arrays;
 
 public class FormattedFloatingDecimal{
-    boolean     isExceptional;
-    boolean     isNegative;
-    int         decExponent;  // value set at construction, then immutable
-    int         decExponentRounded;
-    char        digits[];
-    int         nDigits;
-    int         bigIntExp;
-    int         bigIntNBits;
-    boolean     mustSetRoundDir = false;
-    boolean     fromHex = false;
-    int         roundDir = 0; // set by doubleValue
-    int         precision;    // number of digits to the right of decimal
 
     public enum Form { SCIENTIFIC, COMPATIBLE, DECIMAL_FLOAT, GENERAL };
 
-    private Form form;
 
-    private     FormattedFloatingDecimal( boolean negSign, int decExponent, char []digits, int n, boolean e, int precision, Form form )
-    {
-        isNegative = negSign;
-        isExceptional = e;
-        this.decExponent = decExponent;
-        this.digits = digits;
-        this.nDigits = n;
-        this.precision = precision;
-        this.form = form;
+    public static FormattedFloatingDecimal valueOf(double d, int precision, Form form){
+        FloatingDecimal.BinaryToASCIIConverter fdConverter =
+                FloatingDecimal.getBinaryToASCIIConverter(d, form == Form.COMPATIBLE);
+        return new FormattedFloatingDecimal(precision,form, fdConverter);
     }
 
-    /*
-     * Constants of the implementation
-     * Most are IEEE-754 related.
-     * (There are more really boring constants at the end.)
-     */
-    static final long   signMask = 0x8000000000000000L;
-    static final long   expMask  = 0x7ff0000000000000L;
-    static final long   fractMask= ~(signMask|expMask);
-    static final int    expShift = 52;
-    static final int    expBias  = 1023;
-    static final long   fractHOB = ( 1L< 0L ) { // i.e. while ((v&highbit) == 0L )
-            v <<= 1;
-        }
-
-        int n = 0;
-        while (( v & lowbytes ) != 0L ){
-            v <<= 8;
-            n += 8;
-        }
-        while ( v != 0L ){
-            v <<= 1;
-            n += 1;
-        }
-        return n;
-    }
-
-    /*
-     * Keep big powers of 5 handy for future reference.
-     */
-    private static FDBigInt b5p[];
+    private static final ThreadLocal threadLocalCharBuffer =
+            new ThreadLocal() {
+                @Override
+                protected Object initialValue() {
+                    return new char[20];
+                }
+            };
 
-    private static synchronized FDBigInt
-    big5pow( int p ){
-        assert p >= 0 : p; // negative power of 5
-        if ( b5p == null ){
-            b5p = new FDBigInt[ p+1 ];
-        }else if (b5p.length <= p ){
-            FDBigInt t[] = new FDBigInt[ p+1 ];
-            System.arraycopy( b5p, 0, t, 0, b5p.length );
-            b5p = t;
-        }
-        if ( b5p[p] != null )
-            return b5p[p];
-        else if ( p < small5pow.length )
-            return b5p[p] = new FDBigInt( small5pow[p] );
-        else if ( p < long5pow.length )
-            return b5p[p] = new FDBigInt( long5pow[p] );
-        else {
-            // construct the value.
-            // recursively.
-            int q, r;
-            // in order to compute 5^p,
-            // compute its square root, 5^(p/2) and square.
-            // or, let q = p / 2, r = p -q, then
-            // 5^p = 5^(q+r) = 5^q * 5^r
-            q = p >> 1;
-            r = p - q;
-            FDBigInt bigq =  b5p[q];
-            if ( bigq == null )
-                bigq = big5pow ( q );
-            if ( r < small5pow.length ){
-                return (b5p[p] = bigq.mult( small5pow[r] ) );
-            }else{
-                FDBigInt bigr = b5p[ r ];
-                if ( bigr == null )
-                    bigr = big5pow( r );
-                return (b5p[p] = bigq.mult( bigr ) );
-            }
-        }
+    private static char[] getBuffer(){
+        return (char[]) threadLocalCharBuffer.get();
     }
 
-    //
-    // a common operation
-    //
-    private static FDBigInt
-    multPow52( FDBigInt v, int p5, int p2 ){
-        if ( p5 != 0 ){
-            if ( p5 < small5pow.length ){
-                v = v.mult( small5pow[p5] );
-            } else {
-                v = v.mult( big5pow( p5 ) );
-            }
-        }
-        if ( p2 != 0 ){
-            v.lshiftMe( p2 );
+    private FormattedFloatingDecimal(int precision, Form form, FloatingDecimal.BinaryToASCIIConverter fdConverter) {
+        if (fdConverter.isExceptional()) {
+            this.mantissa = fdConverter.toJavaFormatString().toCharArray();
+            this.exponent = null;
+            return;
         }
-        return v;
-    }
-
-    //
-    // another common operation
-    //
-    private static FDBigInt
-    constructPow52( int p5, int p2 ){
-        FDBigInt v = new FDBigInt( big5pow( p5 ) );
-        if ( p2 != 0 ){
-            v.lshiftMe( p2 );
+        char[] digits = getBuffer();
+        int nDigits = fdConverter.getDigits(digits);
+        int decExp = fdConverter.getDecimalExponent();
+        int exp;
+        boolean isNegative = fdConverter.isNegative();
+        switch (form) {
+            case COMPATIBLE:
+                exp = decExp;
+                this.decExponentRounded = exp;
+                fillCompatible(precision, digits, nDigits, exp, isNegative);
+                break;
+            case DECIMAL_FLOAT:
+                exp = applyPrecision(decExp, digits, nDigits, decExp + precision);
+                fillDecimal(precision, digits, nDigits, exp, isNegative);
+                this.decExponentRounded = exp;
+                break;
+            case SCIENTIFIC:
+                exp = applyPrecision(decExp, digits, nDigits, precision + 1);
+                fillScientific(precision, digits, nDigits, exp, isNegative);
+                this.decExponentRounded = exp;
+                break;
+            case GENERAL:
+                exp = applyPrecision(decExp, digits, nDigits, precision);
+                // adjust precision to be the number of digits to right of decimal
+                // the real exponent to be output is actually exp - 1, not exp
+                if (exp - 1 < -4 || exp - 1 >= precision) {
+                    // form = Form.SCIENTIFIC;
+                    precision--;
+                    fillScientific(precision, digits, nDigits, exp, isNegative);
+                } else {
+                    // form = Form.DECIMAL_FLOAT;
+                    precision = precision - exp;
+                    fillDecimal(precision, digits, nDigits, exp, isNegative);
+                }
+                this.decExponentRounded = exp;
+                break;
+            default:
+                assert false;
         }
-        return v;
     }
 
-    /*
-     * Make a floating double into a FDBigInt.
-     * This could also be structured as a FDBigInt
-     * constructor, but we'd have to build a lot of knowledge
-     * about floating-point representation into it, and we don't want to.
-     *
-     * AS A SIDE EFFECT, THIS METHOD WILL SET THE INSTANCE VARIABLES
-     * bigIntExp and bigIntNBits
-     *
-     */
-    private FDBigInt
-    doubleToBigInt( double dval ){
-        long lbits = Double.doubleToLongBits( dval ) & ~signMask;
-        int binexp = (int)(lbits >>> expShift);
-        lbits &= fractMask;
-        if ( binexp > 0 ){
-            lbits |= fractHOB;
-        } else {
-            assert lbits != 0L : lbits; // doubleToBigInt(0.0)
-            binexp +=1;
-            while ( (lbits & fractHOB ) == 0L){
-                lbits <<= 1;
-                binexp -= 1;
-            }
-        }
-        binexp -= expBias;
-        int nbits = countBits( lbits );
-        /*
-         * We now know where the high-order 1 bit is,
-         * and we know how many there are.
-         */
-        int lowOrderZeros = expShift+1-nbits;
-        lbits >>>= lowOrderZeros;
-
-        bigIntExp = binexp+1-nbits;
-        bigIntNBits = nbits;
-        return new FDBigInt( lbits );
+    // returns the exponent after rounding has been done by applyPrecision
+    public int getExponentRounded() {
+        return decExponentRounded - 1;
     }
 
-    /*
-     * Compute a number that is the ULP of the given value,
-     * for purposes of addition/subtraction. Generally easy.
-     * More difficult if subtracting and the argument
-     * is a normalized a power of 2, as the ULP changes at these points.
-     */
-    private static double ulp( double dval, boolean subtracting ){
-        long lbits = Double.doubleToLongBits( dval ) & ~signMask;
-        int binexp = (int)(lbits >>> expShift);
-        double ulpval;
-        if ( subtracting && ( binexp >= expShift ) && ((lbits&fractMask) == 0L) ){
-            // for subtraction from normalized, powers of 2,
-            // use next-smaller exponent
-            binexp -= 1;
-        }
-        if ( binexp > expShift ){
-            ulpval = Double.longBitsToDouble( ((long)(binexp-expShift))< 0L (not zero, nor negative).
-     *
-     * The only reason that we develop the digits here, rather than
-     * calling on Long.toString() is that we can do it a little faster,
-     * and besides want to treat trailing 0s specially. If Long.toString
-     * changes, we should re-evaluate this strategy!
+    /**
+     * Returns new decExp in case of overflow.
      */
-    private void
-    developLongDigits( int decExponent, long lvalue, long insignificant ){
-        char digits[];
-        int  ndigits;
-        int  digitno;
-        int  c;
-        //
-        // Discard non-significant low-order bits, while rounding,
-        // up to insignificant value.
-        int i;
-        for ( i = 0; insignificant >= 10L; i++ )
-            insignificant /= 10L;
-        if ( i != 0 ){
-            long pow10 = long5pow[i] << i; // 10^i == 5^i * 2^i;
-            long residue = lvalue % pow10;
-            lvalue /= pow10;
-            decExponent += i;
-            if ( residue >= (pow10>>1) ){
-                // round up based on the low-order bits we're discarding
-                lvalue++;
-            }
-        }
-        if ( lvalue <= Integer.MAX_VALUE ){
-            assert lvalue > 0L : lvalue; // lvalue <= 0
-            // even easier subcase!
-            // can do int arithmetic rather than long!
-            int  ivalue = (int)lvalue;
-            ndigits = 10;
-            digits = perThreadBuffer.get();
-            digitno = ndigits-1;
-            c = ivalue%10;
-            ivalue /= 10;
-            while ( c == 0 ){
-                decExponent++;
-                c = ivalue%10;
-                ivalue /= 10;
-            }
-            while ( ivalue != 0){
-                digits[digitno--] = (char)(c+'0');
-                decExponent++;
-                c = ivalue%10;
-                ivalue /= 10;
-            }
-            digits[digitno] = (char)(c+'0');
-        } else {
-            // same algorithm as above (same bugs, too )
-            // but using long arithmetic.
-            ndigits = 20;
-            digits = perThreadBuffer.get();
-            digitno = ndigits-1;
-            c = (int)(lvalue%10L);
-            lvalue /= 10L;
-            while ( c == 0 ){
-                decExponent++;
-                c = (int)(lvalue%10L);
-                lvalue /= 10L;
-            }
-            while ( lvalue != 0L ){
-                digits[digitno--] = (char)(c+'0');
-                decExponent++;
-                c = (int)(lvalue%10L);
-                lvalue /= 10;
-            }
-            digits[digitno] = (char)(c+'0');
-        }
-        char result [];
-        ndigits -= digitno;
-        result = new char[ ndigits ];
-        System.arraycopy( digits, digitno, result, 0, ndigits );
-        this.digits = result;
-        this.decExponent = decExponent+1;
-        this.nDigits = ndigits;
-    }
-
-    //
-    // add one to the least significant digit.
-    // in the unlikely event there is a carry out,
-    // deal with it.
-    // assert that this will only happen where there
-    // is only one digit, e.g. (float)1e-44 seems to do it.
-    //
-    private void
-    roundup(){
-        int i;
-        int q = digits[ i = (nDigits-1)];
-        if ( q == '9' ){
-            while ( q == '9' && i > 0 ){
-                digits[i] = '0';
-                q = digits[--i];
-            }
-            if ( q == '9' ){
-                // carryout! High-order 1, rest 0s, larger exp.
-                decExponent += 1;
-                digits[0] = '1';
-                return;
-            }
-            // else fall through.
-        }
-        digits[i] = (char)(q+1);
-    }
-
-    // Given the desired number of digits predict the result's exponent.
-    private int checkExponent(int length) {
-        if (length >= nDigits || length < 0)
-            return decExponent;
-
-        for (int i = 0; i < length; i++)
-            if (digits[i] != '9')
-                // a '9' anywhere in digits will absorb the round
-                return decExponent;
-        return decExponent + (digits[length] >= '5' ? 1 : 0);
-    }
-
-    // Unlike roundup(), this method does not modify digits.  It also
-    // rounds at a particular precision.
-    private char [] applyPrecision(int length) {
-        char [] result = new char[nDigits];
-        for (int i = 0; i < result.length; i++) result[i] = '0';
-
-        if (length >= nDigits || length < 0) {
+    private static int applyPrecision(int decExp, char[] digits, int nDigits, int prec) {
+        if (prec >= nDigits || prec < 0) {
             // no rounding necessary
-            System.arraycopy(digits, 0, result, 0, nDigits);
-            return result;
+            return decExp;
         }
-        if (length == 0) {
+        if (prec == 0) {
             // only one digit (0 or 1) is returned because the precision
             // excludes all significant digits
             if (digits[0] >= '5') {
-                result[0] = '1';
+                digits[0] = '1';
+                Arrays.fill(digits, 1, nDigits, '0');
+                return decExp + 1;
+            } else {
+                Arrays.fill(digits, 0, nDigits, '0');
+                return decExp;
             }
-            return result;
         }
-
-        int i = length;
-        int q = digits[i];
-        if (q >= '5' && i > 0) {
+        int q = digits[prec];
+        if (q >= '5') {
+            int i = prec;
             q = digits[--i];
             if ( q == '9' ) {
                 while ( q == '9' && i > 0 ){
@@ -448,1319 +144,206 @@
                 }
                 if ( q == '9' ){
                     // carryout! High-order 1, rest 0s, larger exp.
-                    result[0] = '1';
-                    return result;
+                    digits[0] = '1';
+                    Arrays.fill(digits, 1, nDigits, '0');
+                    return decExp+1;
                 }
             }
-            result[i] = (char)(q + 1);
-        }
-        while (--i >= 0) {
-            result[i] = digits[i];
-        }
-        return result;
-    }
-
-    /*
-     * FIRST IMPORTANT CONSTRUCTOR: DOUBLE
-     */
-    public FormattedFloatingDecimal( double d )
-    {
-        this(d, Integer.MAX_VALUE, Form.COMPATIBLE);
-    }
-
-    public FormattedFloatingDecimal( double d, int precision, Form form )
-    {
-        long    dBits = Double.doubleToLongBits( d );
-        long    fractBits;
-        int     binExp;
-        int     nSignificantBits;
-
-        this.precision = precision;
-        this.form      = form;
-
-        // discover and delete sign
-        if ( (dBits&signMask) != 0 ){
-            isNegative = true;
-            dBits ^= signMask;
-        } else {
-            isNegative = false;
-        }
-        // Begin to unpack
-        // Discover obvious special cases of NaN and Infinity.
-        binExp = (int)( (dBits&expMask) >> expShift );
-        fractBits = dBits&fractMask;
-        if ( binExp == (int)(expMask>>expShift) ) {
-            isExceptional = true;
-            if ( fractBits == 0L ){
-                digits =  infinity;
-            } else {
-                digits = notANumber;
-                isNegative = false; // NaN has no sign!
-            }
-            nDigits = digits.length;
-            return;
-        }
-        isExceptional = false;
-        // Finish unpacking
-        // Normalize denormalized numbers.
-        // Insert assumed high-order bit for normalized numbers.
-        // Subtract exponent bias.
-        if ( binExp == 0 ){
-            if ( fractBits == 0L ){
-                // not a denorm, just a 0!
-                decExponent = 0;
-                digits = zero;
-                nDigits = 1;
-                return;
-            }
-            while ( (fractBits&fractHOB) == 0L ){
-                fractBits <<= 1;
-                binExp -= 1;
-            }
-            nSignificantBits = expShift + binExp +1; // recall binExp is  - shift count.
-            binExp += 1;
+            digits[i] = (char)(q + 1);
+            Arrays.fill(digits, i+1, nDigits, '0');
         } else {
-            fractBits |= fractHOB;
-            nSignificantBits = expShift+1;
+            Arrays.fill(digits, prec, nDigits, '0');
         }
-        binExp -= expBias;
-        // call the routine that actually does all the hard work.
-        dtoa( binExp, fractBits, nSignificantBits );
+        return decExp;
     }
 
-    /*
-     * SECOND IMPORTANT CONSTRUCTOR: SINGLE
+    /**
+     * Fills mantissa and exponent char arrays for compatible format.
      */
-    public FormattedFloatingDecimal( float f )
-    {
-        this(f, Integer.MAX_VALUE, Form.COMPATIBLE);
-    }
-    public FormattedFloatingDecimal( float f, int precision, Form form )
-    {
-        int     fBits = Float.floatToIntBits( f );
-        int     fractBits;
-        int     binExp;
-        int     nSignificantBits;
-
-        this.precision = precision;
-        this.form      = form;
-
-        // discover and delete sign
-        if ( (fBits&singleSignMask) != 0 ){
-            isNegative = true;
-            fBits ^= singleSignMask;
-        } else {
-            isNegative = false;
-        }
-        // Begin to unpack
-        // Discover obvious special cases of NaN and Infinity.
-        binExp = (fBits&singleExpMask) >> singleExpShift;
-        fractBits = fBits&singleFractMask;
-        if ( binExp == (singleExpMask>>singleExpShift) ) {
-            isExceptional = true;
-            if ( fractBits == 0L ){
-                digits =  infinity;
-            } else {
-                digits = notANumber;
-                isNegative = false; // NaN has no sign!
-            }
-            nDigits = digits.length;
-            return;
-        }
-        isExceptional = false;
-        // Finish unpacking
-        // Normalize denormalized numbers.
-        // Insert assumed high-order bit for normalized numbers.
-        // Subtract exponent bias.
-        if ( binExp == 0 ){
-            if ( fractBits == 0 ){
-                // not a denorm, just a 0!
-                decExponent = 0;
-                digits = zero;
-                nDigits = 1;
-                return;
-            }
-            while ( (fractBits&singleFractHOB) == 0 ){
-                fractBits <<= 1;
-                binExp -= 1;
-            }
-            nSignificantBits = singleExpShift + binExp +1; // recall binExp is  - shift count.
-            binExp += 1;
-        } else {
-            fractBits |= singleFractHOB;
-            nSignificantBits = singleExpShift+1;
-        }
-        binExp -= singleExpBias;
-        // call the routine that actually does all the hard work.
-        dtoa( binExp, ((long)fractBits)<<(expShift-singleExpShift), nSignificantBits );
-    }
-
-    private void
-    dtoa( int binExp, long fractBits, int nSignificantBits )
-    {
-        int     nFractBits; // number of significant bits of fractBits;
-        int     nTinyBits;  // number of these to the right of the point.
-        int     decExp;
-
-        // Examine number. Determine if it is an easy case,
-        // which we can do pretty trivially using float/long conversion,
-        // or whether we must do real work.
-        nFractBits = countBits( fractBits );
-        nTinyBits = Math.max( 0, nFractBits - binExp - 1 );
-        if ( binExp <= maxSmallBinExp && binExp >= minSmallBinExp ){
-            // Look more closely at the number to decide if,
-            // with scaling by 10^nTinyBits, the result will fit in
-            // a long.
-            if ( (nTinyBits < long5pow.length) && ((nFractBits + n5bits[nTinyBits]) < 64 ) ){
-                /*
-                 * We can do this:
-                 * take the fraction bits, which are normalized.
-                 * (a) nTinyBits == 0: Shift left or right appropriately
-                 *     to align the binary point at the extreme right, i.e.
-                 *     where a long int point is expected to be. The integer
-                 *     result is easily converted to a string.
-                 * (b) nTinyBits > 0: Shift right by expShift-nFractBits,
-                 *     which effectively converts to long and scales by
-                 *     2^nTinyBits. Then multiply by 5^nTinyBits to
-                 *     complete the scaling. We know this won't overflow
-                 *     because we just counted the number of bits necessary
-                 *     in the result. The integer you get from this can
-                 *     then be converted to a string pretty easily.
-                 */
-                long halfULP;
-                if ( nTinyBits == 0 ) {
-                    if ( binExp > nSignificantBits ){
-                        halfULP = 1L << ( binExp-nSignificantBits-1);
-                    } else {
-                        halfULP = 0L;
-                    }
-                    if ( binExp >= expShift ){
-                        fractBits <<= (binExp-expShift);
-                    } else {
-                        fractBits >>>= (expShift-binExp) ;
-                    }
-                    developLongDigits( 0, fractBits, halfULP );
-                    return;
-                }
-                /*
-                 * The following causes excess digits to be printed
-                 * out in the single-float case. Our manipulation of
-                 * halfULP here is apparently not correct. If we
-                 * better understand how this works, perhaps we can
-                 * use this special case again. But for the time being,
-                 * we do not.
-                 * else {
-                 *     fractBits >>>= expShift+1-nFractBits;
-                 *     fractBits *= long5pow[ nTinyBits ];
-                 *     halfULP = long5pow[ nTinyBits ] >> (1+nSignificantBits-nFractBits);
-                 *     developLongDigits( -nTinyBits, fractBits, halfULP );
-                 *     return;
-                 * }
-                 */
-            }
-        }
-        /*
-         * This is the hard case. We are going to compute large positive
-         * integers B and S and integer decExp, s.t.
-         *      d = ( B / S ) * 10^decExp
-         *      1 <= B / S < 10
-         * Obvious choices are:
-         *      decExp = floor( log10(d) )
-         *      B      = d * 2^nTinyBits * 10^max( 0, -decExp )
-         *      S      = 10^max( 0, decExp) * 2^nTinyBits
-         * (noting that nTinyBits has already been forced to non-negative)
-         * I am also going to compute a large positive integer
-         *      M      = (1/2^nSignificantBits) * 2^nTinyBits * 10^max( 0, -decExp )
-         * i.e. M is (1/2) of the ULP of d, scaled like B.
-         * When we iterate through dividing B/S and picking off the
-         * quotient bits, we will know when to stop when the remainder
-         * is <= M.
-         *
-         * We keep track of powers of 2 and powers of 5.
-         */
-
-        /*
-         * Estimate decimal exponent. (If it is small-ish,
-         * we could double-check.)
-         *
-         * First, scale the mantissa bits such that 1 <= d2 < 2.
-         * We are then going to estimate
-         *          log10(d2) ~=~  (d2-1.5)/1.5 + log(1.5)
-         * and so we can estimate
-         *      log10(d) ~=~ log10(d2) + binExp * log10(2)
-         * take the floor and call it decExp.
-         * FIXME -- use more precise constants here. It costs no more.
-         */
-        double d2 = Double.longBitsToDouble(
-            expOne | ( fractBits &~ fractHOB ) );
-        decExp = (int)Math.floor(
-            (d2-1.5D)*0.289529654D + 0.176091259 + (double)binExp * 0.301029995663981 );
-        int B2, B5; // powers of 2 and powers of 5, respectively, in B
-        int S2, S5; // powers of 2 and powers of 5, respectively, in S
-        int M2, M5; // powers of 2 and powers of 5, respectively, in M
-        int Bbits; // binary digits needed to represent B, approx.
-        int tenSbits; // binary digits needed to represent 10*S, approx.
-        FDBigInt Sval, Bval, Mval;
-
-        B5 = Math.max( 0, -decExp );
-        B2 = B5 + nTinyBits + binExp;
-
-        S5 = Math.max( 0, decExp );
-        S2 = S5 + nTinyBits;
-
-        M5 = B5;
-        M2 = B2 - nSignificantBits;
-
-        /*
-         * the long integer fractBits contains the (nFractBits) interesting
-         * bits from the mantissa of d ( hidden 1 added if necessary) followed
-         * by (expShift+1-nFractBits) zeros. In the interest of compactness,
-         * I will shift out those zeros before turning fractBits into a
-         * FDBigInt. The resulting whole number will be
-         *      d * 2^(nFractBits-1-binExp).
-         */
-        fractBits >>>= (expShift+1-nFractBits);
-        B2 -= nFractBits-1;
-        int common2factor = Math.min( B2, S2 );
-        B2 -= common2factor;
-        S2 -= common2factor;
-        M2 -= common2factor;
-
-        /*
-         * HACK!! For exact powers of two, the next smallest number
-         * is only half as far away as we think (because the meaning of
-         * ULP changes at power-of-two bounds) for this reason, we
-         * hack M2. Hope this works.
-         */
-        if ( nFractBits == 1 )
-            M2 -= 1;
-
-        if ( M2 < 0 ){
-            // oops.
-            // since we cannot scale M down far enough,
-            // we must scale the other values up.
-            B2 -= M2;
-            S2 -= M2;
-            M2 =  0;
-        }
-        /*
-         * Construct, Scale, iterate.
-         * Some day, we'll write a stopping test that takes
-         * account of the assymetry of the spacing of floating-point
-         * numbers below perfect powers of 2
-         * 26 Sept 96 is not that day.
-         * So we use a symmetric test.
-         */
-        char digits[] = this.digits = new char[18];
-        int  ndigit = 0;
-        boolean low, high;
-        long lowDigitDifference;
-        int  q;
-
-        /*
-         * Detect the special cases where all the numbers we are about
-         * to compute will fit in int or long integers.
-         * In these cases, we will avoid doing FDBigInt arithmetic.
-         * We use the same algorithms, except that we "normalize"
-         * our FDBigInts before iterating. This is to make division easier,
-         * as it makes our fist guess (quotient of high-order words)
-         * more accurate!
-         *
-         * Some day, we'll write a stopping test that takes
-         * account of the assymetry of the spacing of floating-point
-         * numbers below perfect powers of 2
-         * 26 Sept 96 is not that day.
-         * So we use a symmetric test.
-         */
-        Bbits = nFractBits + B2 + (( B5 < n5bits.length )? n5bits[B5] : ( B5*3 ));
-        tenSbits = S2+1 + (( (S5+1) < n5bits.length )? n5bits[(S5+1)] : ( (S5+1)*3 ));
-        if ( Bbits < 64 && tenSbits < 64){
-            if ( Bbits < 32 && tenSbits < 32){
-                // wa-hoo! They're all ints!
-                int b = ((int)fractBits * small5pow[B5] ) << B2;
-                int s = small5pow[S5] << S2;
-                int m = small5pow[M5] << M2;
-                int tens = s * 10;
-                /*
-                 * Unroll the first iteration. If our decExp estimate
-                 * was too high, our first quotient will be zero. In this
-                 * case, we discard it and decrement decExp.
-                 */
-                ndigit = 0;
-                q = b / s;
-                b = 10 * ( b % s );
-                m *= 10;
-                low  = (b <  m );
-                high = (b+m > tens );
-                assert q < 10 : q; // excessively large digit
-                if ( (q == 0) && ! high ){
-                    // oops. Usually ignore leading zero.
-                    decExp--;
-                } else {
-                    digits[ndigit++] = (char)('0' + q);
-                }
-                /*
-                 * HACK! Java spec sez that we always have at least
-                 * one digit after the . in either F- or E-form output.
-                 * Thus we will need more than one digit if we're using
-                 * E-form
-                 */
-                if (! (form == Form.COMPATIBLE && -3 < decExp && decExp < 8)) {
-                    high = low = false;
-                }
-                while( ! low && ! high ){
-                    q = b / s;
-                    b = 10 * ( b % s );
-                    m *= 10;
-                    assert q < 10 : q; // excessively large digit
-                    if ( m > 0L ){
-                        low  = (b <  m );
-                        high = (b+m > tens );
-                    } else {
-                        // hack -- m might overflow!
-                        // in this case, it is certainly > b,
-                        // which won't
-                        // and b+m > tens, too, since that has overflowed
-                        // either!
-                        low = true;
-                        high = true;
-                    }
-                    digits[ndigit++] = (char)('0' + q);
+    private void fillCompatible(int precision, char[] digits, int nDigits, int exp, boolean isNegative) {
+        int startIndex = isNegative ? 1 : 0;
+        if (exp > 0 && exp < 8) {
+            // print digits.digits.
+            if (nDigits < exp) {
+                int extraZeros = exp - nDigits;
+                mantissa = create(isNegative, nDigits + extraZeros + 2);
+                System.arraycopy(digits, 0, mantissa, startIndex, nDigits);
+                Arrays.fill(mantissa, startIndex + nDigits, startIndex + nDigits + extraZeros, '0');
+                mantissa[startIndex + nDigits + extraZeros] = '.';
+                mantissa[startIndex + nDigits + extraZeros+1] = '0';
+            } else if (exp < nDigits) {
+                int t = Math.min(nDigits - exp, precision);
+                mantissa = create(isNegative, exp + 1 + t);
+                System.arraycopy(digits, 0, mantissa, startIndex, exp);
+                mantissa[startIndex + exp ] = '.';
+                System.arraycopy(digits, exp, mantissa, startIndex+exp+1, t);
+            } else { // exp == digits.length
+                mantissa = create(isNegative, nDigits + 2);
+                System.arraycopy(digits, 0, mantissa, startIndex, nDigits);
+                mantissa[startIndex + nDigits ] = '.';
+                mantissa[startIndex + nDigits +1] = '0';
+            }
+        } else if (exp <= 0 && exp > -3) {
+            int zeros = Math.max(0, Math.min(-exp, precision));
+            int t = Math.max(0, Math.min(nDigits, precision + exp));
+            // write '0' s before the significant digits
+            if (zeros > 0) {
+                mantissa = create(isNegative, zeros + 2 + t);
+                mantissa[startIndex] = '0';
+                mantissa[startIndex+1] = '.';
+                Arrays.fill(mantissa, startIndex + 2, startIndex + 2 + zeros, '0');
+                if (t > 0) {
+                    // copy only when significant digits are within the precision
+                    System.arraycopy(digits, 0, mantissa, startIndex + 2 + zeros, t);
                 }
-                lowDigitDifference = (b<<1) - tens;
+            } else if (t > 0) {
+                mantissa = create(isNegative, zeros + 2 + t);
+                mantissa[startIndex] = '0';
+                mantissa[startIndex + 1] = '.';
+                // copy only when significant digits are within the precision
+                System.arraycopy(digits, 0, mantissa, startIndex + 2, t);
             } else {
-                // still good! they're all longs!
-                long b = (fractBits * long5pow[B5] ) << B2;
-                long s = long5pow[S5] << S2;
-                long m = long5pow[M5] << M2;
-                long tens = s * 10L;
-                /*
-                 * Unroll the first iteration. If our decExp estimate
-                 * was too high, our first quotient will be zero. In this
-                 * case, we discard it and decrement decExp.
-                 */
-                ndigit = 0;
-                q = (int) ( b / s );
-                b = 10L * ( b % s );
-                m *= 10L;
-                low  = (b <  m );
-                high = (b+m > tens );
-                assert q < 10 : q; // excessively large digit
-                if ( (q == 0) && ! high ){
-                    // oops. Usually ignore leading zero.
-                    decExp--;
-                } else {
-                    digits[ndigit++] = (char)('0' + q);
-                }
-                /*
-                 * HACK! Java spec sez that we always have at least
-                 * one digit after the . in either F- or E-form output.
-                 * Thus we will need more than one digit if we're using
-                 * E-form
-                 */
-                if (! (form == Form.COMPATIBLE && -3 < decExp && decExp < 8)) {
-                    high = low = false;
-                }
-                while( ! low && ! high ){
-                    q = (int) ( b / s );
-                    b = 10 * ( b % s );
-                    m *= 10;
-                    assert q < 10 : q;  // excessively large digit
-                    if ( m > 0L ){
-                        low  = (b <  m );
-                        high = (b+m > tens );
-                    } else {
-                        // hack -- m might overflow!
-                        // in this case, it is certainly > b,
-                        // which won't
-                        // and b+m > tens, too, since that has overflowed
-                        // either!
-                        low = true;
-                        high = true;
-                    }
-                    digits[ndigit++] = (char)('0' + q);
-                }
-                lowDigitDifference = (b<<1) - tens;
+                this.mantissa = create(isNegative, 1);
+                this.mantissa[startIndex] = '0';
             }
         } else {
-            FDBigInt tenSval;
-            int  shiftBias;
-
-            /*
-             * We really must do FDBigInt arithmetic.
-             * Fist, construct our FDBigInt initial values.
-             */
-            Bval = multPow52( new FDBigInt( fractBits  ), B5, B2 );
-            Sval = constructPow52( S5, S2 );
-            Mval = constructPow52( M5, M2 );
-
-
-            // normalize so that division works better
-            Bval.lshiftMe( shiftBias = Sval.normalizeMe() );
-            Mval.lshiftMe( shiftBias );
-            tenSval = Sval.mult( 10 );
-            /*
-             * Unroll the first iteration. If our decExp estimate
-             * was too high, our first quotient will be zero. In this
-             * case, we discard it and decrement decExp.
-             */
-            ndigit = 0;
-            q = Bval.quoRemIteration( Sval );
-            Mval = Mval.mult( 10 );
-            low  = (Bval.cmp( Mval ) < 0);
-            high = (Bval.add( Mval ).cmp( tenSval ) > 0 );
-            assert q < 10 : q; // excessively large digit
-            if ( (q == 0) && ! high ){
-                // oops. Usually ignore leading zero.
-                decExp--;
+            if (nDigits > 1) {
+                mantissa = create(isNegative, nDigits + 1);
+                mantissa[startIndex] = digits[0];
+                mantissa[startIndex + 1] = '.';
+                System.arraycopy(digits, 1, mantissa, startIndex + 2, nDigits - 1);
             } else {
-                digits[ndigit++] = (char)('0' + q);
-            }
-            /*
-             * HACK! Java spec sez that we always have at least
-             * one digit after the . in either F- or E-form output.
-             * Thus we will need more than one digit if we're using
-             * E-form
-             */
-            if (! (form == Form.COMPATIBLE && -3 < decExp && decExp < 8)) {
-                high = low = false;
-            }
-            while( ! low && ! high ){
-                q = Bval.quoRemIteration( Sval );
-                Mval = Mval.mult( 10 );
-                assert q < 10 : q;  // excessively large digit
-                low  = (Bval.cmp( Mval ) < 0);
-                high = (Bval.add( Mval ).cmp( tenSval ) > 0 );
-                digits[ndigit++] = (char)('0' + q);
+                mantissa = create(isNegative, 3);
+                mantissa[startIndex] = digits[0];
+                mantissa[startIndex + 1] = '.';
+                mantissa[startIndex + 2] = '0';
+            }
+            int e, expStartIntex;
+            boolean isNegExp = (exp <= 0);
+            if (isNegExp) {
+                e = -exp + 1;
+                expStartIntex = 1;
+            } else {
+                e = exp - 1;
+                expStartIntex = 0;
             }
-            if ( high && low ){
-                Bval.lshiftMe(1);
-                lowDigitDifference = Bval.cmp(tenSval);
-            } else
-                lowDigitDifference = 0L; // this here only for flow analysis!
-        }
-        this.decExponent = decExp+1;
-        this.digits = digits;
-        this.nDigits = ndigit;
-        /*
-         * Last digit gets rounded based on stopping condition.
-         */
-        if ( high ){
-            if ( low ){
-                if ( lowDigitDifference == 0L ){
-                    // it's a tie!
-                    // choose based on which digits we like.
-                    if ( (digits[nDigits-1]&1) != 0 ) roundup();
-                } else if ( lowDigitDifference > 0 ){
-                    roundup();
-                }
+            // decExponent has 1, 2, or 3, digits
+            if (e <= 9) {
+                exponent = create(isNegExp,1);
+                exponent[expStartIntex] = (char) (e + '0');
+            } else if (e <= 99) {
+                exponent = create(isNegExp,2);
+                exponent[expStartIntex] = (char) (e / 10 + '0');
+                exponent[expStartIntex+1] = (char) (e % 10 + '0');
             } else {
-                roundup();
+                exponent = create(isNegExp,3);
+                exponent[expStartIntex] = (char) (e / 100 + '0');
+                e %= 100;
+                exponent[expStartIntex+1] = (char) (e / 10 + '0');
+                exponent[expStartIntex+2] = (char) (e % 10 + '0');
             }
         }
     }
 
-    public String
-    toString(){
-        // most brain-dead version
-        StringBuffer result = new StringBuffer( nDigits+8 );
-        if ( isNegative ){ result.append( '-' ); }
-        if ( isExceptional ){
-            result.append( digits, 0, nDigits );
+    private static char[] create(boolean isNegative, int size) {
+        if(isNegative) {
+            char[] r = new char[size +1];
+            r[0] = '-';
+            return r;
         } else {
-            result.append( "0.");
-            result.append( digits, 0, nDigits );
-            result.append('e');
-            result.append( decExponent );
+            return new char[size];
         }
-        return new String(result);
-    }
-
-    // returns the exponent before rounding
-    public int getExponent() {
-        return decExponent - 1;
-    }
-
-    // returns the exponent after rounding has been done by applyPrecision
-    public int getExponentRounded() {
-        return decExponentRounded - 1;
     }
 
-    public int getChars(char[] result) {
-        assert nDigits <= 19 : nDigits; // generous bound on size of nDigits
-        int i = 0;
-        if (isNegative) { result[0] = '-'; i = 1; }
-        if (isExceptional) {
-            System.arraycopy(digits, 0, result, i, nDigits);
-            i += nDigits;
-        } else {
-            char digits [] = this.digits;
-            int exp = decExponent;
-            switch (form) {
-            case COMPATIBLE:
-                break;
-            case DECIMAL_FLOAT:
-                exp = checkExponent(decExponent + precision);
-                digits = applyPrecision(decExponent + precision);
-                break;
-            case SCIENTIFIC:
-                exp = checkExponent(precision + 1);
-                digits = applyPrecision(precision + 1);
-                break;
-            case GENERAL:
-                exp = checkExponent(precision);
-                digits = applyPrecision(precision);
-                // adjust precision to be the number of digits to right of decimal
-                // the real exponent to be output is actually exp - 1, not exp
-                if (exp - 1 < -4 || exp - 1 >= precision) {
-                    form = Form.SCIENTIFIC;
-                    precision--;
-                } else {
-                    form = Form.DECIMAL_FLOAT;
-                    precision = precision - exp;
+    /*
+     * Fills mantissa char arrays for DECIMAL_FLOAT format.
+     * Exponent should be equal to null.
+     */
+    private void fillDecimal(int precision, char[] digits, int nDigits, int exp, boolean isNegative) {
+        int startIndex = isNegative ? 1 : 0;
+        if (exp > 0) {
+            // print digits.digits.
+            if (nDigits < exp) {
+                mantissa = create(isNegative,exp);
+                System.arraycopy(digits, 0, mantissa, startIndex, nDigits);
+                Arrays.fill(mantissa, startIndex + nDigits, startIndex + exp, '0');
+                // Do not append ".0" for formatted floats since the user
+                // may request that it be omitted. It is added as necessary
+                // by the Formatter.
+            } else {
+                int t = Math.min(nDigits - exp, precision);
+                mantissa = create(isNegative, exp + (t > 0 ? (t + 1) : 0));
+                System.arraycopy(digits, 0, mantissa, startIndex, exp);
+                // Do not append ".0" for formatted floats since the user
+                // may request that it be omitted. It is added as necessary
+                // by the Formatter.
+                if (t > 0) {
+                    mantissa[startIndex + exp] = '.';
+                    System.arraycopy(digits, exp, mantissa, startIndex + exp + 1, t);
                 }
-                break;
-            default:
-                assert false;
             }
-            decExponentRounded = exp;
-
-            if (exp > 0
-                && ((form == Form.COMPATIBLE && (exp < 8))
-                    || (form == Form.DECIMAL_FLOAT)))
-            {
-                // print digits.digits.
-                int charLength = Math.min(nDigits, exp);
-                System.arraycopy(digits, 0, result, i, charLength);
-                i += charLength;
-                if (charLength < exp) {
-                    charLength = exp-charLength;
-                    for (int nz = 0; nz < charLength; nz++)
-                        result[i++] = '0';
-                    // Do not append ".0" for formatted floats since the user
-                    // may request that it be omitted. It is added as necessary
-                    // by the Formatter.
-                    if (form == Form.COMPATIBLE) {
-                        result[i++] = '.';
-                        result[i++] = '0';
-                    }
-                } else {
-                    // Do not append ".0" for formatted floats since the user
-                    // may request that it be omitted. It is added as necessary
-                    // by the Formatter.
-                    if (form == Form.COMPATIBLE) {
-                        result[i++] = '.';
-                        if (charLength < nDigits) {
-                            int t = Math.min(nDigits - charLength, precision);
-                            System.arraycopy(digits, charLength, result, i, t);
-                            i += t;
-                        } else {
-                            result[i++] = '0';
-                        }
-                    } else {
-                        int t = Math.min(nDigits - charLength, precision);
-                        if (t > 0) {
-                            result[i++] = '.';
-                            System.arraycopy(digits, charLength, result, i, t);
-                            i += t;
-                        }
-                    }
-                }
-            } else if (exp <= 0
-                       && ((form == Form.COMPATIBLE && exp > -3)
-                       || (form == Form.DECIMAL_FLOAT)))
-            {
-                // print 0.0* digits
-                result[i++] = '0';
-                if (exp != 0) {
-                    // write '0' s before the significant digits
-                    int t = Math.min(-exp, precision);
-                    if (t > 0) {
-                        result[i++] = '.';
-                        for (int nz = 0; nz < t; nz++)
-                            result[i++] = '0';
-                    }
-                }
-                int t = Math.min(digits.length, precision + exp);
+        } else if (exp <= 0) {
+            int zeros = Math.max(0, Math.min(-exp, precision));
+            int t = Math.max(0, Math.min(nDigits, precision + exp));
+            // write '0' s before the significant digits
+            if (zeros > 0) {
+                mantissa = create(isNegative, zeros + 2 + t);
+                mantissa[startIndex] = '0';
+                mantissa[startIndex+1] = '.';
+                Arrays.fill(mantissa, startIndex + 2, startIndex + 2 + zeros, '0');
                 if (t > 0) {
-                    if (i == 1)
-                        result[i++] = '.';
                     // copy only when significant digits are within the precision
-                    System.arraycopy(digits, 0, result, i, t);
-                    i += t;
+                    System.arraycopy(digits, 0, mantissa, startIndex + 2 + zeros, t);
                 }
+            } else if (t > 0) {
+                mantissa = create(isNegative, zeros + 2 + t);
+                mantissa[startIndex] = '0';
+                mantissa[startIndex + 1] = '.';
+                // copy only when significant digits are within the precision
+                System.arraycopy(digits, 0, mantissa, startIndex + 2, t);
             } else {
-                result[i++] = digits[0];
-                if (form == Form.COMPATIBLE) {
-                    result[i++] = '.';
-                    if (nDigits > 1) {
-                        System.arraycopy(digits, 1, result, i, nDigits-1);
-                        i += nDigits-1;
-                    } else {
-                        result[i++] = '0';
-                    }
-                    result[i++] = 'E';
-                } else {
-                    if (nDigits > 1) {
-                        int t = Math.min(nDigits -1, precision);
-                        if (t > 0) {
-                            result[i++] = '.';
-                            System.arraycopy(digits, 1, result, i, t);
-                            i += t;
-                        }
-                    }
-                    result[i++] = 'e';
-                }
-                int e;
-                if (exp <= 0) {
-                    result[i++] = '-';
-                    e = -exp+1;
-                } else {
-                    if (form != Form.COMPATIBLE)
-                        result[i++] = '+';
-                    e = exp-1;
-                }
-                // decExponent has 1, 2, or 3, digits
-                if (e <= 9) {
-                    if (form != Form.COMPATIBLE)
-                        result[i++] = '0';
-                    result[i++] = (char)(e+'0');
-                } else if (e <= 99) {
-                    result[i++] = (char)(e/10 +'0');
-                    result[i++] = (char)(e%10 + '0');
-                } else {
-                    result[i++] = (char)(e/100+'0');
-                    e %= 100;
-                    result[i++] = (char)(e/10+'0');
-                    result[i++] = (char)(e%10 + '0');
-                }
+                this.mantissa = create(isNegative, 1);
+                this.mantissa[startIndex] = '0';
             }
         }
-        return i;
     }
 
-    // Per-thread buffer for string/stringbuffer conversion
-    private static ThreadLocal perThreadBuffer = new ThreadLocal() {
-            protected synchronized char[] initialValue() {
-                return new char[26];
-            }
-        };
-
-    /*
-     * Take a FormattedFloatingDecimal, which we presumably just scanned in,
-     * and find out what its value is, as a double.
-     *
-     * AS A SIDE EFFECT, SET roundDir TO INDICATE PREFERRED
-     * ROUNDING DIRECTION in case the result is really destined
-     * for a single-precision float.
+    /**
+     * Fills mantissa and exponent char arrays for SCIENTIFIC format.
      */
-
-    public strictfp double doubleValue(){
-        int     kDigits = Math.min( nDigits, maxDecimalDigits+1 );
-        long    lValue;
-        double  dValue;
-        double  rValue, tValue;
-
-        // First, check for NaN and Infinity values
-        if(digits == infinity || digits == notANumber) {
-            if(digits == notANumber)
-                return Double.NaN;
-            else
-                return (isNegative?Double.NEGATIVE_INFINITY:Double.POSITIVE_INFINITY);
-        }
-        else {
-            if (mustSetRoundDir) {
-                roundDir = 0;
-            }
-            /*
-             * convert the lead kDigits to a long integer.
-             */
-            // (special performance hack: start to do it using int)
-            int iValue = (int)digits[0]-(int)'0';
-            int iDigits = Math.min( kDigits, intDecimalDigits );
-            for ( int i=1; i < iDigits; i++ ){
-                iValue = iValue*10 + (int)digits[i]-(int)'0';
-            }
-            lValue = (long)iValue;
-            for ( int i=iDigits; i < kDigits; i++ ){
-                lValue = lValue*10L + (long)((int)digits[i]-(int)'0');
-            }
-            dValue = (double)lValue;
-            int exp = decExponent-kDigits;
-            /*
-             * lValue now contains a long integer with the value of
-             * the first kDigits digits of the number.
-             * dValue contains the (double) of the same.
-             */
-
-            if ( nDigits <= maxDecimalDigits ){
-                /*
-                 * possibly an easy case.
-                 * We know that the digits can be represented
-                 * exactly. And if the exponent isn't too outrageous,
-                 * the whole thing can be done with one operation,
-                 * thus one rounding error.
-                 * Note that all our constructors trim all leading and
-                 * trailing zeros, so simple values (including zero)
-                 * will always end up here
-                 */
-                if (exp == 0 || dValue == 0.0)
-                    return (isNegative)? -dValue : dValue; // small floating integer
-                else if ( exp >= 0 ){
-                    if ( exp <= maxSmallTen ){
-                        /*
-                         * Can get the answer with one operation,
-                         * thus one roundoff.
-                         */
-                        rValue = dValue * small10pow[exp];
-                        if ( mustSetRoundDir ){
-                            tValue = rValue / small10pow[exp];
-                            roundDir = ( tValue ==  dValue ) ? 0
-                                :( tValue < dValue ) ? 1
-                                : -1;
-                        }
-                        return (isNegative)? -rValue : rValue;
-                    }
-                    int slop = maxDecimalDigits - kDigits;
-                    if ( exp <= maxSmallTen+slop ){
-                        /*
-                         * We can multiply dValue by 10^(slop)
-                         * and it is still "small" and exact.
-                         * Then we can multiply by 10^(exp-slop)
-                         * with one rounding.
-                         */
-                        dValue *= small10pow[slop];
-                        rValue = dValue * small10pow[exp-slop];
-
-                        if ( mustSetRoundDir ){
-                            tValue = rValue / small10pow[exp-slop];
-                            roundDir = ( tValue ==  dValue ) ? 0
-                                :( tValue < dValue ) ? 1
-                                : -1;
-                        }
-                        return (isNegative)? -rValue : rValue;
-                    }
-                    /*
-                     * Else we have a hard case with a positive exp.
-                     */
-                } else {
-                    if ( exp >= -maxSmallTen ){
-                        /*
-                         * Can get the answer in one division.
-                         */
-                        rValue = dValue / small10pow[-exp];
-                        tValue = rValue * small10pow[-exp];
-                        if ( mustSetRoundDir ){
-                            roundDir = ( tValue ==  dValue ) ? 0
-                                :( tValue < dValue ) ? 1
-                                : -1;
-                        }
-                        return (isNegative)? -rValue : rValue;
-                    }
-                    /*
-                     * Else we have a hard case with a negative exp.
-                     */
-                }
-            }
-
-            /*
-             * Harder cases:
-             * The sum of digits plus exponent is greater than
-             * what we think we can do with one error.
-             *
-             * Start by approximating the right answer by,
-             * naively, scaling by powers of 10.
-             */
-            if ( exp > 0 ){
-                if ( decExponent > maxDecimalExponent+1 ){
-                    /*
-                     * Lets face it. This is going to be
-                     * Infinity. Cut to the chase.
-                     */
-                    return (isNegative)? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY;
-                }
-                if ( (exp&15) != 0 ){
-                    dValue *= small10pow[exp&15];
-                }
-                if ( (exp>>=4) != 0 ){
-                    int j;
-                    for( j = 0; exp > 1; j++, exp>>=1 ){
-                        if ( (exp&1)!=0)
-                            dValue *= big10pow[j];
-                    }
-                    /*
-                     * The reason for the weird exp > 1 condition
-                     * in the above loop was so that the last multiply
-                     * would get unrolled. We handle it here.
-                     * It could overflow.
-                     */
-                    double t = dValue * big10pow[j];
-                    if ( Double.isInfinite( t ) ){
-                        /*
-                         * It did overflow.
-                         * Look more closely at the result.
-                         * If the exponent is just one too large,
-                         * then use the maximum finite as our estimate
-                         * value. Else call the result infinity
-                         * and punt it.
-                         * ( I presume this could happen because
-                         * rounding forces the result here to be
-                         * an ULP or two larger than
-                         * Double.MAX_VALUE ).
-                         */
-                        t = dValue / 2.0;
-                        t *= big10pow[j];
-                        if ( Double.isInfinite( t ) ){
-                            return (isNegative)? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY;
-                        }
-                        t = Double.MAX_VALUE;
-                    }
-                    dValue = t;
-                }
-            } else if ( exp < 0 ){
-                exp = -exp;
-                if ( decExponent < minDecimalExponent-1 ){
-                    /*
-                     * Lets face it. This is going to be
-                     * zero. Cut to the chase.
-                     */
-                    return (isNegative)? -0.0 : 0.0;
-                }
-                if ( (exp&15) != 0 ){
-                    dValue /= small10pow[exp&15];
-                }
-                if ( (exp>>=4) != 0 ){
-                    int j;
-                    for( j = 0; exp > 1; j++, exp>>=1 ){
-                        if ( (exp&1)!=0)
-                            dValue *= tiny10pow[j];
-                    }
-                    /*
-                     * The reason for the weird exp > 1 condition
-                     * in the above loop was so that the last multiply
-                     * would get unrolled. We handle it here.
-                     * It could underflow.
-                     */
-                    double t = dValue * tiny10pow[j];
-                    if ( t == 0.0 ){
-                        /*
-                         * It did underflow.
-                         * Look more closely at the result.
-                         * If the exponent is just one too small,
-                         * then use the minimum finite as our estimate
-                         * value. Else call the result 0.0
-                         * and punt it.
-                         * ( I presume this could happen because
-                         * rounding forces the result here to be
-                         * an ULP or two less than
-                         * Double.MIN_VALUE ).
-                         */
-                        t = dValue * 2.0;
-                        t *= tiny10pow[j];
-                        if ( t == 0.0 ){
-                            return (isNegative)? -0.0 : 0.0;
-                        }
-                        t = Double.MIN_VALUE;
-                    }
-                    dValue = t;
-                }
-            }
-
-            /*
-             * dValue is now approximately the result.
-             * The hard part is adjusting it, by comparison
-             * with FDBigInt arithmetic.
-             * Formulate the EXACT big-number result as
-             * bigD0 * 10^exp
-             */
-            FDBigInt bigD0 = new FDBigInt( lValue, digits, kDigits, nDigits );
-            exp   = decExponent - nDigits;
-
-            correctionLoop:
-            while(true){
-                /* AS A SIDE EFFECT, THIS METHOD WILL SET THE INSTANCE VARIABLES
-                 * bigIntExp and bigIntNBits
-                 */
-                FDBigInt bigB = doubleToBigInt( dValue );
-
-                /*
-                 * Scale bigD, bigB appropriately for
-                 * big-integer operations.
-                 * Naively, we multipy by powers of ten
-                 * and powers of two. What we actually do
-                 * is keep track of the powers of 5 and
-                 * powers of 2 we would use, then factor out
-                 * common divisors before doing the work.
-                 */
-                int B2, B5; // powers of 2, 5 in bigB
-                int     D2, D5; // powers of 2, 5 in bigD
-                int Ulp2;   // powers of 2 in halfUlp.
-                if ( exp >= 0 ){
-                    B2 = B5 = 0;
-                    D2 = D5 = exp;
-                } else {
-                    B2 = B5 = -exp;
-                    D2 = D5 = 0;
-                }
-                if ( bigIntExp >= 0 ){
-                    B2 += bigIntExp;
-                } else {
-                    D2 -= bigIntExp;
-                }
-                Ulp2 = B2;
-                // shift bigB and bigD left by a number s. t.
-                // halfUlp is still an integer.
-                int hulpbias;
-                if ( bigIntExp+bigIntNBits <= -expBias+1 ){
-                    // This is going to be a denormalized number
-                    // (if not actually zero).
-                    // half an ULP is at 2^-(expBias+expShift+1)
-                    hulpbias = bigIntExp+ expBias + expShift;
-                } else {
-                    hulpbias = expShift + 2 - bigIntNBits;
-                }
-                B2 += hulpbias;
-                D2 += hulpbias;
-                // if there are common factors of 2, we might just as well
-                // factor them out, as they add nothing useful.
-                int common2 = Math.min( B2, Math.min( D2, Ulp2 ) );
-                B2 -= common2;
-                D2 -= common2;
-                Ulp2 -= common2;
-                // do multiplications by powers of 5 and 2
-                bigB = multPow52( bigB, B5, B2 );
-                FDBigInt bigD = multPow52( new FDBigInt( bigD0 ), D5, D2 );
-                //
-                // to recap:
-                // bigB is the scaled-big-int version of our floating-point
-                // candidate.
-                // bigD is the scaled-big-int version of the exact value
-                // as we understand it.
-                // halfUlp is 1/2 an ulp of bigB, except for special cases
-                // of exact powers of 2
-                //
-                // the plan is to compare bigB with bigD, and if the difference
-                // is less than halfUlp, then we're satisfied. Otherwise,
-                // use the ratio of difference to halfUlp to calculate a fudge
-                // factor to add to the floating value, then go 'round again.
-                //
-                FDBigInt diff;
-                int cmpResult;
-                boolean overvalue;
-                if ( (cmpResult = bigB.cmp( bigD ) ) > 0 ){
-                    overvalue = true; // our candidate is too big.
-                    diff = bigB.sub( bigD );
-                    if ( (bigIntNBits == 1) && (bigIntExp > -expBias) ){
-                        // candidate is a normalized exact power of 2 and
-                        // is too big. We will be subtracting.
-                        // For our purposes, ulp is the ulp of the
-                        // next smaller range.
-                        Ulp2 -= 1;
-                        if ( Ulp2 < 0 ){
-                            // rats. Cannot de-scale ulp this far.
-                            // must scale diff in other direction.
-                            Ulp2 = 0;
-                            diff.lshiftMe( 1 );
-                        }
-                    }
-                } else if ( cmpResult < 0 ){
-                    overvalue = false; // our candidate is too small.
-                    diff = bigD.sub( bigB );
-                } else {
-                    // the candidate is exactly right!
-                    // this happens with surprising fequency
-                    break correctionLoop;
-                }
-                FDBigInt halfUlp = constructPow52( B5, Ulp2 );
-                if ( (cmpResult = diff.cmp( halfUlp ) ) < 0 ){
-                    // difference is small.
-                    // this is close enough
-                    if (mustSetRoundDir) {
-                        roundDir = overvalue ? -1 : 1;
-                    }
-                    break correctionLoop;
-                } else if ( cmpResult == 0 ){
-                    // difference is exactly half an ULP
-                    // round to some other value maybe, then finish
-                    dValue += 0.5*ulp( dValue, overvalue );
-                    // should check for bigIntNBits == 1 here??
-                    if (mustSetRoundDir) {
-                        roundDir = overvalue ? -1 : 1;
-                    }
-                    break correctionLoop;
-                } else {
-                    // difference is non-trivial.
-                    // could scale addend by ratio of difference to
-                    // halfUlp here, if we bothered to compute that difference.
-                    // Most of the time ( I hope ) it is about 1 anyway.
-                    dValue += ulp( dValue, overvalue );
-                    if ( dValue == 0.0 || dValue == Double.POSITIVE_INFINITY )
-                        break correctionLoop; // oops. Fell off end of range.
-                    continue; // try again.
-                }
-
-            }
-            return (isNegative)? -dValue : dValue;
+    private void fillScientific(int precision, char[] digits, int nDigits, int exp, boolean isNegative) {
+        int startIndex = isNegative ? 1 : 0;
+        int t = Math.max(0, Math.min(nDigits - 1, precision));
+        if (t > 0) {
+            mantissa = create(isNegative, t + 2);
+            mantissa[startIndex] = digits[0];
+            mantissa[startIndex + 1] = '.';
+            System.arraycopy(digits, 1, mantissa, startIndex + 2, t);
+        } else {
+            mantissa = create(isNegative, 1);
+            mantissa[startIndex] = digits[0];
         }
-    }
-
-    /*
-     * Take a FormattedFloatingDecimal, which we presumably just scanned in,
-     * and find out what its value is, as a float.
-     * This is distinct from doubleValue() to avoid the extremely
-     * unlikely case of a double rounding error, wherein the converstion
-     * to double has one rounding error, and the conversion of that double
-     * to a float has another rounding error, IN THE WRONG DIRECTION,
-     * ( because of the preference to a zero low-order bit ).
-     */
-
-    public strictfp float floatValue(){
-        int     kDigits = Math.min( nDigits, singleMaxDecimalDigits+1 );
-        int     iValue;
-        float   fValue;
-
-        // First, check for NaN and Infinity values
-        if(digits == infinity || digits == notANumber) {
-            if(digits == notANumber)
-                return Float.NaN;
-            else
-                return (isNegative?Float.NEGATIVE_INFINITY:Float.POSITIVE_INFINITY);
+        char expSign;
+        int e;
+        if (exp <= 0) {
+            expSign = '-';
+            e = -exp + 1;
+        } else {
+            expSign = '+' ;
+            e = exp - 1;
         }
-        else {
-            /*
-             * convert the lead kDigits to an integer.
-             */
-            iValue = (int)digits[0]-(int)'0';
-            for ( int i=1; i < kDigits; i++ ){
-                iValue = iValue*10 + (int)digits[i]-(int)'0';
-            }
-            fValue = (float)iValue;
-            int exp = decExponent-kDigits;
-            /*
-             * iValue now contains an integer with the value of
-             * the first kDigits digits of the number.
-             * fValue contains the (float) of the same.
-             */
-
-            if ( nDigits <= singleMaxDecimalDigits ){
-                /*
-                 * possibly an easy case.
-                 * We know that the digits can be represented
-                 * exactly. And if the exponent isn't too outrageous,
-                 * the whole thing can be done with one operation,
-                 * thus one rounding error.
-                 * Note that all our constructors trim all leading and
-                 * trailing zeros, so simple values (including zero)
-                 * will always end up here.
-                 */
-                if (exp == 0 || fValue == 0.0f)
-                    return (isNegative)? -fValue : fValue; // small floating integer
-                else if ( exp >= 0 ){
-                    if ( exp <= singleMaxSmallTen ){
-                        /*
-                         * Can get the answer with one operation,
-                         * thus one roundoff.
-                         */
-                        fValue *= singleSmall10pow[exp];
-                        return (isNegative)? -fValue : fValue;
-                    }
-                    int slop = singleMaxDecimalDigits - kDigits;
-                    if ( exp <= singleMaxSmallTen+slop ){
-                        /*
-                         * We can multiply dValue by 10^(slop)
-                         * and it is still "small" and exact.
-                         * Then we can multiply by 10^(exp-slop)
-                         * with one rounding.
-                         */
-                        fValue *= singleSmall10pow[slop];
-                        fValue *= singleSmall10pow[exp-slop];
-                        return (isNegative)? -fValue : fValue;
-                    }
-                    /*
-                     * Else we have a hard case with a positive exp.
-                     */
-                } else {
-                    if ( exp >= -singleMaxSmallTen ){
-                        /*
-                         * Can get the answer in one division.
-                         */
-                        fValue /= singleSmall10pow[-exp];
-                        return (isNegative)? -fValue : fValue;
-                    }
-                    /*
-                     * Else we have a hard case with a negative exp.
-                     */
-                }
-            } else if ( (decExponent >= nDigits) && (nDigits+decExponent <= maxDecimalDigits) ){
-                /*
-                 * In double-precision, this is an exact floating integer.
-                 * So we can compute to double, then shorten to float
-                 * with one round, and get the right answer.
-                 *
-                 * First, finish accumulating digits.
-                 * Then convert that integer to a double, multiply
-                 * by the appropriate power of ten, and convert to float.
-                 */
-                long lValue = (long)iValue;
-                for ( int i=kDigits; i < nDigits; i++ ){
-                    lValue = lValue*10L + (long)((int)digits[i]-(int)'0');
-                }
-                double dValue = (double)lValue;
-                exp = decExponent-nDigits;
-                dValue *= small10pow[exp];
-                fValue = (float)dValue;
-                return (isNegative)? -fValue : fValue;
-
-            }
-            /*
-             * Harder cases:
-             * The sum of digits plus exponent is greater than
-             * what we think we can do with one error.
-             *
-             * Start by weeding out obviously out-of-range
-             * results, then convert to double and go to
-             * common hard-case code.
-             */
-            if ( decExponent > singleMaxDecimalExponent+1 ){
-                /*
-                 * Lets face it. This is going to be
-                 * Infinity. Cut to the chase.
-                 */
-                return (isNegative)? Float.NEGATIVE_INFINITY : Float.POSITIVE_INFINITY;
-            } else if ( decExponent < singleMinDecimalExponent-1 ){
-                /*
-                 * Lets face it. This is going to be
-                 * zero. Cut to the chase.
-                 */
-                return (isNegative)? -0.0f : 0.0f;
-            }
-
-            /*
-             * Here, we do 'way too much work, but throwing away
-             * our partial results, and going and doing the whole
-             * thing as double, then throwing away half the bits that computes
-             * when we convert back to float.
-             *
-             * The alternative is to reproduce the whole multiple-precision
-             * algorythm for float precision, or to try to parameterize it
-             * for common usage. The former will take about 400 lines of code,
-             * and the latter I tried without success. Thus the semi-hack
-             * answer here.
-             */
-            mustSetRoundDir = !fromHex;
-            double dValue = doubleValue();
-            return stickyRound( dValue );
+        // decExponent has 1, 2, or 3, digits
+        if (e <= 9) {
+            exponent = new char[] { expSign,
+                    '0', (char) (e + '0') };
+        } else if (e <= 99) {
+            exponent = new char[] { expSign,
+                    (char) (e / 10 + '0'), (char) (e % 10 + '0') };
+        } else {
+            char hiExpChar = (char) (e / 100 + '0');
+            e %= 100;
+            exponent = new char[] { expSign,
+                    hiExpChar, (char) (e / 10 + '0'), (char) (e % 10 + '0') };
         }
     }
-
-
-    /*
-     * All the positive powers of 10 that can be
-     * represented exactly in double/float.
-     */
-    private static final double small10pow[] = {
-        1.0e0,
-        1.0e1, 1.0e2, 1.0e3, 1.0e4, 1.0e5,
-        1.0e6, 1.0e7, 1.0e8, 1.0e9, 1.0e10,
-        1.0e11, 1.0e12, 1.0e13, 1.0e14, 1.0e15,
-        1.0e16, 1.0e17, 1.0e18, 1.0e19, 1.0e20,
-        1.0e21, 1.0e22
-    };
-
-    private static final float singleSmall10pow[] = {
-        1.0e0f,
-        1.0e1f, 1.0e2f, 1.0e3f, 1.0e4f, 1.0e5f,
-        1.0e6f, 1.0e7f, 1.0e8f, 1.0e9f, 1.0e10f
-    };
-
-    private static final double big10pow[] = {
-        1e16, 1e32, 1e64, 1e128, 1e256 };
-    private static final double tiny10pow[] = {
-        1e-16, 1e-32, 1e-64, 1e-128, 1e-256 };
-
-    private static final int maxSmallTen = small10pow.length-1;
-    private static final int singleMaxSmallTen = singleSmall10pow.length-1;
-
-    private static final int small5pow[] = {
-        1,
-        5,
-        5*5,
-        5*5*5,
-        5*5*5*5,
-        5*5*5*5*5,
-        5*5*5*5*5*5,
-        5*5*5*5*5*5*5,
-        5*5*5*5*5*5*5*5,
-        5*5*5*5*5*5*5*5*5,
-        5*5*5*5*5*5*5*5*5*5,
-        5*5*5*5*5*5*5*5*5*5*5,
-        5*5*5*5*5*5*5*5*5*5*5*5,
-        5*5*5*5*5*5*5*5*5*5*5*5*5
-    };
-
-
-    private static final long long5pow[] = {
-        1L,
-        5L,
-        5L*5,
-        5L*5*5,
-        5L*5*5*5,
-        5L*5*5*5*5,
-        5L*5*5*5*5*5,
-        5L*5*5*5*5*5*5,
-        5L*5*5*5*5*5*5*5,
-        5L*5*5*5*5*5*5*5*5,
-        5L*5*5*5*5*5*5*5*5*5,
-        5L*5*5*5*5*5*5*5*5*5*5,
-        5L*5*5*5*5*5*5*5*5*5*5*5,
-        5L*5*5*5*5*5*5*5*5*5*5*5*5,
-        5L*5*5*5*5*5*5*5*5*5*5*5*5*5,
-        5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
-        5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
-        5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
-        5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
-        5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
-        5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
-        5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
-        5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
-        5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
-        5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
-        5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
-        5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5,
-    };
-
-    // approximately ceil( log2( long5pow[i] ) )
-    private static final int n5bits[] = {
-        0,
-        3,
-        5,
-        7,
-        10,
-        12,
-        14,
-        17,
-        19,
-        21,
-        24,
-        26,
-        28,
-        31,
-        33,
-        35,
-        38,
-        40,
-        42,
-        45,
-        47,
-        49,
-        52,
-        54,
-        56,
-        59,
-        61,
-    };
-
-    private static final char infinity[] = { 'I', 'n', 'f', 'i', 'n', 'i', 't', 'y' };
-    private static final char notANumber[] = { 'N', 'a', 'N' };
-    private static final char zero[] = { '0', '0', '0', '0', '0', '0', '0', '0' };
 }
--- /dev/null	2013-06-07 13:08:34.000000000 -0700
+++ new/src/share/classes/sun/misc/FDBigInteger.java	2013-06-07 13:08:34.000000000 -0700
@@ -0,0 +1,1508 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package sun.misc;
+
+import java.math.BigInteger;
+import java.util.Arrays;
+//@ model import org.jmlspecs.models.JMLMath;
+
+/**
+ * A simple big integer package specifically for floating point base conversion.
+ */
+public /*@ spec_bigint_math @*/ class FDBigInteger {
+
+    //
+    // This class contains many comments that start with "/*@" mark.
+    // They are behavourial specification in
+    // the Java Modelling Language (JML):
+    // http://www.eecs.ucf.edu/~leavens/JML//index.shtml
+    //
+
+    /*@
+    @ public pure model static \bigint UNSIGNED(int v) {
+    @     return v >= 0 ? v : v + (((\bigint)1) << 32);
+    @ }
+    @
+    @ public pure model static \bigint UNSIGNED(long v) {
+    @     return v >= 0 ? v : v + (((\bigint)1) << 64);
+    @ }
+    @
+    @ public pure model static \bigint AP(int[] data, int len) {
+    @     return (\sum int i; 0 <= 0 && i < len; UNSIGNED(data[i]) << (i*32));
+    @ }
+    @
+    @ public pure model static \bigint pow52(int p5, int p2) {
+    @     ghost \bigint v = 1;
+    @     for (int i = 0; i < p5; i++) v *= 5;
+    @     return v << p2;
+    @ }
+    @
+    @ public pure model static \bigint pow10(int p10) {
+    @     return pow52(p10, p10);
+    @ }
+    @*/
+
+    static final int[] SMALL_5_POW = {
+            1,
+            5,
+            5 * 5,
+            5 * 5 * 5,
+            5 * 5 * 5 * 5,
+            5 * 5 * 5 * 5 * 5,
+            5 * 5 * 5 * 5 * 5 * 5,
+            5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5
+    };
+
+    static final long[] LONG_5_POW = {
+            1L,
+            5L,
+            5L * 5,
+            5L * 5 * 5,
+            5L * 5 * 5 * 5,
+            5L * 5 * 5 * 5 * 5,
+            5L * 5 * 5 * 5 * 5 * 5,
+            5L * 5 * 5 * 5 * 5 * 5 * 5,
+            5L * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+            5L * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5 * 5,
+    };
+
+    // Maximum size of cache of powers of 5 as FDBigIntegers.
+    private static final int MAX_FIVE_POW = 340;
+
+    // Cache of big powers of 5 as FDBigIntegers.
+    private static final FDBigInteger POW_5_CACHE[];
+
+    // Initialize FDBigInteger cache of powers of 5.
+    static {
+        POW_5_CACHE = new FDBigInteger[MAX_FIVE_POW];
+        int i = 0;
+        while (i < SMALL_5_POW.length) {
+            FDBigInteger pow5 = new FDBigInteger(new int[]{SMALL_5_POW[i]}, 0);
+            pow5.makeImmutable();
+            POW_5_CACHE[i] = pow5;
+            i++;
+        }
+        FDBigInteger prev = POW_5_CACHE[i - 1];
+        while (i < MAX_FIVE_POW) {
+            POW_5_CACHE[i] = prev = prev.mult(5);
+            prev.makeImmutable();
+            i++;
+        }
+    }
+
+    // Zero as an FDBigInteger.
+    public static final FDBigInteger ZERO = new FDBigInteger(new int[0], 0);
+
+    // Ensure ZERO is immutable.
+    static {
+        ZERO.makeImmutable();
+    }
+
+    // Constant for casting an int to a long via bitwise AND.
+    private final static long LONG_MASK = 0xffffffffL;
+
+    //@ spec_public non_null;
+    private int data[];  // value: data[0] is least significant
+    //@ spec_public;
+    private int offset;  // number of least significant zero padding ints
+    //@ spec_public;
+    private int nWords;  // data[nWords-1]!=0, all values above are zero
+                 // if nWords==0 -> this FDBigInteger is zero
+    //@ spec_public;
+    private boolean isImmutable = false;
+
+    /*@
+     @ public invariant 0 <= nWords && nWords <= data.length && offset >= 0;
+     @ public invariant nWords == 0 ==> offset == 0;
+     @ public invariant nWords > 0 ==> data[nWords - 1] != 0;
+     @ public invariant (\forall int i; nWords <= i && i < data.length; data[i] == 0);
+     @ public pure model \bigint value() {
+     @     return AP(data, nWords) << (offset*32);
+     @ }
+     @*/
+
+    /**
+     * Constructs an FDBigInteger from data and padding. The
+     * data parameter has the least significant int at
+     * the zeroth index. The offset parameter gives the number of
+     * zero ints to be inferred below the least significant element
+     * of data.
+     *
+     * @param data An array containing all non-zero ints of the value.
+     * @param offset An offset indicating the number of zero ints to pad
+     * below the least significant element of data.
+     */
+    /*@
+     @ requires data != null && offset >= 0;
+     @ ensures this.value() == \old(AP(data, data.length) << (offset*32));
+     @ ensures this.data == \old(data);
+     @*/
+    private FDBigInteger(int[] data, int offset) {
+        this.data = data;
+        this.offset = offset;
+        this.nWords = data.length;
+        trimLeadingZeros();
+    }
+
+    /**
+     * Constructs an FDBigInteger from a starting value and some
+     * decimal digits.
+     *
+     * @param lValue The starting value.
+     * @param digits The decimal digits.
+     * @param kDigits The initial index into digits.
+     * @param nDigits The final index into digits.
+     */
+    /*@
+     @ requires digits != null;
+     @ requires 0 <= kDigits && kDigits <= nDigits && nDigits <= digits.length;
+     @ requires (\forall int i; 0 <= i && i < nDigits; '0' <= digits[i] && digits[i] <= '9');
+     @ ensures this.value() == \old(lValue * pow10(nDigits - kDigits) + (\sum int i; kDigits <= i && i < nDigits; (digits[i] - '0') * pow10(nDigits - i - 1)));
+     @*/
+    public FDBigInteger(long lValue, char[] digits, int kDigits, int nDigits) {
+        int n = Math.max((nDigits + 8) / 9, 2);        // estimate size needed.
+        data = new int[n];      // allocate enough space
+        data[0] = (int) lValue;    // starting value
+        data[1] = (int) (lValue >>> 32);
+        offset = 0;
+        nWords = 2;
+        int i = kDigits;
+        int limit = nDigits - 5;       // slurp digits 5 at a time.
+        int v;
+        while (i < limit) {
+            int ilim = i + 5;
+            v = (int) digits[i++] - (int) '0';
+            while (i < ilim) {
+                v = 10 * v + (int) digits[i++] - (int) '0';
+            }
+            multAddMe(100000, v); // ... where 100000 is 10^5.
+        }
+        int factor = 1;
+        v = 0;
+        while (i < nDigits) {
+            v = 10 * v + (int) digits[i++] - (int) '0';
+            factor *= 10;
+        }
+        if (factor != 1) {
+            multAddMe(factor, v);
+        }
+        trimLeadingZeros();
+    }
+
+    /**
+     * Returns an FDBigInteger with the numerical value
+     * 5p5 * 2p2.
+     *
+     * @param p5 The exponent of the power-of-five factor.
+     * @param p2 The exponent of the power-of-two factor.
+     * @return 5p5 * 2p2
+     */
+    /*@
+     @ requires p5 >= 0 && p2 >= 0;
+     @ assignable \nothing;
+     @ ensures \result.value() == \old(pow52(p5, p2));
+     @*/
+    public static FDBigInteger valueOfPow52(int p5, int p2) {
+        if (p5 != 0) {
+            if (p2 == 0) {
+                return big5pow(p5);
+            } else if (p5 < SMALL_5_POW.length) {
+                int pow5 = SMALL_5_POW[p5];
+                int wordcount = p2 >> 5;
+                int bitcount = p2 & 0x1f;
+                if (bitcount == 0) {
+                    return new FDBigInteger(new int[]{pow5}, wordcount);
+                } else {
+                    return new FDBigInteger(new int[]{
+                            pow5 << bitcount,
+                            pow5 >>> (32 - bitcount)
+                    }, wordcount);
+                }
+            } else {
+                return big5pow(p5).leftShift(p2);
+            }
+        } else {
+            return valueOfPow2(p2);
+        }
+    }
+
+    /**
+     * Returns an FDBigInteger with the numerical value
+     * value * 5p5 * 2p2.
+     *
+     * @param value The constant factor.
+     * @param p5 The exponent of the power-of-five factor.
+     * @param p2 The exponent of the power-of-two factor.
+     * @return value * 5p5 * 2p2
+     */
+    /*@
+     @ requires p5 >= 0 && p2 >= 0;
+     @ assignable \nothing;
+     @ ensures \result.value() == \old(UNSIGNED(value) * pow52(p5, p2));
+     @*/
+    public static FDBigInteger valueOfMulPow52(long value, int p5, int p2) {
+        assert p5 >= 0 : p5;
+        assert p2 >= 0 : p2;
+        int v0 = (int) value;
+        int v1 = (int) (value >>> 32);
+        int wordcount = p2 >> 5;
+        int bitcount = p2 & 0x1f;
+        if (p5 != 0) {
+            if (p5 < SMALL_5_POW.length) {
+                long pow5 = SMALL_5_POW[p5] & LONG_MASK;
+                long carry = (v0 & LONG_MASK) * pow5;
+                v0 = (int) carry;
+                carry >>>= 32;
+                carry = (v1 & LONG_MASK) * pow5 + carry;
+                v1 = (int) carry;
+                int v2 = (int) (carry >>> 32);
+                if (bitcount == 0) {
+                    return new FDBigInteger(new int[]{v0, v1, v2}, wordcount);
+                } else {
+                    return new FDBigInteger(new int[]{
+                            v0 << bitcount,
+                            (v1 << bitcount) | (v0 >>> (32 - bitcount)),
+                            (v2 << bitcount) | (v1 >>> (32 - bitcount)),
+                            v2 >>> (32 - bitcount)
+                    }, wordcount);
+                }
+            } else {
+                FDBigInteger pow5 = big5pow(p5);
+                int[] r;
+                if (v1 == 0) {
+                    r = new int[pow5.nWords + 1 + ((p2 != 0) ? 1 : 0)];
+                    mult(pow5.data, pow5.nWords, v0, r);
+                } else {
+                    r = new int[pow5.nWords + 2 + ((p2 != 0) ? 1 : 0)];
+                    mult(pow5.data, pow5.nWords, v0, v1, r);
+                }
+                return (new FDBigInteger(r, pow5.offset)).leftShift(p2);
+            }
+        } else if (p2 != 0) {
+            if (bitcount == 0) {
+                return new FDBigInteger(new int[]{v0, v1}, wordcount);
+            } else {
+                return new FDBigInteger(new int[]{
+                         v0 << bitcount,
+                        (v1 << bitcount) | (v0 >>> (32 - bitcount)),
+                        v1 >>> (32 - bitcount)
+                }, wordcount);
+            }
+        }
+        return new FDBigInteger(new int[]{v0, v1}, 0);
+    }
+
+    /**
+     * Returns an FDBigInteger with the numerical value
+     * 2p2.
+     *
+     * @param p2 The exponent of 2.
+     * @return 2p2
+     */
+    /*@
+     @ requires p2 >= 0;
+     @ assignable \nothing;
+     @ ensures \result.value() == pow52(0, p2);
+     @*/
+    private static FDBigInteger valueOfPow2(int p2) {
+        int wordcount = p2 >> 5;
+        int bitcount = p2 & 0x1f;
+        return new FDBigInteger(new int[]{1 << bitcount}, wordcount);
+    }
+
+    /**
+     * Removes all leading zeros from this FDBigInteger adjusting
+     * the offset and number of non-zero leading words accordingly.
+     */
+    /*@
+     @ requires data != null;
+     @ requires 0 <= nWords && nWords <= data.length && offset >= 0;
+     @ requires nWords == 0 ==> offset == 0;
+     @ ensures nWords == 0 ==> offset == 0;
+     @ ensures nWords > 0 ==> data[nWords - 1] != 0;
+     @*/
+    private /*@ helper @*/ void trimLeadingZeros() {
+        int i = nWords;
+        if (i > 0 && (data[--i] == 0)) {
+            //for (; i > 0 && data[i - 1] == 0; i--) ;
+            while(i > 0 && data[i - 1] == 0) {
+                i--;
+            }
+            this.nWords = i;
+            if (i == 0) { // all words are zero
+                this.offset = 0;
+            }
+        }
+    }
+
+    /**
+     * Retrieves the normalization bias of the FDBigIntger. The
+     * normalization bias is a left shift such that after it the highest word
+     * of the value will have the 4 highest bits equal to zero:
+     * (highestWord & 0xf0000000) == 0, but the next bit should be 1
+     * (highestWord & 0x08000000) != 0.
+     *
+     * @return The normalization bias.
+     */
+    /*@
+     @ requires this.value() > 0;
+     @*/
+    public /*@ pure @*/ int getNormalizationBias() {
+        if (nWords == 0) {
+            throw new IllegalArgumentException("Zero value cannot be normalized");
+        }
+        int zeros = Integer.numberOfLeadingZeros(data[nWords - 1]);
+        return (zeros < 4) ? 28 + zeros : zeros - 4;
+    }
+
+    // TODO: Why is anticount param needed if it is always 32 - bitcount?
+    /**
+     * Left shifts the contents of one int array into another.
+     *
+     * @param src The source array.
+     * @param idx The initial index of the source array.
+     * @param result The destination array.
+     * @param bitcount The left shift.
+     * @param anticount The left anti-shift, e.g., 32-bitcount.
+     * @param prev The prior source value.
+     */
+    /*@
+     @ requires 0 < bitcount && bitcount < 32 && anticount == 32 - bitcount;
+     @ requires src.length >= idx && result.length > idx;
+     @ assignable result[*];
+     @ ensures AP(result, \old(idx + 1)) == \old((AP(src, idx) + UNSIGNED(prev) << (idx*32)) << bitcount);
+     @*/
+    private static void leftShift(int[] src, int idx, int result[], int bitcount, int anticount, int prev){
+        for (; idx > 0; idx--) {
+            int v = (prev << bitcount);
+            prev = src[idx - 1];
+            v |= (prev >>> anticount);
+            result[idx] = v;
+        }
+        int v = prev << bitcount;
+        result[0] = v;
+    }
+
+    /**
+     * Shifts this FDBigInteger to the left. The shift is performed
+     * in-place unless the FDBigInteger is immutable in which case
+     * a new instance of FDBigInteger is returned.
+     *
+     * @param shift The number of bits to shift left.
+     * @return The shifted FDBigInteger.
+     */
+    /*@
+     @ requires this.value() == 0 || shift == 0;
+     @ assignable \nothing;
+     @ ensures \result == this;
+     @
+     @  also
+     @
+     @ requires this.value() > 0 && shift > 0 && this.isImmutable;
+     @ assignable \nothing;
+     @ ensures \result.value() == \old(this.value() << shift);
+     @
+     @  also
+     @
+     @ requires this.value() > 0 && shift > 0 && this.isImmutable;
+     @ assignable \nothing;
+     @ ensures \result == this;
+     @ ensures \result.value() == \old(this.value() << shift);
+     @*/
+    public FDBigInteger leftShift(int shift) {
+        if (shift == 0 || nWords == 0) {
+            return this;
+        }
+        int wordcount = shift >> 5;
+        int bitcount = shift & 0x1f;
+        if (this.isImmutable) {
+            if (bitcount == 0) {
+                return new FDBigInteger(Arrays.copyOf(data, nWords), offset + wordcount);
+            } else {
+                int anticount = 32 - bitcount;
+                int idx = nWords - 1;
+                int prev = data[idx];
+                int hi = prev >>> anticount;
+                int[] result;
+                if (hi != 0) {
+                    result = new int[nWords + 1];
+                    result[nWords] = hi;
+                } else {
+                    result = new int[nWords];
+                }
+                leftShift(data,idx,result,bitcount,anticount,prev);
+                return new FDBigInteger(result, offset + wordcount);
+            }
+        } else {
+            if (bitcount != 0) {
+                int anticount = 32 - bitcount;
+                if ((data[0] << bitcount) == 0) {
+                    int idx = 0;
+                    int prev = data[idx];
+                    for (; idx < nWords - 1; idx++) {
+                        int v = (prev >>> anticount);
+                        prev = data[idx + 1];
+                        v |= (prev << bitcount);
+                        data[idx] = v;
+                    }
+                    int v = prev >>> anticount;
+                    data[idx] = v;
+                    if(v==0) {
+                        nWords--;
+                    }
+                    offset++;
+                } else {
+                    int idx = nWords - 1;
+                    int prev = data[idx];
+                    int hi = prev >>> anticount;
+                    int[] result = data;
+                    int[] src = data;
+                    if (hi != 0) {
+                        if(nWords == data.length) {
+                            data = result = new int[nWords + 1];
+                        }
+                        result[nWords++] = hi;
+                    }
+                    leftShift(src,idx,result,bitcount,anticount,prev);
+                }
+            }
+            offset += wordcount;
+            return this;
+        }
+    }
+
+    /**
+     * Returns the number of ints this FDBigInteger represents.
+     *
+     * @return Number of ints required to represent this FDBigInteger.
+     */
+    /*@
+     @ requires this.value() == 0;
+     @ ensures \result == 0;
+     @
+     @  also
+     @
+     @ requires this.value() > 0;
+     @ ensures ((\bigint)1) << (\result - 1) <= this.value() && this.value() <= ((\bigint)1) << \result;
+     @*/
+    private /*@ pure @*/ int size() {
+        return nWords + offset;
+    }
+
+
+    /**
+     * Computes
+     * 
+     * q = (int)( this / S )
+     * this = 10 * ( this mod S )
+     * Return q.
+     * 
+ * This is the iteration step of digit development for output. + * We assume that S has been normalized, as above, and that + * "this" has been left-shifted accordingly. + * Also assumed, of course, is that the result, q, can be expressed + * as an integer, 0 <= q < 10. + * + * @param The divisor of this FDBigInteger. + * @return q = (int)(this / S). + */ + /*@ + @ requires !this.isImmutable; + @ requires this.size() <= S.size(); + @ requires this.data.length + this.offset >= S.size(); + @ requires S.value() >= ((\bigint)1) << (S.size()*32 - 4); + @ assignable this.nWords, this.offset, this.data, this.data[*]; + @ ensures \result == \old(this.value() / S.value()); + @ ensures this.value() == \old(10 * (this.value() % S.value())); + @*/ + public int quoRemIteration(FDBigInteger S) throws IllegalArgumentException { + assert !this.isImmutable : "cannot modify immutable value"; + // ensure that this and S have the same number of + // digits. If S is properly normalized and q < 10 then + // this must be so. + int thSize = this.size(); + int sSize = S.size(); + if (thSize < sSize) { + // this value is significantly less than S, result of division is zero. + // just mult this by 10. + int p = multAndCarryBy10(this.data, this.nWords, this.data); + if(p!=0) { + this.data[nWords++] = p; + } else { + trimLeadingZeros(); + } + return 0; + } else if (thSize > sSize) { + throw new IllegalArgumentException("disparate values"); + } + // estimate q the obvious way. We will usually be + // right. If not, then we're only off by a little and + // will re-add. + long q = (this.data[this.nWords - 1] & LONG_MASK) / (S.data[S.nWords - 1] & LONG_MASK); + long diff = multDiffMe(q, S); + if (diff != 0L) { + //@ assert q != 0; + //@ assert this.offset == \old(Math.min(this.offset, S.offset)); + //@ assert this.offset <= S.offset; + + // q is too big. + // add S back in until this turns +. This should + // not be very many times! + long sum = 0L; + int tStart = S.offset - this.offset; + //@ assert tStart >= 0; + int[] sd = S.data; + int[] td = this.data; + while (sum == 0L) { + for (int sIndex = 0, tIndex = tStart; tIndex < this.nWords; sIndex++, tIndex++) { + sum += (td[tIndex] & LONG_MASK) + (sd[sIndex] & LONG_MASK); + td[tIndex] = (int) sum; + sum >>>= 32; // Signed or unsigned, answer is 0 or 1 + } + // + // Originally the following line read + // "if ( sum !=0 && sum != -1 )" + // but that would be wrong, because of the + // treatment of the two values as entirely unsigned, + // it would be impossible for a carry-out to be interpreted + // as -1 -- it would have to be a single-bit carry-out, or +1. + // + assert sum == 0 || sum == 1 : sum; // carry out of division correction + q -= 1; + } + } + // finally, we can multiply this by 10. + // it cannot overflow, right, as the high-order word has + // at least 4 high-order zeros! + int p = multAndCarryBy10(this.data, this.nWords, this.data); + assert p == 0 : p; // Carry out of *10 + trimLeadingZeros(); + return (int) q; + } + + /** + * Multiplies this FDBigInteger by 10. The operation will be + * performed in place unless the FDBigInteger is immutable in + * which case a new FDBigInteger will be returned. + * + * @return The FDBigInteger multiplied by 10. + */ + /*@ + @ requires this.value() == 0; + @ assignable \nothing; + @ ensures \result == this; + @ + @ also + @ + @ requires this.value() > 0 && this.isImmutable; + @ assignable \nothing; + @ ensures \result.value() == \old(this.value() * 10); + @ + @ also + @ + @ requires this.value() > 0 && !this.isImmutable; + @ assignable this.nWords, this.data, this.data[*]; + @ ensures \result == this; + @ ensures \result.value() == \old(this.value() * 10); + @*/ + public FDBigInteger multBy10() { + if (nWords == 0) { + return this; + } + if (isImmutable) { + int[] res = new int[nWords + 1]; + res[nWords] = multAndCarryBy10(data, nWords, res); + return new FDBigInteger(res, offset); + } else { + int p = multAndCarryBy10(this.data, this.nWords, this.data); + if (p != 0) { + if (nWords == data.length) { + if (data[0] == 0) { + System.arraycopy(data, 1, data, 0, --nWords); + offset++; + } else { + data = Arrays.copyOf(data, data.length + 1); + } + } + data[nWords++] = p; + } else { + trimLeadingZeros(); + } + return this; + } + } + + /** + * Multiplies this FDBigInteger by + * 5p5 * 2p2. The operation will be + * performed in place if possible, otherwise a new FDBigInteger + * will be returned. + * + * @param p5 The exponent of the power-of-five factor. + * @param p2 The exponent of the power-of-two factor. + * @return + */ + /*@ + @ requires this.value() == 0 || p5 == 0 && p2 == 0; + @ assignable \nothing; + @ ensures \result == this; + @ + @ also + @ + @ requires this.value() > 0 && (p5 > 0 && p2 >= 0 || p5 == 0 && p2 > 0 && this.isImmutable); + @ assignable \nothing; + @ ensures \result.value() == \old(this.value() * pow52(p5, p2)); + @ + @ also + @ + @ requires this.value() > 0 && p5 == 0 && p2 > 0 && !this.isImmutable; + @ assignable this.nWords, this.data, this.data[*]; + @ ensures \result == this; + @ ensures \result.value() == \old(this.value() * pow52(p5, p2)); + @*/ + public FDBigInteger multByPow52(int p5, int p2) { + if (this.nWords == 0) { + return this; + } + FDBigInteger res = this; + if (p5 != 0) { + int[] r; + int extraSize = (p2 != 0) ? 1 : 0; + if (p5 < SMALL_5_POW.length) { + r = new int[this.nWords + 1 + extraSize]; + mult(this.data, this.nWords, SMALL_5_POW[p5], r); + res = new FDBigInteger(r, this.offset); + } else { + FDBigInteger pow5 = big5pow(p5); + r = new int[this.nWords + pow5.size() + extraSize]; + mult(this.data, this.nWords, pow5.data, pow5.nWords, r); + res = new FDBigInteger(r, this.offset + pow5.offset); + } + } + return res.leftShift(p2); + } + + /** + * Multiplies two big integers represented as int arrays. + * + * @param s1 The first array factor. + * @param s1Len The number of elements of s1 to use. + * @param s2 The second array factor. + * @param s2Len The number of elements of s2 to use. + * @param dst The product array. + */ + /*@ + @ requires s1 != dst && s2 != dst; + @ requires s1.length >= s1Len && s2.length >= s2Len && dst.length >= s1Len + s2Len; + @ assignable dst[0 .. s1Len + s2Len - 1]; + @ ensures AP(dst, s1Len + s2Len) == \old(AP(s1, s1Len) * AP(s2, s2Len)); + @*/ + private static void mult(int[] s1, int s1Len, int[] s2, int s2Len, int[] dst) { + for (int i = 0; i < s1Len; i++) { + long v = s1[i] & LONG_MASK; + long p = 0L; + for (int j = 0; j < s2Len; j++) { + p += (dst[i + j] & LONG_MASK) + v * (s2[j] & LONG_MASK); + dst[i + j] = (int) p; + p >>>= 32; + } + dst[i + s2Len] = (int) p; + } + } + + /** + * Subtracts the supplied FDBigInteger subtrahend from this + * FDBigInteger. Assert that the result is positive. + * If the subtrahend is immutable, store the result in this(minuend). + * If this(minuend) is immutable a new FDBigInteger is created. + * + * @param subtrahend The FDBigInteger to be subtracted. + * @return This FDBigInteger less the subtrahend. + */ + /*@ + @ requires this.isImmutable; + @ requires this.value() >= subtrahend.value(); + @ assignable \nothing; + @ ensures \result.value() == \old(this.value() - subtrahend.value()); + @ + @ also + @ + @ requires !subtrahend.isImmutable; + @ requires this.value() >= subtrahend.value(); + @ assignable this.nWords, this.offset, this.data, this.data[*]; + @ ensures \result == this; + @ ensures \result.value() == \old(this.value() - subtrahend.value()); + @*/ + public FDBigInteger leftInplaceSub(FDBigInteger subtrahend) { + assert this.size() >= subtrahend.size() : "result should be positive"; + FDBigInteger minuend; + if (this.isImmutable) { + minuend = new FDBigInteger(this.data, this.offset); + } else { + minuend = this; + } + int offsetDiff = subtrahend.offset - minuend.offset; + int[] sData = subtrahend.data; + int[] mData = minuend.data; + int subLen = subtrahend.nWords; + int minLen = minuend.nWords; + if (offsetDiff < 0) { + // need to expand minuend + int rLen = minLen - offsetDiff; + if (rLen < mData.length) { + System.arraycopy(mData, 0, mData, -offsetDiff, minLen); + Arrays.fill(mData, 0, -offsetDiff, 0); + } else { + int[] r = new int[rLen]; + System.arraycopy(mData, 0, r, -offsetDiff, minLen); + minuend.data = mData = r; + } + minuend.offset = subtrahend.offset; + minuend.nWords = minLen = rLen; + offsetDiff = 0; + } + long borrow = 0L; + int mIndex = offsetDiff; + for (int sIndex = 0; sIndex < subLen && mIndex < minLen; sIndex++, mIndex++) { + long diff = (mData[mIndex] & LONG_MASK) - (sData[sIndex] & LONG_MASK) + borrow; + mData[mIndex] = (int) diff; + borrow = diff >> 32; // signed shift + } + for (; borrow != 0 && mIndex < minLen; mIndex++) { + long diff = (mData[mIndex] & LONG_MASK) + borrow; + mData[mIndex] = (int) diff; + borrow = diff >> 32; // signed shift + } + assert borrow == 0L : borrow; // borrow out of subtract, + // result should be positive + minuend.trimLeadingZeros(); + return minuend; + } + + /** + * Subtracts the supplied FDBigInteger subtrahend from this + * FDBigInteger. Assert that the result is positive. + * If the this(minuend) is immutable, store the result in subtrahend. + * If subtrahend is immutable a new FDBigInteger is created. + * + * @param subtrahend The FDBigInteger to be subtracted. + * @return This FDBigInteger less the subtrahend. + */ + /*@ + @ requires subtrahend.isImmutable; + @ requires this.value() >= subtrahend.value(); + @ assignable \nothing; + @ ensures \result.value() == \old(this.value() - subtrahend.value()); + @ + @ also + @ + @ requires !subtrahend.isImmutable; + @ requires this.value() >= subtrahend.value(); + @ assignable subtrahend.nWords, subtrahend.offset, subtrahend.data, subtrahend.data[*]; + @ ensures \result == subtrahend; + @ ensures \result.value() == \old(this.value() - subtrahend.value()); + @*/ + public FDBigInteger rightInplaceSub(FDBigInteger subtrahend) { + assert this.size() >= subtrahend.size() : "result should be positive"; + FDBigInteger minuend = this; + if (subtrahend.isImmutable) { + subtrahend = new FDBigInteger(subtrahend.data, subtrahend.offset); + } + int offsetDiff = minuend.offset - subtrahend.offset; + int[] sData = subtrahend.data; + int[] mData = minuend.data; + int subLen = subtrahend.nWords; + int minLen = minuend.nWords; + if (offsetDiff < 0) { + int rLen = minLen; + if (rLen < sData.length) { + System.arraycopy(sData, 0, sData, -offsetDiff, subLen); + Arrays.fill(sData, 0, -offsetDiff, 0); + } else { + int[] r = new int[rLen]; + System.arraycopy(sData, 0, r, -offsetDiff, subLen); + subtrahend.data = sData = r; + } + subtrahend.offset = minuend.offset; + subLen -= offsetDiff; + offsetDiff = 0; + } else { + int rLen = minLen + offsetDiff; + if (rLen >= sData.length) { + subtrahend.data = sData = Arrays.copyOf(sData, rLen); + } + } + //@ assert minuend == this && minuend.value() == \old(this.value()); + //@ assert mData == minuend.data && minLen == minuend.nWords; + //@ assert subtrahend.offset + subtrahend.data.length >= minuend.size(); + //@ assert sData == subtrahend.data; + //@ assert AP(subtrahend.data, subtrahend.data.length) << subtrahend.offset == \old(subtrahend.value()); + //@ assert subtrahend.offset == Math.min(\old(this.offset), minuend.offset); + //@ assert offsetDiff == minuend.offset - subtrahend.offset; + //@ assert 0 <= offsetDiff && offsetDiff + minLen <= sData.length; + int sIndex = 0; + long borrow = 0L; + for (; sIndex < offsetDiff; sIndex++) { + long diff = 0L - (sData[sIndex] & LONG_MASK) + borrow; + sData[sIndex] = (int) diff; + borrow = diff >> 32; // signed shift + } + //@ assert sIndex == offsetDiff; + for (int mIndex = 0; mIndex < minLen; sIndex++, mIndex++) { + //@ assert sIndex == offsetDiff + mIndex; + long diff = (mData[mIndex] & LONG_MASK) - (sData[sIndex] & LONG_MASK) + borrow; + sData[sIndex] = (int) diff; + borrow = diff >> 32; // signed shift + } + assert borrow == 0L : borrow; // borrow out of subtract, + // result should be positive + subtrahend.nWords = sIndex; + subtrahend.trimLeadingZeros(); + return subtrahend; + + } + + /** + * Determines whether all elements of an array are zero for all indices less + * than a given index. + * + * @param a The array to be examined. + * @param from The index strictly below which elements are to be examined. + * @return Zero if all elements in range are zero, 1 otherwise. + */ + /*@ + @ requires 0 <= from && from <= a.length; + @ ensures \result == (AP(a, from) == 0 ? 0 : 1); + @*/ + private /*@ pure @*/ static int checkZeroTail(int[] a, int from) { + while (from > 0) { + if (a[--from] != 0) { + return 1; + } + } + return 0; + } + + /** + * Compares the parameter with this FDBigInteger. Returns an + * integer accordingly as: + *
+     * >0: this > other
+     *  0: this == other
+     * <0: this < other
+     * 
+ * + * @param other The FDBigInteger to compare. + * @return A negative value, zero, or a positive value according to the + * result of the comparison. + */ + /*@ + @ ensures \result == (this.value() < other.value() ? -1 : this.value() > other.value() ? +1 : 0); + @*/ + public /*@ pure @*/ int cmp(FDBigInteger other) { + int aSize = nWords + offset; + int bSize = other.nWords + other.offset; + if (aSize > bSize) { + return 1; + } else if (aSize < bSize) { + return -1; + } + int aLen = nWords; + int bLen = other.nWords; + while (aLen > 0 && bLen > 0) { + int a = data[--aLen]; + int b = other.data[--bLen]; + if (a != b) { + return ((a & LONG_MASK) < (b & LONG_MASK)) ? -1 : 1; + } + } + if (aLen > 0) { + return checkZeroTail(data, aLen); + } + if (bLen > 0) { + return -checkZeroTail(other.data, bLen); + } + return 0; + } + + /** + * Compares this FDBigInteger with + * 5p5 * 2p2. + * Returns an integer accordingly as: + *
+     * >0: this > other
+     *  0: this == other
+     * <0: this < other
+     * 
+ * @param p5 The exponent of the power-of-five factor. + * @param p2 The exponent of the power-of-two factor. + * @return A negative value, zero, or a positive value according to the + * result of the comparison. + */ + /*@ + @ requires p5 >= 0 && p2 >= 0; + @ ensures \result == (this.value() < pow52(p5, p2) ? -1 : this.value() > pow52(p5, p2) ? +1 : 0); + @*/ + public /*@ pure @*/ int cmpPow52(int p5, int p2) { + if (p5 == 0) { + int wordcount = p2 >> 5; + int bitcount = p2 & 0x1f; + int size = this.nWords + this.offset; + if (size > wordcount + 1) { + return 1; + } else if (size < wordcount + 1) { + return -1; + } + int a = this.data[this.nWords -1]; + int b = 1 << bitcount; + if (a != b) { + return ( (a & LONG_MASK) < (b & LONG_MASK)) ? -1 : 1; + } + return checkZeroTail(this.data, this.nWords - 1); + } + return this.cmp(big5pow(p5).leftShift(p2)); + } + + /** + * Compares this FDBigInteger with x + y. Returns a + * value according to the comparison as: + *
+     * -1: this <  x + y
+     *  0: this == x + y
+     *  1: this >  x + y
+     * 
+ * @param x The first addend of the sum to compare. + * @param y The second addend of the sum to compare. + * @return -1, 0, or 1 according to the result of the comparison. + */ + /*@ + @ ensures \result == (this.value() < x.value() + y.value() ? -1 : this.value() > x.value() + y.value() ? +1 : 0); + @*/ + public /*@ pure @*/ int addAndCmp(FDBigInteger x, FDBigInteger y) { + FDBigInteger big; + FDBigInteger small; + int xSize = x.size(); + int ySize = y.size(); + int bSize; + int sSize; + if (xSize >= ySize) { + big = x; + small = y; + bSize = xSize; + sSize = ySize; + } else { + big = y; + small = x; + bSize = ySize; + sSize = xSize; + } + int thSize = this.size(); + if (bSize == 0) { + return thSize == 0 ? 0 : 1; + } + if (sSize == 0) { + return this.cmp(big); + } + if (bSize > thSize) { + return -1; + } + if (bSize + 1 < thSize) { + return 1; + } + long top = (big.data[big.nWords - 1] & LONG_MASK); + if (sSize == bSize) { + top += (small.data[small.nWords - 1] & LONG_MASK); + } + if ((top >>> 32) == 0) { + if (((top + 1) >>> 32) == 0) { + // good case - no carry extension + if (bSize < thSize) { + return 1; + } + // here sum.nWords == this.nWords + long v = (this.data[this.nWords - 1] & LONG_MASK); + if (v < top) { + return -1; + } + if (v > top + 1) { + return 1; + } + } + } else { // (top>>>32)!=0 guaranteed carry extension + if (bSize + 1 > thSize) { + return -1; + } + // here sum.nWords == this.nWords + top >>>= 32; + long v = (this.data[this.nWords - 1] & LONG_MASK); + if (v < top) { + return -1; + } + if (v > top + 1) { + return 1; + } + } + return this.cmp(big.add(small)); + } + + /** + * Makes this FDBigInteger immutable. + */ + /*@ + @ assignable this.isImmutable; + @ ensures this.isImmutable; + @*/ + public void makeImmutable() { + this.isImmutable = true; + } + + /** + * Multiplies this FDBigInteger by an integer. + * + * @param i The factor by which to multiply this FDBigInteger. + * @return This FDBigInteger multiplied by an integer. + */ + /*@ + @ requires this.value() == 0; + @ assignable \nothing; + @ ensures \result == this; + @ + @ also + @ + @ requires this.value() != 0; + @ assignable \nothing; + @ ensures \result.value() == \old(this.value() * UNSIGNED(i)); + @*/ + private FDBigInteger mult(int i) { + if (this.nWords == 0) { + return this; + } + int[] r = new int[nWords + 1]; + mult(data, nWords, i, r); + return new FDBigInteger(r, offset); + } + + /** + * Multiplies this FDBigInteger by another FDBigInteger. + * + * @param other The FDBigInteger factor by which to multiply. + * @return The product of this and the parameter FDBigIntegers. + */ + /*@ + @ requires this.value() == 0; + @ assignable \nothing; + @ ensures \result == this; + @ + @ also + @ + @ requires this.value() != 0 && other.value() == 0; + @ assignable \nothing; + @ ensures \result == other; + @ + @ also + @ + @ requires this.value() != 0 && other.value() != 0; + @ assignable \nothing; + @ ensures \result.value() == \old(this.value() * other.value()); + @*/ + private FDBigInteger mult(FDBigInteger other) { + if (this.nWords == 0) { + return this; + } + if (this.size() == 1) { + return other.mult(data[0]); + } + if (other.nWords == 0) { + return other; + } + if (other.size() == 1) { + return this.mult(other.data[0]); + } + int[] r = new int[nWords + other.nWords]; + mult(this.data, this.nWords, other.data, other.nWords, r); + return new FDBigInteger(r, this.offset + other.offset); + } + + /** + * Adds another FDBigInteger to this FDBigInteger. + * + * @param other The FDBigInteger to add. + * @return The sum of the FDBigIntegers. + */ + /*@ + @ assignable \nothing; + @ ensures \result.value() == \old(this.value() + other.value()); + @*/ + private FDBigInteger add(FDBigInteger other) { + FDBigInteger big, small; + int bigLen, smallLen; + int tSize = this.size(); + int oSize = other.size(); + if (tSize >= oSize) { + big = this; + bigLen = tSize; + small = other; + smallLen = oSize; + } else { + big = other; + bigLen = oSize; + small = this; + smallLen = tSize; + } + int[] r = new int[bigLen + 1]; + int i = 0; + long carry = 0L; + for (; i < smallLen; i++) { + carry += (i < big.offset ? 0L : (big.data[i - big.offset] & LONG_MASK) ) + + ((i < small.offset ? 0L : (small.data[i - small.offset] & LONG_MASK))); + r[i] = (int) carry; + carry >>= 32; // signed shift. + } + for (; i < bigLen; i++) { + carry += (i < big.offset ? 0L : (big.data[i - big.offset] & LONG_MASK) ); + r[i] = (int) carry; + carry >>= 32; // signed shift. + } + r[bigLen] = (int) carry; + return new FDBigInteger(r, 0); + } + + + /** + * Multiplies a FDBigInteger by an int and adds another int. The + * result is computed in place. This method is intended only to be invoked + * from + * + * FDBigInteger(long lValue, char[] digits, int kDigits, int nDigits) + * . + * + * @param iv The factor by which to multiply this FDBigInteger. + * @param addend The value to add to the product of this + * FDBigInteger and iv. + */ + /*@ + @ requires this.value()*UNSIGNED(iv) + UNSIGNED(addend) < ((\bigint)1) << ((this.data.length + this.offset)*32); + @ assignable this.data[*]; + @ ensures this.value() == \old(this.value()*UNSIGNED(iv) + UNSIGNED(addend)); + @*/ + private /*@ helper @*/ void multAddMe(int iv, int addend) { + long v = iv & LONG_MASK; + // unroll 0th iteration, doing addition. + long p = v * (data[0] & LONG_MASK) + (addend & LONG_MASK); + data[0] = (int) p; + p >>>= 32; + for (int i = 1; i < nWords; i++) { + p += v * (data[i] & LONG_MASK); + data[i] = (int) p; + p >>>= 32; + } + if (p != 0L) { + data[nWords++] = (int) p; // will fail noisily if illegal! + } + } + + // + // original doc: + // + // do this -=q*S + // returns borrow + // + /** + * Multiplies the parameters and subtracts them from this + * FDBigInteger. + * + * @param q The integer parameter. + * @param S The FDBigInteger parameter. + * @return this - q*S. + */ + /*@ + @ ensures nWords == 0 ==> offset == 0; + @ ensures nWords > 0 ==> data[nWords - 1] != 0; + @*/ + /*@ + @ requires 0 < q && q <= (1L << 31); + @ requires data != null; + @ requires 0 <= nWords && nWords <= data.length && offset >= 0; + @ requires !this.isImmutable; + @ requires this.size() == S.size(); + @ requires this != S; + @ assignable this.nWords, this.offset, this.data, this.data[*]; + @ ensures -q <= \result && \result <= 0; + @ ensures this.size() == \old(this.size()); + @ ensures this.value() + (\result << (this.size()*32)) == \old(this.value() - q*S.value()); + @ ensures this.offset == \old(Math.min(this.offset, S.offset)); + @ ensures \old(this.offset <= S.offset) ==> this.nWords == \old(this.nWords); + @ ensures \old(this.offset <= S.offset) ==> this.offset == \old(this.offset); + @ ensures \old(this.offset <= S.offset) ==> this.data == \old(this.data); + @ + @ also + @ + @ requires q == 0; + @ assignable \nothing; + @ ensures \result == 0; + @*/ + private /*@ helper @*/ long multDiffMe(long q, FDBigInteger S) { + long diff = 0L; + if (q != 0) { + int deltaSize = S.offset - this.offset; + if (deltaSize >= 0) { + int[] sd = S.data; + int[] td = this.data; + for (int sIndex = 0, tIndex = deltaSize; sIndex < S.nWords; sIndex++, tIndex++) { + diff += (td[tIndex] & LONG_MASK) - q * (sd[sIndex] & LONG_MASK); + td[tIndex] = (int) diff; + diff >>= 32; // N.B. SIGNED shift. + } + } else { + deltaSize = -deltaSize; + int[] rd = new int[nWords + deltaSize]; + int sIndex = 0; + int rIndex = 0; + int[] sd = S.data; + for (; rIndex < deltaSize && sIndex < S.nWords; sIndex++, rIndex++) { + diff -= q * (sd[sIndex] & LONG_MASK); + rd[rIndex] = (int) diff; + diff >>= 32; // N.B. SIGNED shift. + } + int tIndex = 0; + int[] td = this.data; + for (; sIndex < S.nWords; sIndex++, tIndex++, rIndex++) { + diff += (td[tIndex] & LONG_MASK) - q * (sd[sIndex] & LONG_MASK); + rd[rIndex] = (int) diff; + diff >>= 32; // N.B. SIGNED shift. + } + this.nWords += deltaSize; + this.offset -= deltaSize; + this.data = rd; + } + } + return diff; + } + + + /** + * Multiplies by 10 a big integer represented as an array. The final carry + * is returned. + * + * @param src The array representation of the big integer. + * @param srcLen The number of elements of src to use. + * @param dst The product array. + * @return The final carry of the multiplication. + */ + /*@ + @ requires src.length >= srcLen && dst.length >= srcLen; + @ assignable dst[0 .. srcLen - 1]; + @ ensures 0 <= \result && \result < 10; + @ ensures AP(dst, srcLen) + (\result << (srcLen*32)) == \old(AP(src, srcLen) * 10); + @*/ + private static int multAndCarryBy10(int[] src, int srcLen, int[] dst) { + long carry = 0; + for (int i = 0; i < srcLen; i++) { + long product = (src[i] & LONG_MASK) * 10L + carry; + dst[i] = (int) product; + carry = product >>> 32; + } + return (int) carry; + } + + /** + * Multiplies by a constant value a big integer represented as an array. + * The constant factor is an int. + * + * @param src The array representation of the big integer. + * @param srcLen The number of elements of src to use. + * @param value The constant factor by which to multiply. + * @param dst The product array. + */ + /*@ + @ requires src.length >= srcLen && dst.length >= srcLen + 1; + @ assignable dst[0 .. srcLen]; + @ ensures AP(dst, srcLen + 1) == \old(AP(src, srcLen) * UNSIGNED(value)); + @*/ + private static void mult(int[] src, int srcLen, int value, int[] dst) { + long val = value & LONG_MASK; + long carry = 0; + for (int i = 0; i < srcLen; i++) { + long product = (src[i] & LONG_MASK) * val + carry; + dst[i] = (int) product; + carry = product >>> 32; + } + dst[srcLen] = (int) carry; + } + + /** + * Multiplies by a constant value a big integer represented as an array. + * The constant factor is a long represent as two ints. + * + * @param src The array representation of the big integer. + * @param srcLen The number of elements of src to use. + * @param v0 The lower 32 bits of the long factor. + * @param v1 The upper 32 bits of the long factor. + * @param dst The product array. + */ + /*@ + @ requires src != dst; + @ requires src.length >= srcLen && dst.length >= srcLen + 2; + @ assignable dst[0 .. srcLen + 1]; + @ ensures AP(dst, srcLen + 2) == \old(AP(src, srcLen) * (UNSIGNED(v0) + (UNSIGNED(v1) << 32))); + @*/ + private static void mult(int[] src, int srcLen, int v0, int v1, int[] dst) { + long v = v0 & LONG_MASK; + long carry = 0; + for (int j = 0; j < srcLen; j++) { + long product = v * (src[j] & LONG_MASK) + carry; + dst[j] = (int) product; + carry = product >>> 32; + } + dst[srcLen] = (int) carry; + v = v1 & LONG_MASK; + carry = 0; + for (int j = 0; j < srcLen; j++) { + long product = (dst[j + 1] & LONG_MASK) + v * (src[j] & LONG_MASK) + carry; + dst[j + 1] = (int) product; + carry = product >>> 32; + } + dst[srcLen + 1] = (int) carry; + } + + // Fails assertion for negative exponent. + /** + * Computes 5 raised to a given power. + * + * @param p The exponent of 5. + * @return 5p. + */ + private static FDBigInteger big5pow(int p) { + assert p >= 0 : p; // negative power of 5 + if (p < MAX_FIVE_POW) { + return POW_5_CACHE[p]; + } + return big5powRec(p); + } + + // slow path + /** + * Computes 5 raised to a given power. + * + * @param p The exponent of 5. + * @return 5p. + */ + private static FDBigInteger big5powRec(int p) { + if (p < MAX_FIVE_POW) { + return POW_5_CACHE[p]; + } + // construct the value. + // recursively. + int q, r; + // in order to compute 5^p, + // compute its square root, 5^(p/2) and square. + // or, let q = p / 2, r = p -q, then + // 5^p = 5^(q+r) = 5^q * 5^r + q = p >> 1; + r = p - q; + FDBigInteger bigq = big5powRec(q); + if (r < SMALL_5_POW.length) { + return bigq.mult(SMALL_5_POW[r]); + } else { + return bigq.mult(big5powRec(r)); + } + } + + // for debugging ... + /** + * Converts this FDBigInteger to a hexadecimal string. + * + * @return The hexadecimal string representation. + */ + public String toHexString(){ + if(nWords ==0) { + return "0"; + } + StringBuilder sb = new StringBuilder((nWords +offset)*8); + for(int i= nWords -1; i>=0; i--) { + String subStr = Integer.toHexString(data[i]); + for(int j = subStr.length(); j<8; j++) { + sb.append('0'); + } + sb.append(subStr); + } + for(int i=offset; i>0; i--) { + sb.append("00000000"); + } + return sb.toString(); + } + + // for debugging ... + /** + * Converts this FDBigInteger to a BigInteger. + * + * @return The BigInteger representation. + */ + public BigInteger toBigInteger() { + byte[] magnitude = new byte[nWords * 4 + 1]; + for (int i = 0; i < nWords; i++) { + int w = data[i]; + magnitude[magnitude.length - 4 * i - 1] = (byte) w; + magnitude[magnitude.length - 4 * i - 2] = (byte) (w >> 8); + magnitude[magnitude.length - 4 * i - 3] = (byte) (w >> 16); + magnitude[magnitude.length - 4 * i - 4] = (byte) (w >> 24); + } + return new BigInteger(magnitude).shiftLeft(offset * 32); + } + + // for debugging ... + /** + * Converts this FDBigInteger to a string. + * + * @return The string representation. + */ + @Override + public String toString(){ + return toBigInteger().toString(); + } +} --- /dev/null 2013-06-07 13:08:35.000000000 -0700 +++ new/test/sun/misc/FloatingDecimal/OldFDBigIntForTest.java 2013-06-07 13:08:35.000000000 -0700 @@ -0,0 +1,491 @@ +/* + * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +//package sun.misc; + +/* + * A really, really simple bigint package + * tailored to the needs of floating base conversion. + */ +class OldFDBigIntForTest { + int nWords; // number of words used + int data[]; // value: data[0] is least significant + + + public OldFDBigIntForTest( int v ){ + nWords = 1; + data = new int[1]; + data[0] = v; + } + + public OldFDBigIntForTest( long v ){ + data = new int[2]; + data[0] = (int)v; + data[1] = (int)(v>>>32); + nWords = (data[1]==0) ? 1 : 2; + } + + public OldFDBigIntForTest( OldFDBigIntForTest other ){ + data = new int[nWords = other.nWords]; + System.arraycopy( other.data, 0, data, 0, nWords ); + } + + private OldFDBigIntForTest( int [] d, int n ){ + data = d; + nWords = n; + } + + public OldFDBigIntForTest( long seed, char digit[], int nd0, int nd ){ + int n= (nd+8)/9; // estimate size needed. + if ( n < 2 ) n = 2; + data = new int[n]; // allocate enough space + data[0] = (int)seed; // starting value + data[1] = (int)(seed>>>32); + nWords = (data[1]==0) ? 1 : 2; + int i = nd0; + int limit = nd-5; // slurp digits 5 at a time. + int v; + while ( i < limit ){ + int ilim = i+5; + v = (int)digit[i++]-(int)'0'; + while( i >5; + int bitcount = c & 0x1f; + int anticount = 32-bitcount; + int t[] = data; + int s[] = data; + if ( nWords+wordcount+1 > t.length ){ + // reallocate. + t = new int[ nWords+wordcount+1 ]; + } + int target = nWords+wordcount; + int src = nWords-1; + if ( bitcount == 0 ){ + // special hack, since an anticount of 32 won't go! + System.arraycopy( s, 0, t, wordcount, nWords ); + target = wordcount-1; + } else { + t[target--] = s[src]>>>anticount; + while ( src >= 1 ){ + t[target--] = (s[src]<>>anticount); + } + t[target--] = s[src]<= 0 ){ + t[target--] = 0; + } + data = t; + nWords += wordcount + 1; + // may have constructed high-order word of 0. + // if so, trim it + while ( nWords > 1 && data[nWords-1] == 0 ) + nWords--; + } + + /* + * normalize this number by shifting until + * the MSB of the number is at 0x08000000. + * This is in preparation for quoRemIteration, below. + * The idea is that, to make division easier, we want the + * divisor to be "normalized" -- usually this means shifting + * the MSB into the high words sign bit. But because we know that + * the quotient will be 0 < q < 10, we would like to arrange that + * the dividend not span up into another word of precision. + * (This needs to be explained more clearly!) + */ + public int + normalizeMe() throws IllegalArgumentException { + int src; + int wordcount = 0; + int bitcount = 0; + int v = 0; + for ( src= nWords-1 ; src >= 0 && (v=data[src]) == 0 ; src--){ + wordcount += 1; + } + if ( src < 0 ){ + // oops. Value is zero. Cannot normalize it! + throw new IllegalArgumentException("zero value"); + } + /* + * In most cases, we assume that wordcount is zero. This only + * makes sense, as we try not to maintain any high-order + * words full of zeros. In fact, if there are zeros, we will + * simply SHORTEN our number at this point. Watch closely... + */ + nWords -= wordcount; + /* + * Compute how far left we have to shift v s.t. its highest- + * order bit is in the right place. Then call lshiftMe to + * do the work. + */ + if ( (v & 0xf0000000) != 0 ){ + // will have to shift up into the next word. + // too bad. + for( bitcount = 32 ; (v & 0xf0000000) != 0 ; bitcount-- ) + v >>>= 1; + } else { + while ( v <= 0x000fffff ){ + // hack: byte-at-a-time shifting + v <<= 8; + bitcount += 8; + } + while ( v <= 0x07ffffff ){ + v <<= 1; + bitcount += 1; + } + } + if ( bitcount != 0 ) + lshiftMe( bitcount ); + return bitcount; + } + + /* + * Multiply a OldFDBigIntForTest by an int. + * Result is a new OldFDBigIntForTest. + */ + public OldFDBigIntForTest + mult( int iv ) { + long v = iv; + int r[]; + long p; + + // guess adequate size of r. + r = new int[ ( v * ((long)data[nWords-1]&0xffffffffL) > 0xfffffffL ) ? nWords+1 : nWords ]; + p = 0L; + for( int i=0; i < nWords; i++ ) { + p += v * ((long)data[i]&0xffffffffL); + r[i] = (int)p; + p >>>= 32; + } + if ( p == 0L){ + return new OldFDBigIntForTest( r, nWords ); + } else { + r[nWords] = (int)p; + return new OldFDBigIntForTest( r, nWords+1 ); + } + } + + /* + * Multiply a OldFDBigIntForTest by an int and add another int. + * Result is computed in place. + * Hope it fits! + */ + public void + multaddMe( int iv, int addend ) { + long v = iv; + long p; + + // unroll 0th iteration, doing addition. + p = v * ((long)data[0]&0xffffffffL) + ((long)addend&0xffffffffL); + data[0] = (int)p; + p >>>= 32; + for( int i=1; i < nWords; i++ ) { + p += v * ((long)data[i]&0xffffffffL); + data[i] = (int)p; + p >>>= 32; + } + if ( p != 0L){ + data[nWords] = (int)p; // will fail noisily if illegal! + nWords++; + } + } + + /* + * Multiply a OldFDBigIntForTest by another OldFDBigIntForTest. + * Result is a new OldFDBigIntForTest. + */ + public OldFDBigIntForTest + mult( OldFDBigIntForTest other ){ + // crudely guess adequate size for r + int r[] = new int[ nWords + other.nWords ]; + int i; + // I think I am promised zeros... + + for( i = 0; i < this.nWords; i++ ){ + long v = (long)this.data[i] & 0xffffffffL; // UNSIGNED CONVERSION + long p = 0L; + int j; + for( j = 0; j < other.nWords; j++ ){ + p += ((long)r[i+j]&0xffffffffL) + v*((long)other.data[j]&0xffffffffL); // UNSIGNED CONVERSIONS ALL 'ROUND. + r[i+j] = (int)p; + p >>>= 32; + } + r[i+j] = (int)p; + } + // compute how much of r we actually needed for all that. + for ( i = r.length-1; i> 0; i--) + if ( r[i] != 0 ) + break; + return new OldFDBigIntForTest( r, i+1 ); + } + + /* + * Add one OldFDBigIntForTest to another. Return a OldFDBigIntForTest + */ + public OldFDBigIntForTest + add( OldFDBigIntForTest other ){ + int i; + int a[], b[]; + int n, m; + long c = 0L; + // arrange such that a.nWords >= b.nWords; + // n = a.nWords, m = b.nWords + if ( this.nWords >= other.nWords ){ + a = this.data; + n = this.nWords; + b = other.data; + m = other.nWords; + } else { + a = other.data; + n = other.nWords; + b = this.data; + m = this.nWords; + } + int r[] = new int[ n ]; + for ( i = 0; i < n; i++ ){ + c += (long)a[i] & 0xffffffffL; + if ( i < m ){ + c += (long)b[i] & 0xffffffffL; + } + r[i] = (int) c; + c >>= 32; // signed shift. + } + if ( c != 0L ){ + // oops -- carry out -- need longer result. + int s[] = new int[ r.length+1 ]; + System.arraycopy( r, 0, s, 0, r.length ); + s[i++] = (int)c; + return new OldFDBigIntForTest( s, i ); + } + return new OldFDBigIntForTest( r, i ); + } + + /* + * Subtract one OldFDBigIntForTest from another. Return a OldFDBigIntForTest + * Assert that the result is positive. + */ + public OldFDBigIntForTest + sub( OldFDBigIntForTest other ){ + int r[] = new int[ this.nWords ]; + int i; + int n = this.nWords; + int m = other.nWords; + int nzeros = 0; + long c = 0L; + for ( i = 0; i < n; i++ ){ + c += (long)this.data[i] & 0xffffffffL; + if ( i < m ){ + c -= (long)other.data[i] & 0xffffffffL; + } + if ( ( r[i] = (int) c ) == 0 ) + nzeros++; + else + nzeros = 0; + c >>= 32; // signed shift + } + assert c == 0L : c; // borrow out of subtract + assert dataInRangeIsZero(i, m, other); // negative result of subtract + return new OldFDBigIntForTest( r, n-nzeros ); + } + + private static boolean dataInRangeIsZero(int i, int m, OldFDBigIntForTest other) { + while ( i < m ) + if (other.data[i++] != 0) + return false; + return true; + } + + /* + * Compare OldFDBigIntForTest with another OldFDBigIntForTest. Return an integer + * >0: this > other + * 0: this == other + * <0: this < other + */ + public int + cmp( OldFDBigIntForTest other ){ + int i; + if ( this.nWords > other.nWords ){ + // if any of my high-order words is non-zero, + // then the answer is evident + int j = other.nWords-1; + for ( i = this.nWords-1; i > j ; i-- ) + if ( this.data[i] != 0 ) return 1; + }else if ( this.nWords < other.nWords ){ + // if any of other's high-order words is non-zero, + // then the answer is evident + int j = this.nWords-1; + for ( i = other.nWords-1; i > j ; i-- ) + if ( other.data[i] != 0 ) return -1; + } else{ + i = this.nWords-1; + } + for ( ; i > 0 ; i-- ) + if ( this.data[i] != other.data[i] ) + break; + // careful! want unsigned compare! + // use brute force here. + int a = this.data[i]; + int b = other.data[i]; + if ( a < 0 ){ + // a is really big, unsigned + if ( b < 0 ){ + return a-b; // both big, negative + } else { + return 1; // b not big, answer is obvious; + } + } else { + // a is not really big + if ( b < 0 ) { + // but b is really big + return -1; + } else { + return a - b; + } + } + } + + /* + * Compute + * q = (int)( this / S ) + * this = 10 * ( this mod S ) + * Return q. + * This is the iteration step of digit development for output. + * We assume that S has been normalized, as above, and that + * "this" has been lshift'ed accordingly. + * Also assume, of course, that the result, q, can be expressed + * as an integer, 0 <= q < 10. + */ + public int + quoRemIteration( OldFDBigIntForTest S )throws IllegalArgumentException { + // ensure that this and S have the same number of + // digits. If S is properly normalized and q < 10 then + // this must be so. + if ( nWords != S.nWords ){ + throw new IllegalArgumentException("disparate values"); + } + // estimate q the obvious way. We will usually be + // right. If not, then we're only off by a little and + // will re-add. + int n = nWords-1; + long q = ((long)data[n]&0xffffffffL) / (long)S.data[n]; + long diff = 0L; + for ( int i = 0; i <= n ; i++ ){ + diff += ((long)data[i]&0xffffffffL) - q*((long)S.data[i]&0xffffffffL); + data[i] = (int)diff; + diff >>= 32; // N.B. SIGNED shift. + } + if ( diff != 0L ) { + // damn, damn, damn. q is too big. + // add S back in until this turns +. This should + // not be very many times! + long sum = 0L; + while ( sum == 0L ){ + sum = 0L; + for ( int i = 0; i <= n; i++ ){ + sum += ((long)data[i]&0xffffffffL) + ((long)S.data[i]&0xffffffffL); + data[i] = (int) sum; + sum >>= 32; // Signed or unsigned, answer is 0 or 1 + } + /* + * Originally the following line read + * "if ( sum !=0 && sum != -1 )" + * but that would be wrong, because of the + * treatment of the two values as entirely unsigned, + * it would be impossible for a carry-out to be interpreted + * as -1 -- it would have to be a single-bit carry-out, or + * +1. + */ + assert sum == 0 || sum == 1 : sum; // carry out of division correction + q -= 1; + } + } + // finally, we can multiply this by 10. + // it cannot overflow, right, as the high-order word has + // at least 4 high-order zeros! + long p = 0L; + for ( int i = 0; i <= n; i++ ){ + p += 10*((long)data[i]&0xffffffffL); + data[i] = (int)p; + p >>= 32; // SIGNED shift. + } + assert p == 0L : p; // Carry out of *10 + return (int)q; + } + + public long + longValue(){ + // if this can be represented as a long, return the value + assert this.nWords > 0 : this.nWords; // longValue confused + + if (this.nWords == 1) + return ((long)data[0]&0xffffffffL); + + assert dataInRangeIsZero(2, this.nWords, this); // value too big + assert data[1] >= 0; // value too big + return ((long)(data[1]) << 32) | ((long)data[0]&0xffffffffL); + } + + public String + toString() { + StringBuffer r = new StringBuffer(30); + r.append('['); + int i = Math.min( nWords-1, data.length-1) ; + if ( nWords > data.length ){ + r.append( "("+data.length+"<"+nWords+"!)" ); + } + for( ; i> 0 ; i-- ){ + r.append( Integer.toHexString( data[i] ) ); + r.append(' '); + } + r.append( Integer.toHexString( data[0] ) ); + r.append(']'); + return new String( r ); + } +} --- /dev/null 2013-06-07 13:08:37.000000000 -0700 +++ new/test/sun/misc/FloatingDecimal/OldFloatingDecimalForTest.java 2013-06-07 13:08:36.000000000 -0700 @@ -0,0 +1,2436 @@ +/* + * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +//package sun.misc; + +import sun.misc.DoubleConsts; +import sun.misc.FloatConsts; +import java.util.regex.*; + +public class OldFloatingDecimalForTest{ + boolean isExceptional; + boolean isNegative; + int decExponent; + char digits[]; + int nDigits; + int bigIntExp; + int bigIntNBits; + boolean mustSetRoundDir = false; + boolean fromHex = false; + int roundDir = 0; // set by doubleValue + + /* + * The fields below provides additional information about the result of + * the binary to decimal digits conversion done in dtoa() and roundup() + * methods. They are changed if needed by those two methods. + */ + + // True if the dtoa() binary to decimal conversion was exact. + boolean exactDecimalConversion = false; + + // True if the result of the binary to decimal conversion was rounded-up + // at the end of the conversion process, i.e. roundUp() method was called. + boolean decimalDigitsRoundedUp = false; + + private OldFloatingDecimalForTest( boolean negSign, int decExponent, char []digits, int n, boolean e ) + { + isNegative = negSign; + isExceptional = e; + this.decExponent = decExponent; + this.digits = digits; + this.nDigits = n; + } + + /* + * Constants of the implementation + * Most are IEEE-754 related. + * (There are more really boring constants at the end.) + */ + static final long signMask = 0x8000000000000000L; + static final long expMask = 0x7ff0000000000000L; + static final long fractMask= ~(signMask|expMask); + static final int expShift = 52; + static final int expBias = 1023; + static final long fractHOB = ( 1L< 0L ) { // i.e. while ((v&highbit) == 0L ) + v <<= 1; + } + + int n = 0; + while (( v & lowbytes ) != 0L ){ + v <<= 8; + n += 8; + } + while ( v != 0L ){ + v <<= 1; + n += 1; + } + return n; + } + + /* + * Keep big powers of 5 handy for future reference. + */ + private static OldFDBigIntForTest b5p[]; + + private static synchronized OldFDBigIntForTest + big5pow( int p ){ + assert p >= 0 : p; // negative power of 5 + if ( b5p == null ){ + b5p = new OldFDBigIntForTest[ p+1 ]; + }else if (b5p.length <= p ){ + OldFDBigIntForTest t[] = new OldFDBigIntForTest[ p+1 ]; + System.arraycopy( b5p, 0, t, 0, b5p.length ); + b5p = t; + } + if ( b5p[p] != null ) + return b5p[p]; + else if ( p < small5pow.length ) + return b5p[p] = new OldFDBigIntForTest( small5pow[p] ); + else if ( p < long5pow.length ) + return b5p[p] = new OldFDBigIntForTest( long5pow[p] ); + else { + // construct the value. + // recursively. + int q, r; + // in order to compute 5^p, + // compute its square root, 5^(p/2) and square. + // or, let q = p / 2, r = p -q, then + // 5^p = 5^(q+r) = 5^q * 5^r + q = p >> 1; + r = p - q; + OldFDBigIntForTest bigq = b5p[q]; + if ( bigq == null ) + bigq = big5pow ( q ); + if ( r < small5pow.length ){ + return (b5p[p] = bigq.mult( small5pow[r] ) ); + }else{ + OldFDBigIntForTest bigr = b5p[ r ]; + if ( bigr == null ) + bigr = big5pow( r ); + return (b5p[p] = bigq.mult( bigr ) ); + } + } + } + + // + // a common operation + // + private static OldFDBigIntForTest + multPow52( OldFDBigIntForTest v, int p5, int p2 ){ + if ( p5 != 0 ){ + if ( p5 < small5pow.length ){ + v = v.mult( small5pow[p5] ); + } else { + v = v.mult( big5pow( p5 ) ); + } + } + if ( p2 != 0 ){ + v.lshiftMe( p2 ); + } + return v; + } + + // + // another common operation + // + private static OldFDBigIntForTest + constructPow52( int p5, int p2 ){ + OldFDBigIntForTest v = new OldFDBigIntForTest( big5pow( p5 ) ); + if ( p2 != 0 ){ + v.lshiftMe( p2 ); + } + return v; + } + + /* + * Make a floating double into a OldFDBigIntForTest. + * This could also be structured as a OldFDBigIntForTest + * constructor, but we'd have to build a lot of knowledge + * about floating-point representation into it, and we don't want to. + * + * AS A SIDE EFFECT, THIS METHOD WILL SET THE INSTANCE VARIABLES + * bigIntExp and bigIntNBits + * + */ + private OldFDBigIntForTest + doubleToBigInt( double dval ){ + long lbits = Double.doubleToLongBits( dval ) & ~signMask; + int binexp = (int)(lbits >>> expShift); + lbits &= fractMask; + if ( binexp > 0 ){ + lbits |= fractHOB; + } else { + assert lbits != 0L : lbits; // doubleToBigInt(0.0) + binexp +=1; + while ( (lbits & fractHOB ) == 0L){ + lbits <<= 1; + binexp -= 1; + } + } + binexp -= expBias; + int nbits = countBits( lbits ); + /* + * We now know where the high-order 1 bit is, + * and we know how many there are. + */ + int lowOrderZeros = expShift+1-nbits; + lbits >>>= lowOrderZeros; + + bigIntExp = binexp+1-nbits; + bigIntNBits = nbits; + return new OldFDBigIntForTest( lbits ); + } + + /* + * Compute a number that is the ULP of the given value, + * for purposes of addition/subtraction. Generally easy. + * More difficult if subtracting and the argument + * is a normalized a power of 2, as the ULP changes at these points. + */ + private static double ulp( double dval, boolean subtracting ){ + long lbits = Double.doubleToLongBits( dval ) & ~signMask; + int binexp = (int)(lbits >>> expShift); + double ulpval; + if ( subtracting && ( binexp >= expShift ) && ((lbits&fractMask) == 0L) ){ + // for subtraction from normalized, powers of 2, + // use next-smaller exponent + binexp -= 1; + } + if ( binexp > expShift ){ + ulpval = Double.longBitsToDouble( ((long)(binexp-expShift))< 0L (not zero, nor negative). + * + * The only reason that we develop the digits here, rather than + * calling on Long.toString() is that we can do it a little faster, + * and besides want to treat trailing 0s specially. If Long.toString + * changes, we should re-evaluate this strategy! + */ + private void + developLongDigits( int decExponent, long lvalue, long insignificant ){ + char digits[]; + int ndigits; + int digitno; + int c; + // + // Discard non-significant low-order bits, while rounding, + // up to insignificant value. + int i; + for ( i = 0; insignificant >= 10L; i++ ) + insignificant /= 10L; + if ( i != 0 ){ + long pow10 = long5pow[i] << i; // 10^i == 5^i * 2^i; + long residue = lvalue % pow10; + lvalue /= pow10; + decExponent += i; + if ( residue >= (pow10>>1) ){ + // round up based on the low-order bits we're discarding + lvalue++; + } + } + if ( lvalue <= Integer.MAX_VALUE ){ + assert lvalue > 0L : lvalue; // lvalue <= 0 + // even easier subcase! + // can do int arithmetic rather than long! + int ivalue = (int)lvalue; + ndigits = 10; + digits = perThreadBuffer.get(); + digitno = ndigits-1; + c = ivalue%10; + ivalue /= 10; + while ( c == 0 ){ + decExponent++; + c = ivalue%10; + ivalue /= 10; + } + while ( ivalue != 0){ + digits[digitno--] = (char)(c+'0'); + decExponent++; + c = ivalue%10; + ivalue /= 10; + } + digits[digitno] = (char)(c+'0'); + } else { + // same algorithm as above (same bugs, too ) + // but using long arithmetic. + ndigits = 20; + digits = perThreadBuffer.get(); + digitno = ndigits-1; + c = (int)(lvalue%10L); + lvalue /= 10L; + while ( c == 0 ){ + decExponent++; + c = (int)(lvalue%10L); + lvalue /= 10L; + } + while ( lvalue != 0L ){ + digits[digitno--] = (char)(c+'0'); + decExponent++; + c = (int)(lvalue%10L); + lvalue /= 10; + } + digits[digitno] = (char)(c+'0'); + } + char result []; + ndigits -= digitno; + result = new char[ ndigits ]; + System.arraycopy( digits, digitno, result, 0, ndigits ); + this.digits = result; + this.decExponent = decExponent+1; + this.nDigits = ndigits; + } + + // + // add one to the least significant digit. + // in the unlikely event there is a carry out, + // deal with it. + // assert that this will only happen where there + // is only one digit, e.g. (float)1e-44 seems to do it. + // + private void + roundup(){ + int i; + int q = digits[ i = (nDigits-1)]; + if ( q == '9' ){ + while ( q == '9' && i > 0 ){ + digits[i] = '0'; + q = digits[--i]; + } + if ( q == '9' ){ + // carryout! High-order 1, rest 0s, larger exp. + decExponent += 1; + digits[0] = '1'; + return; + } + // else fall through. + } + digits[i] = (char)(q+1); + decimalDigitsRoundedUp = true; + } + + public boolean digitsRoundedUp() { + return decimalDigitsRoundedUp; + } + + /* + * FIRST IMPORTANT CONSTRUCTOR: DOUBLE + */ + public OldFloatingDecimalForTest( double d ) + { + long dBits = Double.doubleToLongBits( d ); + long fractBits; + int binExp; + int nSignificantBits; + + // discover and delete sign + if ( (dBits&signMask) != 0 ){ + isNegative = true; + dBits ^= signMask; + } else { + isNegative = false; + } + // Begin to unpack + // Discover obvious special cases of NaN and Infinity. + binExp = (int)( (dBits&expMask) >> expShift ); + fractBits = dBits&fractMask; + if ( binExp == (int)(expMask>>expShift) ) { + isExceptional = true; + if ( fractBits == 0L ){ + digits = infinity; + } else { + digits = notANumber; + isNegative = false; // NaN has no sign! + } + nDigits = digits.length; + return; + } + isExceptional = false; + // Finish unpacking + // Normalize denormalized numbers. + // Insert assumed high-order bit for normalized numbers. + // Subtract exponent bias. + if ( binExp == 0 ){ + if ( fractBits == 0L ){ + // not a denorm, just a 0! + decExponent = 0; + digits = zero; + nDigits = 1; + return; + } + while ( (fractBits&fractHOB) == 0L ){ + fractBits <<= 1; + binExp -= 1; + } + nSignificantBits = expShift + binExp +1; // recall binExp is - shift count. + binExp += 1; + } else { + fractBits |= fractHOB; + nSignificantBits = expShift+1; + } + binExp -= expBias; + // call the routine that actually does all the hard work. + dtoa( binExp, fractBits, nSignificantBits ); + } + + /* + * SECOND IMPORTANT CONSTRUCTOR: SINGLE + */ + public OldFloatingDecimalForTest( float f ) + { + int fBits = Float.floatToIntBits( f ); + int fractBits; + int binExp; + int nSignificantBits; + + // discover and delete sign + if ( (fBits&singleSignMask) != 0 ){ + isNegative = true; + fBits ^= singleSignMask; + } else { + isNegative = false; + } + // Begin to unpack + // Discover obvious special cases of NaN and Infinity. + binExp = (fBits&singleExpMask) >> singleExpShift; + fractBits = fBits&singleFractMask; + if ( binExp == (singleExpMask>>singleExpShift) ) { + isExceptional = true; + if ( fractBits == 0L ){ + digits = infinity; + } else { + digits = notANumber; + isNegative = false; // NaN has no sign! + } + nDigits = digits.length; + return; + } + isExceptional = false; + // Finish unpacking + // Normalize denormalized numbers. + // Insert assumed high-order bit for normalized numbers. + // Subtract exponent bias. + if ( binExp == 0 ){ + if ( fractBits == 0 ){ + // not a denorm, just a 0! + decExponent = 0; + digits = zero; + nDigits = 1; + return; + } + while ( (fractBits&singleFractHOB) == 0 ){ + fractBits <<= 1; + binExp -= 1; + } + nSignificantBits = singleExpShift + binExp +1; // recall binExp is - shift count. + binExp += 1; + } else { + fractBits |= singleFractHOB; + nSignificantBits = singleExpShift+1; + } + binExp -= singleExpBias; + // call the routine that actually does all the hard work. + dtoa( binExp, ((long)fractBits)<<(expShift-singleExpShift), nSignificantBits ); + } + + private void + dtoa( int binExp, long fractBits, int nSignificantBits ) + { + int nFractBits; // number of significant bits of fractBits; + int nTinyBits; // number of these to the right of the point. + int decExp; + + // Examine number. Determine if it is an easy case, + // which we can do pretty trivially using float/long conversion, + // or whether we must do real work. + nFractBits = countBits( fractBits ); + nTinyBits = Math.max( 0, nFractBits - binExp - 1 ); + if ( binExp <= maxSmallBinExp && binExp >= minSmallBinExp ){ + // Look more closely at the number to decide if, + // with scaling by 10^nTinyBits, the result will fit in + // a long. + if ( (nTinyBits < long5pow.length) && ((nFractBits + n5bits[nTinyBits]) < 64 ) ){ + /* + * We can do this: + * take the fraction bits, which are normalized. + * (a) nTinyBits == 0: Shift left or right appropriately + * to align the binary point at the extreme right, i.e. + * where a long int point is expected to be. The integer + * result is easily converted to a string. + * (b) nTinyBits > 0: Shift right by expShift-nFractBits, + * which effectively converts to long and scales by + * 2^nTinyBits. Then multiply by 5^nTinyBits to + * complete the scaling. We know this won't overflow + * because we just counted the number of bits necessary + * in the result. The integer you get from this can + * then be converted to a string pretty easily. + */ + long halfULP; + if ( nTinyBits == 0 ) { + if ( binExp > nSignificantBits ){ + halfULP = 1L << ( binExp-nSignificantBits-1); + } else { + halfULP = 0L; + } + if ( binExp >= expShift ){ + fractBits <<= (binExp-expShift); + } else { + fractBits >>>= (expShift-binExp) ; + } + developLongDigits( 0, fractBits, halfULP ); + return; + } + /* + * The following causes excess digits to be printed + * out in the single-float case. Our manipulation of + * halfULP here is apparently not correct. If we + * better understand how this works, perhaps we can + * use this special case again. But for the time being, + * we do not. + * else { + * fractBits >>>= expShift+1-nFractBits; + * fractBits *= long5pow[ nTinyBits ]; + * halfULP = long5pow[ nTinyBits ] >> (1+nSignificantBits-nFractBits); + * developLongDigits( -nTinyBits, fractBits, halfULP ); + * return; + * } + */ + } + } + /* + * This is the hard case. We are going to compute large positive + * integers B and S and integer decExp, s.t. + * d = ( B / S ) * 10^decExp + * 1 <= B / S < 10 + * Obvious choices are: + * decExp = floor( log10(d) ) + * B = d * 2^nTinyBits * 10^max( 0, -decExp ) + * S = 10^max( 0, decExp) * 2^nTinyBits + * (noting that nTinyBits has already been forced to non-negative) + * I am also going to compute a large positive integer + * M = (1/2^nSignificantBits) * 2^nTinyBits * 10^max( 0, -decExp ) + * i.e. M is (1/2) of the ULP of d, scaled like B. + * When we iterate through dividing B/S and picking off the + * quotient bits, we will know when to stop when the remainder + * is <= M. + * + * We keep track of powers of 2 and powers of 5. + */ + + /* + * Estimate decimal exponent. (If it is small-ish, + * we could double-check.) + * + * First, scale the mantissa bits such that 1 <= d2 < 2. + * We are then going to estimate + * log10(d2) ~=~ (d2-1.5)/1.5 + log(1.5) + * and so we can estimate + * log10(d) ~=~ log10(d2) + binExp * log10(2) + * take the floor and call it decExp. + * FIXME -- use more precise constants here. It costs no more. + */ + double d2 = Double.longBitsToDouble( + expOne | ( fractBits &~ fractHOB ) ); + decExp = (int)Math.floor( + (d2-1.5D)*0.289529654D + 0.176091259 + (double)binExp * 0.301029995663981 ); + int B2, B5; // powers of 2 and powers of 5, respectively, in B + int S2, S5; // powers of 2 and powers of 5, respectively, in S + int M2, M5; // powers of 2 and powers of 5, respectively, in M + int Bbits; // binary digits needed to represent B, approx. + int tenSbits; // binary digits needed to represent 10*S, approx. + OldFDBigIntForTest Sval, Bval, Mval; + + B5 = Math.max( 0, -decExp ); + B2 = B5 + nTinyBits + binExp; + + S5 = Math.max( 0, decExp ); + S2 = S5 + nTinyBits; + + M5 = B5; + M2 = B2 - nSignificantBits; + + /* + * the long integer fractBits contains the (nFractBits) interesting + * bits from the mantissa of d ( hidden 1 added if necessary) followed + * by (expShift+1-nFractBits) zeros. In the interest of compactness, + * I will shift out those zeros before turning fractBits into a + * OldFDBigIntForTest. The resulting whole number will be + * d * 2^(nFractBits-1-binExp). + */ + fractBits >>>= (expShift+1-nFractBits); + B2 -= nFractBits-1; + int common2factor = Math.min( B2, S2 ); + B2 -= common2factor; + S2 -= common2factor; + M2 -= common2factor; + + /* + * HACK!! For exact powers of two, the next smallest number + * is only half as far away as we think (because the meaning of + * ULP changes at power-of-two bounds) for this reason, we + * hack M2. Hope this works. + */ + if ( nFractBits == 1 ) + M2 -= 1; + + if ( M2 < 0 ){ + // oops. + // since we cannot scale M down far enough, + // we must scale the other values up. + B2 -= M2; + S2 -= M2; + M2 = 0; + } + /* + * Construct, Scale, iterate. + * Some day, we'll write a stopping test that takes + * account of the asymmetry of the spacing of floating-point + * numbers below perfect powers of 2 + * 26 Sept 96 is not that day. + * So we use a symmetric test. + */ + char digits[] = this.digits = new char[18]; + int ndigit = 0; + boolean low, high; + long lowDigitDifference; + int q; + + /* + * Detect the special cases where all the numbers we are about + * to compute will fit in int or long integers. + * In these cases, we will avoid doing OldFDBigIntForTest arithmetic. + * We use the same algorithms, except that we "normalize" + * our OldFDBigIntForTests before iterating. This is to make division easier, + * as it makes our fist guess (quotient of high-order words) + * more accurate! + * + * Some day, we'll write a stopping test that takes + * account of the asymmetry of the spacing of floating-point + * numbers below perfect powers of 2 + * 26 Sept 96 is not that day. + * So we use a symmetric test. + */ + Bbits = nFractBits + B2 + (( B5 < n5bits.length )? n5bits[B5] : ( B5*3 )); + tenSbits = S2+1 + (( (S5+1) < n5bits.length )? n5bits[(S5+1)] : ( (S5+1)*3 )); + if ( Bbits < 64 && tenSbits < 64){ + if ( Bbits < 32 && tenSbits < 32){ + // wa-hoo! They're all ints! + int b = ((int)fractBits * small5pow[B5] ) << B2; + int s = small5pow[S5] << S2; + int m = small5pow[M5] << M2; + int tens = s * 10; + /* + * Unroll the first iteration. If our decExp estimate + * was too high, our first quotient will be zero. In this + * case, we discard it and decrement decExp. + */ + ndigit = 0; + q = b / s; + b = 10 * ( b % s ); + m *= 10; + low = (b < m ); + high = (b+m > tens ); + assert q < 10 : q; // excessively large digit + if ( (q == 0) && ! high ){ + // oops. Usually ignore leading zero. + decExp--; + } else { + digits[ndigit++] = (char)('0' + q); + } + /* + * HACK! Java spec sez that we always have at least + * one digit after the . in either F- or E-form output. + * Thus we will need more than one digit if we're using + * E-form + */ + if ( decExp < -3 || decExp >= 8 ){ + high = low = false; + } + while( ! low && ! high ){ + q = b / s; + b = 10 * ( b % s ); + m *= 10; + assert q < 10 : q; // excessively large digit + if ( m > 0L ){ + low = (b < m ); + high = (b+m > tens ); + } else { + // hack -- m might overflow! + // in this case, it is certainly > b, + // which won't + // and b+m > tens, too, since that has overflowed + // either! + low = true; + high = true; + } + digits[ndigit++] = (char)('0' + q); + } + lowDigitDifference = (b<<1) - tens; + exactDecimalConversion = (b == 0); + } else { + // still good! they're all longs! + long b = (fractBits * long5pow[B5] ) << B2; + long s = long5pow[S5] << S2; + long m = long5pow[M5] << M2; + long tens = s * 10L; + /* + * Unroll the first iteration. If our decExp estimate + * was too high, our first quotient will be zero. In this + * case, we discard it and decrement decExp. + */ + ndigit = 0; + q = (int) ( b / s ); + b = 10L * ( b % s ); + m *= 10L; + low = (b < m ); + high = (b+m > tens ); + assert q < 10 : q; // excessively large digit + if ( (q == 0) && ! high ){ + // oops. Usually ignore leading zero. + decExp--; + } else { + digits[ndigit++] = (char)('0' + q); + } + /* + * HACK! Java spec sez that we always have at least + * one digit after the . in either F- or E-form output. + * Thus we will need more than one digit if we're using + * E-form + */ + if ( decExp < -3 || decExp >= 8 ){ + high = low = false; + } + while( ! low && ! high ){ + q = (int) ( b / s ); + b = 10 * ( b % s ); + m *= 10; + assert q < 10 : q; // excessively large digit + if ( m > 0L ){ + low = (b < m ); + high = (b+m > tens ); + } else { + // hack -- m might overflow! + // in this case, it is certainly > b, + // which won't + // and b+m > tens, too, since that has overflowed + // either! + low = true; + high = true; + } + digits[ndigit++] = (char)('0' + q); + } + lowDigitDifference = (b<<1) - tens; + exactDecimalConversion = (b == 0); + } + } else { + OldFDBigIntForTest ZeroVal = new OldFDBigIntForTest(0); + OldFDBigIntForTest tenSval; + int shiftBias; + + /* + * We really must do OldFDBigIntForTest arithmetic. + * Fist, construct our OldFDBigIntForTest initial values. + */ + Bval = multPow52( new OldFDBigIntForTest( fractBits ), B5, B2 ); + Sval = constructPow52( S5, S2 ); + Mval = constructPow52( M5, M2 ); + + + // normalize so that division works better + Bval.lshiftMe( shiftBias = Sval.normalizeMe() ); + Mval.lshiftMe( shiftBias ); + tenSval = Sval.mult( 10 ); + /* + * Unroll the first iteration. If our decExp estimate + * was too high, our first quotient will be zero. In this + * case, we discard it and decrement decExp. + */ + ndigit = 0; + q = Bval.quoRemIteration( Sval ); + Mval = Mval.mult( 10 ); + low = (Bval.cmp( Mval ) < 0); + high = (Bval.add( Mval ).cmp( tenSval ) > 0 ); + assert q < 10 : q; // excessively large digit + if ( (q == 0) && ! high ){ + // oops. Usually ignore leading zero. + decExp--; + } else { + digits[ndigit++] = (char)('0' + q); + } + /* + * HACK! Java spec sez that we always have at least + * one digit after the . in either F- or E-form output. + * Thus we will need more than one digit if we're using + * E-form + */ + if ( decExp < -3 || decExp >= 8 ){ + high = low = false; + } + while( ! low && ! high ){ + q = Bval.quoRemIteration( Sval ); + Mval = Mval.mult( 10 ); + assert q < 10 : q; // excessively large digit + low = (Bval.cmp( Mval ) < 0); + high = (Bval.add( Mval ).cmp( tenSval ) > 0 ); + digits[ndigit++] = (char)('0' + q); + } + if ( high && low ){ + Bval.lshiftMe(1); + lowDigitDifference = Bval.cmp(tenSval); + } else { + lowDigitDifference = 0L; // this here only for flow analysis! + } + exactDecimalConversion = (Bval.cmp( ZeroVal ) == 0); + } + this.decExponent = decExp+1; + this.digits = digits; + this.nDigits = ndigit; + /* + * Last digit gets rounded based on stopping condition. + */ + if ( high ){ + if ( low ){ + if ( lowDigitDifference == 0L ){ + // it's a tie! + // choose based on which digits we like. + if ( (digits[nDigits-1]&1) != 0 ) roundup(); + } else if ( lowDigitDifference > 0 ){ + roundup(); + } + } else { + roundup(); + } + } + } + + public boolean decimalDigitsExact() { + return exactDecimalConversion; + } + + public String + toString(){ + // most brain-dead version + StringBuffer result = new StringBuffer( nDigits+8 ); + if ( isNegative ){ result.append( '-' ); } + if ( isExceptional ){ + result.append( digits, 0, nDigits ); + } else { + result.append( "0."); + result.append( digits, 0, nDigits ); + result.append('e'); + result.append( decExponent ); + } + return new String(result); + } + + public String toJavaFormatString() { + char result[] = perThreadBuffer.get(); + int i = getChars(result); + return new String(result, 0, i); + } + + private int getChars(char[] result) { + assert nDigits <= 19 : nDigits; // generous bound on size of nDigits + int i = 0; + if (isNegative) { result[0] = '-'; i = 1; } + if (isExceptional) { + System.arraycopy(digits, 0, result, i, nDigits); + i += nDigits; + } else { + if (decExponent > 0 && decExponent < 8) { + // print digits.digits. + int charLength = Math.min(nDigits, decExponent); + System.arraycopy(digits, 0, result, i, charLength); + i += charLength; + if (charLength < decExponent) { + charLength = decExponent-charLength; + System.arraycopy(zero, 0, result, i, charLength); + i += charLength; + result[i++] = '.'; + result[i++] = '0'; + } else { + result[i++] = '.'; + if (charLength < nDigits) { + int t = nDigits - charLength; + System.arraycopy(digits, charLength, result, i, t); + i += t; + } else { + result[i++] = '0'; + } + } + } else if (decExponent <=0 && decExponent > -3) { + result[i++] = '0'; + result[i++] = '.'; + if (decExponent != 0) { + System.arraycopy(zero, 0, result, i, -decExponent); + i -= decExponent; + } + System.arraycopy(digits, 0, result, i, nDigits); + i += nDigits; + } else { + result[i++] = digits[0]; + result[i++] = '.'; + if (nDigits > 1) { + System.arraycopy(digits, 1, result, i, nDigits-1); + i += nDigits-1; + } else { + result[i++] = '0'; + } + result[i++] = 'E'; + int e; + if (decExponent <= 0) { + result[i++] = '-'; + e = -decExponent+1; + } else { + e = decExponent-1; + } + // decExponent has 1, 2, or 3, digits + if (e <= 9) { + result[i++] = (char)(e+'0'); + } else if (e <= 99) { + result[i++] = (char)(e/10 +'0'); + result[i++] = (char)(e%10 + '0'); + } else { + result[i++] = (char)(e/100+'0'); + e %= 100; + result[i++] = (char)(e/10+'0'); + result[i++] = (char)(e%10 + '0'); + } + } + } + return i; + } + + // Per-thread buffer for string/stringbuffer conversion + private static ThreadLocal perThreadBuffer = new ThreadLocal() { + protected synchronized char[] initialValue() { + return new char[26]; + } + }; + + public void appendTo(Appendable buf) { + char result[] = perThreadBuffer.get(); + int i = getChars(result); + if (buf instanceof StringBuilder) + ((StringBuilder) buf).append(result, 0, i); + else if (buf instanceof StringBuffer) + ((StringBuffer) buf).append(result, 0, i); + else + assert false; + } + + @SuppressWarnings("fallthrough") + public static OldFloatingDecimalForTest + readJavaFormatString( String in ) throws NumberFormatException { + boolean isNegative = false; + boolean signSeen = false; + int decExp; + char c; + + parseNumber: + try{ + in = in.trim(); // don't fool around with white space. + // throws NullPointerException if null + int l = in.length(); + if ( l == 0 ) throw new NumberFormatException("empty String"); + int i = 0; + switch ( c = in.charAt( i ) ){ + case '-': + isNegative = true; + //FALLTHROUGH + case '+': + i++; + signSeen = true; + } + + // Check for NaN and Infinity strings + c = in.charAt(i); + if(c == 'N' || c == 'I') { // possible NaN or infinity + boolean potentialNaN = false; + char targetChars[] = null; // char array of "NaN" or "Infinity" + + if(c == 'N') { + targetChars = notANumber; + potentialNaN = true; + } else { + targetChars = infinity; + } + + // compare Input string to "NaN" or "Infinity" + int j = 0; + while(i < l && j < targetChars.length) { + if(in.charAt(i) == targetChars[j]) { + i++; j++; + } + else // something is amiss, throw exception + break parseNumber; + } + + // For the candidate string to be a NaN or infinity, + // all characters in input string and target char[] + // must be matched ==> j must equal targetChars.length + // and i must equal l + if( (j == targetChars.length) && (i == l) ) { // return NaN or infinity + return (potentialNaN ? new OldFloatingDecimalForTest(Double.NaN) // NaN has no sign + : new OldFloatingDecimalForTest(isNegative? + Double.NEGATIVE_INFINITY: + Double.POSITIVE_INFINITY)) ; + } + else { // something went wrong, throw exception + break parseNumber; + } + + } else if (c == '0') { // check for hexadecimal floating-point number + if (l > i+1 ) { + char ch = in.charAt(i+1); + if (ch == 'x' || ch == 'X' ) // possible hex string + return parseHexString(in); + } + } // look for and process decimal floating-point string + + char[] digits = new char[ l ]; + int nDigits= 0; + boolean decSeen = false; + int decPt = 0; + int nLeadZero = 0; + int nTrailZero= 0; + digitLoop: + while ( i < l ){ + switch ( c = in.charAt( i ) ){ + case '0': + if ( nDigits > 0 ){ + nTrailZero += 1; + } else { + nLeadZero += 1; + } + break; // out of switch. + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + while ( nTrailZero > 0 ){ + digits[nDigits++] = '0'; + nTrailZero -= 1; + } + digits[nDigits++] = c; + break; // out of switch. + case '.': + if ( decSeen ){ + // already saw one ., this is the 2nd. + throw new NumberFormatException("multiple points"); + } + decPt = i; + if ( signSeen ){ + decPt -= 1; + } + decSeen = true; + break; // out of switch. + default: + break digitLoop; + } + i++; + } + /* + * At this point, we've scanned all the digits and decimal + * point we're going to see. Trim off leading and trailing + * zeros, which will just confuse us later, and adjust + * our initial decimal exponent accordingly. + * To review: + * we have seen i total characters. + * nLeadZero of them were zeros before any other digits. + * nTrailZero of them were zeros after any other digits. + * if ( decSeen ), then a . was seen after decPt characters + * ( including leading zeros which have been discarded ) + * nDigits characters were neither lead nor trailing + * zeros, nor point + */ + /* + * special hack: if we saw no non-zero digits, then the + * answer is zero! + * Unfortunately, we feel honor-bound to keep parsing! + */ + if ( nDigits == 0 ){ + digits = zero; + nDigits = 1; + if ( nLeadZero == 0 ){ + // we saw NO DIGITS AT ALL, + // not even a crummy 0! + // this is not allowed. + break parseNumber; // go throw exception + } + + } + + /* Our initial exponent is decPt, adjusted by the number of + * discarded zeros. Or, if there was no decPt, + * then its just nDigits adjusted by discarded trailing zeros. + */ + if ( decSeen ){ + decExp = decPt - nLeadZero; + } else { + decExp = nDigits+nTrailZero; + } + + /* + * Look for 'e' or 'E' and an optionally signed integer. + */ + if ( (i < l) && (((c = in.charAt(i) )=='e') || (c == 'E') ) ){ + int expSign = 1; + int expVal = 0; + int reallyBig = Integer.MAX_VALUE / 10; + boolean expOverflow = false; + switch( in.charAt(++i) ){ + case '-': + expSign = -1; + //FALLTHROUGH + case '+': + i++; + } + int expAt = i; + expLoop: + while ( i < l ){ + if ( expVal >= reallyBig ){ + // the next character will cause integer + // overflow. + expOverflow = true; + } + switch ( c = in.charAt(i++) ){ + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + expVal = expVal*10 + ( (int)c - (int)'0' ); + continue; + default: + i--; // back up. + break expLoop; // stop parsing exponent. + } + } + int expLimit = bigDecimalExponent+nDigits+nTrailZero; + if ( expOverflow || ( expVal > expLimit ) ){ + // + // The intent here is to end up with + // infinity or zero, as appropriate. + // The reason for yielding such a small decExponent, + // rather than something intuitive such as + // expSign*Integer.MAX_VALUE, is that this value + // is subject to further manipulation in + // doubleValue() and floatValue(), and I don't want + // it to be able to cause overflow there! + // (The only way we can get into trouble here is for + // really outrageous nDigits+nTrailZero, such as 2 billion. ) + // + decExp = expSign*expLimit; + } else { + // this should not overflow, since we tested + // for expVal > (MAX+N), where N >= abs(decExp) + decExp = decExp + expSign*expVal; + } + + // if we saw something not a digit ( or end of string ) + // after the [Ee][+-], without seeing any digits at all + // this is certainly an error. If we saw some digits, + // but then some trailing garbage, that might be ok. + // so we just fall through in that case. + // HUMBUG + if ( i == expAt ) + break parseNumber; // certainly bad + } + /* + * We parsed everything we could. + * If there are leftovers, then this is not good input! + */ + if ( i < l && + ((i != l - 1) || + (in.charAt(i) != 'f' && + in.charAt(i) != 'F' && + in.charAt(i) != 'd' && + in.charAt(i) != 'D'))) { + break parseNumber; // go throw exception + } + + return new OldFloatingDecimalForTest( isNegative, decExp, digits, nDigits, false ); + } catch ( StringIndexOutOfBoundsException e ){ } + throw new NumberFormatException("For input string: \"" + in + "\""); + } + + /* + * Take a FloatingDecimal, which we presumably just scanned in, + * and find out what its value is, as a double. + * + * AS A SIDE EFFECT, SET roundDir TO INDICATE PREFERRED + * ROUNDING DIRECTION in case the result is really destined + * for a single-precision float. + */ + + public strictfp double doubleValue(){ + int kDigits = Math.min( nDigits, maxDecimalDigits+1 ); + long lValue; + double dValue; + double rValue, tValue; + + // First, check for NaN and Infinity values + if(digits == infinity || digits == notANumber) { + if(digits == notANumber) + return Double.NaN; + else + return (isNegative?Double.NEGATIVE_INFINITY:Double.POSITIVE_INFINITY); + } + else { + if (mustSetRoundDir) { + roundDir = 0; + } + /* + * convert the lead kDigits to a long integer. + */ + // (special performance hack: start to do it using int) + int iValue = (int)digits[0]-(int)'0'; + int iDigits = Math.min( kDigits, intDecimalDigits ); + for ( int i=1; i < iDigits; i++ ){ + iValue = iValue*10 + (int)digits[i]-(int)'0'; + } + lValue = (long)iValue; + for ( int i=iDigits; i < kDigits; i++ ){ + lValue = lValue*10L + (long)((int)digits[i]-(int)'0'); + } + dValue = (double)lValue; + int exp = decExponent-kDigits; + /* + * lValue now contains a long integer with the value of + * the first kDigits digits of the number. + * dValue contains the (double) of the same. + */ + + if ( nDigits <= maxDecimalDigits ){ + /* + * possibly an easy case. + * We know that the digits can be represented + * exactly. And if the exponent isn't too outrageous, + * the whole thing can be done with one operation, + * thus one rounding error. + * Note that all our constructors trim all leading and + * trailing zeros, so simple values (including zero) + * will always end up here + */ + if (exp == 0 || dValue == 0.0) + return (isNegative)? -dValue : dValue; // small floating integer + else if ( exp >= 0 ){ + if ( exp <= maxSmallTen ){ + /* + * Can get the answer with one operation, + * thus one roundoff. + */ + rValue = dValue * small10pow[exp]; + if ( mustSetRoundDir ){ + tValue = rValue / small10pow[exp]; + roundDir = ( tValue == dValue ) ? 0 + :( tValue < dValue ) ? 1 + : -1; + } + return (isNegative)? -rValue : rValue; + } + int slop = maxDecimalDigits - kDigits; + if ( exp <= maxSmallTen+slop ){ + /* + * We can multiply dValue by 10^(slop) + * and it is still "small" and exact. + * Then we can multiply by 10^(exp-slop) + * with one rounding. + */ + dValue *= small10pow[slop]; + rValue = dValue * small10pow[exp-slop]; + + if ( mustSetRoundDir ){ + tValue = rValue / small10pow[exp-slop]; + roundDir = ( tValue == dValue ) ? 0 + :( tValue < dValue ) ? 1 + : -1; + } + return (isNegative)? -rValue : rValue; + } + /* + * Else we have a hard case with a positive exp. + */ + } else { + if ( exp >= -maxSmallTen ){ + /* + * Can get the answer in one division. + */ + rValue = dValue / small10pow[-exp]; + tValue = rValue * small10pow[-exp]; + if ( mustSetRoundDir ){ + roundDir = ( tValue == dValue ) ? 0 + :( tValue < dValue ) ? 1 + : -1; + } + return (isNegative)? -rValue : rValue; + } + /* + * Else we have a hard case with a negative exp. + */ + } + } + + /* + * Harder cases: + * The sum of digits plus exponent is greater than + * what we think we can do with one error. + * + * Start by approximating the right answer by, + * naively, scaling by powers of 10. + */ + if ( exp > 0 ){ + if ( decExponent > maxDecimalExponent+1 ){ + /* + * Lets face it. This is going to be + * Infinity. Cut to the chase. + */ + return (isNegative)? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY; + } + if ( (exp&15) != 0 ){ + dValue *= small10pow[exp&15]; + } + if ( (exp>>=4) != 0 ){ + int j; + for( j = 0; exp > 1; j++, exp>>=1 ){ + if ( (exp&1)!=0) + dValue *= big10pow[j]; + } + /* + * The reason for the weird exp > 1 condition + * in the above loop was so that the last multiply + * would get unrolled. We handle it here. + * It could overflow. + */ + double t = dValue * big10pow[j]; + if ( Double.isInfinite( t ) ){ + /* + * It did overflow. + * Look more closely at the result. + * If the exponent is just one too large, + * then use the maximum finite as our estimate + * value. Else call the result infinity + * and punt it. + * ( I presume this could happen because + * rounding forces the result here to be + * an ULP or two larger than + * Double.MAX_VALUE ). + */ + t = dValue / 2.0; + t *= big10pow[j]; + if ( Double.isInfinite( t ) ){ + return (isNegative)? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY; + } + t = Double.MAX_VALUE; + } + dValue = t; + } + } else if ( exp < 0 ){ + exp = -exp; + if ( decExponent < minDecimalExponent-1 ){ + /* + * Lets face it. This is going to be + * zero. Cut to the chase. + */ + return (isNegative)? -0.0 : 0.0; + } + if ( (exp&15) != 0 ){ + dValue /= small10pow[exp&15]; + } + if ( (exp>>=4) != 0 ){ + int j; + for( j = 0; exp > 1; j++, exp>>=1 ){ + if ( (exp&1)!=0) + dValue *= tiny10pow[j]; + } + /* + * The reason for the weird exp > 1 condition + * in the above loop was so that the last multiply + * would get unrolled. We handle it here. + * It could underflow. + */ + double t = dValue * tiny10pow[j]; + if ( t == 0.0 ){ + /* + * It did underflow. + * Look more closely at the result. + * If the exponent is just one too small, + * then use the minimum finite as our estimate + * value. Else call the result 0.0 + * and punt it. + * ( I presume this could happen because + * rounding forces the result here to be + * an ULP or two less than + * Double.MIN_VALUE ). + */ + t = dValue * 2.0; + t *= tiny10pow[j]; + if ( t == 0.0 ){ + return (isNegative)? -0.0 : 0.0; + } + t = Double.MIN_VALUE; + } + dValue = t; + } + } + + /* + * dValue is now approximately the result. + * The hard part is adjusting it, by comparison + * with OldFDBigIntForTest arithmetic. + * Formulate the EXACT big-number result as + * bigD0 * 10^exp + */ + OldFDBigIntForTest bigD0 = new OldFDBigIntForTest( lValue, digits, kDigits, nDigits ); + exp = decExponent - nDigits; + + correctionLoop: + while(true){ + /* AS A SIDE EFFECT, THIS METHOD WILL SET THE INSTANCE VARIABLES + * bigIntExp and bigIntNBits + */ + OldFDBigIntForTest bigB = doubleToBigInt( dValue ); + + /* + * Scale bigD, bigB appropriately for + * big-integer operations. + * Naively, we multiply by powers of ten + * and powers of two. What we actually do + * is keep track of the powers of 5 and + * powers of 2 we would use, then factor out + * common divisors before doing the work. + */ + int B2, B5; // powers of 2, 5 in bigB + int D2, D5; // powers of 2, 5 in bigD + int Ulp2; // powers of 2 in halfUlp. + if ( exp >= 0 ){ + B2 = B5 = 0; + D2 = D5 = exp; + } else { + B2 = B5 = -exp; + D2 = D5 = 0; + } + if ( bigIntExp >= 0 ){ + B2 += bigIntExp; + } else { + D2 -= bigIntExp; + } + Ulp2 = B2; + // shift bigB and bigD left by a number s. t. + // halfUlp is still an integer. + int hulpbias; + if ( bigIntExp+bigIntNBits <= -expBias+1 ){ + // This is going to be a denormalized number + // (if not actually zero). + // half an ULP is at 2^-(expBias+expShift+1) + hulpbias = bigIntExp+ expBias + expShift; + } else { + hulpbias = expShift + 2 - bigIntNBits; + } + B2 += hulpbias; + D2 += hulpbias; + // if there are common factors of 2, we might just as well + // factor them out, as they add nothing useful. + int common2 = Math.min( B2, Math.min( D2, Ulp2 ) ); + B2 -= common2; + D2 -= common2; + Ulp2 -= common2; + // do multiplications by powers of 5 and 2 + bigB = multPow52( bigB, B5, B2 ); + OldFDBigIntForTest bigD = multPow52( new OldFDBigIntForTest( bigD0 ), D5, D2 ); + // + // to recap: + // bigB is the scaled-big-int version of our floating-point + // candidate. + // bigD is the scaled-big-int version of the exact value + // as we understand it. + // halfUlp is 1/2 an ulp of bigB, except for special cases + // of exact powers of 2 + // + // the plan is to compare bigB with bigD, and if the difference + // is less than halfUlp, then we're satisfied. Otherwise, + // use the ratio of difference to halfUlp to calculate a fudge + // factor to add to the floating value, then go 'round again. + // + OldFDBigIntForTest diff; + int cmpResult; + boolean overvalue; + if ( (cmpResult = bigB.cmp( bigD ) ) > 0 ){ + overvalue = true; // our candidate is too big. + diff = bigB.sub( bigD ); + if ( (bigIntNBits == 1) && (bigIntExp > -expBias+1) ){ + // candidate is a normalized exact power of 2 and + // is too big. We will be subtracting. + // For our purposes, ulp is the ulp of the + // next smaller range. + Ulp2 -= 1; + if ( Ulp2 < 0 ){ + // rats. Cannot de-scale ulp this far. + // must scale diff in other direction. + Ulp2 = 0; + diff.lshiftMe( 1 ); + } + } + } else if ( cmpResult < 0 ){ + overvalue = false; // our candidate is too small. + diff = bigD.sub( bigB ); + } else { + // the candidate is exactly right! + // this happens with surprising frequency + break correctionLoop; + } + OldFDBigIntForTest halfUlp = constructPow52( B5, Ulp2 ); + if ( (cmpResult = diff.cmp( halfUlp ) ) < 0 ){ + // difference is small. + // this is close enough + if (mustSetRoundDir) { + roundDir = overvalue ? -1 : 1; + } + break correctionLoop; + } else if ( cmpResult == 0 ){ + // difference is exactly half an ULP + // round to some other value maybe, then finish + dValue += 0.5*ulp( dValue, overvalue ); + // should check for bigIntNBits == 1 here?? + if (mustSetRoundDir) { + roundDir = overvalue ? -1 : 1; + } + break correctionLoop; + } else { + // difference is non-trivial. + // could scale addend by ratio of difference to + // halfUlp here, if we bothered to compute that difference. + // Most of the time ( I hope ) it is about 1 anyway. + dValue += ulp( dValue, overvalue ); + if ( dValue == 0.0 || dValue == Double.POSITIVE_INFINITY ) + break correctionLoop; // oops. Fell off end of range. + continue; // try again. + } + + } + return (isNegative)? -dValue : dValue; + } + } + + /* + * Take a FloatingDecimal, which we presumably just scanned in, + * and find out what its value is, as a float. + * This is distinct from doubleValue() to avoid the extremely + * unlikely case of a double rounding error, wherein the conversion + * to double has one rounding error, and the conversion of that double + * to a float has another rounding error, IN THE WRONG DIRECTION, + * ( because of the preference to a zero low-order bit ). + */ + + public strictfp float floatValue(){ + int kDigits = Math.min( nDigits, singleMaxDecimalDigits+1 ); + int iValue; + float fValue; + + // First, check for NaN and Infinity values + if(digits == infinity || digits == notANumber) { + if(digits == notANumber) + return Float.NaN; + else + return (isNegative?Float.NEGATIVE_INFINITY:Float.POSITIVE_INFINITY); + } + else { + /* + * convert the lead kDigits to an integer. + */ + iValue = (int)digits[0]-(int)'0'; + for ( int i=1; i < kDigits; i++ ){ + iValue = iValue*10 + (int)digits[i]-(int)'0'; + } + fValue = (float)iValue; + int exp = decExponent-kDigits; + /* + * iValue now contains an integer with the value of + * the first kDigits digits of the number. + * fValue contains the (float) of the same. + */ + + if ( nDigits <= singleMaxDecimalDigits ){ + /* + * possibly an easy case. + * We know that the digits can be represented + * exactly. And if the exponent isn't too outrageous, + * the whole thing can be done with one operation, + * thus one rounding error. + * Note that all our constructors trim all leading and + * trailing zeros, so simple values (including zero) + * will always end up here. + */ + if (exp == 0 || fValue == 0.0f) + return (isNegative)? -fValue : fValue; // small floating integer + else if ( exp >= 0 ){ + if ( exp <= singleMaxSmallTen ){ + /* + * Can get the answer with one operation, + * thus one roundoff. + */ + fValue *= singleSmall10pow[exp]; + return (isNegative)? -fValue : fValue; + } + int slop = singleMaxDecimalDigits - kDigits; + if ( exp <= singleMaxSmallTen+slop ){ + /* + * We can multiply dValue by 10^(slop) + * and it is still "small" and exact. + * Then we can multiply by 10^(exp-slop) + * with one rounding. + */ + fValue *= singleSmall10pow[slop]; + fValue *= singleSmall10pow[exp-slop]; + return (isNegative)? -fValue : fValue; + } + /* + * Else we have a hard case with a positive exp. + */ + } else { + if ( exp >= -singleMaxSmallTen ){ + /* + * Can get the answer in one division. + */ + fValue /= singleSmall10pow[-exp]; + return (isNegative)? -fValue : fValue; + } + /* + * Else we have a hard case with a negative exp. + */ + } + } else if ( (decExponent >= nDigits) && (nDigits+decExponent <= maxDecimalDigits) ){ + /* + * In double-precision, this is an exact floating integer. + * So we can compute to double, then shorten to float + * with one round, and get the right answer. + * + * First, finish accumulating digits. + * Then convert that integer to a double, multiply + * by the appropriate power of ten, and convert to float. + */ + long lValue = (long)iValue; + for ( int i=kDigits; i < nDigits; i++ ){ + lValue = lValue*10L + (long)((int)digits[i]-(int)'0'); + } + double dValue = (double)lValue; + exp = decExponent-nDigits; + dValue *= small10pow[exp]; + fValue = (float)dValue; + return (isNegative)? -fValue : fValue; + + } + /* + * Harder cases: + * The sum of digits plus exponent is greater than + * what we think we can do with one error. + * + * Start by weeding out obviously out-of-range + * results, then convert to double and go to + * common hard-case code. + */ + if ( decExponent > singleMaxDecimalExponent+1 ){ + /* + * Lets face it. This is going to be + * Infinity. Cut to the chase. + */ + return (isNegative)? Float.NEGATIVE_INFINITY : Float.POSITIVE_INFINITY; + } else if ( decExponent < singleMinDecimalExponent-1 ){ + /* + * Lets face it. This is going to be + * zero. Cut to the chase. + */ + return (isNegative)? -0.0f : 0.0f; + } + + /* + * Here, we do 'way too much work, but throwing away + * our partial results, and going and doing the whole + * thing as double, then throwing away half the bits that computes + * when we convert back to float. + * + * The alternative is to reproduce the whole multiple-precision + * algorithm for float precision, or to try to parameterize it + * for common usage. The former will take about 400 lines of code, + * and the latter I tried without success. Thus the semi-hack + * answer here. + */ + mustSetRoundDir = !fromHex; + double dValue = doubleValue(); + return stickyRound( dValue ); + } + } + + + /* + * All the positive powers of 10 that can be + * represented exactly in double/float. + */ + private static final double small10pow[] = { + 1.0e0, + 1.0e1, 1.0e2, 1.0e3, 1.0e4, 1.0e5, + 1.0e6, 1.0e7, 1.0e8, 1.0e9, 1.0e10, + 1.0e11, 1.0e12, 1.0e13, 1.0e14, 1.0e15, + 1.0e16, 1.0e17, 1.0e18, 1.0e19, 1.0e20, + 1.0e21, 1.0e22 + }; + + private static final float singleSmall10pow[] = { + 1.0e0f, + 1.0e1f, 1.0e2f, 1.0e3f, 1.0e4f, 1.0e5f, + 1.0e6f, 1.0e7f, 1.0e8f, 1.0e9f, 1.0e10f + }; + + private static final double big10pow[] = { + 1e16, 1e32, 1e64, 1e128, 1e256 }; + private static final double tiny10pow[] = { + 1e-16, 1e-32, 1e-64, 1e-128, 1e-256 }; + + private static final int maxSmallTen = small10pow.length-1; + private static final int singleMaxSmallTen = singleSmall10pow.length-1; + + private static final int small5pow[] = { + 1, + 5, + 5*5, + 5*5*5, + 5*5*5*5, + 5*5*5*5*5, + 5*5*5*5*5*5, + 5*5*5*5*5*5*5, + 5*5*5*5*5*5*5*5, + 5*5*5*5*5*5*5*5*5, + 5*5*5*5*5*5*5*5*5*5, + 5*5*5*5*5*5*5*5*5*5*5, + 5*5*5*5*5*5*5*5*5*5*5*5, + 5*5*5*5*5*5*5*5*5*5*5*5*5 + }; + + + private static final long long5pow[] = { + 1L, + 5L, + 5L*5, + 5L*5*5, + 5L*5*5*5, + 5L*5*5*5*5, + 5L*5*5*5*5*5, + 5L*5*5*5*5*5*5, + 5L*5*5*5*5*5*5*5, + 5L*5*5*5*5*5*5*5*5, + 5L*5*5*5*5*5*5*5*5*5, + 5L*5*5*5*5*5*5*5*5*5*5, + 5L*5*5*5*5*5*5*5*5*5*5*5, + 5L*5*5*5*5*5*5*5*5*5*5*5*5, + 5L*5*5*5*5*5*5*5*5*5*5*5*5*5, + 5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5, + 5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5, + 5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5, + 5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5, + 5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5, + 5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5, + 5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5, + 5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5, + 5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5, + 5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5, + 5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5, + 5L*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5*5, + }; + + // approximately ceil( log2( long5pow[i] ) ) + private static final int n5bits[] = { + 0, + 3, + 5, + 7, + 10, + 12, + 14, + 17, + 19, + 21, + 24, + 26, + 28, + 31, + 33, + 35, + 38, + 40, + 42, + 45, + 47, + 49, + 52, + 54, + 56, + 59, + 61, + }; + + private static final char infinity[] = { 'I', 'n', 'f', 'i', 'n', 'i', 't', 'y' }; + private static final char notANumber[] = { 'N', 'a', 'N' }; + private static final char zero[] = { '0', '0', '0', '0', '0', '0', '0', '0' }; + + + /* + * Grammar is compatible with hexadecimal floating-point constants + * described in section 6.4.4.2 of the C99 specification. + */ + private static Pattern hexFloatPattern = null; + private static synchronized Pattern getHexFloatPattern() { + if (hexFloatPattern == null) { + hexFloatPattern = Pattern.compile( + //1 234 56 7 8 9 + "([-+])?0[xX](((\\p{XDigit}+)\\.?)|((\\p{XDigit}*)\\.(\\p{XDigit}+)))[pP]([-+])?(\\p{Digit}+)[fFdD]?" + ); + } + return hexFloatPattern; + } + + /* + * Convert string s to a suitable floating decimal; uses the + * double constructor and set the roundDir variable appropriately + * in case the value is later converted to a float. + */ + static OldFloatingDecimalForTest parseHexString(String s) { + // Verify string is a member of the hexadecimal floating-point + // string language. + Matcher m = getHexFloatPattern().matcher(s); + boolean validInput = m.matches(); + + if (!validInput) { + // Input does not match pattern + throw new NumberFormatException("For input string: \"" + s + "\""); + } else { // validInput + /* + * We must isolate the sign, significand, and exponent + * fields. The sign value is straightforward. Since + * floating-point numbers are stored with a normalized + * representation, the significand and exponent are + * interrelated. + * + * After extracting the sign, we normalized the + * significand as a hexadecimal value, calculating an + * exponent adjust for any shifts made during + * normalization. If the significand is zero, the + * exponent doesn't need to be examined since the output + * will be zero. + * + * Next the exponent in the input string is extracted. + * Afterwards, the significand is normalized as a *binary* + * value and the input value's normalized exponent can be + * computed. The significand bits are copied into a + * double significand; if the string has more logical bits + * than can fit in a double, the extra bits affect the + * round and sticky bits which are used to round the final + * value. + */ + + // Extract significand sign + String group1 = m.group(1); + double sign = (( group1 == null ) || group1.equals("+"))? 1.0 : -1.0; + + + // Extract Significand magnitude + /* + * Based on the form of the significand, calculate how the + * binary exponent needs to be adjusted to create a + * normalized *hexadecimal* floating-point number; that + * is, a number where there is one nonzero hex digit to + * the left of the (hexa)decimal point. Since we are + * adjusting a binary, not hexadecimal exponent, the + * exponent is adjusted by a multiple of 4. + * + * There are a number of significand scenarios to consider; + * letters are used in indicate nonzero digits: + * + * 1. 000xxxx => x.xxx normalized + * increase exponent by (number of x's - 1)*4 + * + * 2. 000xxx.yyyy => x.xxyyyy normalized + * increase exponent by (number of x's - 1)*4 + * + * 3. .000yyy => y.yy normalized + * decrease exponent by (number of zeros + 1)*4 + * + * 4. 000.00000yyy => y.yy normalized + * decrease exponent by (number of zeros to right of point + 1)*4 + * + * If the significand is exactly zero, return a properly + * signed zero. + */ + + String significandString =null; + int signifLength = 0; + int exponentAdjust = 0; + { + int leftDigits = 0; // number of meaningful digits to + // left of "decimal" point + // (leading zeros stripped) + int rightDigits = 0; // number of digits to right of + // "decimal" point; leading zeros + // must always be accounted for + /* + * The significand is made up of either + * + * 1. group 4 entirely (integer portion only) + * + * OR + * + * 2. the fractional portion from group 7 plus any + * (optional) integer portions from group 6. + */ + String group4; + if( (group4 = m.group(4)) != null) { // Integer-only significand + // Leading zeros never matter on the integer portion + significandString = stripLeadingZeros(group4); + leftDigits = significandString.length(); + } + else { + // Group 6 is the optional integer; leading zeros + // never matter on the integer portion + String group6 = stripLeadingZeros(m.group(6)); + leftDigits = group6.length(); + + // fraction + String group7 = m.group(7); + rightDigits = group7.length(); + + // Turn "integer.fraction" into "integer"+"fraction" + significandString = + ((group6 == null)?"":group6) + // is the null + // check necessary? + group7; + } + + significandString = stripLeadingZeros(significandString); + signifLength = significandString.length(); + + /* + * Adjust exponent as described above + */ + if (leftDigits >= 1) { // Cases 1 and 2 + exponentAdjust = 4*(leftDigits - 1); + } else { // Cases 3 and 4 + exponentAdjust = -4*( rightDigits - signifLength + 1); + } + + // If the significand is zero, the exponent doesn't + // matter; return a properly signed zero. + + if (signifLength == 0) { // Only zeros in input + return new OldFloatingDecimalForTest(sign * 0.0); + } + } + + // Extract Exponent + /* + * Use an int to read in the exponent value; this should + * provide more than sufficient range for non-contrived + * inputs. If reading the exponent in as an int does + * overflow, examine the sign of the exponent and + * significand to determine what to do. + */ + String group8 = m.group(8); + boolean positiveExponent = ( group8 == null ) || group8.equals("+"); + long unsignedRawExponent; + try { + unsignedRawExponent = Integer.parseInt(m.group(9)); + } + catch (NumberFormatException e) { + // At this point, we know the exponent is + // syntactically well-formed as a sequence of + // digits. Therefore, if an NumberFormatException + // is thrown, it must be due to overflowing int's + // range. Also, at this point, we have already + // checked for a zero significand. Thus the signs + // of the exponent and significand determine the + // final result: + // + // significand + // + - + // exponent + +infinity -infinity + // - +0.0 -0.0 + return new OldFloatingDecimalForTest(sign * (positiveExponent ? + Double.POSITIVE_INFINITY : 0.0)); + } + + long rawExponent = + (positiveExponent ? 1L : -1L) * // exponent sign + unsignedRawExponent; // exponent magnitude + + // Calculate partially adjusted exponent + long exponent = rawExponent + exponentAdjust ; + + // Starting copying non-zero bits into proper position in + // a long; copy explicit bit too; this will be masked + // later for normal values. + + boolean round = false; + boolean sticky = false; + int bitsCopied=0; + int nextShift=0; + long significand=0L; + // First iteration is different, since we only copy + // from the leading significand bit; one more exponent + // adjust will be needed... + + // IMPORTANT: make leadingDigit a long to avoid + // surprising shift semantics! + long leadingDigit = getHexDigit(significandString, 0); + + /* + * Left shift the leading digit (53 - (bit position of + * leading 1 in digit)); this sets the top bit of the + * significand to 1. The nextShift value is adjusted + * to take into account the number of bit positions of + * the leadingDigit actually used. Finally, the + * exponent is adjusted to normalize the significand + * as a binary value, not just a hex value. + */ + if (leadingDigit == 1) { + significand |= leadingDigit << 52; + nextShift = 52 - 4; + /* exponent += 0 */ } + else if (leadingDigit <= 3) { // [2, 3] + significand |= leadingDigit << 51; + nextShift = 52 - 5; + exponent += 1; + } + else if (leadingDigit <= 7) { // [4, 7] + significand |= leadingDigit << 50; + nextShift = 52 - 6; + exponent += 2; + } + else if (leadingDigit <= 15) { // [8, f] + significand |= leadingDigit << 49; + nextShift = 52 - 7; + exponent += 3; + } else { + throw new AssertionError("Result from digit conversion too large!"); + } + // The preceding if-else could be replaced by a single + // code block based on the high-order bit set in + // leadingDigit. Given leadingOnePosition, + + // significand |= leadingDigit << (SIGNIFICAND_WIDTH - leadingOnePosition); + // nextShift = 52 - (3 + leadingOnePosition); + // exponent += (leadingOnePosition-1); + + + /* + * Now the exponent variable is equal to the normalized + * binary exponent. Code below will make representation + * adjustments if the exponent is incremented after + * rounding (includes overflows to infinity) or if the + * result is subnormal. + */ + + // Copy digit into significand until the significand can't + // hold another full hex digit or there are no more input + // hex digits. + int i = 0; + for(i = 1; + i < signifLength && nextShift >= 0; + i++) { + long currentDigit = getHexDigit(significandString, i); + significand |= (currentDigit << nextShift); + nextShift-=4; + } + + // After the above loop, the bulk of the string is copied. + // Now, we must copy any partial hex digits into the + // significand AND compute the round bit and start computing + // sticky bit. + + if ( i < signifLength ) { // at least one hex input digit exists + long currentDigit = getHexDigit(significandString, i); + + // from nextShift, figure out how many bits need + // to be copied, if any + switch(nextShift) { // must be negative + case -1: + // three bits need to be copied in; can + // set round bit + significand |= ((currentDigit & 0xEL) >> 1); + round = (currentDigit & 0x1L) != 0L; + break; + + case -2: + // two bits need to be copied in; can + // set round and start sticky + significand |= ((currentDigit & 0xCL) >> 2); + round = (currentDigit &0x2L) != 0L; + sticky = (currentDigit & 0x1L) != 0; + break; + + case -3: + // one bit needs to be copied in + significand |= ((currentDigit & 0x8L)>>3); + // Now set round and start sticky, if possible + round = (currentDigit &0x4L) != 0L; + sticky = (currentDigit & 0x3L) != 0; + break; + + case -4: + // all bits copied into significand; set + // round and start sticky + round = ((currentDigit & 0x8L) != 0); // is top bit set? + // nonzeros in three low order bits? + sticky = (currentDigit & 0x7L) != 0; + break; + + default: + throw new AssertionError("Unexpected shift distance remainder."); + // break; + } + + // Round is set; sticky might be set. + + // For the sticky bit, it suffices to check the + // current digit and test for any nonzero digits in + // the remaining unprocessed input. + i++; + while(i < signifLength && !sticky) { + currentDigit = getHexDigit(significandString,i); + sticky = sticky || (currentDigit != 0); + i++; + } + + } + // else all of string was seen, round and sticky are + // correct as false. + + + // Check for overflow and update exponent accordingly. + + if (exponent > DoubleConsts.MAX_EXPONENT) { // Infinite result + // overflow to properly signed infinity + return new OldFloatingDecimalForTest(sign * Double.POSITIVE_INFINITY); + } else { // Finite return value + if (exponent <= DoubleConsts.MAX_EXPONENT && // (Usually) normal result + exponent >= DoubleConsts.MIN_EXPONENT) { + + // The result returned in this block cannot be a + // zero or subnormal; however after the + // significand is adjusted from rounding, we could + // still overflow in infinity. + + // AND exponent bits into significand; if the + // significand is incremented and overflows from + // rounding, this combination will update the + // exponent correctly, even in the case of + // Double.MAX_VALUE overflowing to infinity. + + significand = (( (exponent + + (long)DoubleConsts.EXP_BIAS) << + (DoubleConsts.SIGNIFICAND_WIDTH-1)) + & DoubleConsts.EXP_BIT_MASK) | + (DoubleConsts.SIGNIF_BIT_MASK & significand); + + } else { // Subnormal or zero + // (exponent < DoubleConsts.MIN_EXPONENT) + + if (exponent < (DoubleConsts.MIN_SUB_EXPONENT -1 )) { + // No way to round back to nonzero value + // regardless of significand if the exponent is + // less than -1075. + return new OldFloatingDecimalForTest(sign * 0.0); + } else { // -1075 <= exponent <= MIN_EXPONENT -1 = -1023 + /* + * Find bit position to round to; recompute + * round and sticky bits, and shift + * significand right appropriately. + */ + + sticky = sticky || round; + round = false; + + // Number of bits of significand to preserve is + // exponent - abs_min_exp +1 + // check: + // -1075 +1074 + 1 = 0 + // -1023 +1074 + 1 = 52 + + int bitsDiscarded = 53 - + ((int)exponent - DoubleConsts.MIN_SUB_EXPONENT + 1); + assert bitsDiscarded >= 1 && bitsDiscarded <= 53; + + // What to do here: + // First, isolate the new round bit + round = (significand & (1L << (bitsDiscarded -1))) != 0L; + if (bitsDiscarded > 1) { + // create mask to update sticky bits; low + // order bitsDiscarded bits should be 1 + long mask = ~((~0L) << (bitsDiscarded -1)); + sticky = sticky || ((significand & mask) != 0L ) ; + } + + // Now, discard the bits + significand = significand >> bitsDiscarded; + + significand = (( ((long)(DoubleConsts.MIN_EXPONENT -1) + // subnorm exp. + (long)DoubleConsts.EXP_BIAS) << + (DoubleConsts.SIGNIFICAND_WIDTH-1)) + & DoubleConsts.EXP_BIT_MASK) | + (DoubleConsts.SIGNIF_BIT_MASK & significand); + } + } + + // The significand variable now contains the currently + // appropriate exponent bits too. + + /* + * Determine if significand should be incremented; + * making this determination depends on the least + * significant bit and the round and sticky bits. + * + * Round to nearest even rounding table, adapted from + * table 4.7 in "Computer Arithmetic" by IsraelKoren. + * The digit to the left of the "decimal" point is the + * least significant bit, the digits to the right of + * the point are the round and sticky bits + * + * Number Round(x) + * x0.00 x0. + * x0.01 x0. + * x0.10 x0. + * x0.11 x1. = x0. +1 + * x1.00 x1. + * x1.01 x1. + * x1.10 x1. + 1 + * x1.11 x1. + 1 + */ + boolean incremented = false; + boolean leastZero = ((significand & 1L) == 0L); + if( ( leastZero && round && sticky ) || + ((!leastZero) && round )) { + incremented = true; + significand++; + } + + OldFloatingDecimalForTest fd = new OldFloatingDecimalForTest(Math.copySign( + Double.longBitsToDouble(significand), + sign)); + + /* + * Set roundingDir variable field of fd properly so + * that the input string can be properly rounded to a + * float value. There are two cases to consider: + * + * 1. rounding to double discards sticky bit + * information that would change the result of a float + * rounding (near halfway case between two floats) + * + * 2. rounding to double rounds up when rounding up + * would not occur when rounding to float. + * + * For former case only needs to be considered when + * the bits rounded away when casting to float are all + * zero; otherwise, float round bit is properly set + * and sticky will already be true. + * + * The lower exponent bound for the code below is the + * minimum (normalized) subnormal exponent - 1 since a + * value with that exponent can round up to the + * minimum subnormal value and the sticky bit + * information must be preserved (i.e. case 1). + */ + if ((exponent >= FloatConsts.MIN_SUB_EXPONENT-1) && + (exponent <= FloatConsts.MAX_EXPONENT ) ){ + // Outside above exponent range, the float value + // will be zero or infinity. + + /* + * If the low-order 28 bits of a rounded double + * significand are 0, the double could be a + * half-way case for a rounding to float. If the + * double value is a half-way case, the double + * significand may have to be modified to round + * the the right float value (see the stickyRound + * method). If the rounding to double has lost + * what would be float sticky bit information, the + * double significand must be incremented. If the + * double value's significand was itself + * incremented, the float value may end up too + * large so the increment should be undone. + */ + if ((significand & 0xfffffffL) == 0x0L) { + // For negative values, the sign of the + // roundDir is the same as for positive values + // since adding 1 increasing the significand's + // magnitude and subtracting 1 decreases the + // significand's magnitude. If neither round + // nor sticky is true, the double value is + // exact and no adjustment is required for a + // proper float rounding. + if( round || sticky) { + if (leastZero) { // prerounding lsb is 0 + // If round and sticky were both true, + // and the least significant + // significand bit were 0, the rounded + // significand would not have its + // low-order bits be zero. Therefore, + // we only need to adjust the + // significand if round XOR sticky is + // true. + if (round ^ sticky) { + fd.roundDir = 1; + } + } + else { // prerounding lsb is 1 + // If the prerounding lsb is 1 and the + // resulting significand has its + // low-order bits zero, the significand + // was incremented. Here, we undo the + // increment, which will ensure the + // right guard and sticky bits for the + // float rounding. + if (round) + fd.roundDir = -1; + } + } + } + } + + fd.fromHex = true; + return fd; + } + } + } + + /** + * Return s with any leading zeros removed. + */ + static String stripLeadingZeros(String s) { + return s.replaceFirst("^0+", ""); + } + + /** + * Extract a hexadecimal digit from position position + * of string s. + */ + static int getHexDigit(String s, int position) { + int value = Character.digit(s.charAt(position), 16); + if (value <= -1 || value >= 16) { + throw new AssertionError("Unexpected failure of digit conversion of " + + s.charAt(position)); + } + return value; + } + + +} --- /dev/null 2013-06-07 13:08:38.000000000 -0700 +++ new/test/sun/misc/FloatingDecimal/TestFDBigInteger.java 2013-06-07 13:08:38.000000000 -0700 @@ -0,0 +1,426 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.math.BigInteger; +import java.util.Random; +import sun.misc.FDBigInteger; + +/** + * @test + * @bug 7032154 + * @summary unit testys of sun.misc.FDBigInteger + * @author Dmitry Nadezhin + */ +public class TestFDBigInteger { + + private static final int MAX_P5 = 413; + private static final int MAX_P2 = 65; + private static final long LONG_SIGN_MASK = (1L << 63); + private static final BigInteger FIVE = BigInteger.valueOf(5); + private static final FDBigInteger MUTABLE_ZERO = FDBigInteger.valueOfPow52(0, 0).leftInplaceSub(FDBigInteger.valueOfPow52(0, 0)); + private static final FDBigInteger IMMUTABLE_ZERO = FDBigInteger.valueOfPow52(0, 0).leftInplaceSub(FDBigInteger.valueOfPow52(0, 0)); + private static final FDBigInteger IMMUTABLE_MILLION = genMillion1(); + private static final FDBigInteger IMMUTABLE_BILLION = genBillion1(); + private static final FDBigInteger IMMUTABLE_TEN18 = genTen18(); + + static { + IMMUTABLE_ZERO.makeImmutable(); + IMMUTABLE_MILLION.makeImmutable(); + IMMUTABLE_BILLION.makeImmutable(); + IMMUTABLE_TEN18.makeImmutable(); + } + + private static FDBigInteger mutable(String hex, int offset) { + char[] chars = new BigInteger(hex, 16).toString().toCharArray(); + return new FDBigInteger(0, chars, 0, chars.length).multByPow52(0, offset * 32); + } + + private static FDBigInteger immutable(String hex, int offset) { + FDBigInteger fd = mutable(hex, offset); + fd.makeImmutable(); + return fd; + } + + private static BigInteger biPow52(int p5, int p2) { + return FIVE.pow(p5).shiftLeft(p2); + } + + // data.length == 1, nWords == 1, offset == 0 + private static FDBigInteger genMillion1() { + return FDBigInteger.valueOfPow52(6, 0).leftShift(6); + } + + // data.length == 2, nWords == 1, offset == 0 + private static FDBigInteger genMillion2() { + return FDBigInteger.valueOfMulPow52(1000000L, 0, 0); + } + + // data.length == 1, nWords == 1, offset == 0 + private static FDBigInteger genBillion1() { + return FDBigInteger.valueOfPow52(9, 0).leftShift(9); + } + + // data.length == 2, nWords == 2, offset == 0 + private static FDBigInteger genTen18() { + return FDBigInteger.valueOfPow52(18, 0).leftShift(18); + } + + private static void check(BigInteger expected, FDBigInteger actual, String message) throws Exception { + if (!expected.equals(actual.toBigInteger())) { + throw new Exception(message + " result " + actual.toHexString() + " expected " + expected.toString(16)); + } + } + + private static void testValueOfPow52(int p5, int p2) throws Exception { + check(biPow52(p5, p2), FDBigInteger.valueOfPow52(p5, p2), + "valueOfPow52(" + p5 + "," + p2 + ")"); + } + + private static void testValueOfPow52() throws Exception { + for (int p5 = 0; p5 <= MAX_P5; p5++) { + for (int p2 = 0; p2 <= MAX_P2; p2++) { + testValueOfPow52(p5, p2); + } + } + } + + private static void testValueOfMulPow52(long value, int p5, int p2) throws Exception { + BigInteger bi = BigInteger.valueOf(value & ~LONG_SIGN_MASK); + if (value < 0) { + bi = bi.setBit(63); + } + check(biPow52(p5, p2).multiply(bi), FDBigInteger.valueOfMulPow52(value, p5, p2), + "valueOfMulPow52(" + Long.toHexString(value) + "." + p5 + "," + p2 + ")"); + } + + private static void testValueOfMulPow52(long value, int p5) throws Exception { + testValueOfMulPow52(value, p5, 0); + testValueOfMulPow52(value, p5, 1); + testValueOfMulPow52(value, p5, 30); + testValueOfMulPow52(value, p5, 31); + testValueOfMulPow52(value, p5, 33); + testValueOfMulPow52(value, p5, 63); + } + + private static void testValueOfMulPow52() throws Exception { + for (int p5 = 0; p5 <= MAX_P5; p5++) { + testValueOfMulPow52(0xFFFFFFFFL, p5); + testValueOfMulPow52(0x123456789AL, p5); + testValueOfMulPow52(0x7FFFFFFFFFFFFFFFL, p5); + testValueOfMulPow52(0xFFFFFFFFFFF54321L, p5); + } + } + + private static void testLeftShift(FDBigInteger t, int shift, boolean isImmutable) throws Exception { + BigInteger bt = t.toBigInteger(); + FDBigInteger r = t.leftShift(shift); + if ((bt.signum() == 0 || shift == 0 || !isImmutable) && r != t) { + throw new Exception("leftShift doesn't reuse its argument"); + } + if (isImmutable) { + check(bt, t, "leftShift corrupts its argument"); + } + check(bt.shiftLeft(shift), r, "leftShift returns wrong result"); + } + + private static void testLeftShift() throws Exception { + testLeftShift(IMMUTABLE_ZERO, 0, true); + testLeftShift(IMMUTABLE_ZERO, 10, true); + testLeftShift(MUTABLE_ZERO, 0, false); + testLeftShift(MUTABLE_ZERO, 10, false); + + testLeftShift(IMMUTABLE_MILLION, 0, true); + testLeftShift(IMMUTABLE_MILLION, 1, true); + testLeftShift(IMMUTABLE_MILLION, 12, true); + testLeftShift(IMMUTABLE_MILLION, 13, true); + testLeftShift(IMMUTABLE_MILLION, 32, true); + testLeftShift(IMMUTABLE_MILLION, 33, true); + testLeftShift(IMMUTABLE_MILLION, 44, true); + testLeftShift(IMMUTABLE_MILLION, 45, true); + + testLeftShift(genMillion1(), 0, false); + testLeftShift(genMillion1(), 1, false); + testLeftShift(genMillion1(), 12, false); + testLeftShift(genMillion1(), 13, false); + testLeftShift(genMillion1(), 25, false); + testLeftShift(genMillion1(), 26, false); + testLeftShift(genMillion1(), 32, false); + testLeftShift(genMillion1(), 33, false); + testLeftShift(genMillion1(), 44, false); + testLeftShift(genMillion1(), 45, false); + + testLeftShift(genMillion2(), 0, false); + testLeftShift(genMillion2(), 1, false); + testLeftShift(genMillion2(), 12, false); + testLeftShift(genMillion2(), 13, false); + testLeftShift(genMillion2(), 25, false); + testLeftShift(genMillion2(), 26, false); + testLeftShift(genMillion2(), 32, false); + testLeftShift(genMillion2(), 33, false); + testLeftShift(genMillion2(), 44, false); + testLeftShift(genMillion2(), 45, false); + } + + private static void testQuoRemIteration(FDBigInteger t, FDBigInteger s) throws Exception { + BigInteger bt = t.toBigInteger(); + BigInteger bs = s.toBigInteger(); + int q = t.quoRemIteration(s); + BigInteger[] qr = bt.divideAndRemainder(bs); + if (!BigInteger.valueOf(q).equals(qr[0])) { + throw new Exception("quoRemIteration returns incorrect quo"); + } + check(qr[1].multiply(BigInteger.TEN), t, "quoRemIteration returns incorrect rem"); + } + + private static void testQuoRemIteration() throws Exception { + // IMMUTABLE_TEN18 == 0de0b6b3a7640000 + // q = 0 + testQuoRemIteration(mutable("00000001", 0), IMMUTABLE_TEN18); + testQuoRemIteration(mutable("00000001", 1), IMMUTABLE_TEN18); + testQuoRemIteration(mutable("0de0b6b2", 1), IMMUTABLE_TEN18); + // q = 1 -> q = 0 + testQuoRemIteration(mutable("0de0b6b3", 1), IMMUTABLE_TEN18); + testQuoRemIteration(mutable("0de0b6b3a763FFFF", 0), IMMUTABLE_TEN18); + // q = 1 + testQuoRemIteration(mutable("0de0b6b3a7640000", 0), IMMUTABLE_TEN18); + testQuoRemIteration(mutable("0de0b6b3FFFFFFFF", 0), IMMUTABLE_TEN18); + testQuoRemIteration(mutable("8ac72304", 1), IMMUTABLE_TEN18); + testQuoRemIteration(mutable("0de0b6b400000000", 0), IMMUTABLE_TEN18); + testQuoRemIteration(mutable("8ac72305", 1), IMMUTABLE_TEN18); + // q = 18 + testQuoRemIteration(mutable("FFFFFFFF", 1), IMMUTABLE_TEN18); + } + + private static void testCmp(FDBigInteger t, FDBigInteger o) throws Exception { + BigInteger bt = t.toBigInteger(); + BigInteger bo = o.toBigInteger(); + int cmp = t.cmp(o); + int bcmp = bt.compareTo(bo); + if (bcmp != cmp) { + throw new Exception("cmp returns " + cmp + " expected " + bcmp); + } + check(bt, t, "cmp corrupts this"); + check(bo, o, "cmp corrupts other"); + if (o.cmp(t) != -cmp) { + throw new Exception("asymmetrical cmp"); + } + check(bt, t, "cmp corrupts this"); + check(bo, o, "cmp corrupts other"); + } + + private static void testCmp() throws Exception { + testCmp(mutable("FFFFFFFF", 0), mutable("100000000", 0)); + testCmp(mutable("FFFFFFFF", 0), mutable("1", 1)); + testCmp(mutable("5", 0), mutable("6", 0)); + testCmp(mutable("5", 0), mutable("5", 0)); + testCmp(mutable("5000000001", 0), mutable("500000001", 0)); + testCmp(mutable("5000000001", 0), mutable("6", 1)); + testCmp(mutable("5000000001", 0), mutable("5", 1)); + testCmp(mutable("5000000000", 0), mutable("5", 1)); + } + + private static void testCmpPow52(FDBigInteger t, int p5, int p2) throws Exception { + FDBigInteger o = FDBigInteger.valueOfPow52(p5, p2); + BigInteger bt = t.toBigInteger(); + BigInteger bo = biPow52(p5, p2); + int cmp = t.cmp(o); + int bcmp = bt.compareTo(bo); + if (bcmp != cmp) { + throw new Exception("cmpPow52 returns " + cmp + " expected " + bcmp); + } + check(bt, t, "cmpPow52 corrupts this"); + check(bo, o, "cmpPow5 corrupts other"); + } + + private static void testCmpPow52() throws Exception { + testCmpPow52(mutable("00000002", 1), 0, 31); + testCmpPow52(mutable("00000002", 1), 0, 32); + testCmpPow52(mutable("00000002", 1), 0, 33); + testCmpPow52(mutable("00000002", 1), 0, 34); + testCmpPow52(mutable("00000002", 1), 0, 64); + testCmpPow52(mutable("00000003", 1), 0, 32); + testCmpPow52(mutable("00000003", 1), 0, 33); + testCmpPow52(mutable("00000003", 1), 0, 34); + } + + private static void testAddAndCmp(FDBigInteger t, FDBigInteger x, FDBigInteger y) throws Exception { + BigInteger bt = t.toBigInteger(); + BigInteger bx = x.toBigInteger(); + BigInteger by = y.toBigInteger(); + int cmp = t.addAndCmp(x, y); + int bcmp = bt.compareTo(bx.add(by)); + if (bcmp != cmp) { + throw new Exception("addAndCmp returns " + cmp + " expected " + bcmp); + } + check(bt, t, "addAndCmp corrupts this"); + check(bx, x, "addAndCmp corrupts x"); + check(by, y, "addAndCmp corrupts y"); + } + + private static void testAddAndCmp() throws Exception { + testAddAndCmp(MUTABLE_ZERO, MUTABLE_ZERO, MUTABLE_ZERO); + testAddAndCmp(mutable("00000001", 0), MUTABLE_ZERO, MUTABLE_ZERO); + testAddAndCmp(mutable("00000001", 0), mutable("00000001", 0), MUTABLE_ZERO); + testAddAndCmp(mutable("00000001", 0), MUTABLE_ZERO, mutable("00000001", 0)); + testAddAndCmp(mutable("00000001", 0), mutable("00000002", 0), MUTABLE_ZERO); + testAddAndCmp(mutable("00000001", 0), MUTABLE_ZERO, mutable("00000002", 0)); + testAddAndCmp(mutable("00000001", 2), mutable("FFFFFFFF", 0), mutable("FFFFFFFF", 0)); + testAddAndCmp(mutable("00000001", 0), mutable("00000001", 1), mutable("00000001", 0)); + + testAddAndCmp(mutable("00000001", 2), mutable("0F0F0F0F80000000", 1), mutable("F0F0F0F080000000", 1)); + testAddAndCmp(mutable("00000001", 2), mutable("0F0F0F0E80000000", 1), mutable("F0F0F0F080000000", 1)); + + testAddAndCmp(mutable("00000002", 1), mutable("0000000180000000", 1), mutable("0000000280000000", 1)); + testAddAndCmp(mutable("00000003", 1), mutable("0000000180000000", 1), mutable("0000000280000000", 1)); + testAddAndCmp(mutable("00000004", 1), mutable("0000000180000000", 1), mutable("0000000280000000", 1)); + testAddAndCmp(mutable("00000005", 1), mutable("0000000180000000", 1), mutable("0000000280000000", 1)); + + testAddAndCmp(mutable("00000001", 2), mutable("8000000000000000", 0), mutable("8000000000000000", 0)); + testAddAndCmp(mutable("00000001", 2), mutable("8000000000000000", 0), mutable("8000000000000001", 0)); + testAddAndCmp(mutable("00000002", 2), mutable("8000000000000000", 0), mutable("8000000000000000", 0)); + testAddAndCmp(mutable("00000003", 2), mutable("8000000000000000", 0), mutable("8000000000000000", 0)); + } + + private static void testMultBy10(FDBigInteger t, boolean isImmutable) throws Exception { + BigInteger bt = t.toBigInteger(); + FDBigInteger r = t.multBy10(); + if ((bt.signum() == 0 || !isImmutable) && r != t) { + throw new Exception("multBy10 of doesn't reuse its argument"); + } + if (isImmutable) { + check(bt, t, "multBy10 corrupts its argument"); + } + check(bt.multiply(BigInteger.TEN), r, "multBy10 returns wrong result"); + } + + private static void testMultBy10() throws Exception { + for (int p5 = 0; p5 <= MAX_P5; p5++) { + for (int p2 = 0; p2 <= MAX_P2; p2++) { + // This strange way of creating a value ensures that it is mutable. + FDBigInteger value = FDBigInteger.valueOfPow52(0, 0).multByPow52(p5, p2); + testMultBy10(value, false); + value.makeImmutable(); + testMultBy10(value, true); + } + } + } + + private static void testMultByPow52(FDBigInteger t, int p5, int p2) throws Exception { + BigInteger bt = t.toBigInteger(); + FDBigInteger r = t.multByPow52(p5, p2); + if (bt.signum() == 0 && r != t) { + throw new Exception("multByPow52 of doesn't reuse its argument"); + } + check(bt.multiply(biPow52(p5, p2)), r, "multByPow52 returns wrong result"); + } + + private static void testMultByPow52() throws Exception { + for (int p5 = 0; p5 <= MAX_P5; p5++) { + for (int p2 = 0; p2 <= MAX_P2; p2++) { + // This strange way of creating a value ensures that it is mutable. + FDBigInteger value = FDBigInteger.valueOfPow52(0, 0).multByPow52(p5, p2); + testMultByPow52(value, p5, p2); + } + } + } + + private static void testLeftInplaceSub(FDBigInteger left, FDBigInteger right, boolean isImmutable) throws Exception { + BigInteger biLeft = left.toBigInteger(); + BigInteger biRight = right.toBigInteger(); + FDBigInteger diff = left.leftInplaceSub(right); + if (!isImmutable && diff != left) { + throw new Exception("leftInplaceSub of doesn't reuse its argument"); + } + check(biLeft.subtract(biRight), diff, "leftInplaceSub returns wrong result"); + } + + private static void testLeftInplaceSub() throws Exception { + for (int p5 = 0; p5 <= MAX_P5; p5++) { + for (int p2 = 0; p2 <= MAX_P2; p2++) { +// for (int p5r = 0; p5r <= p5; p5r += 10) { +// for (int p2r = 0; p2r <= p2; p2r += 10) { + for (int p5r = 0; p5r <= p5; p5r++) { + for (int p2r = 0; p2r <= p2; p2r++) { + // This strange way of creating a value ensures that it is mutable. + FDBigInteger left = FDBigInteger.valueOfPow52(0, 0).multByPow52(p5, p2); + FDBigInteger right = FDBigInteger.valueOfPow52(0, 0).multByPow52(p5r, p2r); + testLeftInplaceSub(left, right, false); + left = FDBigInteger.valueOfPow52(0, 0).multByPow52(p5, p2); + left.makeImmutable(); + testLeftInplaceSub(left, right, true); + } + } + } + } + } + + private static void testRightInplaceSub(FDBigInteger left, FDBigInteger right, boolean isImmutable) throws Exception { + BigInteger biLeft = left.toBigInteger(); + BigInteger biRight = right.toBigInteger(); + FDBigInteger diff = left.rightInplaceSub(right); + if (!isImmutable && diff != right) { + throw new Exception("rightInplaceSub of doesn't reuse its argument"); + } + try { + check(biLeft.subtract(biRight), diff, "rightInplaceSub returns wrong result"); + } catch (Exception e) { + System.out.println(biLeft+" - "+biRight+" = "+biLeft.subtract(biRight)); + throw e; + } + } + + private static void testRightInplaceSub() throws Exception { + for (int p5 = 0; p5 <= MAX_P5; p5++) { + for (int p2 = 0; p2 <= MAX_P2; p2++) { +// for (int p5r = 0; p5r <= p5; p5r += 10) { +// for (int p2r = 0; p2r <= p2; p2r += 10) { + for (int p5r = 0; p5r <= p5; p5r++) { + for (int p2r = 0; p2r <= p2; p2r++) { + // This strange way of creating a value ensures that it is mutable. + FDBigInteger left = FDBigInteger.valueOfPow52(0, 0).multByPow52(p5, p2); + FDBigInteger right = FDBigInteger.valueOfPow52(0, 0).multByPow52(p5r, p2r); + testRightInplaceSub(left, right, false); + right = FDBigInteger.valueOfPow52(0, 0).multByPow52(p5r, p2r); + right.makeImmutable(); + testRightInplaceSub(left, right, true); + } + } + } + } + } + + public static void main(String[] args) throws Exception { + testValueOfPow52(); + testValueOfMulPow52(); + testLeftShift(); + testQuoRemIteration(); + testCmp(); + testCmpPow52(); + testAddAndCmp(); + // Uncomment the following for more comprehensize but slow testing. + // testLeftInplaceSub(); + // testMultBy10(); + // testMultByPow52(); + // testRightInplaceSub(); + } +} --- /dev/null 2013-06-07 13:08:39.000000000 -0700 +++ new/test/sun/misc/FloatingDecimal/TestFloatingDecimal.java 2013-06-07 13:08:39.000000000 -0700 @@ -0,0 +1,324 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.util.Random; +import sun.misc.FloatingDecimal; + +/* +OldFloatingDecimalForTest + +public class OldFloatingDecimalForTest { + public boolean digitsRoundedUp(); + public OldFloatingDecimalForTest(double); + public OldFloatingDecimalForTest(float); + public boolean decimalDigitsExact(); + public java.lang.String toString(); + public java.lang.String toJavaFormatString(); + public void appendTo(java.lang.Appendable); + public static OldFloatingDecimalForTest readJavaFormatString(java.lang.String) throws java.lang.NumberFormatException; + public strictfp double doubleValue(); + public strictfp float floatValue(); +} + +sun.misc.FloatingDecimal + +public class sun.misc.FloatingDecimal { + public sun.misc.FloatingDecimal(); + public static java.lang.String toJavaFormatString(double); + public static java.lang.String toJavaFormatString(float); + public static void appendTo(double, java.lang.Appendable); + public static void appendTo(float, java.lang.Appendable); + public static double parseDouble(java.lang.String) throws java.lang.NumberFormatException; + public static float parseFloat(java.lang.String) throws java.lang.NumberFormatException; + public static sun.misc.FloatingDecimal$AbstractD2ABuffer getD2ABuffer(double); +} +*/ + +/** + * @test + * @bug 7032154 + * @summary unit tests of sun.misc.FloatingDecimal + * @author Brian Burkhalter + */ +public class TestFloatingDecimal { + private static enum ResultType { + RESULT_EXCEPTION, + RESULT_PRINT + } + + private static final ResultType RESULT_TYPE = ResultType.RESULT_PRINT; + private static final int NUM_RANDOM_TESTS = 100000; + + private static final Random RANDOM = new Random(); + + private static void result(String message) { + switch (RESULT_TYPE) { + case RESULT_EXCEPTION: + throw new RuntimeException(message); + case RESULT_PRINT: + System.err.println(message); + break; + default: + assert false; + } + } + + private static int check(String test, Object expected, Object actual) { + int failures = 0; + if(!actual.equals(expected)) { + failures++; + result("Test "+test+" expected "+expected+" but obtained "+actual); + } + return failures; + } + + private static int testAppendToDouble() { + System.out.println(" testAppendToDouble"); + int failures = 0; + + for(int i = 0; i < NUM_RANDOM_TESTS; i++) { + double[] d = new double[] { + RANDOM.nextLong(), + RANDOM.nextGaussian(), + RANDOM.nextDouble()*Double.MAX_VALUE + }; + for(int j = 0; j < d.length; j++) { + OldFloatingDecimalForTest ofd = new OldFloatingDecimalForTest(d[j]); + StringBuilder sb = new StringBuilder(); + ofd.appendTo(sb); + String oldString = sb.toString(); + sb = new StringBuilder(); + FloatingDecimal.appendTo(d[j], sb); + String newString = sb.toString(); + failures += check("testAppendToDouble", oldString, newString); + } + } + + return failures; + } + + private static int testAppendToFloat() { + System.out.println(" testAppendToFloat"); + int failures = 0; + + for(int i = 0; i < NUM_RANDOM_TESTS; i++) { + float[] f = new float[] { + RANDOM.nextLong(), + (float)RANDOM.nextGaussian(), + RANDOM.nextFloat()*Float.MAX_VALUE + }; + for(int j = 0; j < f.length; j++) { + OldFloatingDecimalForTest ofd = new OldFloatingDecimalForTest(f[j]); + StringBuilder sb = new StringBuilder(); + ofd.appendTo(sb); + String oldString = sb.toString(); + sb = new StringBuilder(); + FloatingDecimal.appendTo(f[j], sb); + String newString = sb.toString(); + failures += check("testAppendToFloat", oldString, newString); + } + } + + return failures; + } + + private static int testAppendTo() { + System.out.println("testAppendTo"); + int failures = 0; + + failures += testAppendToDouble(); + failures += testAppendToFloat(); + + return failures; + } + + private static int testParseDouble() { + System.out.println(" testParseDouble"); + int failures = 0; + + for(int i = 0; i < NUM_RANDOM_TESTS; i++) { + double[] d = new double[] { + RANDOM.nextLong(), + RANDOM.nextGaussian(), + RANDOM.nextDouble()*Double.MAX_VALUE + }; + for(int j = 0; j < d.length; j++) { + OldFloatingDecimalForTest ofd = new OldFloatingDecimalForTest(d[j]); + String javaFormatString = ofd.toJavaFormatString(); + ofd = OldFloatingDecimalForTest.readJavaFormatString(javaFormatString); + double oldDouble = ofd.doubleValue(); + double newDouble = FloatingDecimal.parseDouble(javaFormatString); + failures += check("testParseDouble", oldDouble, newDouble); + } + } + + return failures; + } + + private static int testParseFloat() { + System.out.println(" testParseFloat"); + int failures = 0; + + for(int i = 0; i < NUM_RANDOM_TESTS; i++) { + float[] f = new float[] { + RANDOM.nextInt(), + (float)RANDOM.nextGaussian(), + RANDOM.nextFloat()*Float.MAX_VALUE + }; + for(int j = 0; j < f.length; j++) { + OldFloatingDecimalForTest ofd = new OldFloatingDecimalForTest(f[j]); + String javaFormatString = ofd.toJavaFormatString(); + ofd = OldFloatingDecimalForTest.readJavaFormatString(javaFormatString); + float oldFloat = ofd.floatValue(); + float newFloat = FloatingDecimal.parseFloat(javaFormatString); + failures += check("testParseFloat", oldFloat, newFloat); + } + } + + return failures; + } + + private static int testParse() { + System.out.println("testParse"); + int failures = 0; + + failures += testParseDouble(); + failures += testParseFloat(); + + return failures; + } + + private static int testToJavaFormatStringDoubleFixed() { + System.out.println(" testToJavaFormatStringDoubleFixed"); + int failures = 0; + + double[] d = new double [] { + -5.9522650387500933e18, // dtoa() fast path + 0.872989018674569, // dtoa() fast iterative - long + 1.1317400099603851e308 // dtoa() slow iterative + }; + + for(int i = 0; i < d.length; i++) { + OldFloatingDecimalForTest ofd = new OldFloatingDecimalForTest(d[i]); + failures += check("testToJavaFormatStringDoubleFixed", ofd.toJavaFormatString(), FloatingDecimal.toJavaFormatString(d[i])); + } + + return failures; + } + + private static int testToJavaFormatStringDoubleRandom() { + System.out.println(" testToJavaFormatStringDoubleRandom"); + int failures = 0; + + for(int i = 0; i < NUM_RANDOM_TESTS; i++) { + double[] d = new double[] { + RANDOM.nextLong(), + RANDOM.nextGaussian(), + RANDOM.nextDouble()*Double.MAX_VALUE + }; + for(int j = 0; j < d.length; j++) { + OldFloatingDecimalForTest ofd = new OldFloatingDecimalForTest(d[j]); + failures += check("testToJavaFormatStringDoubleRandom", ofd.toJavaFormatString(), FloatingDecimal.toJavaFormatString(d[j])); + } + } + + return failures; + } + + private static int testToJavaFormatStringDouble() { + System.out.println(" testToJavaFormatStringDouble"); + int failures = 0; + failures += testToJavaFormatStringDoubleFixed(); + failures += testToJavaFormatStringDoubleRandom(); + return failures; + } + + private static int testToJavaFormatStringFloatFixed() { + System.out.println(" testToJavaFormatStringFloatFixed"); + int failures = 0; + + float[] f = new float[] { + -9.8784166e8f, // dtoa() fast path + 0.70443946f, // dtoa() fast iterative - int + 1.8254228e37f // dtoa() slow iterative + }; + + for(int i = 0; i < f.length; i++) { + OldFloatingDecimalForTest ofd = new OldFloatingDecimalForTest(f[i]); + failures += check("testToJavaFormatStringFloatFixed", ofd.toJavaFormatString(), FloatingDecimal.toJavaFormatString(f[i])); + } + + return failures; + } + + private static int testToJavaFormatStringFloatRandom() { + System.out.println(" testToJavaFormatStringFloatRandom"); + int failures = 0; + + for(int i = 0; i < NUM_RANDOM_TESTS; i++) { + float[] f = new float[] { + RANDOM.nextInt(), + (float)RANDOM.nextGaussian(), + RANDOM.nextFloat()*Float.MAX_VALUE + }; + for(int j = 0; j < f.length; j++) { + OldFloatingDecimalForTest ofd = new OldFloatingDecimalForTest(f[j]); + failures += check("testToJavaFormatStringFloatRandom", ofd.toJavaFormatString(), FloatingDecimal.toJavaFormatString(f[j])); + } + } + + return failures; + } + + private static int testToJavaFormatStringFloat() { + System.out.println(" testToJavaFormatStringFloat"); + int failures = 0; + + failures += testToJavaFormatStringFloatFixed(); + failures += testToJavaFormatStringFloatRandom(); + + return failures; + } + + private static int testToJavaFormatString() { + System.out.println("testToJavaFormatString"); + int failures = 0; + + failures += testToJavaFormatStringDouble(); + failures += testToJavaFormatStringFloat(); + + return failures; + } + + public static void main(String[] args) { + int failures = 0; + + failures += testAppendTo(); + failures += testParse(); + failures += testToJavaFormatString(); + + if (failures != 0) { + throw new RuntimeException("" + failures + " failures while testing FloatingDecimal"); + } + } +} --- old/src/share/classes/sun/misc/FDBigInt.java 2013-06-07 13:08:40.000000000 -0700 +++ /dev/null 2013-06-07 13:08:40.000000000 -0700 @@ -1,493 +0,0 @@ -/* - * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package sun.misc; - -/* - * A really, really simple bigint package - * tailored to the needs of floating base conversion. - */ -class FDBigInt { - int nWords; // number of words used - int data[]; // value: data[0] is least significant - - - public FDBigInt( int v ){ - nWords = 1; - data = new int[1]; - data[0] = v; - } - - public FDBigInt( long v ){ - data = new int[2]; - data[0] = (int)v; - data[1] = (int)(v>>>32); - nWords = (data[1]==0) ? 1 : 2; - } - - public FDBigInt( FDBigInt other ){ - data = new int[nWords = other.nWords]; - System.arraycopy( other.data, 0, data, 0, nWords ); - } - - private FDBigInt( int [] d, int n ){ - data = d; - nWords = n; - } - - public FDBigInt( long seed, char digit[], int nd0, int nd ){ - int n= (nd+8)/9; // estimate size needed. - if ( n < 2 ) n = 2; - data = new int[n]; // allocate enough space - data[0] = (int)seed; // starting value - data[1] = (int)(seed>>>32); - nWords = (data[1]==0) ? 1 : 2; - int i = nd0; - int limit = nd-5; // slurp digits 5 at a time. - int v; - while ( i < limit ){ - int ilim = i+5; - v = (int)digit[i++]-(int)'0'; - while( i >5; - int bitcount = c & 0x1f; - int anticount = 32-bitcount; - int t[] = data; - int s[] = data; - if ( nWords+wordcount+1 > t.length ){ - // reallocate. - t = new int[ nWords+wordcount+1 ]; - } - int target = nWords+wordcount; - int src = nWords-1; - if ( bitcount == 0 ){ - // special hack, since an anticount of 32 won't go! - System.arraycopy( s, 0, t, wordcount, nWords ); - target = wordcount-1; - } else { - t[target--] = s[src]>>>anticount; - while ( src >= 1 ){ - t[target--] = (s[src]<>>anticount); - } - t[target--] = s[src]<= 0 ){ - t[target--] = 0; - } - data = t; - nWords += wordcount + 1; - // may have constructed high-order word of 0. - // if so, trim it - while ( nWords > 1 && data[nWords-1] == 0 ) - nWords--; - } - - /* - * normalize this number by shifting until - * the MSB of the number is at 0x08000000. - * This is in preparation for quoRemIteration, below. - * The idea is that, to make division easier, we want the - * divisor to be "normalized" -- usually this means shifting - * the MSB into the high words sign bit. But because we know that - * the quotient will be 0 < q < 10, we would like to arrange that - * the dividend not span up into another word of precision. - * (This needs to be explained more clearly!) - */ - public int - normalizeMe() throws IllegalArgumentException { - int src; - int wordcount = 0; - int bitcount = 0; - int v = 0; - for ( src= nWords-1 ; src >= 0 && (v=data[src]) == 0 ; src--){ - wordcount += 1; - } - if ( src < 0 ){ - // oops. Value is zero. Cannot normalize it! - throw new IllegalArgumentException("zero value"); - } - /* - * In most cases, we assume that wordcount is zero. This only - * makes sense, as we try not to maintain any high-order - * words full of zeros. In fact, if there are zeros, we will - * simply SHORTEN our number at this point. Watch closely... - */ - nWords -= wordcount; - /* - * Compute how far left we have to shift v s.t. its highest- - * order bit is in the right place. Then call lshiftMe to - * do the work. - */ - if ( (v & 0xf0000000) != 0 ){ - // will have to shift up into the next word. - // too bad. - for( bitcount = 32 ; (v & 0xf0000000) != 0 ; bitcount-- ) - v >>>= 1; - } else { - while ( v <= 0x000fffff ){ - // hack: byte-at-a-time shifting - v <<= 8; - bitcount += 8; - } - while ( v <= 0x07ffffff ){ - v <<= 1; - bitcount += 1; - } - } - if ( bitcount != 0 ) - lshiftMe( bitcount ); - return bitcount; - } - - /* - * Multiply a FDBigInt by an int. - * Result is a new FDBigInt. - */ - public FDBigInt - mult( int iv ) { - long v = iv; - int r[]; - long p; - - // guess adequate size of r. - r = new int[ ( v * ((long)data[nWords-1]&0xffffffffL) > 0xfffffffL ) ? nWords+1 : nWords ]; - p = 0L; - for( int i=0; i < nWords; i++ ) { - p += v * ((long)data[i]&0xffffffffL); - r[i] = (int)p; - p >>>= 32; - } - if ( p == 0L){ - return new FDBigInt( r, nWords ); - } else { - r[nWords] = (int)p; - return new FDBigInt( r, nWords+1 ); - } - } - - /* - * Multiply a FDBigInt by an int and add another int. - * Result is computed in place. - * Hope it fits! - */ - public void - multaddMe( int iv, int addend ) { - long v = iv; - long p; - - // unroll 0th iteration, doing addition. - p = v * ((long)data[0]&0xffffffffL) + ((long)addend&0xffffffffL); - data[0] = (int)p; - p >>>= 32; - for( int i=1; i < nWords; i++ ) { - p += v * ((long)data[i]&0xffffffffL); - data[i] = (int)p; - p >>>= 32; - } - if ( p != 0L){ - data[nWords] = (int)p; // will fail noisily if illegal! - nWords++; - } - } - - /* - * Multiply a FDBigInt by another FDBigInt. - * Result is a new FDBigInt. - */ - public FDBigInt - mult( FDBigInt other ){ - // crudely guess adequate size for r - int r[] = new int[ nWords + other.nWords ]; - int i; - // I think I am promised zeros... - - for( i = 0; i < this.nWords; i++ ){ - long v = (long)this.data[i] & 0xffffffffL; // UNSIGNED CONVERSION - long p = 0L; - int j; - for( j = 0; j < other.nWords; j++ ){ - p += ((long)r[i+j]&0xffffffffL) + v*((long)other.data[j]&0xffffffffL); // UNSIGNED CONVERSIONS ALL 'ROUND. - r[i+j] = (int)p; - p >>>= 32; - } - r[i+j] = (int)p; - } - // compute how much of r we actually needed for all that. - for ( i = r.length-1; i> 0; i--) - if ( r[i] != 0 ) - break; - return new FDBigInt( r, i+1 ); - } - - /* - * Add one FDBigInt to another. Return a FDBigInt - */ - public FDBigInt - add( FDBigInt other ){ - int i; - int a[], b[]; - int n, m; - long c = 0L; - // arrange such that a.nWords >= b.nWords; - // n = a.nWords, m = b.nWords - if ( this.nWords >= other.nWords ){ - a = this.data; - n = this.nWords; - b = other.data; - m = other.nWords; - } else { - a = other.data; - n = other.nWords; - b = this.data; - m = this.nWords; - } - int r[] = new int[ n ]; - for ( i = 0; i < n; i++ ){ - c += (long)a[i] & 0xffffffffL; - if ( i < m ){ - c += (long)b[i] & 0xffffffffL; - } - r[i] = (int) c; - c >>= 32; // signed shift. - } - if ( c != 0L ){ - // oops -- carry out -- need longer result. - int s[] = new int[ r.length+1 ]; - System.arraycopy( r, 0, s, 0, r.length ); - s[i++] = (int)c; - return new FDBigInt( s, i ); - } - return new FDBigInt( r, i ); - } - - /* - * Subtract one FDBigInt from another. Return a FDBigInt - * Assert that the result is positive. - */ - public FDBigInt - sub( FDBigInt other ){ - int r[] = new int[ this.nWords ]; - int i; - int n = this.nWords; - int m = other.nWords; - int nzeros = 0; - long c = 0L; - for ( i = 0; i < n; i++ ){ - c += (long)this.data[i] & 0xffffffffL; - if ( i < m ){ - c -= (long)other.data[i] & 0xffffffffL; - } - if ( ( r[i] = (int) c ) == 0 ) - nzeros++; - else - nzeros = 0; - c >>= 32; // signed shift - } - assert c == 0L : c; // borrow out of subtract - assert dataInRangeIsZero(i, m, other); // negative result of subtract - return new FDBigInt( r, n-nzeros ); - } - - private static boolean dataInRangeIsZero(int i, int m, FDBigInt other) { - while ( i < m ) - if (other.data[i++] != 0) - return false; - return true; - } - - /* - * Compare FDBigInt with another FDBigInt. Return an integer - * >0: this > other - * 0: this == other - * <0: this < other - */ - public int - cmp( FDBigInt other ){ - int i; - if ( this.nWords > other.nWords ){ - // if any of my high-order words is non-zero, - // then the answer is evident - int j = other.nWords-1; - for ( i = this.nWords-1; i > j ; i-- ) - if ( this.data[i] != 0 ) return 1; - }else if ( this.nWords < other.nWords ){ - // if any of other's high-order words is non-zero, - // then the answer is evident - int j = this.nWords-1; - for ( i = other.nWords-1; i > j ; i-- ) - if ( other.data[i] != 0 ) return -1; - } else{ - i = this.nWords-1; - } - for ( ; i > 0 ; i-- ) - if ( this.data[i] != other.data[i] ) - break; - // careful! want unsigned compare! - // use brute force here. - int a = this.data[i]; - int b = other.data[i]; - if ( a < 0 ){ - // a is really big, unsigned - if ( b < 0 ){ - return a-b; // both big, negative - } else { - return 1; // b not big, answer is obvious; - } - } else { - // a is not really big - if ( b < 0 ) { - // but b is really big - return -1; - } else { - return a - b; - } - } - } - - /* - * Compute - * q = (int)( this / S ) - * this = 10 * ( this mod S ) - * Return q. - * This is the iteration step of digit development for output. - * We assume that S has been normalized, as above, and that - * "this" has been lshift'ed accordingly. - * Also assume, of course, that the result, q, can be expressed - * as an integer, 0 <= q < 10. - */ - public int - quoRemIteration( FDBigInt S )throws IllegalArgumentException { - // ensure that this and S have the same number of - // digits. If S is properly normalized and q < 10 then - // this must be so. - if ( nWords != S.nWords ){ - throw new IllegalArgumentException("disparate values"); - } - // estimate q the obvious way. We will usually be - // right. If not, then we're only off by a little and - // will re-add. - int n = nWords-1; - long q = ((long)data[n]&0xffffffffL) / (long)S.data[n]; - long diff = 0L; - for ( int i = 0; i <= n ; i++ ){ - diff += ((long)data[i]&0xffffffffL) - q*((long)S.data[i]&0xffffffffL); - data[i] = (int)diff; - diff >>= 32; // N.B. SIGNED shift. - } - if ( diff != 0L ) { - // damn, damn, damn. q is too big. - // add S back in until this turns +. This should - // not be very many times! - long sum = 0L; - while ( sum == 0L ){ - sum = 0L; - for ( int i = 0; i <= n; i++ ){ - sum += ((long)data[i]&0xffffffffL) + ((long)S.data[i]&0xffffffffL); - data[i] = (int) sum; - sum >>= 32; // Signed or unsigned, answer is 0 or 1 - } - /* - * Originally the following line read - * "if ( sum !=0 && sum != -1 )" - * but that would be wrong, because of the - * treatment of the two values as entirely unsigned, - * it would be impossible for a carry-out to be interpreted - * as -1 -- it would have to be a single-bit carry-out, or - * +1. - */ - assert sum == 0 || sum == 1 : sum; // carry out of division correction - q -= 1; - } - } - // finally, we can multiply this by 10. - // it cannot overflow, right, as the high-order word has - // at least 4 high-order zeros! - long p = 0L; - for ( int i = 0; i <= n; i++ ){ - p += 10*((long)data[i]&0xffffffffL); - data[i] = (int)p; - p >>= 32; // SIGNED shift. - } - assert p == 0L : p; // Carry out of *10 - return (int)q; - } - - public long - longValue(){ - // if this can be represented as a long, return the value - assert this.nWords > 0 : this.nWords; // longValue confused - - if (this.nWords == 1) - return ((long)data[0]&0xffffffffL); - - assert dataInRangeIsZero(2, this.nWords, this); // value too big - assert data[1] >= 0; // value too big - return ((long)(data[1]) << 32) | ((long)data[0]&0xffffffffL); - } - - public String - toString() { - StringBuffer r = new StringBuffer(30); - r.append('['); - int i = Math.min( nWords-1, data.length-1) ; - if ( nWords > data.length ){ - r.append( "("+data.length+"<"+nWords+"!)" ); - } - for( ; i> 0 ; i-- ){ - r.append( Integer.toHexString( data[i] ) ); - r.append(' '); - } - r.append( Integer.toHexString( data[0] ) ); - r.append(']'); - return new String( r ); - } -}