src/share/classes/sun/misc/FormattedFloatingDecimal.java

Print this page

        

*** 1,7 **** /* ! * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this --- 1,7 ---- /* ! * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this
*** 23,1766 **** * questions. */ package sun.misc; ! import sun.misc.DoubleConsts; ! import sun.misc.FloatConsts; ! import java.util.regex.*; public class FormattedFloatingDecimal{ - boolean isExceptional; - boolean isNegative; - int decExponent; // value set at construction, then immutable - int decExponentRounded; - char digits[]; - int nDigits; - int bigIntExp; - int bigIntNBits; - boolean mustSetRoundDir = false; - boolean fromHex = false; - int roundDir = 0; // set by doubleValue - int precision; // number of digits to the right of decimal public enum Form { SCIENTIFIC, COMPATIBLE, DECIMAL_FLOAT, GENERAL }; - private Form form; ! private FormattedFloatingDecimal( boolean negSign, int decExponent, char []digits, int n, boolean e, int precision, Form form ) ! { ! isNegative = negSign; ! isExceptional = e; ! this.decExponent = decExponent; ! this.digits = digits; ! this.nDigits = n; ! this.precision = precision; ! this.form = form; } ! /* ! * 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. ! * In particular: ! * lvalue is a finite number (not Inf, nor NaN) ! * lvalue > 0L (not zero, nor negative). ! * ! * The only reason that we develop the digits here, rather than ! * calling on Long.toString() is that we can do it a little faster, ! * and besides want to treat trailing 0s specially. If Long.toString ! * changes, we should re-evaluate this strategy! */ ! private void ! developLongDigits( int decExponent, long lvalue, long insignificant ){ ! char digits[]; ! int ndigits; ! int digitno; ! int c; ! // ! // Discard non-significant low-order bits, while rounding, ! // up to insignificant value. ! int i; ! for ( i = 0; insignificant >= 10L; i++ ) ! insignificant /= 10L; ! if ( i != 0 ){ ! long pow10 = long5pow[i] << i; // 10^i == 5^i * 2^i; ! long residue = lvalue % pow10; ! lvalue /= pow10; ! decExponent += i; ! if ( residue >= (pow10>>1) ){ ! // round up based on the low-order bits we're discarding ! lvalue++; ! } ! } ! if ( lvalue <= Integer.MAX_VALUE ){ ! assert lvalue > 0L : lvalue; // lvalue <= 0 ! // even easier subcase! ! // can do int arithmetic rather than long! ! int ivalue = (int)lvalue; ! ndigits = 10; ! digits = perThreadBuffer.get(); ! digitno = ndigits-1; ! c = ivalue%10; ! ivalue /= 10; ! while ( c == 0 ){ ! decExponent++; ! c = ivalue%10; ! ivalue /= 10; ! } ! while ( ivalue != 0){ ! digits[digitno--] = (char)(c+'0'); ! decExponent++; ! c = ivalue%10; ! ivalue /= 10; ! } ! digits[digitno] = (char)(c+'0'); ! } else { ! // same algorithm as above (same bugs, too ) ! // but using long arithmetic. ! ndigits = 20; ! digits = perThreadBuffer.get(); ! digitno = ndigits-1; ! c = (int)(lvalue%10L); ! lvalue /= 10L; ! while ( c == 0 ){ ! decExponent++; ! c = (int)(lvalue%10L); ! lvalue /= 10L; ! } ! while ( lvalue != 0L ){ ! digits[digitno--] = (char)(c+'0'); ! decExponent++; ! c = (int)(lvalue%10L); ! lvalue /= 10; ! } ! digits[digitno] = (char)(c+'0'); ! } ! char result []; ! ndigits -= digitno; ! result = new char[ ndigits ]; ! System.arraycopy( digits, digitno, result, 0, ndigits ); ! this.digits = result; ! this.decExponent = decExponent+1; ! this.nDigits = ndigits; ! } ! ! // ! // add one to the least significant digit. ! // in the unlikely event there is a carry out, ! // deal with it. ! // assert that this will only happen where there ! // is only one digit, e.g. (float)1e-44 seems to do it. ! // ! private void ! roundup(){ ! int i; ! int q = digits[ i = (nDigits-1)]; ! if ( q == '9' ){ ! while ( q == '9' && i > 0 ){ ! digits[i] = '0'; ! q = digits[--i]; ! } ! if ( q == '9' ){ ! // carryout! High-order 1, rest 0s, larger exp. ! decExponent += 1; ! digits[0] = '1'; ! return; ! } ! // else fall through. ! } ! digits[i] = (char)(q+1); ! } ! ! // Given the desired number of digits predict the result's exponent. ! private int checkExponent(int length) { ! if (length >= nDigits || length < 0) ! return decExponent; ! ! for (int i = 0; i < length; i++) ! if (digits[i] != '9') ! // a '9' anywhere in digits will absorb the round ! return decExponent; ! return decExponent + (digits[length] >= '5' ? 1 : 0); ! } ! ! // Unlike roundup(), this method does not modify digits. It also ! // rounds at a particular precision. ! private char [] applyPrecision(int length) { ! char [] result = new char[nDigits]; ! for (int i = 0; i < result.length; i++) result[i] = '0'; ! ! if (length >= nDigits || length < 0) { // no rounding necessary ! System.arraycopy(digits, 0, result, 0, nDigits); ! return result; } ! if (length == 0) { // only one digit (0 or 1) is returned because the precision // excludes all significant digits if (digits[0] >= '5') { ! result[0] = '1'; } - return result; } ! ! int i = length; ! int q = digits[i]; ! if (q >= '5' && i > 0) { q = digits[--i]; if ( q == '9' ) { while ( q == '9' && i > 0 ){ q = digits[--i]; } if ( q == '9' ){ // carryout! High-order 1, rest 0s, larger exp. ! result[0] = '1'; ! return result; ! } ! } ! result[i] = (char)(q + 1); ! } ! while (--i >= 0) { ! result[i] = digits[i]; ! } ! return result; ! } ! ! /* ! * FIRST IMPORTANT CONSTRUCTOR: DOUBLE ! */ ! public FormattedFloatingDecimal( double d ) ! { ! this(d, Integer.MAX_VALUE, Form.COMPATIBLE); ! } ! ! public FormattedFloatingDecimal( double d, int precision, Form form ) ! { ! long dBits = Double.doubleToLongBits( d ); ! long fractBits; ! int binExp; ! int nSignificantBits; ! ! this.precision = precision; ! this.form = form; ! ! // discover and delete sign ! if ( (dBits&signMask) != 0 ){ ! isNegative = true; ! dBits ^= signMask; ! } else { ! isNegative = false; ! } ! // Begin to unpack ! // Discover obvious special cases of NaN and Infinity. ! binExp = (int)( (dBits&expMask) >> expShift ); ! fractBits = dBits&fractMask; ! if ( binExp == (int)(expMask>>expShift) ) { ! isExceptional = true; ! if ( fractBits == 0L ){ ! digits = infinity; ! } else { ! digits = notANumber; ! isNegative = false; // NaN has no sign! ! } ! nDigits = digits.length; ! return; ! } ! isExceptional = false; ! // Finish unpacking ! // Normalize denormalized numbers. ! // Insert assumed high-order bit for normalized numbers. ! // Subtract exponent bias. ! if ( binExp == 0 ){ ! if ( fractBits == 0L ){ ! // not a denorm, just a 0! ! decExponent = 0; ! digits = zero; ! nDigits = 1; ! return; } - while ( (fractBits&fractHOB) == 0L ){ - fractBits <<= 1; - binExp -= 1; } ! nSignificantBits = expShift + binExp +1; // recall binExp is - shift count. ! binExp += 1; } 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 FormattedFloatingDecimal( float f ) ! { ! this(f, Integer.MAX_VALUE, Form.COMPATIBLE); ! } ! public FormattedFloatingDecimal( float f, int precision, Form form ) ! { ! int fBits = Float.floatToIntBits( f ); ! int fractBits; ! int binExp; ! int nSignificantBits; ! ! this.precision = precision; ! this.form = form; ! ! // discover and delete sign ! if ( (fBits&singleSignMask) != 0 ){ ! isNegative = true; ! fBits ^= singleSignMask; ! } else { ! isNegative = false; } ! // Begin to unpack ! // Discover obvious special cases of NaN and Infinity. ! binExp = (fBits&singleExpMask) >> singleExpShift; ! fractBits = fBits&singleFractMask; ! if ( binExp == (singleExpMask>>singleExpShift) ) { ! isExceptional = true; ! if ( fractBits == 0L ){ ! digits = infinity; } else { ! digits = notANumber; ! isNegative = false; // NaN has no sign! ! } ! nDigits = digits.length; ! return; ! } ! isExceptional = false; ! // Finish unpacking ! // Normalize denormalized numbers. ! // Insert assumed high-order bit for normalized numbers. ! // Subtract exponent bias. ! if ( binExp == 0 ){ ! if ( fractBits == 0 ){ ! // not a denorm, just a 0! ! decExponent = 0; ! digits = zero; ! nDigits = 1; ! return; ! } ! while ( (fractBits&singleFractHOB) == 0 ){ ! fractBits <<= 1; ! binExp -= 1; } - nSignificantBits = singleExpShift + binExp +1; // recall binExp is - shift count. - binExp += 1; } else { ! fractBits |= singleFractHOB; ! nSignificantBits = singleExpShift+1; ! } ! binExp -= singleExpBias; ! // call the routine that actually does all the hard work. ! dtoa( binExp, ((long)fractBits)<<(expShift-singleExpShift), nSignificantBits ); ! } ! ! private void ! dtoa( int binExp, long fractBits, int nSignificantBits ) ! { ! int nFractBits; // number of significant bits of fractBits; ! int nTinyBits; // number of these to the right of the point. ! int decExp; ! ! // Examine number. Determine if it is an easy case, ! // which we can do pretty trivially using float/long conversion, ! // or whether we must do real work. ! nFractBits = countBits( fractBits ); ! nTinyBits = Math.max( 0, nFractBits - binExp - 1 ); ! if ( binExp <= maxSmallBinExp && binExp >= minSmallBinExp ){ ! // Look more closely at the number to decide if, ! // with scaling by 10^nTinyBits, the result will fit in ! // a long. ! if ( (nTinyBits < long5pow.length) && ((nFractBits + n5bits[nTinyBits]) < 64 ) ){ ! /* ! * We can do this: ! * take the fraction bits, which are normalized. ! * (a) nTinyBits == 0: Shift left or right appropriately ! * to align the binary point at the extreme right, i.e. ! * where a long int point is expected to be. The integer ! * result is easily converted to a string. ! * (b) nTinyBits > 0: Shift right by expShift-nFractBits, ! * which effectively converts to long and scales by ! * 2^nTinyBits. Then multiply by 5^nTinyBits to ! * complete the scaling. We know this won't overflow ! * because we just counted the number of bits necessary ! * in the result. The integer you get from this can ! * then be converted to a string pretty easily. ! */ ! long halfULP; ! if ( nTinyBits == 0 ) { ! if ( binExp > nSignificantBits ){ ! halfULP = 1L << ( binExp-nSignificantBits-1); } else { ! halfULP = 0L; } ! if ( binExp >= expShift ){ ! fractBits <<= (binExp-expShift); } else { ! fractBits >>>= (expShift-binExp) ; ! } ! developLongDigits( 0, fractBits, halfULP ); ! return; ! } ! /* ! * The following causes excess digits to be printed ! * out in the single-float case. Our manipulation of ! * halfULP here is apparently not correct. If we ! * better understand how this works, perhaps we can ! * use this special case again. But for the time being, ! * we do not. ! * else { ! * fractBits >>>= expShift+1-nFractBits; ! * fractBits *= long5pow[ nTinyBits ]; ! * halfULP = long5pow[ nTinyBits ] >> (1+nSignificantBits-nFractBits); ! * developLongDigits( -nTinyBits, fractBits, halfULP ); ! * return; ! * } ! */ } } - /* - * This is the hard case. We are going to compute large positive - * integers B and S and integer decExp, s.t. - * d = ( B / S ) * 10^decExp - * 1 <= B / S < 10 - * Obvious choices are: - * decExp = floor( log10(d) ) - * B = d * 2^nTinyBits * 10^max( 0, -decExp ) - * S = 10^max( 0, decExp) * 2^nTinyBits - * (noting that nTinyBits has already been forced to non-negative) - * I am also going to compute a large positive integer - * M = (1/2^nSignificantBits) * 2^nTinyBits * 10^max( 0, -decExp ) - * i.e. M is (1/2) of the ULP of d, scaled like B. - * When we iterate through dividing B/S and picking off the - * quotient bits, we will know when to stop when the remainder - * is <= M. - * - * We keep track of powers of 2 and powers of 5. - */ - - /* - * Estimate decimal exponent. (If it is small-ish, - * we could double-check.) - * - * First, scale the mantissa bits such that 1 <= d2 < 2. - * We are then going to estimate - * log10(d2) ~=~ (d2-1.5)/1.5 + log(1.5) - * and so we can estimate - * log10(d) ~=~ log10(d2) + binExp * log10(2) - * take the floor and call it decExp. - * FIXME -- use more precise constants here. It costs no more. - */ - double d2 = Double.longBitsToDouble( - expOne | ( fractBits &~ fractHOB ) ); - decExp = (int)Math.floor( - (d2-1.5D)*0.289529654D + 0.176091259 + (double)binExp * 0.301029995663981 ); - int B2, B5; // powers of 2 and powers of 5, respectively, in B - int S2, S5; // powers of 2 and powers of 5, respectively, in S - int M2, M5; // powers of 2 and powers of 5, respectively, in M - int Bbits; // binary digits needed to represent B, approx. - int tenSbits; // binary digits needed to represent 10*S, approx. - FDBigInt Sval, Bval, Mval; - - B5 = Math.max( 0, -decExp ); - B2 = B5 + nTinyBits + binExp; - - S5 = Math.max( 0, decExp ); - S2 = S5 + nTinyBits; - - M5 = B5; - M2 = B2 - nSignificantBits; - - /* - * the long integer fractBits contains the (nFractBits) interesting - * bits from the mantissa of d ( hidden 1 added if necessary) followed - * by (expShift+1-nFractBits) zeros. In the interest of compactness, - * I will shift out those zeros before turning fractBits into a - * FDBigInt. The resulting whole number will be - * d * 2^(nFractBits-1-binExp). - */ - fractBits >>>= (expShift+1-nFractBits); - B2 -= nFractBits-1; - int common2factor = Math.min( B2, S2 ); - B2 -= common2factor; - S2 -= common2factor; - M2 -= common2factor; - - /* - * HACK!! For exact powers of two, the next smallest number - * is only half as far away as we think (because the meaning of - * ULP changes at power-of-two bounds) for this reason, we - * hack M2. Hope this works. - */ - if ( nFractBits == 1 ) - M2 -= 1; - - if ( M2 < 0 ){ - // oops. - // since we cannot scale M down far enough, - // we must scale the other values up. - B2 -= M2; - S2 -= M2; - M2 = 0; } - /* - * Construct, Scale, iterate. - * Some day, we'll write a stopping test that takes - * account of the assymetry of the spacing of floating-point - * numbers below perfect powers of 2 - * 26 Sept 96 is not that day. - * So we use a symmetric test. - */ - char digits[] = this.digits = new char[18]; - int ndigit = 0; - boolean low, high; - long lowDigitDifference; - int q; ! /* ! * Detect the special cases where all the numbers we are about ! * to compute will fit in int or long integers. ! * In these cases, we will avoid doing FDBigInt arithmetic. ! * We use the same algorithms, except that we "normalize" ! * our FDBigInts before iterating. This is to make division easier, ! * as it makes our fist guess (quotient of high-order words) ! * more accurate! ! * ! * Some day, we'll write a stopping test that takes ! * account of the assymetry of the spacing of floating-point ! * numbers below perfect powers of 2 ! * 26 Sept 96 is not that day. ! * So we use a symmetric test. ! */ ! Bbits = nFractBits + B2 + (( B5 < n5bits.length )? n5bits[B5] : ( B5*3 )); ! tenSbits = S2+1 + (( (S5+1) < n5bits.length )? n5bits[(S5+1)] : ( (S5+1)*3 )); ! if ( Bbits < 64 && tenSbits < 64){ ! if ( Bbits < 32 && tenSbits < 32){ ! // wa-hoo! They're all ints! ! int b = ((int)fractBits * small5pow[B5] ) << B2; ! int s = small5pow[S5] << S2; ! int m = small5pow[M5] << M2; ! int tens = s * 10; ! /* ! * Unroll the first iteration. If our decExp estimate ! * was too high, our first quotient will be zero. In this ! * case, we discard it and decrement decExp. ! */ ! ndigit = 0; ! q = b / s; ! b = 10 * ( b % s ); ! m *= 10; ! low = (b < m ); ! high = (b+m > tens ); ! assert q < 10 : q; // excessively large digit ! if ( (q == 0) && ! high ){ ! // oops. Usually ignore leading zero. ! decExp--; ! } else { ! digits[ndigit++] = (char)('0' + q); ! } ! /* ! * HACK! Java spec sez that we always have at least ! * one digit after the . in either F- or E-form output. ! * Thus we will need more than one digit if we're using ! * E-form ! */ ! if (! (form == Form.COMPATIBLE && -3 < decExp && decExp < 8)) { ! high = low = false; ! } ! while( ! low && ! high ){ ! q = b / s; ! b = 10 * ( b % s ); ! m *= 10; ! assert q < 10 : q; // excessively large digit ! if ( m > 0L ){ ! low = (b < m ); ! high = (b+m > tens ); ! } else { ! // hack -- m might overflow! ! // in this case, it is certainly > b, ! // which won't ! // and b+m > tens, too, since that has overflowed ! // either! ! low = true; ! high = true; ! } ! digits[ndigit++] = (char)('0' + q); ! } ! lowDigitDifference = (b<<1) - tens; ! } else { ! // still good! they're all longs! ! long b = (fractBits * long5pow[B5] ) << B2; ! long s = long5pow[S5] << S2; ! long m = long5pow[M5] << M2; ! long tens = s * 10L; ! /* ! * Unroll the first iteration. If our decExp estimate ! * was too high, our first quotient will be zero. In this ! * case, we discard it and decrement decExp. ! */ ! ndigit = 0; ! q = (int) ( b / s ); ! b = 10L * ( b % s ); ! m *= 10L; ! low = (b < m ); ! high = (b+m > tens ); ! assert q < 10 : q; // excessively large digit ! if ( (q == 0) && ! high ){ ! // oops. Usually ignore leading zero. ! decExp--; ! } else { ! digits[ndigit++] = (char)('0' + q); ! } ! /* ! * HACK! Java spec sez that we always have at least ! * one digit after the . in either F- or E-form output. ! * Thus we will need more than one digit if we're using ! * E-form ! */ ! if (! (form == Form.COMPATIBLE && -3 < decExp && decExp < 8)) { ! high = low = false; ! } ! while( ! low && ! high ){ ! q = (int) ( b / s ); ! b = 10 * ( b % s ); ! m *= 10; ! assert q < 10 : q; // excessively large digit ! if ( m > 0L ){ ! low = (b < m ); ! high = (b+m > tens ); } else { ! // hack -- m might overflow! ! // in this case, it is certainly > b, ! // which won't ! // and b+m > tens, too, since that has overflowed ! // either! ! low = true; ! high = true; } - digits[ndigit++] = (char)('0' + q); } - lowDigitDifference = (b<<1) - tens; - } - } else { - FDBigInt tenSval; - int shiftBias; /* ! * We really must do FDBigInt arithmetic. ! * Fist, construct our FDBigInt initial values. */ ! Bval = multPow52( new FDBigInt( fractBits ), B5, B2 ); ! Sval = constructPow52( S5, S2 ); ! Mval = constructPow52( M5, M2 ); ! ! ! // normalize so that division works better ! Bval.lshiftMe( shiftBias = Sval.normalizeMe() ); ! Mval.lshiftMe( shiftBias ); ! tenSval = Sval.mult( 10 ); ! /* ! * Unroll the first iteration. If our decExp estimate ! * was too high, our first quotient will be zero. In this ! * case, we discard it and decrement decExp. ! */ ! ndigit = 0; ! q = Bval.quoRemIteration( Sval ); ! Mval = Mval.mult( 10 ); ! low = (Bval.cmp( Mval ) < 0); ! high = (Bval.add( Mval ).cmp( tenSval ) > 0 ); ! assert q < 10 : q; // excessively large digit ! if ( (q == 0) && ! high ){ ! // oops. Usually ignore leading zero. ! decExp--; ! } else { ! digits[ndigit++] = (char)('0' + q); ! } ! /* ! * HACK! Java spec sez that we always have at least ! * one digit after the . in either F- or E-form output. ! * Thus we will need more than one digit if we're using ! * E-form ! */ ! if (! (form == Form.COMPATIBLE && -3 < decExp && decExp < 8)) { ! high = low = false; ! } ! while( ! low && ! high ){ ! q = Bval.quoRemIteration( Sval ); ! Mval = Mval.mult( 10 ); ! assert q < 10 : q; // excessively large digit ! low = (Bval.cmp( Mval ) < 0); ! high = (Bval.add( Mval ).cmp( tenSval ) > 0 ); ! digits[ndigit++] = (char)('0' + q); ! } ! if ( high && low ){ ! Bval.lshiftMe(1); ! lowDigitDifference = Bval.cmp(tenSval); ! } else ! lowDigitDifference = 0L; // this here only for flow analysis! ! } ! this.decExponent = decExp+1; ! this.digits = digits; ! this.nDigits = ndigit; ! /* ! * Last digit gets rounded based on stopping condition. ! */ ! if ( high ){ ! if ( low ){ ! if ( lowDigitDifference == 0L ){ ! // it's a tie! ! // choose based on which digits we like. ! if ( (digits[nDigits-1]&1) != 0 ) roundup(); ! } else if ( lowDigitDifference > 0 ){ ! roundup(); ! } ! } else { ! roundup(); ! } ! } ! } ! ! 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); ! } ! ! // returns the exponent before rounding ! public int getExponent() { ! return decExponent - 1; ! } ! ! // returns the exponent after rounding has been done by applyPrecision ! public int getExponentRounded() { ! return decExponentRounded - 1; ! } ! ! public int getChars(char[] result) { ! assert nDigits <= 19 : nDigits; // generous bound on size of nDigits ! int i = 0; ! if (isNegative) { result[0] = '-'; i = 1; } ! if (isExceptional) { ! System.arraycopy(digits, 0, result, i, nDigits); ! i += nDigits; ! } else { ! char digits [] = this.digits; ! int exp = decExponent; ! switch (form) { ! case COMPATIBLE: ! break; ! case DECIMAL_FLOAT: ! exp = checkExponent(decExponent + precision); ! digits = applyPrecision(decExponent + precision); ! break; ! case SCIENTIFIC: ! exp = checkExponent(precision + 1); ! digits = applyPrecision(precision + 1); ! break; ! case GENERAL: ! exp = checkExponent(precision); ! digits = applyPrecision(precision); ! // adjust precision to be the number of digits to right of decimal ! // the real exponent to be output is actually exp - 1, not exp ! if (exp - 1 < -4 || exp - 1 >= precision) { ! form = Form.SCIENTIFIC; ! precision--; ! } else { ! form = Form.DECIMAL_FLOAT; ! precision = precision - exp; ! } ! break; ! default: ! assert false; ! } ! decExponentRounded = exp; ! ! if (exp > 0 ! && ((form == Form.COMPATIBLE && (exp < 8)) ! || (form == Form.DECIMAL_FLOAT))) ! { // print digits.digits. ! int charLength = Math.min(nDigits, exp); ! System.arraycopy(digits, 0, result, i, charLength); ! i += charLength; ! if (charLength < exp) { ! charLength = exp-charLength; ! for (int nz = 0; nz < charLength; nz++) ! result[i++] = '0'; // Do not append ".0" for formatted floats since the user // may request that it be omitted. It is added as necessary // by the Formatter. - if (form == Form.COMPATIBLE) { - result[i++] = '.'; - result[i++] = '0'; - } } else { // Do not append ".0" for formatted floats since the user // may request that it be omitted. It is added as necessary // by the Formatter. - if (form == Form.COMPATIBLE) { - result[i++] = '.'; - if (charLength < nDigits) { - int t = Math.min(nDigits - charLength, precision); - System.arraycopy(digits, charLength, result, i, t); - i += t; - } else { - result[i++] = '0'; - } - } else { - int t = Math.min(nDigits - charLength, precision); if (t > 0) { ! result[i++] = '.'; ! System.arraycopy(digits, charLength, result, i, t); ! i += t; } } ! } ! } else if (exp <= 0 ! && ((form == Form.COMPATIBLE && exp > -3) ! || (form == Form.DECIMAL_FLOAT))) ! { ! // print 0.0* digits ! result[i++] = '0'; ! if (exp != 0) { // write '0' s before the significant digits ! int t = Math.min(-exp, precision); ! if (t > 0) { ! result[i++] = '.'; ! for (int nz = 0; nz < t; nz++) ! result[i++] = '0'; ! } ! } ! int t = Math.min(digits.length, precision + exp); if (t > 0) { - if (i == 1) - result[i++] = '.'; // copy only when significant digits are within the precision ! System.arraycopy(digits, 0, result, i, t); ! i += t; } } else { ! result[i++] = digits[0]; ! if (form == Form.COMPATIBLE) { ! result[i++] = '.'; ! if (nDigits > 1) { ! System.arraycopy(digits, 1, result, i, nDigits-1); ! i += nDigits-1; ! } else { ! result[i++] = '0'; } - result[i++] = 'E'; - } else { - if (nDigits > 1) { - int t = Math.min(nDigits -1, precision); - if (t > 0) { - result[i++] = '.'; - System.arraycopy(digits, 1, result, i, t); - i += t; } } ! result[i++] = 'e'; } int e; if (exp <= 0) { ! result[i++] = '-'; ! e = -exp+1; } else { ! if (form != Form.COMPATIBLE) ! result[i++] = '+'; ! e = exp-1; } // decExponent has 1, 2, or 3, digits if (e <= 9) { ! if (form != Form.COMPATIBLE) ! result[i++] = '0'; ! result[i++] = (char)(e+'0'); } else if (e <= 99) { ! result[i++] = (char)(e/10 +'0'); ! result[i++] = (char)(e%10 + '0'); } else { ! result[i++] = (char)(e/100+'0'); e %= 100; ! result[i++] = (char)(e/10+'0'); ! result[i++] = (char)(e%10 + '0'); ! } ! } ! } ! 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]; ! } ! }; ! ! /* ! * Take a FormattedFloatingDecimal, which we presumably just scanned in, ! * and find out what its value is, as a double. ! * ! * AS A SIDE EFFECT, SET roundDir TO INDICATE PREFERRED ! * ROUNDING DIRECTION in case the result is really destined ! * for a single-precision float. ! */ ! ! public strictfp double doubleValue(){ ! int kDigits = Math.min( nDigits, maxDecimalDigits+1 ); ! long lValue; ! double dValue; ! double rValue, tValue; ! ! // First, check for NaN and Infinity values ! if(digits == infinity || digits == notANumber) { ! if(digits == notANumber) ! return Double.NaN; ! else ! return (isNegative?Double.NEGATIVE_INFINITY:Double.POSITIVE_INFINITY); ! } ! else { ! if (mustSetRoundDir) { ! roundDir = 0; ! } ! /* ! * convert the lead kDigits to a long integer. ! */ ! // (special performance hack: start to do it using int) ! int iValue = (int)digits[0]-(int)'0'; ! int iDigits = Math.min( kDigits, intDecimalDigits ); ! for ( int i=1; i < iDigits; i++ ){ ! iValue = iValue*10 + (int)digits[i]-(int)'0'; ! } ! lValue = (long)iValue; ! for ( int i=iDigits; i < kDigits; i++ ){ ! lValue = lValue*10L + (long)((int)digits[i]-(int)'0'); ! } ! dValue = (double)lValue; ! int exp = decExponent-kDigits; ! /* ! * lValue now contains a long integer with the value of ! * the first kDigits digits of the number. ! * dValue contains the (double) of the same. ! */ ! ! if ( nDigits <= maxDecimalDigits ){ ! /* ! * possibly an easy case. ! * We know that the digits can be represented ! * exactly. And if the exponent isn't too outrageous, ! * the whole thing can be done with one operation, ! * thus one rounding error. ! * Note that all our constructors trim all leading and ! * trailing zeros, so simple values (including zero) ! * will always end up here ! */ ! if (exp == 0 || dValue == 0.0) ! return (isNegative)? -dValue : dValue; // small floating integer ! else if ( exp >= 0 ){ ! if ( exp <= maxSmallTen ){ ! /* ! * Can get the answer with one operation, ! * thus one roundoff. ! */ ! rValue = dValue * small10pow[exp]; ! if ( mustSetRoundDir ){ ! tValue = rValue / small10pow[exp]; ! roundDir = ( tValue == dValue ) ? 0 ! :( tValue < dValue ) ? 1 ! : -1; ! } ! return (isNegative)? -rValue : rValue; ! } ! int slop = maxDecimalDigits - kDigits; ! if ( exp <= maxSmallTen+slop ){ ! /* ! * We can multiply dValue by 10^(slop) ! * and it is still "small" and exact. ! * Then we can multiply by 10^(exp-slop) ! * with one rounding. ! */ ! dValue *= small10pow[slop]; ! rValue = dValue * small10pow[exp-slop]; ! ! if ( mustSetRoundDir ){ ! tValue = rValue / small10pow[exp-slop]; ! roundDir = ( tValue == dValue ) ? 0 ! :( tValue < dValue ) ? 1 ! : -1; } - return (isNegative)? -rValue : rValue; } - /* - * Else we have a hard case with a positive exp. - */ - } else { - if ( exp >= -maxSmallTen ){ - /* - * Can get the answer in one division. - */ - rValue = dValue / small10pow[-exp]; - tValue = rValue * small10pow[-exp]; - if ( mustSetRoundDir ){ - roundDir = ( tValue == dValue ) ? 0 - :( tValue < dValue ) ? 1 - : -1; - } - return (isNegative)? -rValue : rValue; - } - /* - * Else we have a hard case with a negative exp. - */ - } - } - - /* - * Harder cases: - * The sum of digits plus exponent is greater than - * what we think we can do with one error. - * - * Start by approximating the right answer by, - * naively, scaling by powers of 10. - */ - if ( exp > 0 ){ - if ( decExponent > maxDecimalExponent+1 ){ - /* - * Lets face it. This is going to be - * Infinity. Cut to the chase. - */ - return (isNegative)? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY; - } - if ( (exp&15) != 0 ){ - dValue *= small10pow[exp&15]; - } - if ( (exp>>=4) != 0 ){ - int j; - for( j = 0; exp > 1; j++, exp>>=1 ){ - if ( (exp&1)!=0) - dValue *= big10pow[j]; - } - /* - * The reason for the weird exp > 1 condition - * in the above loop was so that the last multiply - * would get unrolled. We handle it here. - * It could overflow. - */ - double t = dValue * big10pow[j]; - if ( Double.isInfinite( t ) ){ - /* - * It did overflow. - * Look more closely at the result. - * If the exponent is just one too large, - * then use the maximum finite as our estimate - * value. Else call the result infinity - * and punt it. - * ( I presume this could happen because - * rounding forces the result here to be - * an ULP or two larger than - * Double.MAX_VALUE ). - */ - t = dValue / 2.0; - t *= big10pow[j]; - if ( Double.isInfinite( t ) ){ - return (isNegative)? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY; - } - t = Double.MAX_VALUE; - } - dValue = t; - } - } else if ( exp < 0 ){ - exp = -exp; - if ( decExponent < minDecimalExponent-1 ){ - /* - * Lets face it. This is going to be - * zero. Cut to the chase. - */ - return (isNegative)? -0.0 : 0.0; - } - if ( (exp&15) != 0 ){ - dValue /= small10pow[exp&15]; - } - if ( (exp>>=4) != 0 ){ - int j; - for( j = 0; exp > 1; j++, exp>>=1 ){ - if ( (exp&1)!=0) - dValue *= tiny10pow[j]; - } - /* - * The reason for the weird exp > 1 condition - * in the above loop was so that the last multiply - * would get unrolled. We handle it here. - * It could underflow. - */ - double t = dValue * tiny10pow[j]; - if ( t == 0.0 ){ - /* - * It did underflow. - * Look more closely at the result. - * If the exponent is just one too small, - * then use the minimum finite as our estimate - * value. Else call the result 0.0 - * and punt it. - * ( I presume this could happen because - * rounding forces the result here to be - * an ULP or two less than - * Double.MIN_VALUE ). - */ - t = dValue * 2.0; - t *= tiny10pow[j]; - if ( t == 0.0 ){ - return (isNegative)? -0.0 : 0.0; - } - t = Double.MIN_VALUE; - } - dValue = t; - } - } - - /* - * dValue is now approximately the result. - * The hard part is adjusting it, by comparison - * with FDBigInt arithmetic. - * Formulate the EXACT big-number result as - * bigD0 * 10^exp - */ - FDBigInt bigD0 = new FDBigInt( lValue, digits, kDigits, nDigits ); - exp = decExponent - nDigits; - - correctionLoop: - while(true){ - /* AS A SIDE EFFECT, THIS METHOD WILL SET THE INSTANCE VARIABLES - * bigIntExp and bigIntNBits - */ - FDBigInt bigB = doubleToBigInt( dValue ); - - /* - * Scale bigD, bigB appropriately for - * big-integer operations. - * Naively, we multipy by powers of ten - * and powers of two. What we actually do - * is keep track of the powers of 5 and - * powers of 2 we would use, then factor out - * common divisors before doing the work. - */ - int B2, B5; // powers of 2, 5 in bigB - int D2, D5; // powers of 2, 5 in bigD - int Ulp2; // powers of 2 in halfUlp. - if ( exp >= 0 ){ - B2 = B5 = 0; - D2 = D5 = exp; - } else { - B2 = B5 = -exp; - D2 = D5 = 0; - } - if ( bigIntExp >= 0 ){ - B2 += bigIntExp; - } else { - D2 -= bigIntExp; - } - Ulp2 = B2; - // shift bigB and bigD left by a number s. t. - // halfUlp is still an integer. - int hulpbias; - if ( bigIntExp+bigIntNBits <= -expBias+1 ){ - // This is going to be a denormalized number - // (if not actually zero). - // half an ULP is at 2^-(expBias+expShift+1) - hulpbias = bigIntExp+ expBias + expShift; - } else { - hulpbias = expShift + 2 - bigIntNBits; - } - B2 += hulpbias; - D2 += hulpbias; - // if there are common factors of 2, we might just as well - // factor them out, as they add nothing useful. - int common2 = Math.min( B2, Math.min( D2, Ulp2 ) ); - B2 -= common2; - D2 -= common2; - Ulp2 -= common2; - // do multiplications by powers of 5 and 2 - bigB = multPow52( bigB, B5, B2 ); - FDBigInt bigD = multPow52( new FDBigInt( bigD0 ), D5, D2 ); - // - // to recap: - // bigB is the scaled-big-int version of our floating-point - // candidate. - // bigD is the scaled-big-int version of the exact value - // as we understand it. - // halfUlp is 1/2 an ulp of bigB, except for special cases - // of exact powers of 2 - // - // the plan is to compare bigB with bigD, and if the difference - // is less than halfUlp, then we're satisfied. Otherwise, - // use the ratio of difference to halfUlp to calculate a fudge - // factor to add to the floating value, then go 'round again. - // - FDBigInt diff; - int cmpResult; - boolean overvalue; - if ( (cmpResult = bigB.cmp( bigD ) ) > 0 ){ - overvalue = true; // our candidate is too big. - diff = bigB.sub( bigD ); - if ( (bigIntNBits == 1) && (bigIntExp > -expBias) ){ - // candidate is a normalized exact power of 2 and - // is too big. We will be subtracting. - // For our purposes, ulp is the ulp of the - // next smaller range. - Ulp2 -= 1; - if ( Ulp2 < 0 ){ - // rats. Cannot de-scale ulp this far. - // must scale diff in other direction. - Ulp2 = 0; - diff.lshiftMe( 1 ); - } - } - } else if ( cmpResult < 0 ){ - overvalue = false; // our candidate is too small. - diff = bigD.sub( bigB ); - } else { - // the candidate is exactly right! - // this happens with surprising fequency - break correctionLoop; - } - FDBigInt halfUlp = constructPow52( B5, Ulp2 ); - if ( (cmpResult = diff.cmp( halfUlp ) ) < 0 ){ - // difference is small. - // this is close enough - if (mustSetRoundDir) { - roundDir = overvalue ? -1 : 1; - } - break correctionLoop; - } else if ( cmpResult == 0 ){ - // difference is exactly half an ULP - // round to some other value maybe, then finish - dValue += 0.5*ulp( dValue, overvalue ); - // should check for bigIntNBits == 1 here?? - if (mustSetRoundDir) { - roundDir = overvalue ? -1 : 1; - } - break correctionLoop; - } else { - // difference is non-trivial. - // could scale addend by ratio of difference to - // halfUlp here, if we bothered to compute that difference. - // Most of the time ( I hope ) it is about 1 anyway. - dValue += ulp( dValue, overvalue ); - if ( dValue == 0.0 || dValue == Double.POSITIVE_INFINITY ) - break correctionLoop; // oops. Fell off end of range. - continue; // try again. - } - - } - return (isNegative)? -dValue : dValue; - } - } - - /* - * Take a FormattedFloatingDecimal, which we presumably just scanned in, - * and find out what its value is, as a float. - * This is distinct from doubleValue() to avoid the extremely - * unlikely case of a double rounding error, wherein the converstion - * to double has one rounding error, and the conversion of that double - * to a float has another rounding error, IN THE WRONG DIRECTION, - * ( because of the preference to a zero low-order bit ). - */ - - public strictfp float floatValue(){ - int kDigits = Math.min( nDigits, singleMaxDecimalDigits+1 ); - int iValue; - float fValue; - - // First, check for NaN and Infinity values - if(digits == infinity || digits == notANumber) { - if(digits == notANumber) - return Float.NaN; - else - return (isNegative?Float.NEGATIVE_INFINITY:Float.POSITIVE_INFINITY); - } - else { - /* - * convert the lead kDigits to an integer. - */ - iValue = (int)digits[0]-(int)'0'; - for ( int i=1; i < kDigits; i++ ){ - iValue = iValue*10 + (int)digits[i]-(int)'0'; - } - fValue = (float)iValue; - int exp = decExponent-kDigits; - /* - * iValue now contains an integer with the value of - * the first kDigits digits of the number. - * fValue contains the (float) of the same. - */ - - if ( nDigits <= singleMaxDecimalDigits ){ - /* - * possibly an easy case. - * We know that the digits can be represented - * exactly. And if the exponent isn't too outrageous, - * the whole thing can be done with one operation, - * thus one rounding error. - * Note that all our constructors trim all leading and - * trailing zeros, so simple values (including zero) - * will always end up here. - */ - if (exp == 0 || fValue == 0.0f) - return (isNegative)? -fValue : fValue; // small floating integer - else if ( exp >= 0 ){ - if ( exp <= singleMaxSmallTen ){ - /* - * Can get the answer with one operation, - * thus one roundoff. - */ - fValue *= singleSmall10pow[exp]; - return (isNegative)? -fValue : fValue; - } - int slop = singleMaxDecimalDigits - kDigits; - if ( exp <= singleMaxSmallTen+slop ){ - /* - * We can multiply dValue by 10^(slop) - * and it is still "small" and exact. - * Then we can multiply by 10^(exp-slop) - * with one rounding. - */ - fValue *= singleSmall10pow[slop]; - fValue *= singleSmall10pow[exp-slop]; - return (isNegative)? -fValue : fValue; - } - /* - * Else we have a hard case with a positive exp. - */ - } else { - if ( exp >= -singleMaxSmallTen ){ - /* - * Can get the answer in one division. - */ - fValue /= singleSmall10pow[-exp]; - return (isNegative)? -fValue : fValue; - } - /* - * Else we have a hard case with a negative exp. - */ - } - } else if ( (decExponent >= nDigits) && (nDigits+decExponent <= maxDecimalDigits) ){ - /* - * In double-precision, this is an exact floating integer. - * So we can compute to double, then shorten to float - * with one round, and get the right answer. - * - * First, finish accumulating digits. - * Then convert that integer to a double, multiply - * by the appropriate power of ten, and convert to float. - */ - long lValue = (long)iValue; - for ( int i=kDigits; i < nDigits; i++ ){ - lValue = lValue*10L + (long)((int)digits[i]-(int)'0'); - } - double dValue = (double)lValue; - exp = decExponent-nDigits; - dValue *= small10pow[exp]; - fValue = (float)dValue; - return (isNegative)? -fValue : fValue; - - } - /* - * Harder cases: - * The sum of digits plus exponent is greater than - * what we think we can do with one error. - * - * Start by weeding out obviously out-of-range - * results, then convert to double and go to - * common hard-case code. - */ - if ( decExponent > singleMaxDecimalExponent+1 ){ - /* - * Lets face it. This is going to be - * Infinity. Cut to the chase. - */ - return (isNegative)? Float.NEGATIVE_INFINITY : Float.POSITIVE_INFINITY; - } else if ( decExponent < singleMinDecimalExponent-1 ){ - /* - * Lets face it. This is going to be - * zero. Cut to the chase. - */ - return (isNegative)? -0.0f : 0.0f; - } - - /* - * Here, we do 'way too much work, but throwing away - * our partial results, and going and doing the whole - * thing as double, then throwing away half the bits that computes - * when we convert back to float. - * - * The alternative is to reproduce the whole multiple-precision - * algorythm for float precision, or to try to parameterize it - * for common usage. The former will take about 400 lines of code, - * and the latter I tried without success. Thus the semi-hack - * answer here. - */ - mustSetRoundDir = !fromHex; - double dValue = doubleValue(); - return stickyRound( dValue ); - } - } - - - /* - * 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' }; } --- 23,349 ---- * questions. */ package sun.misc; ! import java.util.Arrays; public class FormattedFloatingDecimal{ public enum Form { SCIENTIFIC, COMPATIBLE, DECIMAL_FLOAT, GENERAL }; ! public static FormattedFloatingDecimal valueOf(double d, int precision, Form form){ ! FloatingDecimal.BinaryToASCIIConverter fdConverter = ! FloatingDecimal.getBinaryToASCIIConverter(d, form == Form.COMPATIBLE); ! return new FormattedFloatingDecimal(precision,form, fdConverter); } ! private int decExponentRounded; ! private char[] mantissa; ! private char[] exponent; ! ! private static final ThreadLocal<Object> threadLocalCharBuffer = ! new ThreadLocal<Object>() { ! @Override ! protected Object initialValue() { ! return new char[20]; } + }; ! private static char[] getBuffer(){ ! return (char[]) threadLocalCharBuffer.get(); } ! private FormattedFloatingDecimal(int precision, Form form, FloatingDecimal.BinaryToASCIIConverter fdConverter) { ! if (fdConverter.isExceptional()) { ! this.mantissa = fdConverter.toJavaFormatString().toCharArray(); ! this.exponent = null; ! return; } ! char[] digits = getBuffer(); ! int nDigits = fdConverter.getDigits(digits); ! int decExp = fdConverter.getDecimalExponent(); ! int exp; ! boolean isNegative = fdConverter.isNegative(); ! switch (form) { ! case COMPATIBLE: ! exp = decExp; ! this.decExponentRounded = exp; ! fillCompatible(precision, digits, nDigits, exp, isNegative); ! break; ! case DECIMAL_FLOAT: ! exp = applyPrecision(decExp, digits, nDigits, decExp + precision); ! fillDecimal(precision, digits, nDigits, exp, isNegative); ! this.decExponentRounded = exp; ! break; ! case SCIENTIFIC: ! exp = applyPrecision(decExp, digits, nDigits, precision + 1); ! fillScientific(precision, digits, nDigits, exp, isNegative); ! this.decExponentRounded = exp; ! break; ! case GENERAL: ! exp = applyPrecision(decExp, digits, nDigits, precision); ! // adjust precision to be the number of digits to right of decimal ! // the real exponent to be output is actually exp - 1, not exp ! if (exp - 1 < -4 || exp - 1 >= precision) { ! // form = Form.SCIENTIFIC; ! precision--; ! fillScientific(precision, digits, nDigits, exp, isNegative); } else { ! // form = Form.DECIMAL_FLOAT; ! precision = precision - exp; ! fillDecimal(precision, digits, nDigits, exp, isNegative); } + this.decExponentRounded = exp; + break; + default: + assert false; } } ! // returns the exponent after rounding has been done by applyPrecision ! public int getExponentRounded() { ! return decExponentRounded - 1; } ! public char[] getMantissa(){ ! return mantissa; } ! public char[] getExponent(){ ! return exponent; } ! /** ! * Returns new decExp in case of overflow. */ ! private static int applyPrecision(int decExp, char[] digits, int nDigits, int prec) { ! if (prec >= nDigits || prec < 0) { // no rounding necessary ! return decExp; } ! if (prec == 0) { // only one digit (0 or 1) is returned because the precision // excludes all significant digits if (digits[0] >= '5') { ! digits[0] = '1'; ! Arrays.fill(digits, 1, nDigits, '0'); ! return decExp + 1; ! } else { ! Arrays.fill(digits, 0, nDigits, '0'); ! return decExp; } } ! int q = digits[prec]; ! if (q >= '5') { ! int i = prec; q = digits[--i]; if ( q == '9' ) { while ( q == '9' && i > 0 ){ q = digits[--i]; } if ( q == '9' ){ // carryout! High-order 1, rest 0s, larger exp. ! digits[0] = '1'; ! Arrays.fill(digits, 1, nDigits, '0'); ! return decExp+1; } } ! digits[i] = (char)(q + 1); ! Arrays.fill(digits, i+1, nDigits, '0'); } else { ! Arrays.fill(digits, prec, nDigits, '0'); } ! return decExp; } ! /** ! * Fills mantissa and exponent char arrays for compatible format. */ ! private void fillCompatible(int precision, char[] digits, int nDigits, int exp, boolean isNegative) { ! int startIndex = isNegative ? 1 : 0; ! if (exp > 0 && exp < 8) { ! // print digits.digits. ! if (nDigits < exp) { ! int extraZeros = exp - nDigits; ! mantissa = create(isNegative, nDigits + extraZeros + 2); ! System.arraycopy(digits, 0, mantissa, startIndex, nDigits); ! Arrays.fill(mantissa, startIndex + nDigits, startIndex + nDigits + extraZeros, '0'); ! mantissa[startIndex + nDigits + extraZeros] = '.'; ! mantissa[startIndex + nDigits + extraZeros+1] = '0'; ! } else if (exp < nDigits) { ! int t = Math.min(nDigits - exp, precision); ! mantissa = create(isNegative, exp + 1 + t); ! System.arraycopy(digits, 0, mantissa, startIndex, exp); ! mantissa[startIndex + exp ] = '.'; ! System.arraycopy(digits, exp, mantissa, startIndex+exp+1, t); ! } else { // exp == digits.length ! mantissa = create(isNegative, nDigits + 2); ! System.arraycopy(digits, 0, mantissa, startIndex, nDigits); ! mantissa[startIndex + nDigits ] = '.'; ! mantissa[startIndex + nDigits +1] = '0'; ! } ! } else if (exp <= 0 && exp > -3) { ! int zeros = Math.max(0, Math.min(-exp, precision)); ! int t = Math.max(0, Math.min(nDigits, precision + exp)); ! // write '0' s before the significant digits ! if (zeros > 0) { ! mantissa = create(isNegative, zeros + 2 + t); ! mantissa[startIndex] = '0'; ! mantissa[startIndex+1] = '.'; ! Arrays.fill(mantissa, startIndex + 2, startIndex + 2 + zeros, '0'); ! if (t > 0) { ! // copy only when significant digits are within the precision ! System.arraycopy(digits, 0, mantissa, startIndex + 2 + zeros, t); } ! } else if (t > 0) { ! mantissa = create(isNegative, zeros + 2 + t); ! mantissa[startIndex] = '0'; ! mantissa[startIndex + 1] = '.'; ! // copy only when significant digits are within the precision ! System.arraycopy(digits, 0, mantissa, startIndex + 2, t); } else { ! this.mantissa = create(isNegative, 1); ! this.mantissa[startIndex] = '0'; } } else { ! if (nDigits > 1) { ! mantissa = create(isNegative, nDigits + 1); ! mantissa[startIndex] = digits[0]; ! mantissa[startIndex + 1] = '.'; ! System.arraycopy(digits, 1, mantissa, startIndex + 2, nDigits - 1); ! } else { ! mantissa = create(isNegative, 3); ! mantissa[startIndex] = digits[0]; ! mantissa[startIndex + 1] = '.'; ! mantissa[startIndex + 2] = '0'; ! } ! int e, expStartIntex; ! boolean isNegExp = (exp <= 0); ! if (isNegExp) { ! e = -exp + 1; ! expStartIntex = 1; } else { ! e = exp - 1; ! expStartIntex = 0; } ! // decExponent has 1, 2, or 3, digits ! if (e <= 9) { ! exponent = create(isNegExp,1); ! exponent[expStartIntex] = (char) (e + '0'); ! } else if (e <= 99) { ! exponent = create(isNegExp,2); ! exponent[expStartIntex] = (char) (e / 10 + '0'); ! exponent[expStartIntex+1] = (char) (e % 10 + '0'); } else { ! exponent = create(isNegExp,3); ! exponent[expStartIntex] = (char) (e / 100 + '0'); ! e %= 100; ! exponent[expStartIntex+1] = (char) (e / 10 + '0'); ! exponent[expStartIntex+2] = (char) (e % 10 + '0'); } } } ! private static char[] create(boolean isNegative, int size) { ! if(isNegative) { ! char[] r = new char[size +1]; ! r[0] = '-'; ! return r; } else { ! return new char[size]; } } /* ! * Fills mantissa char arrays for DECIMAL_FLOAT format. ! * Exponent should be equal to null. */ ! private void fillDecimal(int precision, char[] digits, int nDigits, int exp, boolean isNegative) { ! int startIndex = isNegative ? 1 : 0; ! if (exp > 0) { // print digits.digits. ! if (nDigits < exp) { ! mantissa = create(isNegative,exp); ! System.arraycopy(digits, 0, mantissa, startIndex, nDigits); ! Arrays.fill(mantissa, startIndex + nDigits, startIndex + exp, '0'); // Do not append ".0" for formatted floats since the user // may request that it be omitted. It is added as necessary // by the Formatter. } else { + int t = Math.min(nDigits - exp, precision); + mantissa = create(isNegative, exp + (t > 0 ? (t + 1) : 0)); + System.arraycopy(digits, 0, mantissa, startIndex, exp); // Do not append ".0" for formatted floats since the user // may request that it be omitted. It is added as necessary // by the Formatter. if (t > 0) { ! mantissa[startIndex + exp] = '.'; ! System.arraycopy(digits, exp, mantissa, startIndex + exp + 1, t); } } ! } else if (exp <= 0) { ! int zeros = Math.max(0, Math.min(-exp, precision)); ! int t = Math.max(0, Math.min(nDigits, precision + exp)); // write '0' s before the significant digits ! if (zeros > 0) { ! mantissa = create(isNegative, zeros + 2 + t); ! mantissa[startIndex] = '0'; ! mantissa[startIndex+1] = '.'; ! Arrays.fill(mantissa, startIndex + 2, startIndex + 2 + zeros, '0'); if (t > 0) { // copy only when significant digits are within the precision ! System.arraycopy(digits, 0, mantissa, startIndex + 2 + zeros, t); } + } else if (t > 0) { + mantissa = create(isNegative, zeros + 2 + t); + mantissa[startIndex] = '0'; + mantissa[startIndex + 1] = '.'; + // copy only when significant digits are within the precision + System.arraycopy(digits, 0, mantissa, startIndex + 2, t); } else { ! this.mantissa = create(isNegative, 1); ! this.mantissa[startIndex] = '0'; } } } ! ! /** ! * Fills mantissa and exponent char arrays for SCIENTIFIC format. ! */ ! private void fillScientific(int precision, char[] digits, int nDigits, int exp, boolean isNegative) { ! int startIndex = isNegative ? 1 : 0; ! int t = Math.max(0, Math.min(nDigits - 1, precision)); ! if (t > 0) { ! mantissa = create(isNegative, t + 2); ! mantissa[startIndex] = digits[0]; ! mantissa[startIndex + 1] = '.'; ! System.arraycopy(digits, 1, mantissa, startIndex + 2, t); ! } else { ! mantissa = create(isNegative, 1); ! mantissa[startIndex] = digits[0]; } + char expSign; int e; if (exp <= 0) { ! expSign = '-'; ! e = -exp + 1; } else { ! expSign = '+' ; ! e = exp - 1; } // decExponent has 1, 2, or 3, digits if (e <= 9) { ! exponent = new char[] { expSign, ! '0', (char) (e + '0') }; } else if (e <= 99) { ! exponent = new char[] { expSign, ! (char) (e / 10 + '0'), (char) (e % 10 + '0') }; } else { ! char hiExpChar = (char) (e / 100 + '0'); e %= 100; ! exponent = new char[] { expSign, ! hiExpChar, (char) (e / 10 + '0'), (char) (e % 10 + '0') }; } } }