src/share/classes/sun/misc/FloatingDecimal.java
Print this page
*** 23,303 ****
* questions.
*/
package sun.misc;
! import sun.misc.DoubleConsts;
! import sun.misc.FloatConsts;
import java.util.regex.*;
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.
! */
! // 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 FloatingDecimal( 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<<expShift ); // assumed High-Order bit
! static final long expOne = ((long)expBias)<<expShift; // exponent of 1.0
! static final int maxSmallBinExp = 62;
! static final int minSmallBinExp = -( 63 / 3 );
! static final int maxDecimalDigits = 15;
! static final int maxDecimalExponent = 308;
! static final int minDecimalExponent = -324;
! static final int bigDecimalExponent = 324; // i.e. abs(minDecimalExponent)
!
! static final long highbyte = 0xff00000000000000L;
! static final long highbit = 0x8000000000000000L;
! static final long lowbytes = ~highbyte;
!
! static final int singleSignMask = 0x80000000;
! static final int singleExpMask = 0x7f800000;
! static final int singleFractMask = ~(singleSignMask|singleExpMask);
! static final int singleExpShift = 23;
! static final int singleFractHOB = 1<<singleExpShift;
! static final int singleExpBias = 127;
! static final int singleMaxDecimalDigits = 7;
! static final int singleMaxDecimalExponent = 38;
! static final int singleMinDecimalExponent = -45;
!
! static final int intDecimalDigits = 9;
!
!
! /*
! * count number of bits from high-order 1 bit to low-order 1 bit,
! * inclusive.
! */
! 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;
! }
!
! /*
! * Keep big powers of 5 handy for future reference.
! */
! 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 ) );
}
}
}
! //
! // 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;
! }
!
! //
! // 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;
! }
!
! /*
! * 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 );
}
! /*
! * 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))<<expShift );
! } else if ( binexp == 0 ){
! ulpval = Double.MIN_VALUE;
} else {
! ulpval = Double.longBitsToDouble( 1L<<(binexp-1) );
}
- if ( subtracting ) ulpval = - ulpval;
! return ulpval;
}
! /*
! * Round 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.
! */
! float
! stickyRound( double dval ){
! long lbits = Double.doubleToLongBits( dval );
! long binexp = lbits & expMask;
! if ( binexp == 0L || binexp == expMask ){
! // what we have here is special.
! // don't worry, the right thing will happen.
! return (float) dval;
}
! lbits += (long)roundDir; // hack-o-matic.
! return (float)Double.longBitsToDouble( lbits );
}
! /*
* 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.
--- 23,355 ----
* questions.
*/
package sun.misc;
! 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 <code>BinaryToASCIIConverter</code>
+ * instance may be obtained and reused.
+ */
public class FloatingDecimal{
! //
! // 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<<EXP_SHIFT ); // assumed High-Order bit
! static final long EXP_ONE = ((long)DoubleConsts.EXP_BIAS)<<EXP_SHIFT; // exponent of 1.0
! static final int MAX_SMALL_BIN_EXP = 62;
! static final int MIN_SMALL_BIN_EXP = -( 63 / 3 );
! static final int MAX_DECIMAL_DIGITS = 15;
! static final int MAX_DECIMAL_EXPONENT = 308;
! static final int MIN_DECIMAL_EXPONENT = -324;
! static final int BIG_DECIMAL_EXPONENT = 324; // i.e. abs(MIN_DECIMAL_EXPONENT)
!
! static final int SINGLE_EXP_SHIFT = FloatConsts.SIGNIFICAND_WIDTH - 1;
! static final int SINGLE_FRACT_HOB = 1<<SINGLE_EXP_SHIFT;
! static final int SINGLE_MAX_DECIMAL_DIGITS = 7;
! static final int SINGLE_MAX_DECIMAL_EXPONENT = 38;
! static final int SINGLE_MIN_DECIMAL_EXPONENT = -45;
! static final int INT_DECIMAL_DIGITS = 9;
! /**
! * Converts a double precision floating point value to a <code>String</code>.
! *
! * @param d The double precision value.
! * @return The value converted to a <code>String</code>.
! */
! public static String toJavaFormatString(double d) {
! return getBinaryToASCIIConverter(d).toJavaFormatString();
! }
! /**
! * Converts a single precision floating point value to a <code>String</code>.
! *
! * @param f The single precision value.
! * @return The value converted to a <code>String</code>.
! */
! public static String toJavaFormatString(float f) {
! return getBinaryToASCIIConverter(f).toJavaFormatString();
! }
! /**
! * Appends a double precision floating point value to an <code>Appendable</code>.
! * @param d The double precision value.
! * @param buf The <code>Appendable</code> with the value appended.
! */
! public static void appendTo(double d, Appendable buf) {
! getBinaryToASCIIConverter(d).appendTo(buf);
}
! /**
! * Appends a single precision floating point value to an <code>Appendable</code>.
! * @param f The single precision value.
! * @param buf The <code>Appendable</code> with the value appended.
! */
! public static void appendTo(float f, Appendable buf) {
! getBinaryToASCIIConverter(f).appendTo(buf);
}
+
+ /**
+ * Converts a <code>String</code> to a double precision floating point value.
+ *
+ * @param s The <code>String</code> to convert.
+ * @return The double precision value.
+ * @throws NumberFormatException If the <code>String</code> does not
+ * represent a properly formatted double precision value.
+ */
+ public static double parseDouble(String s) throws NumberFormatException {
+ return readJavaFormatString(s).doubleValue();
}
+
+ /**
+ * Converts a <code>String</code> to a single precision floating point value.
+ *
+ * @param s The <code>String</code> to convert.
+ * @return The single precision value.
+ * @throws NumberFormatException If the <code>String</code> does not
+ * represent a properly formatted single precision value.
+ */
+ 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 <code>String</code> representation.
! */
! public interface BinaryToASCIIConverter {
! /**
! * Converts a floating point value into an ASCII <code>String</code>.
! * @return The value converted to a <code>String</code>.
! */
! public String toJavaFormatString();
!
! /**
! * Appends a floating point value to an <code>Appendable</code>.
! * @param buf The <code>Appendable</code> to receive the value.
! */
! public void appendTo(Appendable buf);
!
! /**
! * Retrieves the decimal exponent most closely corresponding to this value.
! * @return The decimal exponent.
! */
! public int getDecimalExponent();
!
! /**
! * 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 <code>value < 0.0</code>.
! */
! public boolean isNegative();
!
! /**
! * Indicates whether the value is either infinite or not a number.
! *
! * @return <code>true</code> if and only if the value is <code>NaN</code>
! * or infinite.
! */
! public boolean isExceptional();
!
! /**
! * Indicates whether the value was rounded up during the binary to ASCII
! * conversion.
*
! * @return <code>true</code> if and only if the value was rounded up.
! */
! public boolean digitsRoundedUp();
!
! /**
! * Indicates whether the binary to ASCII conversion was exact.
*
+ * @return <code>true</code> if any only if the conversion was exact.
*/
! public boolean decimalDigitsExact();
! }
!
! /**
! * A <code>BinaryToASCIIConverter</code> which represents <code>NaN</code>
! * and infinite values.
! */
! private static class ExceptionalBinaryToASCIIBuffer implements BinaryToASCIIConverter {
! final private String image;
! private boolean isNegative;
!
! public ExceptionalBinaryToASCIIBuffer(String image, boolean isNegative) {
! this.image = image;
! this.isNegative = isNegative;
! }
!
! @Override
! public String toJavaFormatString() {
! return image;
! }
!
! @Override
! public void appendTo(Appendable buf) {
! if (buf instanceof StringBuilder) {
! ((StringBuilder) buf).append(image);
! } else if (buf instanceof StringBuffer) {
! ((StringBuffer) buf).append(image);
! } else {
! assert false;
}
}
!
! @Override
! public int getDecimalExponent() {
! throw new IllegalArgumentException("Exceptional value does not have an exponent");
}
! @Override
! public int getDigits(char[] digits) {
! throw new IllegalArgumentException("Exceptional value does not have digits");
! }
!
! @Override
! public boolean isNegative() {
! return isNegative;
! }
!
! @Override
! public boolean isExceptional() {
! return true;
! }
!
! @Override
! public boolean digitsRoundedUp() {
! throw new IllegalArgumentException("Exceptional value is not rounded");
! }
!
! @Override
! public boolean decimalDigitsExact() {
! throw new IllegalArgumentException("Exceptional value is not exact");
! }
! }
!
! 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 <code>BinaryToASCIIConverter</code>.
*/
! 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,
! * <code>BinaryToASCIIBuffer</code> may be thread-local and reused
! */
! BinaryToASCIIBuffer(){
! this.digits = new char[20];
}
!
! /**
! * 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 {
! assert false;
! }
}
! @Override
! public int getDecimalExponent() {
! return decExponent;
}
! @Override
! public int getDigits(char[] digits) {
! System.arraycopy(this.digits,firstDigitIndex,digits,0,this.nDigits);
! return this.nDigits;
}
!
! @Override
! public boolean isNegative() {
! return isNegative;
! }
!
! @Override
! public boolean isExceptional() {
! return false;
! }
!
! @Override
! public boolean digitsRoundedUp() {
! return decimalDigitsRoundedUp;
! }
!
! @Override
! public boolean decimalDigitsExact() {
! return exactDecimalConversion;
}
+ private void setSign(boolean isNegative) {
+ this.isNegative = isNegative;
+ }
! /**
* 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.
*** 308,347 ****
* 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;
--- 360,389 ----
* 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, 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;
*** 355,367 ****
}
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);
--- 397,406 ----
*** 373,734 ****
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 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;
! }
! // 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 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;
! }
! // 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 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!
! *
! * 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 );
--- 412,609 ----
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;
! // }
! //
}
}
! //
! // 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 );
*** 738,754 ****
// 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 );
--- 613,629 ----
// 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 = b / s;
b = 10 * ( b % s );
*** 770,788 ****
}
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 );
--- 645,663 ----
}
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 );
*** 792,808 ****
// 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 );
--- 667,683 ----
// 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 );
*** 824,1559 ****
}
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;
}
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<char[]> perThreadBuffer = new ThreadLocal<char[]>() {
! 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 FloatingDecimal
! 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 FloatingDecimal(Double.NaN) // NaN has no sign
! : new FloatingDecimal(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 FloatingDecimal( 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 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 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 );
//
// 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
--- 699,1384 ----
}
lowDigitDifference = (b<<1) - tens;
exactDecimalConversion = (b == 0);
}
} else {
! //
! // 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 = 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.
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 = Bval.quoRemIteration( Sval );
assert q < 10 : q; // excessively large digit
+ Mval = Mval.multBy10(); //Mval = Mval.mult( 10 );
low = (Bval.cmp( Mval ) < 0);
! high = tenSval.addAndCmp(Bval,Mval)<=0;
digits[ndigit++] = (char)('0' + q);
}
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);
}
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();
}
}
}
! // 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.
! }
! digits[i] = (char) (q + 1);
! decimalDigitsRoundedUp = true;
! }
!
! /**
! * 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.
! */
! 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;
! }
}
! private static int insignificantDigits(int insignificant) {
! int i;
! for ( i = 0; insignificant >= 10L; i++ ) {
! insignificant /= 10L;
}
! return i;
}
! /**
! * Calculates
! * <pre>
! * insignificantDigitsForPow2(v) == insignificantDigits(1L<<v)
! * </pre>
! */
! private static int insignificantDigitsForPow2(int p2) {
! if(p2>1 && p2 < insignificantDigitsNumber.length) {
! return insignificantDigitsNumber[p2];
! }
! return 0;
}
+ /**
+ * 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, firstDigitIndex, result, i, charLength);
i += charLength;
if (charLength < decExponent) {
! charLength = decExponent - charLength;
! Arrays.fill(result,i,i+charLength,'0');
i += charLength;
result[i++] = '.';
result[i++] = '0';
} else {
result[i++] = '.';
if (charLength < nDigits) {
int t = nDigits - charLength;
! System.arraycopy(digits, firstDigitIndex+charLength, result, i, t);
i += t;
} else {
result[i++] = '0';
}
}
! } else if (decExponent <= 0 && decExponent > -3) {
result[i++] = '0';
result[i++] = '.';
if (decExponent != 0) {
! Arrays.fill(result, i, i-decExponent, '0');
i -= decExponent;
}
! System.arraycopy(digits, firstDigitIndex, result, i, nDigits);
i += nDigits;
} else {
! result[i++] = digits[firstDigitIndex];
result[i++] = '.';
if (nDigits > 1) {
! System.arraycopy(digits, firstDigitIndex+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;
}
! }
!
! private static final ThreadLocal<BinaryToASCIIBuffer> threadLocalBinaryToASCIIBuffer =
! new ThreadLocal<BinaryToASCIIBuffer>() {
! @Override
! protected BinaryToASCIIBuffer initialValue() {
! return new BinaryToASCIIBuffer();
}
};
! private static BinaryToASCIIBuffer getBinaryToASCIIBuffer() {
! return threadLocalBinaryToASCIIBuffer.get();
}
! /**
! * A converter which can process an ASCII <code>String</code> representation
! * of a single or double precision floating point value into a
! * <code>float</code> or a <code>double</code>.
! */
! interface ASCIIToBinaryConverter {
!
! double doubleValue();
!
! float floatValue();
}
! /**
! * A <code>ASCIIToBinaryConverter</code> container for a <code>double</code>.
! */
! 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 <code>ASCIIToBinaryConverter</code>.
! */
! 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
*** 1564,2009 ****
// 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+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;
}
! 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;
}
}
!
! /*
! * 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 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();
--- 1389,2077 ----
// 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 <code>BinaryToASCIIConverter</code> for a <code>double</code>.
! * The returned object is a <code>ThreadLocal</code> 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 <code>BinaryToASCIIConverter</code> for a <code>double</code>.
! * The returned object is a <code>ThreadLocal</code> 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;
! }
! 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;
! }
!
! 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;
! }
! }
! // 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")
! static ASCIIToBinaryConverter 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 len = in.length();
! if ( len == 0 ) {
! throw new NumberFormatException("empty String");
! }
! int i = 0;
! switch (in.charAt(i)){
! case '-':
! isNegative = true;
! //FALLTHROUGH
! case '+':
! i++;
! signSeen = true;
! }
! c = in.charAt(i);
! 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;
! }
! // something went wrong, throw exception
! break parseNumber;
! } else if (c == '0') { // check for hexadecimal floating-point number
! if (len > 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[ len ];
! int nDigits= 0;
! boolean decSeen = false;
! int decPt = 0;
! int nLeadZero = 0;
! int nTrailZero= 0;
!
! 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");
! }
! 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;
! 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) {
! decPt -= 1;
! }
! decSeen = true;
! } else {
! break digitLoop;
! }
! i++;
! }
! 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.
! //
! if ( decSeen ){
! decExp = decPt - nLeadZero;
! } else {
! decExp = nDigits + nTrailZero;
}
+
+ //
+ // 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;
+ boolean expOverflow = false;
+ switch( in.charAt(++i) ){
+ case '-':
+ expSign = -1;
+ //FALLTHROUGH
+ case '+':
+ i++;
}
! int expAt = i;
! expLoop:
! while ( i < len ){
! if ( expVal >= reallyBig ){
! // the next character will cause integer
! // overflow.
! expOverflow = true;
}
! c = in.charAt(i++);
! if(c>='0' && c<='9') {
! expVal = expVal*10 + ( (int)c - (int)'0' );
! } else {
! i--; // back up.
! break expLoop; // stop parsing exponent.
}
}
! int expLimit = BIG_DECIMAL_EXPONENT+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 < 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
}
! 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 + "\"");
}
! /**
! * 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.
*/
! 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;
! }
! }
! 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]?"
);
}
! /**
! * 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 <code>String</code> 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
! //
! // 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);
! 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();
*** 2011,2055 ****
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) {
--- 2079,2123 ----
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 isNegative ? A2BC_NEGATIVE_ZERO : A2BC_POSITIVE_ZERO;
}
}
// 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) {
*** 2064,2125 ****
//
// 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!");
--- 2132,2192 ----
//
// significand
// + -
// exponent + +infinity -infinity
// - +0.0 -0.0
! return isNegative ?
! (positiveExponent ? A2BC_NEGATIVE_INFINITY : A2BC_NEGATIVE_ZERO)
! : (positiveExponent ? A2BC_POSITIVE_INFINITY : A2BC_POSITIVE_ZERO);
!
}
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);
! //
! // 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!");
*** 2130,2171 ****
// 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;
--- 2197,2237 ----
// 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;
*** 2173,2191 ****
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
--- 2239,2257 ----
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
*** 2204,2229 ****
// 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 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
--- 2270,2293 ----
// 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
*** 2235,2264 ****
// 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
--- 2299,2328 ----
// 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
*** 2266,2438 ****
// 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++;
}
! 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;
}
! }
! 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 <code>s</code> with any leading zeros removed.
*/
static String stripLeadingZeros(String s) {
! return s.replaceFirst("^0+", "");
}
/**
! * Extract a hexadecimal digit from position <code>position</code>
* of string <code>s</code>.
*/
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;
}
-
-
}
--- 2330,2506 ----
// 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 leastZero = ((significand & 1L) == 0L);
! if ((leastZero && round && sticky) ||
! ((!leastZero) && round)) {
significand++;
}
! double value = isNegative ?
! Double.longBitsToDouble(significand | DoubleConsts.SIGN_BIT_MASK) :
! Double.longBitsToDouble(significand );
!
! 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;
}
}
}
}
! }
! return new PreparedASCIIToBinaryBuffer(value,roundDir);
}
}
}
/**
! * Returns <code>s</code> with any leading zeros removed.
*/
static String stripLeadingZeros(String s) {
! // return s.replaceFirst("^0+", "");
! if(!s.isEmpty() && s.charAt(0)=='0') {
! for(int i=1; i<s.length(); i++) {
! if(s.charAt(i)!='0') {
! return s.substring(i);
! }
! }
! return "";
! }
! return s;
}
/**
! * Extracts a hexadecimal digit from position <code>position</code>
* of string <code>s</code>.
*/
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;
}
}